android_GenericMediaPlayer.cpp revision a6c69c7e1665b38da8d6784e65210acbe501b92c
1e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/* 2e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Copyright (C) 2011 The Android Open Source Project 3e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * 4e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * you may not use this file except in compliance with the License. 6e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * You may obtain a copy of the License at 7e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * 8e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * 10e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Unless required by applicable law or agreed to in writing, software 11e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * See the License for the specific language governing permissions and 14e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * limitations under the License. 15e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */ 16e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 179d5316e3f56d138504565ff311145ac01621dff4Romain Guy//#define USE_LOG SLAndroidLogLevel_Verbose 189d5316e3f56d138504565ff311145ac01621dff4Romain Guy 199d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "sles_allinclusive.h" 209d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "android_GenericMediaPlayer.h" 219d5316e3f56d138504565ff311145ac01621dff4Romain Guy 2285bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <media/IMediaPlayerService.h> 23ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <surfaceflinger/ISurfaceComposer.h> 24f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy#include <surfaceflinger/SurfaceComposerClient.h> 25ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <media/stagefright/foundation/ADebug.h> 2685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <media/mediaplayer.h> // media_event_type media_error_type media_info_type 27e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 28bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy// default delay in Us used when reposting an event when the player is not ready to accept 29deba785f122a47915756ffd991f5540d952cf937Romain Guy// the command yet. This is for instance used when seeking on a MediaPlayer that's still preparing 30bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy#define DEFAULT_COMMAND_DELAY_FOR_REPOST_US (100*1000) // 100ms 31f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 325cbbce535744b89df5ecea95de21ee3733298260Romain Guy// table of prefixes for known distant protocols; these are immediately dispatched to mediaserver 33bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guystatic const char* const kDistantProtocolPrefix[] = { "http://", "https://", "rtsp://"}; 345cbbce535744b89df5ecea95de21ee3733298260Romain Guy#define NB_DISTANT_PROTOCOLS (sizeof(kDistantProtocolPrefix)/sizeof(kDistantProtocolPrefix[0])) 35ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 36dda570201ac851dd85af3861f7e575721d3345daRomain Guy// is the specified URI a known distant protocol? 37f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guybool isDistantProtocol(const char *uri) 38f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy{ 39bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy for (unsigned int i = 0; i < NB_DISTANT_PROTOCOLS; i++) { 40e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy if (!strncasecmp(uri, kDistantProtocolPrefix[i], strlen(kDistantProtocolPrefix[i]))) { 419d5316e3f56d138504565ff311145ac01621dff4Romain Guy return true; 42e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 43f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 44f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy return false; 45f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 46f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 475cbbce535744b89df5ecea95de21ee3733298260Romain Guynamespace android { 48026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 49026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy//-------------------------------------------------------------------------------------------------- 50026c5e16704e817cac7d9c382914c947e34f87e0Romain GuyMediaPlayerNotificationClient::MediaPlayerNotificationClient(GenericMediaPlayer* gmp) : 51026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy mGenericMediaPlayer(gmp), 52026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy mPlayerPrepared(PREPARE_NOT_STARTED) 53026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy{ 54026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy SL_LOGV("MediaPlayerNotificationClient::MediaPlayerNotificationClient()"); 55026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy} 56f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 57f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain GuyMediaPlayerNotificationClient::~MediaPlayerNotificationClient() { 58f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy SL_LOGV("MediaPlayerNotificationClient::~MediaPlayerNotificationClient()"); 59f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 605cbbce535744b89df5ecea95de21ee3733298260Romain Guy 615cbbce535744b89df5ecea95de21ee3733298260Romain Guy// Map a media_event_type enum (the msg of an IMediaPlayerClient::notify) to a string or NULL 625cbbce535744b89df5ecea95de21ee3733298260Romain Guystatic const char *media_event_type_to_string(media_event_type msg) 635cbbce535744b89df5ecea95de21ee3733298260Romain Guy{ 6485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy switch (msg) { 65e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#define _(code) case code: return #code; 6685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy _(MEDIA_NOP) 6785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy _(MEDIA_PREPARED) 68e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy _(MEDIA_PLAYBACK_COMPLETE) 69e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy _(MEDIA_BUFFERING_UPDATE) 70e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy _(MEDIA_SEEK_COMPLETE) 7108ae317c21ec3086b5017672bba87420cc38a407Romain Guy _(MEDIA_SET_VIDEO_SIZE) 72bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy _(MEDIA_TIMED_TEXT) 73bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy _(MEDIA_ERROR) 74bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy _(MEDIA_INFO) 75bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy#undef _ 76bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy default: 77bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy return NULL; 78bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } 79bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy} 80f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 81f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Map a media_error_type enum (the ext1 of a MEDIA_ERROR event) to a string or NULL 82f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guystatic const char *media_error_type_to_string(media_error_type err) 83f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy{ 84f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy switch (err) { 85f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy#define _(code, msg) case code: return msg; 86f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy _(MEDIA_ERROR_UNKNOWN, "Unknown media error") 87f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy _(MEDIA_ERROR_SERVER_DIED, "Server died") 889d5316e3f56d138504565ff311145ac01621dff4Romain Guy _(MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK, "Not valid for progressive playback") 89c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy#undef _ 90bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy default: 91bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy return NULL; 92c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy } 93f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy} 948ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 95f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy// Map a media_info_type enum (the ext1 of a MEDIA_INFO event) to a string or NULL 96deba785f122a47915756ffd991f5540d952cf937Romain Guystatic const char *media_info_type_to_string(media_info_type info) 97deba785f122a47915756ffd991f5540d952cf937Romain Guy{ 9885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy switch (info) { 99bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#define _(code, msg) case code: return msg; 10085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy _(MEDIA_INFO_UNKNOWN, "Unknown info") 10108ae317c21ec3086b5017672bba87420cc38a407Romain Guy _(MEDIA_INFO_VIDEO_TRACK_LAGGING, "Video track lagging") 1025cbbce535744b89df5ecea95de21ee3733298260Romain Guy _(MEDIA_INFO_BUFFERING_START, "Buffering start") 1035cbbce535744b89df5ecea95de21ee3733298260Romain Guy _(MEDIA_INFO_BUFFERING_END, "Buffering end") 1045cbbce535744b89df5ecea95de21ee3733298260Romain Guy _(MEDIA_INFO_NETWORK_BANDWIDTH, "Network bandwidth") 1055cbbce535744b89df5ecea95de21ee3733298260Romain Guy _(MEDIA_INFO_BAD_INTERLEAVING, "Bad interleaving") 1065cbbce535744b89df5ecea95de21ee3733298260Romain Guy _(MEDIA_INFO_NOT_SEEKABLE, "Not seekable") 1075cbbce535744b89df5ecea95de21ee3733298260Romain Guy _(MEDIA_INFO_METADATA_UPDATE, "Metadata update") 1085cbbce535744b89df5ecea95de21ee3733298260Romain Guy#undef _ 109bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy default: 1105cbbce535744b89df5ecea95de21ee3733298260Romain Guy return NULL; 1115cbbce535744b89df5ecea95de21ee3733298260Romain Guy } 1125cbbce535744b89df5ecea95de21ee3733298260Romain Guy} 1135cbbce535744b89df5ecea95de21ee3733298260Romain Guy 1145cbbce535744b89df5ecea95de21ee3733298260Romain Guy//-------------------------------------------------- 1155cbbce535744b89df5ecea95de21ee3733298260Romain Guy// IMediaPlayerClient implementation 1165cbbce535744b89df5ecea95de21ee3733298260Romain Guyvoid MediaPlayerNotificationClient::notify(int msg, int ext1, int ext2, const Parcel *obj) { 117bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy SL_LOGV("MediaPlayerNotificationClient::notify(msg=%s (%d), ext1=%d, ext2=%d)", 118bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy media_event_type_to_string((enum media_event_type) msg), msg, ext1, ext2); 1195cbbce535744b89df5ecea95de21ee3733298260Romain Guy 1205cbbce535744b89df5ecea95de21ee3733298260Romain Guy sp<GenericMediaPlayer> genericMediaPlayer(mGenericMediaPlayer.promote()); 1215cbbce535744b89df5ecea95de21ee3733298260Romain Guy if (genericMediaPlayer == NULL) { 1225cbbce535744b89df5ecea95de21ee3733298260Romain Guy SL_LOGW("MediaPlayerNotificationClient::notify after GenericMediaPlayer destroyed"); 123bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy return; 124bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy } 1255cbbce535744b89df5ecea95de21ee3733298260Romain Guy 126d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy switch ((media_event_type) msg) { 127d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy case MEDIA_PREPARED: 128d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy { 129d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy Mutex::Autolock _l(mLock); 130d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy if (PREPARE_IN_PROGRESS == mPlayerPrepared) { 131d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy mPlayerPrepared = PREPARE_COMPLETED_SUCCESSFULLY; 132d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy mPlayerPreparedCondition.signal(); 133d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } else { 134d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy SL_LOGE("Unexpected MEDIA_PREPARED"); 135d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } 136d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } 137d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy break; 138d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 139d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy case MEDIA_SET_VIDEO_SIZE: 140d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // only send video size updates if the player was flagged as having video, to avoid 141d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // sending video size updates of (0,0) 142d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // We're running on a different thread than genericMediaPlayer's ALooper thread, 143d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // so it would normally be racy to access fields within genericMediaPlayer. 144d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // But in this case mHasVideo is const, so it is safe to access. 145d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // Or alternatively, we could notify unconditionally and let it decide whether to handle. 146d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy if (genericMediaPlayer->mHasVideo && (ext1 != 0 || ext2 != 0)) { 147d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy genericMediaPlayer->notify(PLAYEREVENT_VIDEO_SIZE_UPDATE, 148d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy (int32_t)ext1 /*width*/, (int32_t)ext2 /*height*/, true /*async*/); 149d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } 150d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy break; 151d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 152d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy case MEDIA_SEEK_COMPLETE: 153d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy genericMediaPlayer->seekComplete(); 1545cbbce535744b89df5ecea95de21ee3733298260Romain Guy break; 1555cbbce535744b89df5ecea95de21ee3733298260Romain Guy 1565cbbce535744b89df5ecea95de21ee3733298260Romain Guy case MEDIA_PLAYBACK_COMPLETE: 1575cbbce535744b89df5ecea95de21ee3733298260Romain Guy genericMediaPlayer->notify(PLAYEREVENT_ENDOFSTREAM, 1, true /*async*/); 1585cbbce535744b89df5ecea95de21ee3733298260Romain Guy break; 1595cbbce535744b89df5ecea95de21ee3733298260Romain Guy 1605cbbce535744b89df5ecea95de21ee3733298260Romain Guy case MEDIA_BUFFERING_UPDATE: 1615cbbce535744b89df5ecea95de21ee3733298260Romain Guy // if we receive any out-of-range data, then clamp it to reduce further harm 162026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy if (ext1 < 0) { 1635cbbce535744b89df5ecea95de21ee3733298260Romain Guy SL_LOGE("MEDIA_BUFFERING_UPDATE %d%% < 0", ext1); 164026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy ext1 = 0; 165026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy } else if (ext1 > 100) { 1665cbbce535744b89df5ecea95de21ee3733298260Romain Guy SL_LOGE("MEDIA_BUFFERING_UPDATE %d%% > 100", ext1); 1675cbbce535744b89df5ecea95de21ee3733298260Romain Guy ext1 = 100; 1685cbbce535744b89df5ecea95de21ee3733298260Romain Guy } 1695cbbce535744b89df5ecea95de21ee3733298260Romain Guy // values received from Android framework for buffer fill level use percent, 1705cbbce535744b89df5ecea95de21ee3733298260Romain Guy // while SL/XA use permille, so does GenericPlayer 1715cbbce535744b89df5ecea95de21ee3733298260Romain Guy genericMediaPlayer->bufferingUpdate(ext1 * 10 /*fillLevelPerMille*/); 1725cbbce535744b89df5ecea95de21ee3733298260Romain Guy break; 1735cbbce535744b89df5ecea95de21ee3733298260Romain Guy 1745cbbce535744b89df5ecea95de21ee3733298260Romain Guy case MEDIA_ERROR: 1755cbbce535744b89df5ecea95de21ee3733298260Romain Guy { 1765cbbce535744b89df5ecea95de21ee3733298260Romain Guy SL_LOGV("MediaPlayerNotificationClient::notify(msg=MEDIA_ERROR, ext1=%s (%d), ext2=%d)", 177d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy media_error_type_to_string((media_error_type) ext1), ext1, ext2); 178c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy Mutex::Autolock _l(mLock); 1795cbbce535744b89df5ecea95de21ee3733298260Romain Guy if (PREPARE_IN_PROGRESS == mPlayerPrepared) { 180bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy mPlayerPrepared = PREPARE_COMPLETED_UNSUCCESSFULLY; 181a979474f15b454c8e2963f239a3770e200bb227cRomain Guy mPlayerPreparedCondition.signal(); 182c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy } else { 183026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy // inform client of errors after preparation 18482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy genericMediaPlayer->notify(PLAYEREVENT_ERRORAFTERPREPARE, ext1, true /*async*/); 18582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 18682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 18782ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy break; 18882ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy 18982ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_NOP: 19082ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_TIMED_TEXT: 19182ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy break; 19282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy 19382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO: 194a979474f15b454c8e2963f239a3770e200bb227cRomain Guy SL_LOGV("MediaPlayerNotificationClient::notify(msg=MEDIA_INFO, ext1=%s (%d), ext2=%d)", 195a979474f15b454c8e2963f239a3770e200bb227cRomain Guy media_info_type_to_string((media_info_type) ext1), ext1, ext2); 19682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy switch (ext1) { 19782ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO_VIDEO_TRACK_LAGGING: 19882ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy SL_LOGV("MEDIA_INFO_VIDEO_TRACK_LAGGING by %d ms", ext1); 19982ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy break; 20082ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO_NETWORK_BANDWIDTH: 20182ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy SL_LOGV("MEDIA_INFO_NETWORK_BANDWIDTH %d kbps", ext2); 20282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy break; 20382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO_UNKNOWN: 20482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO_BUFFERING_START: 20582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO_BUFFERING_END: 20682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO_BAD_INTERLEAVING: 20782ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO_NOT_SEEKABLE: 20882ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy case MEDIA_INFO_METADATA_UPDATE: 20982ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy default: 21082ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy break; 21182ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 21282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy break; 213f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 214f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy default: 215a979474f15b454c8e2963f239a3770e200bb227cRomain Guy break; 216f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy } 217f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 218f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 219026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 220026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy//-------------------------------------------------- 221026c5e16704e817cac7d9c382914c947e34f87e0Romain Guyvoid MediaPlayerNotificationClient::beforePrepare() 2228ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy{ 223026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy Mutex::Autolock _l(mLock); 224026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy assert(mPlayerPrepared == PREPARE_NOT_STARTED); 225026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy mPlayerPrepared = PREPARE_IN_PROGRESS; 226026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy} 227026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 228026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy//-------------------------------------------------- 229026c5e16704e817cac7d9c382914c947e34f87e0Romain Guybool MediaPlayerNotificationClient::blockUntilPlayerPrepared() { 230026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy Mutex::Autolock _l(mLock); 2318ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy assert(mPlayerPrepared != PREPARE_NOT_STARTED); 2328ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy while (mPlayerPrepared == PREPARE_IN_PROGRESS) { 2338ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy mPlayerPreparedCondition.wait(mLock); 2348ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy } 2358ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy assert(mPlayerPrepared == PREPARE_COMPLETED_SUCCESSFULLY || 2368ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy mPlayerPrepared == PREPARE_COMPLETED_UNSUCCESSFULLY); 2378ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy return mPlayerPrepared == PREPARE_COMPLETED_SUCCESSFULLY; 2388ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy} 2398ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 2408ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy//-------------------------------------------------------------------------------------------------- 241f7f93556c8fcc640ab5adef79d021a80a72a645aRomain GuyGenericMediaPlayer::GenericMediaPlayer(const AudioPlayback_Parameters* params, bool hasVideo) : 24282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy GenericPlayer(params), 24382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy mHasVideo(hasVideo), 24482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy mSeekTimeMsec(0), 245a979474f15b454c8e2963f239a3770e200bb227cRomain Guy mVideoSurfaceTexture(0), 24682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy mPlayer(0), 247260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy mPlayerClient(new MediaPlayerNotificationClient(this)), 248260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy mPlayerDeathNotifier(new MediaPlayerDeathNotifier(mPlayerClient)) 249260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy{ 250260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy SL_LOGD("GenericMediaPlayer::GenericMediaPlayer()"); 251260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy 2526926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy} 2536926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 254260e102162322958cf17dbd895cd6bd30dc87e32Romain GuyGenericMediaPlayer::~GenericMediaPlayer() { 2556926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy SL_LOGD("GenericMediaPlayer::~GenericMediaPlayer()"); 256260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy} 257bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 258bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid GenericMediaPlayer::preDestroy() { 259bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy // FIXME can't access mPlayer from outside the looper (no mutex!) so using mPreparedPlayer 26085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy sp<IMediaPlayer> player; 261260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy getPreparedPlayer(player); 262bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy if (player != NULL) { 263c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy player->stop(); 264c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy // causes CHECK failure in Nuplayer, but commented out in the subclass preDestroy 265c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy // randomly causes a NPE in StagefrightPlayer, heap corruption, or app hang 266bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy //player->setDataSource(NULL); 267bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy player->setVideoSurfaceTexture(NULL); 268f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy player->disconnect(); 269f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy // release all references to the IMediaPlayer 270bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy // FIXME illegal if not on looper 271bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy //mPlayer.clear(); 2729d5316e3f56d138504565ff311145ac01621dff4Romain Guy { 2739d5316e3f56d138504565ff311145ac01621dff4Romain Guy Mutex::Autolock _l(mPreparedPlayerLock); 274260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy mPreparedPlayer.clear(); 2759d5316e3f56d138504565ff311145ac01621dff4Romain Guy } 276bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } 277026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy GenericPlayer::preDestroy(); 278026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy} 279026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 280ce0537b80087a6225273040a987414b1dd081aa0Romain Guy//-------------------------------------------------- 28182ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy// overridden from GenericPlayer 28282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy// pre-condition: 28382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy// msec != NULL 28482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy// post-condition 28582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy// *msec == 28682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy// ANDROID_UNKNOWN_TIME if position is unknown at time of query, 287ce0537b80087a6225273040a987414b1dd081aa0Romain Guy// or the current MediaPlayer position 288dda570201ac851dd85af3861f7e575721d3345daRomain Guyvoid GenericMediaPlayer::getPositionMsec(int* msec) { 289f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy SL_LOGD("GenericMediaPlayer::getPositionMsec()"); 290bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy sp<IMediaPlayer> player; 291e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy getPreparedPlayer(player); 2929d5316e3f56d138504565ff311145ac01621dff4Romain Guy // To avoid deadlock, directly call the MediaPlayer object 293e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy if (player == 0 || player->getCurrentPosition(msec) != NO_ERROR) { 294e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *msec = ANDROID_UNKNOWN_TIME; 2959d5316e3f56d138504565ff311145ac01621dff4Romain Guy } 296} 297 298//-------------------------------------------------- 299void GenericMediaPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { 300 SL_LOGV("GenericMediaPlayer::setVideoSurfaceTexture()"); 301 // FIXME bug - race condition, should do in looper 302 if (mVideoSurfaceTexture.get() == surfaceTexture.get()) { 303 return; 304 } 305 if ((mStateFlags & kFlagPrepared) && (mPlayer != 0)) { 306 mPlayer->setVideoSurfaceTexture(surfaceTexture); 307 } 308 mVideoSurfaceTexture = surfaceTexture; 309} 310 311 312//-------------------------------------------------- 313// Event handlers 314 315// blocks until mPlayer is prepared 316void GenericMediaPlayer::onPrepare() { 317 SL_LOGD("GenericMediaPlayer::onPrepare()"); 318 // Attempt to prepare at most once, and only if there is a MediaPlayer 319 if (!(mStateFlags & (kFlagPrepared | kFlagPreparedUnsuccessfully)) && (mPlayer != 0)) { 320 if (mHasVideo) { 321 if (mVideoSurfaceTexture != 0) { 322 mPlayer->setVideoSurfaceTexture(mVideoSurfaceTexture); 323 } 324 } 325 mPlayer->setAudioStreamType(mPlaybackParams.streamType); 326 mPlayerClient->beforePrepare(); 327 mPlayer->prepareAsync(); 328 if (mPlayerClient->blockUntilPlayerPrepared()) { 329 mStateFlags |= kFlagPrepared; 330 afterMediaPlayerPreparedSuccessfully(); 331 } else { 332 mStateFlags |= kFlagPreparedUnsuccessfully; 333 } 334 } 335 GenericPlayer::onPrepare(); 336 SL_LOGD("GenericMediaPlayer::onPrepare() done, mStateFlags=0x%x", mStateFlags); 337} 338 339 340void GenericMediaPlayer::onPlay() { 341 SL_LOGD("GenericMediaPlayer::onPlay()"); 342 if (((mStateFlags & (kFlagPrepared | kFlagPlaying)) == kFlagPrepared) && (mPlayer != 0)) { 343 mPlayer->start(); 344 } 345 GenericPlayer::onPlay(); 346} 347 348 349void GenericMediaPlayer::onPause() { 350 SL_LOGD("GenericMediaPlayer::onPause()"); 351 if (!(~mStateFlags & (kFlagPrepared | kFlagPlaying)) && (mPlayer != 0)) { 352 mPlayer->pause(); 353 } 354 GenericPlayer::onPause(); 355} 356 357 358void GenericMediaPlayer::onSeekComplete() { 359 SL_LOGV("GenericMediaPlayer::onSeekComplete()"); 360 // did we initiate the seek? 361 if (!(mStateFlags & kFlagSeeking)) { 362 // no, are we looping? 363 if (mStateFlags & kFlagLooping) { 364 // yes, per OpenSL ES 1.0.1 and 1.1 do NOT report it to client 365 // notify(PLAYEREVENT_ENDOFSTREAM, 1, true /*async*/); 366 // no, well that's surprising, but it's probably just a benign race condition 367 } else { 368 SL_LOGW("Unexpected seek complete event ignored"); 369 } 370 } 371 GenericPlayer::onSeekComplete(); 372} 373 374 375/** 376 * pre-condition: WHATPARAM_SEEK_SEEKTIME_MS parameter value >= 0 377 */ 378void GenericMediaPlayer::onSeek(const sp<AMessage> &msg) { 379 SL_LOGV("GenericMediaPlayer::onSeek"); 380 int64_t timeMsec = ANDROID_UNKNOWN_TIME; 381 if (!msg->findInt64(WHATPARAM_SEEK_SEEKTIME_MS, &timeMsec)) { 382 // invalid command, drop it 383 return; 384 } 385 if ((mStateFlags & kFlagSeeking) && (timeMsec == mSeekTimeMsec) && 386 (timeMsec != ANDROID_UNKNOWN_TIME)) { 387 // already seeking to the same non-unknown time, cancel this command 388 return; 389 } else if (mStateFlags & kFlagPreparedUnsuccessfully) { 390 // discard seeks after unsuccessful prepare 391 } else if (!(mStateFlags & kFlagPrepared)) { 392 // we are not ready to accept a seek command at this time, retry later 393 msg->post(DEFAULT_COMMAND_DELAY_FOR_REPOST_US); 394 } else { 395 if (mPlayer != 0) { 396 mStateFlags |= kFlagSeeking; 397 mSeekTimeMsec = (int32_t)timeMsec; 398 // seek to unknown time is used by StreamPlayer after discontinuity 399 if (timeMsec == ANDROID_UNKNOWN_TIME) { 400 // FIXME simulate a MEDIA_SEEK_COMPLETE event in 250 ms; 401 // this is a terrible hack to make up for mediaserver not sending one 402 (new AMessage(kWhatSeekComplete, id()))->post(250000); 403 } else if (OK != mPlayer->seekTo(timeMsec)) { 404 mStateFlags &= ~kFlagSeeking; 405 mSeekTimeMsec = ANDROID_UNKNOWN_TIME; 406 // don't call updateOneShot because seek not yet done 407 } 408 } 409 } 410} 411 412 413void GenericMediaPlayer::onLoop(const sp<AMessage> &msg) { 414 SL_LOGV("GenericMediaPlayer::onLoop"); 415 int32_t loop = 0; 416 if (msg->findInt32(WHATPARAM_LOOP_LOOPING, &loop)) { 417 if (loop) { 418 mStateFlags |= kFlagLooping; 419 } else { 420 mStateFlags &= ~kFlagLooping; 421 } 422 // if we have a MediaPlayer then tell it now, otherwise we'll tell it after it's created 423 if (mPlayer != 0) { 424 (void) mPlayer->setLooping(loop); 425 } 426 } 427} 428 429 430void GenericMediaPlayer::onVolumeUpdate() { 431 SL_LOGD("GenericMediaPlayer::onVolumeUpdate()"); 432 if (mPlayer != 0) { 433 // use settings lock to read the volume settings 434 Mutex::Autolock _l(mSettingsLock); 435 mPlayer->setVolume(mAndroidAudioLevels.mFinalVolume[0], 436 mAndroidAudioLevels.mFinalVolume[1]); 437 } 438} 439 440 441void GenericMediaPlayer::onAttachAuxEffect(const sp<AMessage> &msg) { 442 SL_LOGD("GenericMediaPlayer::onAttachAuxEffect()"); 443 int32_t effectId = 0; 444 if (msg->findInt32(WHATPARAM_ATTACHAUXEFFECT, &effectId)) { 445 if (mPlayer != 0) { 446 status_t status; 447 status = mPlayer->attachAuxEffect(effectId); 448 // attachAuxEffect returns a status but we have no way to report it back to app 449 (void) status; 450 } 451 } 452} 453 454 455void GenericMediaPlayer::onSetAuxEffectSendLevel(const sp<AMessage> &msg) { 456 SL_LOGD("GenericMediaPlayer::onSetAuxEffectSendLevel()"); 457 float level = 0.0f; 458 if (msg->findFloat(WHATPARAM_SETAUXEFFECTSENDLEVEL, &level)) { 459 if (mPlayer != 0) { 460 status_t status; 461 status = mPlayer->setAuxEffectSendLevel(level); 462 // setAuxEffectSendLevel returns a status but we have no way to report it back to app 463 (void) status; 464 } 465 } 466} 467 468 469void GenericMediaPlayer::onBufferingUpdate(const sp<AMessage> &msg) { 470 int32_t fillLevel = 0; 471 if (msg->findInt32(WHATPARAM_BUFFERING_UPDATE, &fillLevel)) { 472 SL_LOGD("GenericMediaPlayer::onBufferingUpdate(fillLevel=%d)", fillLevel); 473 474 Mutex::Autolock _l(mSettingsLock); 475 mCacheFill = fillLevel; 476 // handle cache fill update 477 if (mCacheFill - mLastNotifiedCacheFill >= mCacheFillNotifThreshold) { 478 notifyCacheFill(); 479 } 480 // handle prefetch status update 481 // compute how much time ahead of position is buffered 482 int durationMsec, positionMsec = -1; 483 if ((mStateFlags & kFlagPrepared) && (mPlayer != 0) 484 && (OK == mPlayer->getDuration(&durationMsec)) 485 && (OK == mPlayer->getCurrentPosition(&positionMsec))) { 486 if ((-1 != durationMsec) && (-1 != positionMsec)) { 487 // evaluate prefetch status based on buffer time thresholds 488 int64_t bufferedDurationMsec = (durationMsec * fillLevel / 100) - positionMsec; 489 CacheStatus_t newCacheStatus = mCacheStatus; 490 if (bufferedDurationMsec > DURATION_CACHED_HIGH_MS) { 491 newCacheStatus = kStatusHigh; 492 } else if (bufferedDurationMsec > DURATION_CACHED_MED_MS) { 493 newCacheStatus = kStatusEnough; 494 } else if (bufferedDurationMsec > DURATION_CACHED_LOW_MS) { 495 newCacheStatus = kStatusIntermediate; 496 } else if (bufferedDurationMsec == 0) { 497 newCacheStatus = kStatusEmpty; 498 } else { 499 newCacheStatus = kStatusLow; 500 } 501 502 if (newCacheStatus != mCacheStatus) { 503 mCacheStatus = newCacheStatus; 504 notifyStatus(); 505 } 506 } 507 } 508 } else { 509 SL_LOGV("GenericMediaPlayer::onBufferingUpdate(fillLevel=unknown)"); 510 } 511} 512 513 514//-------------------------------------------------- 515/** 516 * called from GenericMediaPlayer::onPrepare after the MediaPlayer mPlayer is prepared successfully 517 * pre-conditions: 518 * mPlayer != 0 519 * mPlayer is prepared successfully 520 */ 521void GenericMediaPlayer::afterMediaPlayerPreparedSuccessfully() { 522 SL_LOGV("GenericMediaPlayer::afterMediaPlayerPrepared()"); 523 assert(mPlayer != 0); 524 assert(mStateFlags & kFlagPrepared); 525 // Mark this player as prepared successfully, so safe to directly call getCurrentPosition 526 { 527 Mutex::Autolock _l(mPreparedPlayerLock); 528 assert(mPreparedPlayer == 0); 529 mPreparedPlayer = mPlayer; 530 } 531 // retrieve channel count 532 int32_t channelCount; 533 Parcel *reply = new Parcel(); 534 status_t status = mPlayer->getParameter(KEY_PARAMETER_AUDIO_CHANNEL_COUNT, reply); 535 if (status == NO_ERROR) { 536 channelCount = reply->readInt32(); 537 } else { 538 // FIXME MPEG-2 TS doesn't yet implement this key, so default to stereo 539 channelCount = 2; 540 } 541 if (UNKNOWN_NUMCHANNELS != channelCount) { 542 // now that we know the channel count, re-calculate the volumes 543 notify(PLAYEREVENT_CHANNEL_COUNT, channelCount, true /*async*/); 544 } else { 545 ALOGW("channel count is still unknown after prepare"); 546 } 547 delete reply; 548 // retrieve duration 549 { 550 int msec = 0; 551 if (OK == mPlayer->getDuration(&msec)) { 552 Mutex::Autolock _l(mSettingsLock); 553 mDurationMsec = msec; 554 } 555 } 556 // now that we have a MediaPlayer, set the looping flag 557 if (mStateFlags & kFlagLooping) { 558 (void) mPlayer->setLooping(1); 559 } 560 // when the MediaPlayer mPlayer is prepared, there is "sufficient data" in the playback buffers 561 // if the data source was local, and the buffers are considered full so we need to notify that 562 bool isLocalSource = true; 563 if (kDataLocatorUri == mDataLocatorType) { 564 isLocalSource = !isDistantProtocol(mDataLocator.uriRef); 565 } 566 if (isLocalSource) { 567 SL_LOGD("media player prepared on local source"); 568 { 569 Mutex::Autolock _l(mSettingsLock); 570 mCacheStatus = kStatusHigh; 571 mCacheFill = 1000; 572 notifyStatus(); 573 notifyCacheFill(); 574 } 575 } else { 576 SL_LOGD("media player prepared on non-local source"); 577 } 578} 579 580 581//-------------------------------------------------- 582// If player is prepared successfully, set output parameter to that reference, otherwise NULL 583void GenericMediaPlayer::getPreparedPlayer(sp<IMediaPlayer> &preparedPlayer) 584{ 585 Mutex::Autolock _l(mPreparedPlayerLock); 586 preparedPlayer = mPreparedPlayer; 587} 588 589} // namespace android 590