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