AwesomePlayer.cpp revision abd1f4f870925d6776dbe4b930b759a1ab6595ca
1326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams/* 2326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Copyright (C) 2009 The Android Open Source Project 3326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * 4326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 5326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * you may not use this file except in compliance with the License. 6326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * You may obtain a copy of the License at 7326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * 8326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * http://www.apache.org/licenses/LICENSE-2.0 9326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * 10326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Unless required by applicable law or agreed to in writing, software 11326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * distributed under the License is distributed on an "AS IS" BASIS, 12326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * See the License for the specific language governing permissions and 14326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * limitations under the License. 15326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams */ 16326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 17326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams//#define LOG_NDEBUG 0 18326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#define LOG_TAG "AwesomePlayer" 19326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <utils/Log.h> 20326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 21326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <dlfcn.h> 22326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 23326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "include/ARTSPController.h" 24326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "include/AwesomePlayer.h" 25326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "include/LiveSource.h" 26e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams#include "include/SoftwareRenderer.h" 27fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchouk#include "include/NuCachedSource2.h" 28e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams#include "include/ThrottledSource.h" 29326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 30326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <binder/IPCThreadState.h> 31326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <media/stagefright/AudioPlayer.h> 32326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <media/stagefright/DataSource.h> 33e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams#include <media/stagefright/FileSource.h> 34326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <media/stagefright/MediaBuffer.h> 35326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <media/stagefright/MediaDefs.h> 369397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams#include <media/stagefright/MediaExtractor.h> 37e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams#include <media/stagefright/MediaDebug.h> 389397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams#include <media/stagefright/MediaSource.h> 399397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams#include <media/stagefright/MetaData.h> 40e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams#include <media/stagefright/OMXCodec.h> 41e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams 42326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <surfaceflinger/ISurface.h> 43a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams 44fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchouk#include <media/stagefright/foundation/ALooper.h> 45a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams 46a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Samsnamespace android { 47a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams 48a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Samsstruct AwesomeEvent : public TimedEventQueue::Event { 49e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams AwesomeEvent( 50e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams AwesomePlayer *player, 51e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams void (AwesomePlayer::*method)()) 52e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams : mPlayer(player), 53c21cf40f6ae69091bf24f87b5eeabc95e73dd271Jason Sams mMethod(method) { 54e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams } 55e12c1c591b4219e80f29c6c0e0c62c9578b75450Jason Sams 56fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchoukprotected: 57b825f67adb5d1e1751fe108e6dbf9c6f2555c283Alex Sakhartchouk virtual ~AwesomeEvent() {} 58f2649a961db2995e9e24a6c98f8a419f1496c1b7Jason Sams 59605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 60605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams (mPlayer->*mMethod)(); 61f2649a961db2995e9e24a6c98f8a419f1496c1b7Jason Sams } 62f2649a961db2995e9e24a6c98f8a419f1496c1b7Jason Sams 63f2649a961db2995e9e24a6c98f8a419f1496c1b7Jason Samsprivate: 648154954868694e1f233d87d4933a474518b1cb81Jason Sams AwesomePlayer *mPlayer; 65f2649a961db2995e9e24a6c98f8a419f1496c1b7Jason Sams void (AwesomePlayer::*mMethod)(); 66326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 67e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams AwesomeEvent(const AwesomeEvent &); 68e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams AwesomeEvent &operator=(const AwesomeEvent &); 69e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams}; 70e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams 71e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Samsstruct AwesomeRemoteRenderer : public AwesomeRenderer { 72fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchouk AwesomeRemoteRenderer(const sp<IOMXRenderer> &target) 739397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams : mTarget(target) { 749397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams } 75326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 76e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams virtual void render(MediaBuffer *buffer) { 77e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams void *id; 78326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { 79326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mTarget->render((IOMX::buffer_id)id); 809397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams } 819397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams } 82326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 83326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsprivate: 84326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams sp<IOMXRenderer> mTarget; 85326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 86326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams AwesomeRemoteRenderer(const AwesomeRemoteRenderer &); 87326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &); 881030893d9b99b72468034da13df025bda479bb97Jason Sams}; 891030893d9b99b72468034da13df025bda479bb97Jason Sams 90a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Samsstruct AwesomeLocalRenderer : public AwesomeRenderer { 919397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams AwesomeLocalRenderer( 92a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams bool previewOnly, 931030893d9b99b72468034da13df025bda479bb97Jason Sams const char *componentName, 941030893d9b99b72468034da13df025bda479bb97Jason Sams OMX_COLOR_FORMATTYPE colorFormat, 951030893d9b99b72468034da13df025bda479bb97Jason Sams const sp<ISurface> &surface, 961030893d9b99b72468034da13df025bda479bb97Jason Sams size_t displayWidth, size_t displayHeight, 97a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams size_t decodedWidth, size_t decodedHeight) 989397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams : mTarget(NULL), 99a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams mLibHandle(NULL) { 1001030893d9b99b72468034da13df025bda479bb97Jason Sams init(previewOnly, componentName, 1011030893d9b99b72468034da13df025bda479bb97Jason Sams colorFormat, surface, displayWidth, 102326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams displayHeight, decodedWidth, decodedHeight); 103326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 104326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 105326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual void render(MediaBuffer *buffer) { 106326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams render((const uint8_t *)buffer->data() + buffer->range_offset(), 107326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams buffer->range_length()); 108326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 109326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 110a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams void render(const void *data, size_t size) { 1119397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams mTarget->render(data, size, NULL); 112a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams } 113326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 114326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsprotected: 115326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual ~AwesomeLocalRenderer() { 116a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams delete mTarget; 117a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams mTarget = NULL; 118a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams 119a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams if (mLibHandle) { 120326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams dlclose(mLibHandle); 121326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mLibHandle = NULL; 1229397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams } 123326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 124326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 125326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsprivate: 126326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams VideoRenderer *mTarget; 127326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams void *mLibHandle; 128326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 129326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams void init( 130326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams bool previewOnly, 1319397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams const char *componentName, 1329397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams OMX_COLOR_FORMATTYPE colorFormat, 133326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams const sp<ISurface> &surface, 134326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams size_t displayWidth, size_t displayHeight, 135326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams size_t decodedWidth, size_t decodedHeight); 136326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 137326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams AwesomeLocalRenderer(const AwesomeLocalRenderer &); 138326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 139326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}; 140326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 141326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid AwesomeLocalRenderer::init( 142326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams bool previewOnly, 143326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams const char *componentName, 144326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams OMX_COLOR_FORMATTYPE colorFormat, 145326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams const sp<ISurface> &surface, 146 size_t displayWidth, size_t displayHeight, 147 size_t decodedWidth, size_t decodedHeight) { 148 if (!previewOnly) { 149 // We will stick to the vanilla software-color-converting renderer 150 // for "previewOnly" mode, to avoid unneccessarily switching overlays 151 // more often than necessary. 152 153 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW); 154 155 if (mLibHandle) { 156 typedef VideoRenderer *(*CreateRendererFunc)( 157 const sp<ISurface> &surface, 158 const char *componentName, 159 OMX_COLOR_FORMATTYPE colorFormat, 160 size_t displayWidth, size_t displayHeight, 161 size_t decodedWidth, size_t decodedHeight); 162 163 CreateRendererFunc func = 164 (CreateRendererFunc)dlsym( 165 mLibHandle, 166 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20" 167 "OMX_COLOR_FORMATTYPEjjjj"); 168 169 if (func) { 170 mTarget = 171 (*func)(surface, componentName, colorFormat, 172 displayWidth, displayHeight, 173 decodedWidth, decodedHeight); 174 } 175 } 176 } 177 178 if (mTarget == NULL) { 179 mTarget = new SoftwareRenderer( 180 colorFormat, surface, displayWidth, displayHeight, 181 decodedWidth, decodedHeight); 182 } 183} 184 185AwesomePlayer::AwesomePlayer() 186 : mQueueStarted(false), 187 mTimeSource(NULL), 188 mVideoRendererIsPreview(false), 189 mAudioPlayer(NULL), 190 mFlags(0), 191 mExtractorFlags(0), 192 mLastVideoBuffer(NULL), 193 mVideoBuffer(NULL), 194 mSuspensionState(NULL) { 195 CHECK_EQ(mClient.connect(), OK); 196 197 DataSource::RegisterDefaultSniffers(); 198 199 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 200 mVideoEventPending = false; 201 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 202 mStreamDoneEventPending = false; 203 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 204 mBufferingEventPending = false; 205 206 mCheckAudioStatusEvent = new AwesomeEvent( 207 this, &AwesomePlayer::onCheckAudioStatus); 208 209 mAudioStatusEventPending = false; 210 211 reset(); 212} 213 214AwesomePlayer::~AwesomePlayer() { 215 if (mQueueStarted) { 216 mQueue.stop(); 217 } 218 219 reset(); 220 221 mClient.disconnect(); 222} 223 224void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) { 225 mQueue.cancelEvent(mVideoEvent->eventID()); 226 mVideoEventPending = false; 227 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 228 mStreamDoneEventPending = false; 229 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 230 mAudioStatusEventPending = false; 231 232 if (!keepBufferingGoing) { 233 mQueue.cancelEvent(mBufferingEvent->eventID()); 234 mBufferingEventPending = false; 235 } 236} 237 238void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 239 Mutex::Autolock autoLock(mLock); 240 mListener = listener; 241} 242 243status_t AwesomePlayer::setDataSource( 244 const char *uri, const KeyedVector<String8, String8> *headers) { 245 Mutex::Autolock autoLock(mLock); 246 return setDataSource_l(uri, headers); 247} 248 249status_t AwesomePlayer::setDataSource_l( 250 const char *uri, const KeyedVector<String8, String8> *headers) { 251 reset_l(); 252 253 mUri = uri; 254 255 if (headers) { 256 mUriHeaders = *headers; 257 } 258 259 // The actual work will be done during preparation in the call to 260 // ::finishSetDataSource_l to avoid blocking the calling thread in 261 // setDataSource for any significant time. 262 263 return OK; 264} 265 266status_t AwesomePlayer::setDataSource( 267 int fd, int64_t offset, int64_t length) { 268#if 0 269 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_96.m3u8"); 270 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_1500.m3u8"); 271 return setDataSource("httplive://iphone.video.hsn.com/iPhone_high.m3u8"); 272 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/iphonewebcast/webcast090209_all/webcast090209_all.m3u8"); 273 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_062209_iphone/hi/prog_index.m3u8"); 274 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_googmaps/hi/prog_index.m3u8"); 275 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/mtv/ni_spo_25a_rt74137_clip_syn/hi/prog_index.m3u8"); 276#endif 277 278 Mutex::Autolock autoLock(mLock); 279 280 reset_l(); 281 282 sp<DataSource> dataSource = new FileSource(fd, offset, length); 283 284 status_t err = dataSource->initCheck(); 285 286 if (err != OK) { 287 return err; 288 } 289 290 mFileSource = dataSource; 291 292 return setDataSource_l(dataSource); 293} 294 295status_t AwesomePlayer::setDataSource_l( 296 const sp<DataSource> &dataSource) { 297 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 298 299 if (extractor == NULL) { 300 return UNKNOWN_ERROR; 301 } 302 303 return setDataSource_l(extractor); 304} 305 306status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 307 bool haveAudio = false; 308 bool haveVideo = false; 309 for (size_t i = 0; i < extractor->countTracks(); ++i) { 310 sp<MetaData> meta = extractor->getTrackMetaData(i); 311 312 const char *mime; 313 CHECK(meta->findCString(kKeyMIMEType, &mime)); 314 315 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 316 setVideoSource(extractor->getTrack(i)); 317 haveVideo = true; 318 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 319 setAudioSource(extractor->getTrack(i)); 320 haveAudio = true; 321 } 322 323 if (haveAudio && haveVideo) { 324 break; 325 } 326 } 327 328 if (!haveAudio && !haveVideo) { 329 return UNKNOWN_ERROR; 330 } 331 332 mExtractorFlags = extractor->flags(); 333 334 return OK; 335} 336 337void AwesomePlayer::reset() { 338 Mutex::Autolock autoLock(mLock); 339 reset_l(); 340} 341 342void AwesomePlayer::reset_l() { 343 if (mFlags & PREPARING) { 344 mFlags |= PREPARE_CANCELLED; 345 if (mConnectingDataSource != NULL) { 346 LOGI("interrupting the connection process"); 347 mConnectingDataSource->disconnect(); 348 } 349 } 350 351 while (mFlags & PREPARING) { 352 mPreparedCondition.wait(mLock); 353 } 354 355 cancelPlayerEvents(); 356 357 mCachedSource.clear(); 358 mAudioTrack.clear(); 359 mVideoTrack.clear(); 360 361 // Shutdown audio first, so that the respone to the reset request 362 // appears to happen instantaneously as far as the user is concerned 363 // If we did this later, audio would continue playing while we 364 // shutdown the video-related resources and the player appear to 365 // not be as responsive to a reset request. 366 if (mAudioPlayer == NULL && mAudioSource != NULL) { 367 // If we had an audio player, it would have effectively 368 // taken possession of the audio source and stopped it when 369 // _it_ is stopped. Otherwise this is still our responsibility. 370 mAudioSource->stop(); 371 } 372 mAudioSource.clear(); 373 374 mTimeSource = NULL; 375 376 delete mAudioPlayer; 377 mAudioPlayer = NULL; 378 379 mVideoRenderer.clear(); 380 381 if (mLastVideoBuffer) { 382 mLastVideoBuffer->release(); 383 mLastVideoBuffer = NULL; 384 } 385 386 if (mVideoBuffer) { 387 mVideoBuffer->release(); 388 mVideoBuffer = NULL; 389 } 390 391 mRTSPController.clear(); 392 393 if (mVideoSource != NULL) { 394 mVideoSource->stop(); 395 396 // The following hack is necessary to ensure that the OMX 397 // component is completely released by the time we may try 398 // to instantiate it again. 399 wp<MediaSource> tmp = mVideoSource; 400 mVideoSource.clear(); 401 while (tmp.promote() != NULL) { 402 usleep(1000); 403 } 404 IPCThreadState::self()->flushCommands(); 405 } 406 407 mDurationUs = -1; 408 mFlags = 0; 409 mExtractorFlags = 0; 410 mVideoWidth = mVideoHeight = -1; 411 mTimeSourceDeltaUs = 0; 412 mVideoTimeUs = 0; 413 414 mSeeking = false; 415 mSeekNotificationSent = false; 416 mSeekTimeUs = 0; 417 418 mUri.setTo(""); 419 mUriHeaders.clear(); 420 421 mFileSource.clear(); 422 423 delete mSuspensionState; 424 mSuspensionState = NULL; 425} 426 427void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 428 if (mListener != NULL) { 429 sp<MediaPlayerBase> listener = mListener.promote(); 430 431 if (listener != NULL) { 432 listener->sendEvent(msg, ext1, ext2); 433 } 434 } 435} 436 437void AwesomePlayer::onBufferingUpdate() { 438 Mutex::Autolock autoLock(mLock); 439 if (!mBufferingEventPending) { 440 return; 441 } 442 mBufferingEventPending = false; 443 444 if (mCachedSource == NULL) { 445 return; 446 } 447 448 size_t lowWatermark = 400000; 449 size_t highWatermark = 1000000; 450 451 off_t size; 452 if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) { 453 int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec 454 455 size_t cachedSize = mCachedSource->cachedSize(); 456 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate; 457 458 double percentage = (double)cachedDurationUs / mDurationUs; 459 460 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0); 461 462 lowWatermark = 2 * bitrate / 8; // 2 secs 463 highWatermark = 10 * bitrate / 8; // 10 secs 464 } 465 466 bool eos; 467 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos); 468 469 if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) { 470 LOGI("cache is running low (< %d) , pausing.", lowWatermark); 471 mFlags |= CACHE_UNDERRUN; 472 pause_l(); 473 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 474 } else if ((mFlags & CACHE_UNDERRUN) 475 && (eos || cachedDataRemaining > highWatermark)) { 476 LOGI("cache has filled up (> %d), resuming.", highWatermark); 477 mFlags &= ~CACHE_UNDERRUN; 478 play_l(); 479 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 480 } 481 482 postBufferingEvent_l(); 483} 484 485void AwesomePlayer::onStreamDone() { 486 // Posted whenever any stream finishes playing. 487 488 Mutex::Autolock autoLock(mLock); 489 if (!mStreamDoneEventPending) { 490 return; 491 } 492 mStreamDoneEventPending = false; 493 494 if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 495 LOGV("MEDIA_ERROR %d", mStreamDoneStatus); 496 497 notifyListener_l( 498 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 499 500 pause_l(); 501 502 mFlags |= AT_EOS; 503 return; 504 } 505 506 const bool allDone = 507 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 508 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 509 510 if (!allDone) { 511 return; 512 } 513 514 if (mFlags & LOOPING) { 515 seekTo_l(0); 516 517 if (mVideoSource != NULL) { 518 postVideoEvent_l(); 519 } 520 } else { 521 LOGV("MEDIA_PLAYBACK_COMPLETE"); 522 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 523 524 pause_l(); 525 526 mFlags |= AT_EOS; 527 } 528} 529 530status_t AwesomePlayer::play() { 531 Mutex::Autolock autoLock(mLock); 532 533 mFlags &= ~CACHE_UNDERRUN; 534 535 return play_l(); 536} 537 538status_t AwesomePlayer::play_l() { 539 if (mFlags & PLAYING) { 540 return OK; 541 } 542 543 if (!(mFlags & PREPARED)) { 544 status_t err = prepare_l(); 545 546 if (err != OK) { 547 return err; 548 } 549 } 550 551 mFlags |= PLAYING; 552 mFlags |= FIRST_FRAME; 553 554 bool deferredAudioSeek = false; 555 556 if (mAudioSource != NULL) { 557 if (mAudioPlayer == NULL) { 558 if (mAudioSink != NULL) { 559 mAudioPlayer = new AudioPlayer(mAudioSink); 560 mAudioPlayer->setSource(mAudioSource); 561 562 // We've already started the MediaSource in order to enable 563 // the prefetcher to read its data. 564 status_t err = mAudioPlayer->start( 565 true /* sourceAlreadyStarted */); 566 567 if (err != OK) { 568 delete mAudioPlayer; 569 mAudioPlayer = NULL; 570 571 mFlags &= ~(PLAYING | FIRST_FRAME); 572 573 return err; 574 } 575 576 mTimeSource = mAudioPlayer; 577 578 deferredAudioSeek = true; 579 580 mWatchForAudioSeekComplete = false; 581 mWatchForAudioEOS = true; 582 } 583 } else { 584 mAudioPlayer->resume(); 585 } 586 587 postCheckAudioStatusEvent_l(); 588 } 589 590 if (mTimeSource == NULL && mAudioPlayer == NULL) { 591 mTimeSource = &mSystemTimeSource; 592 } 593 594 if (mVideoSource != NULL) { 595 // Kick off video playback 596 postVideoEvent_l(); 597 } 598 599 if (deferredAudioSeek) { 600 // If there was a seek request while we were paused 601 // and we're just starting up again, honor the request now. 602 seekAudioIfNecessary_l(); 603 } 604 605 if (mFlags & AT_EOS) { 606 // Legacy behaviour, if a stream finishes playing and then 607 // is started again, we play from the start... 608 seekTo_l(0); 609 } 610 611 return OK; 612} 613 614void AwesomePlayer::initRenderer_l() { 615 if (mISurface != NULL) { 616 sp<MetaData> meta = mVideoSource->getFormat(); 617 618 int32_t format; 619 const char *component; 620 int32_t decodedWidth, decodedHeight; 621 CHECK(meta->findInt32(kKeyColorFormat, &format)); 622 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 623 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 624 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 625 626 mVideoRenderer.clear(); 627 628 // Must ensure that mVideoRenderer's destructor is actually executed 629 // before creating a new one. 630 IPCThreadState::self()->flushCommands(); 631 632 if (!strncmp("OMX.", component, 4)) { 633 // Our OMX codecs allocate buffers on the media_server side 634 // therefore they require a remote IOMXRenderer that knows how 635 // to display them. 636 mVideoRenderer = new AwesomeRemoteRenderer( 637 mClient.interface()->createRenderer( 638 mISurface, component, 639 (OMX_COLOR_FORMATTYPE)format, 640 decodedWidth, decodedHeight, 641 mVideoWidth, mVideoHeight)); 642 } else { 643 // Other decoders are instantiated locally and as a consequence 644 // allocate their buffers in local address space. 645 mVideoRenderer = new AwesomeLocalRenderer( 646 false, // previewOnly 647 component, 648 (OMX_COLOR_FORMATTYPE)format, 649 mISurface, 650 mVideoWidth, mVideoHeight, 651 decodedWidth, decodedHeight); 652 } 653 } 654} 655 656status_t AwesomePlayer::pause() { 657 Mutex::Autolock autoLock(mLock); 658 659 mFlags &= ~CACHE_UNDERRUN; 660 661 return pause_l(); 662} 663 664status_t AwesomePlayer::pause_l() { 665 if (!(mFlags & PLAYING)) { 666 return OK; 667 } 668 669 cancelPlayerEvents(true /* keepBufferingGoing */); 670 671 if (mAudioPlayer != NULL) { 672 mAudioPlayer->pause(); 673 } 674 675 mFlags &= ~PLAYING; 676 677 return OK; 678} 679 680bool AwesomePlayer::isPlaying() const { 681 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 682} 683 684void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 685 Mutex::Autolock autoLock(mLock); 686 687 mISurface = isurface; 688} 689 690void AwesomePlayer::setAudioSink( 691 const sp<MediaPlayerBase::AudioSink> &audioSink) { 692 Mutex::Autolock autoLock(mLock); 693 694 mAudioSink = audioSink; 695} 696 697status_t AwesomePlayer::setLooping(bool shouldLoop) { 698 Mutex::Autolock autoLock(mLock); 699 700 mFlags = mFlags & ~LOOPING; 701 702 if (shouldLoop) { 703 mFlags |= LOOPING; 704 } 705 706 return OK; 707} 708 709status_t AwesomePlayer::getDuration(int64_t *durationUs) { 710 Mutex::Autolock autoLock(mMiscStateLock); 711 712 if (mDurationUs < 0) { 713 return UNKNOWN_ERROR; 714 } 715 716 *durationUs = mDurationUs; 717 718 return OK; 719} 720 721status_t AwesomePlayer::getPosition(int64_t *positionUs) { 722 if (mSeeking) { 723 *positionUs = mSeekTimeUs; 724 } else if (mVideoSource != NULL) { 725 Mutex::Autolock autoLock(mMiscStateLock); 726 *positionUs = mVideoTimeUs; 727 } else if (mAudioPlayer != NULL) { 728 *positionUs = mAudioPlayer->getMediaTimeUs(); 729 } else { 730 *positionUs = 0; 731 } 732 733 return OK; 734} 735 736status_t AwesomePlayer::seekTo(int64_t timeUs) { 737 if (mExtractorFlags 738 & (MediaExtractor::CAN_SEEK_FORWARD 739 | MediaExtractor::CAN_SEEK_BACKWARD)) { 740 Mutex::Autolock autoLock(mLock); 741 return seekTo_l(timeUs); 742 } 743 744 return OK; 745} 746 747status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 748 if (mFlags & CACHE_UNDERRUN) { 749 mFlags &= ~CACHE_UNDERRUN; 750 play_l(); 751 } 752 753 mSeeking = true; 754 mSeekNotificationSent = false; 755 mSeekTimeUs = timeUs; 756 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS); 757 758 seekAudioIfNecessary_l(); 759 760 if (!(mFlags & PLAYING)) { 761 LOGV("seeking while paused, sending SEEK_COMPLETE notification" 762 " immediately."); 763 764 notifyListener_l(MEDIA_SEEK_COMPLETE); 765 mSeekNotificationSent = true; 766 } 767 768 return OK; 769} 770 771void AwesomePlayer::seekAudioIfNecessary_l() { 772 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) { 773 mAudioPlayer->seekTo(mSeekTimeUs); 774 775 mWatchForAudioSeekComplete = true; 776 mWatchForAudioEOS = true; 777 mSeekNotificationSent = false; 778 } 779} 780 781status_t AwesomePlayer::getVideoDimensions( 782 int32_t *width, int32_t *height) const { 783 Mutex::Autolock autoLock(mLock); 784 785 if (mVideoWidth < 0 || mVideoHeight < 0) { 786 return UNKNOWN_ERROR; 787 } 788 789 *width = mVideoWidth; 790 *height = mVideoHeight; 791 792 return OK; 793} 794 795void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 796 CHECK(source != NULL); 797 798 mAudioTrack = source; 799} 800 801status_t AwesomePlayer::initAudioDecoder() { 802 sp<MetaData> meta = mAudioTrack->getFormat(); 803 804 const char *mime; 805 CHECK(meta->findCString(kKeyMIMEType, &mime)); 806 807 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 808 mAudioSource = mAudioTrack; 809 } else { 810 mAudioSource = OMXCodec::Create( 811 mClient.interface(), mAudioTrack->getFormat(), 812 false, // createEncoder 813 mAudioTrack); 814 } 815 816 if (mAudioSource != NULL) { 817 int64_t durationUs; 818 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 819 Mutex::Autolock autoLock(mMiscStateLock); 820 if (mDurationUs < 0 || durationUs > mDurationUs) { 821 mDurationUs = durationUs; 822 } 823 } 824 825 status_t err = mAudioSource->start(); 826 827 if (err != OK) { 828 mAudioSource.clear(); 829 return err; 830 } 831 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 832 // For legacy reasons we're simply going to ignore the absence 833 // of an audio decoder for QCELP instead of aborting playback 834 // altogether. 835 return OK; 836 } 837 838 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 839} 840 841void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 842 CHECK(source != NULL); 843 844 mVideoTrack = source; 845} 846 847status_t AwesomePlayer::initVideoDecoder() { 848 mVideoSource = OMXCodec::Create( 849 mClient.interface(), mVideoTrack->getFormat(), 850 false, // createEncoder 851 mVideoTrack); 852 853 if (mVideoSource != NULL) { 854 int64_t durationUs; 855 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 856 Mutex::Autolock autoLock(mMiscStateLock); 857 if (mDurationUs < 0 || durationUs > mDurationUs) { 858 mDurationUs = durationUs; 859 } 860 } 861 862 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 863 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 864 865 status_t err = mVideoSource->start(); 866 867 if (err != OK) { 868 mVideoSource.clear(); 869 return err; 870 } 871 } 872 873 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 874} 875 876void AwesomePlayer::onVideoEvent() { 877 Mutex::Autolock autoLock(mLock); 878 if (!mVideoEventPending) { 879 // The event has been cancelled in reset_l() but had already 880 // been scheduled for execution at that time. 881 return; 882 } 883 mVideoEventPending = false; 884 885 if (mSeeking) { 886 if (mLastVideoBuffer) { 887 mLastVideoBuffer->release(); 888 mLastVideoBuffer = NULL; 889 } 890 891 if (mVideoBuffer) { 892 mVideoBuffer->release(); 893 mVideoBuffer = NULL; 894 } 895 896 if (mCachedSource != NULL && mAudioSource != NULL) { 897 // We're going to seek the video source first, followed by 898 // the audio source. 899 // In order to avoid jumps in the DataSource offset caused by 900 // the audio codec prefetching data from the old locations 901 // while the video codec is already reading data from the new 902 // locations, we'll "pause" the audio source, causing it to 903 // stop reading input data until a subsequent seek. 904 905 if (mAudioPlayer != NULL) { 906 mAudioPlayer->pause(); 907 } 908 mAudioSource->pause(); 909 } 910 } 911 912 if (!mVideoBuffer) { 913 MediaSource::ReadOptions options; 914 if (mSeeking) { 915 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 916 917 options.setSeekTo( 918 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 919 } 920 for (;;) { 921 status_t err = mVideoSource->read(&mVideoBuffer, &options); 922 options.clearSeekTo(); 923 924 if (err != OK) { 925 CHECK_EQ(mVideoBuffer, NULL); 926 927 if (err == INFO_FORMAT_CHANGED) { 928 LOGV("VideoSource signalled format change."); 929 930 if (mVideoRenderer != NULL) { 931 mVideoRendererIsPreview = false; 932 initRenderer_l(); 933 } 934 continue; 935 } 936 937 mFlags |= VIDEO_AT_EOS; 938 postStreamDoneEvent_l(err); 939 return; 940 } 941 942 if (mVideoBuffer->range_length() == 0) { 943 // Some decoders, notably the PV AVC software decoder 944 // return spurious empty buffers that we just want to ignore. 945 946 mVideoBuffer->release(); 947 mVideoBuffer = NULL; 948 continue; 949 } 950 951 break; 952 } 953 } 954 955 int64_t timeUs; 956 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 957 958 { 959 Mutex::Autolock autoLock(mMiscStateLock); 960 mVideoTimeUs = timeUs; 961 } 962 963 if (mSeeking) { 964 if (mAudioPlayer != NULL) { 965 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 966 967 mAudioPlayer->seekTo(timeUs); 968 mAudioPlayer->resume(); 969 mWatchForAudioSeekComplete = true; 970 mWatchForAudioEOS = true; 971 } else if (!mSeekNotificationSent) { 972 // If we're playing video only, report seek complete now, 973 // otherwise audio player will notify us later. 974 notifyListener_l(MEDIA_SEEK_COMPLETE); 975 } 976 977 mFlags |= FIRST_FRAME; 978 mSeeking = false; 979 mSeekNotificationSent = false; 980 } 981 982 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource; 983 984 if (mFlags & FIRST_FRAME) { 985 mFlags &= ~FIRST_FRAME; 986 987 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; 988 } 989 990 int64_t realTimeUs, mediaTimeUs; 991 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 992 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 993 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 994 } 995 996 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 997 998 int64_t latenessUs = nowUs - timeUs; 999 1000 if (latenessUs > 40000) { 1001 // We're more than 40ms late. 1002 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 1003 1004 mVideoBuffer->release(); 1005 mVideoBuffer = NULL; 1006 1007 postVideoEvent_l(); 1008 return; 1009 } 1010 1011 if (latenessUs < -10000) { 1012 // We're more than 10ms early. 1013 1014 postVideoEvent_l(10000); 1015 return; 1016 } 1017 1018 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 1019 mVideoRendererIsPreview = false; 1020 1021 initRenderer_l(); 1022 } 1023 1024 if (mVideoRenderer != NULL) { 1025 mVideoRenderer->render(mVideoBuffer); 1026 } 1027 1028 if (mLastVideoBuffer) { 1029 mLastVideoBuffer->release(); 1030 mLastVideoBuffer = NULL; 1031 } 1032 mLastVideoBuffer = mVideoBuffer; 1033 mVideoBuffer = NULL; 1034 1035 postVideoEvent_l(); 1036} 1037 1038void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 1039 if (mVideoEventPending) { 1040 return; 1041 } 1042 1043 mVideoEventPending = true; 1044 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 1045} 1046 1047void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 1048 if (mStreamDoneEventPending) { 1049 return; 1050 } 1051 mStreamDoneEventPending = true; 1052 1053 mStreamDoneStatus = status; 1054 mQueue.postEvent(mStreamDoneEvent); 1055} 1056 1057void AwesomePlayer::postBufferingEvent_l() { 1058 if (mBufferingEventPending) { 1059 return; 1060 } 1061 mBufferingEventPending = true; 1062 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 1063} 1064 1065void AwesomePlayer::postCheckAudioStatusEvent_l() { 1066 if (mAudioStatusEventPending) { 1067 return; 1068 } 1069 mAudioStatusEventPending = true; 1070 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll); 1071} 1072 1073void AwesomePlayer::onCheckAudioStatus() { 1074 Mutex::Autolock autoLock(mLock); 1075 if (!mAudioStatusEventPending) { 1076 // Event was dispatched and while we were blocking on the mutex, 1077 // has already been cancelled. 1078 return; 1079 } 1080 1081 mAudioStatusEventPending = false; 1082 1083 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1084 mWatchForAudioSeekComplete = false; 1085 1086 if (!mSeekNotificationSent) { 1087 notifyListener_l(MEDIA_SEEK_COMPLETE); 1088 mSeekNotificationSent = true; 1089 } 1090 1091 mSeeking = false; 1092 } 1093 1094 status_t finalStatus; 1095 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1096 mWatchForAudioEOS = false; 1097 mFlags |= AUDIO_AT_EOS; 1098 mFlags |= FIRST_FRAME; 1099 postStreamDoneEvent_l(finalStatus); 1100 } 1101 1102 postCheckAudioStatusEvent_l(); 1103} 1104 1105status_t AwesomePlayer::prepare() { 1106 Mutex::Autolock autoLock(mLock); 1107 return prepare_l(); 1108} 1109 1110status_t AwesomePlayer::prepare_l() { 1111 if (mFlags & PREPARED) { 1112 return OK; 1113 } 1114 1115 if (mFlags & PREPARING) { 1116 return UNKNOWN_ERROR; 1117 } 1118 1119 mIsAsyncPrepare = false; 1120 status_t err = prepareAsync_l(); 1121 1122 if (err != OK) { 1123 return err; 1124 } 1125 1126 while (mFlags & PREPARING) { 1127 mPreparedCondition.wait(mLock); 1128 } 1129 1130 return mPrepareResult; 1131} 1132 1133status_t AwesomePlayer::prepareAsync() { 1134 Mutex::Autolock autoLock(mLock); 1135 1136 if (mFlags & PREPARING) { 1137 return UNKNOWN_ERROR; // async prepare already pending 1138 } 1139 1140 mIsAsyncPrepare = true; 1141 return prepareAsync_l(); 1142} 1143 1144status_t AwesomePlayer::prepareAsync_l() { 1145 if (mFlags & PREPARING) { 1146 return UNKNOWN_ERROR; // async prepare already pending 1147 } 1148 1149 if (!mQueueStarted) { 1150 mQueue.start(); 1151 mQueueStarted = true; 1152 } 1153 1154 mFlags |= PREPARING; 1155 mAsyncPrepareEvent = new AwesomeEvent( 1156 this, &AwesomePlayer::onPrepareAsyncEvent); 1157 1158 mQueue.postEvent(mAsyncPrepareEvent); 1159 1160 return OK; 1161} 1162 1163status_t AwesomePlayer::finishSetDataSource_l() { 1164 sp<DataSource> dataSource; 1165 1166 if (!strncasecmp("http://", mUri.string(), 7)) { 1167 mConnectingDataSource = new NuHTTPDataSource; 1168 1169 mLock.unlock(); 1170 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 1171 mLock.lock(); 1172 1173 if (err != OK) { 1174 mConnectingDataSource.clear(); 1175 1176 LOGI("mConnectingDataSource->connect() returned %d", err); 1177 return err; 1178 } 1179 1180#if 0 1181 mCachedSource = new NuCachedSource2( 1182 new ThrottledSource( 1183 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 1184#else 1185 mCachedSource = new NuCachedSource2(mConnectingDataSource); 1186#endif 1187 mConnectingDataSource.clear(); 1188 1189 dataSource = mCachedSource; 1190 } else if (!strncasecmp(mUri.string(), "httplive://", 11)) { 1191 String8 uri("http://"); 1192 uri.append(mUri.string() + 11); 1193 1194 dataSource = new LiveSource(uri.string()); 1195 1196 mCachedSource = new NuCachedSource2(dataSource); 1197 dataSource = mCachedSource; 1198 1199 sp<MediaExtractor> extractor = 1200 MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 1201 1202 return setDataSource_l(extractor); 1203 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) { 1204 if (mLooper == NULL) { 1205 mLooper = new ALooper; 1206 mLooper->start(); 1207 } 1208 mRTSPController = new ARTSPController(mLooper); 1209 status_t err = mRTSPController->connect(mUri.string()); 1210 1211 LOGI("ARTSPController::connect returned %d", err); 1212 1213 if (err != OK) { 1214 mRTSPController.clear(); 1215 return err; 1216 } 1217 1218 sp<MediaExtractor> extractor = mRTSPController.get(); 1219 return setDataSource_l(extractor); 1220 } else { 1221 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 1222 } 1223 1224 if (dataSource == NULL) { 1225 return UNKNOWN_ERROR; 1226 } 1227 1228 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 1229 1230 if (extractor == NULL) { 1231 return UNKNOWN_ERROR; 1232 } 1233 1234 return setDataSource_l(extractor); 1235} 1236 1237void AwesomePlayer::abortPrepare(status_t err) { 1238 CHECK(err != OK); 1239 1240 if (mIsAsyncPrepare) { 1241 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1242 } 1243 1244 mPrepareResult = err; 1245 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1246 mAsyncPrepareEvent = NULL; 1247 mPreparedCondition.broadcast(); 1248} 1249 1250// static 1251bool AwesomePlayer::ContinuePreparation(void *cookie) { 1252 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 1253 1254 return (me->mFlags & PREPARE_CANCELLED) == 0; 1255} 1256 1257void AwesomePlayer::onPrepareAsyncEvent() { 1258 { 1259 Mutex::Autolock autoLock(mLock); 1260 1261 if (mFlags & PREPARE_CANCELLED) { 1262 LOGI("prepare was cancelled before doing anything"); 1263 abortPrepare(UNKNOWN_ERROR); 1264 return; 1265 } 1266 1267 if (mUri.size() > 0) { 1268 status_t err = finishSetDataSource_l(); 1269 1270 if (err != OK) { 1271 abortPrepare(err); 1272 return; 1273 } 1274 } 1275 1276 if (mVideoTrack != NULL && mVideoSource == NULL) { 1277 status_t err = initVideoDecoder(); 1278 1279 if (err != OK) { 1280 abortPrepare(err); 1281 return; 1282 } 1283 } 1284 1285 if (mAudioTrack != NULL && mAudioSource == NULL) { 1286 status_t err = initAudioDecoder(); 1287 1288 if (err != OK) { 1289 abortPrepare(err); 1290 return; 1291 } 1292 } 1293 } 1294 1295 Mutex::Autolock autoLock(mLock); 1296 1297 if (mIsAsyncPrepare) { 1298 if (mVideoWidth < 0 || mVideoHeight < 0) { 1299 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1300 } else { 1301 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight); 1302 } 1303 1304 notifyListener_l(MEDIA_PREPARED); 1305 } 1306 1307 mPrepareResult = OK; 1308 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1309 mFlags |= PREPARED; 1310 mAsyncPrepareEvent = NULL; 1311 mPreparedCondition.broadcast(); 1312 1313 postBufferingEvent_l(); 1314} 1315 1316status_t AwesomePlayer::suspend() { 1317 LOGV("suspend"); 1318 Mutex::Autolock autoLock(mLock); 1319 1320 if (mSuspensionState != NULL) { 1321 if (mLastVideoBuffer == NULL) { 1322 //go into here if video is suspended again 1323 //after resuming without being played between 1324 //them 1325 SuspensionState *state = mSuspensionState; 1326 mSuspensionState = NULL; 1327 reset_l(); 1328 mSuspensionState = state; 1329 return OK; 1330 } 1331 1332 delete mSuspensionState; 1333 mSuspensionState = NULL; 1334 } 1335 1336 if (mFlags & PREPARING) { 1337 mFlags |= PREPARE_CANCELLED; 1338 if (mConnectingDataSource != NULL) { 1339 LOGI("interrupting the connection process"); 1340 mConnectingDataSource->disconnect(); 1341 } 1342 } 1343 1344 while (mFlags & PREPARING) { 1345 mPreparedCondition.wait(mLock); 1346 } 1347 1348 SuspensionState *state = new SuspensionState; 1349 state->mUri = mUri; 1350 state->mUriHeaders = mUriHeaders; 1351 state->mFileSource = mFileSource; 1352 1353 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS); 1354 getPosition(&state->mPositionUs); 1355 1356 if (mLastVideoBuffer) { 1357 size_t size = mLastVideoBuffer->range_length(); 1358 if (size) { 1359 state->mLastVideoFrameSize = size; 1360 state->mLastVideoFrame = malloc(size); 1361 memcpy(state->mLastVideoFrame, 1362 (const uint8_t *)mLastVideoBuffer->data() 1363 + mLastVideoBuffer->range_offset(), 1364 size); 1365 1366 state->mVideoWidth = mVideoWidth; 1367 state->mVideoHeight = mVideoHeight; 1368 1369 sp<MetaData> meta = mVideoSource->getFormat(); 1370 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat)); 1371 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth)); 1372 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight)); 1373 } 1374 } 1375 1376 reset_l(); 1377 1378 mSuspensionState = state; 1379 1380 return OK; 1381} 1382 1383status_t AwesomePlayer::resume() { 1384 LOGV("resume"); 1385 Mutex::Autolock autoLock(mLock); 1386 1387 if (mSuspensionState == NULL) { 1388 return INVALID_OPERATION; 1389 } 1390 1391 SuspensionState *state = mSuspensionState; 1392 mSuspensionState = NULL; 1393 1394 status_t err; 1395 if (state->mFileSource != NULL) { 1396 err = setDataSource_l(state->mFileSource); 1397 1398 if (err == OK) { 1399 mFileSource = state->mFileSource; 1400 } 1401 } else { 1402 err = setDataSource_l(state->mUri, &state->mUriHeaders); 1403 } 1404 1405 if (err != OK) { 1406 delete state; 1407 state = NULL; 1408 1409 return err; 1410 } 1411 1412 seekTo_l(state->mPositionUs); 1413 1414 mFlags = state->mFlags & (LOOPING | AT_EOS); 1415 1416 if (state->mLastVideoFrame && mISurface != NULL) { 1417 mVideoRenderer = 1418 new AwesomeLocalRenderer( 1419 true, // previewOnly 1420 "", 1421 (OMX_COLOR_FORMATTYPE)state->mColorFormat, 1422 mISurface, 1423 state->mVideoWidth, 1424 state->mVideoHeight, 1425 state->mDecodedWidth, 1426 state->mDecodedHeight); 1427 1428 mVideoRendererIsPreview = true; 1429 1430 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render( 1431 state->mLastVideoFrame, state->mLastVideoFrameSize); 1432 } 1433 1434 if (state->mFlags & PLAYING) { 1435 play_l(); 1436 } 1437 1438 mSuspensionState = state; 1439 state = NULL; 1440 1441 return OK; 1442} 1443 1444uint32_t AwesomePlayer::flags() const { 1445 return mExtractorFlags; 1446} 1447 1448} // namespace android 1449 1450