Stagefright框架解读(—)音视频Playback流程

news/2024/12/23 11:22:13

   转载请注明出处:http://blog.csdn.net/itachi85/article/details/7216639

从Android 2.0,Google引进了Stagefright,并在android2.3时用Stagefright在Android中是以shared library的形式存在(libstagefright.so),其中AwesomePlayer可用來播放video/audio。AwesomePlayer提供許多API,可以让上层的应用用程式(Java/JNI)來呼叫,我在这里简单说明一下video playback的流程(采用的是android2.2的源码)。

在Java中,若要播放一个影片,我們通常会这样写:

[java] view plain copy
print ?
  1. MediaPlayer mp = new MediaPlayer();  
  2. mp.setDataSource(PATH_TO_FILE);  
  3. mp.prepare();  
  4. mp.start();  
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(PATH_TO_FILE);
mp.prepare();
mp.start();

在Stagefright中,会看到如下的处理:

1.将影片文件的绝对路径指定给uri:

[cpp] view plain copy
print ?
  1. status_t AwesomePlayer::setDataSource(  
  2.         const char *uri, const KeyedVector<String8, String8> *headers) {  
  3.     Mutex::Autolock autoLock(mLock);  
  4.     return setDataSource_l(uri, headers);  
  5. }  
  6.   
  7. status_t AwesomePlayer::setDataSource_l(  
  8.         const char *uri, const KeyedVector<String8, String8> *headers) {  
  9.     reset_l();  
  10.   
  11.     mUri = uri;  
  12.   
  13.     if (headers) {  
  14.         mUriHeaders = *headers;  
  15.     }  
  16.   
  17.     // The actual work will be done during preparation in the call to  
  18.     // ::finishSetDataSource_l to avoid blocking the calling thread in  
  19.     // setDataSource for any significant time.  
  20.   
  21.     return OK;  
  22. }  
status_t AwesomePlayer::setDataSource(
        const char *uri, const KeyedVector<String8, String8> *headers) {
    Mutex::Autolock autoLock(mLock);
    return setDataSource_l(uri, headers);
}

status_t AwesomePlayer::setDataSource_l(
        const char *uri, const KeyedVector<String8, String8> *headers) {
    reset_l();

    mUri = uri;

    if (headers) {
        mUriHeaders = *headers;
    }

    // The actual work will be done during preparation in the call to
    // ::finishSetDataSource_l to avoid blocking the calling thread in
    // setDataSource for any significant time.

    return OK;
}

2.启动mQueue:

[cpp] view plain copy
print ?
  1. status_t AwesomePlayer::prepare() {  
  2.     Mutex::Autolock autoLock(mLock);  
  3.     return prepare_l();  
  4. }  
  5.   
  6. status_t AwesomePlayer::prepare_l() {  
  7.     if (mFlags & PREPARED) {  
  8.         return OK;  
  9.     }  
  10.   
  11.     if (mFlags & PREPARING) {  
  12.         return UNKNOWN_ERROR;  
  13.     }  
  14.   
  15.     mIsAsyncPrepare = false;  
  16.     status_t err = prepareAsync_l();  
  17.   
  18.     if (err != OK) {  
  19.         return err;  
  20.     }  
  21.   
  22.     while (mFlags & PREPARING) {  
  23.         mPreparedCondition.wait(mLock);  
  24.     }  
  25.   
  26.     return mPrepareResult;  
  27. }  
  28.   
  29.   
  30. status_t AwesomePlayer::prepareAsync() {  
  31.     Mutex::Autolock autoLock(mLock);  
  32.   
  33.     if (mFlags & PREPARING) {  
  34.         return UNKNOWN_ERROR;  // async prepare already pending  
  35.     }  
  36.   
  37.     mIsAsyncPrepare = true;  
  38.     return prepareAsync_l();  
  39. }  
  40.   
  41. status_t AwesomePlayer::prepareAsync_l() {  
  42.     if (mFlags & PREPARING) {  
  43.         return UNKNOWN_ERROR;  // async prepare already pending  
  44.     }  
  45.   
  46.     if (!mQueueStarted) {  
  47.         mQueue.start();  
  48.         mQueueStarted = true;  
  49.     }  
  50.   
  51.     mFlags |= PREPARING;  
  52.     mAsyncPrepareEvent = new AwesomeEvent(  
  53.             this, &AwesomePlayer::onPrepareAsyncEvent);  
  54.   
  55.     mQueue.postEvent(mAsyncPrepareEvent);  
  56.   
  57.     return OK;  
  58. }  
status_t AwesomePlayer::prepare() {
    Mutex::Autolock autoLock(mLock);
    return prepare_l();
}

status_t AwesomePlayer::prepare_l() {
    if (mFlags & PREPARED) {
        return OK;
    }

    if (mFlags & PREPARING) {
        return UNKNOWN_ERROR;
    }

    mIsAsyncPrepare = false;
    status_t err = prepareAsync_l();

    if (err != OK) {
        return err;
    }

    while (mFlags & PREPARING) {
        mPreparedCondition.wait(mLock);
    }

    return mPrepareResult;
}


status_t AwesomePlayer::prepareAsync() {
    Mutex::Autolock autoLock(mLock);

    if (mFlags & PREPARING) {
        return UNKNOWN_ERROR;  // async prepare already pending
    }

    mIsAsyncPrepare = true;
    return prepareAsync_l();
}

status_t AwesomePlayer::prepareAsync_l() {
    if (mFlags & PREPARING) {
        return UNKNOWN_ERROR;  // async prepare already pending
    }

    if (!mQueueStarted) {
        mQueue.start();
        mQueueStarted = true;
    }

    mFlags |= PREPARING;
    mAsyncPrepareEvent = new AwesomeEvent(
            this, &AwesomePlayer::onPrepareAsyncEvent);

    mQueue.postEvent(mAsyncPrepareEvent);

    return OK;
}

3.onprepareAsyncEvent被触发,根据传来文件的header来创建相应的解析器,并初始化音视频解码器:

[cpp] view plain copy
print ?
  1. void AwesomePlayer::onPrepareAsyncEvent() {  
  2.     sp<Prefetcher> prefetcher;  
  3.   
  4.     {  
  5.         Mutex::Autolock autoLock(mLock);  
  6.   
  7.         if (mFlags & PREPARE_CANCELLED) {  
  8.             LOGI(”prepare was cancelled before doing anything”);  
  9.             abortPrepare(UNKNOWN_ERROR);  
  10.             return;  
  11.         }  
  12.   
  13.         if (mUri.size() > 0) {  
  14.            //在这个方法中创建解析器  
  15.            <strong>status_t err = finishSetDataSource_l();</strong>  
  16.   
  17.             if (err != OK) {  
  18.                 abortPrepare(err);  
  19.                 return;  
  20.             }  
  21.         }  
  22.   
  23.         if (mVideoTrack != NULL && mVideoSource == NULL) {  
  24.             //初始化视频解码器  
  25.             <strong>status_t err = initVideoDecoder();</strong>  
  26.   
  27.             if (err != OK) {  
  28.                 abortPrepare(err);  
  29.                 return;  
  30.             }  
  31.         }  
  32.   
  33.         if (mAudioTrack != NULL && mAudioSource == NULL) {  
  34.             //初始化音频解码器  
  35.             <strong>status_t err = initAudioDecoder();  
  36. </strong>  
  37.             if (err != OK) {  
  38.                 abortPrepare(err);  
  39.                 return;  
  40.             }  
  41.         }  
  42.   
  43.         prefetcher = mPrefetcher;  
  44.     }  
  45.  if (prefetcher != NULL) {  
  46.         {  
  47.             Mutex::Autolock autoLock(mLock);  
  48.             if (mFlags & PREPARE_CANCELLED) {  
  49.                 LOGI(”prepare was cancelled before preparing the prefetcher”);  
  50.   
  51.                 prefetcher.clear();  
  52.                 abortPrepare(UNKNOWN_ERROR);  
  53.                 return;  
  54.             }  
  55.         }  
  56.   
  57.         LOGI(”calling prefetcher->prepare()”);  
  58.         status_t result =  
  59.             prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);  
  60.   
  61.         prefetcher.clear();  
  62.   
  63.         if (result == OK) {  
  64.             LOGI(”prefetcher is done preparing”);  
  65.         } else {  
  66.             Mutex::Autolock autoLock(mLock);  
  67.   
  68.             CHECK_EQ(result, -EINTR);  
  69.   
  70.             LOGI(”prefetcher->prepare() was cancelled early.”);  
  71.             abortPrepare(UNKNOWN_ERROR);  
  72.             return;  
  73.         }  
  74.     }  
  75.   
  76.  Mutex::Autolock autoLock(mLock);  
  77.   
  78.     if (mIsAsyncPrepare) {  
  79.         if (mVideoWidth < 0 || mVideoHeight < 0) {  
  80.             notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);  
  81.         } else {  
  82.             notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);  
  83.         }  
  84.   
  85.         notifyListener_l(MEDIA_PREPARED);  
  86.     }  
  87.   
  88.     mPrepareResult = OK;  
  89.     mFlags &= ~(PREPARING|PREPARE_CANCELLED);  
  90.     mFlags |= PREPARED;  
  91.     mAsyncPrepareEvent = NULL;  
  92.     mPreparedCondition.broadcast();  
  93.   
  94.     postBufferingEvent_l();  
  95. }  
void AwesomePlayer::onPrepareAsyncEvent() {
    sp<Prefetcher> prefetcher;

    {
        Mutex::Autolock autoLock(mLock);

        if (mFlags & PREPARE_CANCELLED) {
            LOGI("prepare was cancelled before doing anything");
            abortPrepare(UNKNOWN_ERROR);
            return;
        }

        if (mUri.size() > 0) {
           //在这个方法中创建解析器
           <strong>status_t err = finishSetDataSource_l();</strong>

            if (err != OK) {
                abortPrepare(err);
                return;
            }
        }

        if (mVideoTrack != NULL && mVideoSource == NULL) {
            //初始化视频解码器
            <strong>status_t err = initVideoDecoder();</strong>

            if (err != OK) {
                abortPrepare(err);
                return;
            }
        }

        if (mAudioTrack != NULL && mAudioSource == NULL) {
            //初始化音频解码器
            <strong>status_t err = initAudioDecoder();
</strong>
            if (err != OK) {
                abortPrepare(err);
                return;
            }
        }

        prefetcher = mPrefetcher;
    }
 if (prefetcher != NULL) {
        {
            Mutex::Autolock autoLock(mLock);
            if (mFlags & PREPARE_CANCELLED) {
                LOGI("prepare was cancelled before preparing the prefetcher");

                prefetcher.clear();
                abortPrepare(UNKNOWN_ERROR);
                return;
            }
        }

        LOGI("calling prefetcher->prepare()");
        status_t result =
            prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);

        prefetcher.clear();

        if (result == OK) {
            LOGI("prefetcher is done preparing");
        } else {
            Mutex::Autolock autoLock(mLock);

            CHECK_EQ(result, -EINTR);

            LOGI("prefetcher->prepare() was cancelled early.");
            abortPrepare(UNKNOWN_ERROR);
            return;
        }
    }

 Mutex::Autolock autoLock(mLock);

    if (mIsAsyncPrepare) {
        if (mVideoWidth < 0 || mVideoHeight < 0) {
            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
        } else {
            notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
        }

        notifyListener_l(MEDIA_PREPARED);
    }

    mPrepareResult = OK;
    mFlags &= ~(PREPARING|PREPARE_CANCELLED);
    mFlags |= PREPARED;
    mAsyncPrepareEvent = NULL;
    mPreparedCondition.broadcast();

    postBufferingEvent_l();
}


[cpp] view plain copy
print ?
  1. status_t AwesomePlayer::finishSetDataSource_l() {  
  2.     sp<DataSource> dataSource;  
  3.   
  4.     if (!strncasecmp(“http://”, mUri.string(), 7)) {  
  5.         mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);  
  6.   
  7.         mLock.unlock();  
  8.         status_t err = mConnectingDataSource->connect();  
  9.         mLock.lock();  
  10.   
  11.         if (err != OK) {  
  12.             mConnectingDataSource.clear();  
  13.   
  14.             LOGI(”mConnectingDataSource->connect() returned %d”, err);  
  15.             return err;  
  16.         }  
  17.   
  18.         dataSource = new CachingDataSource(  
  19.                 mConnectingDataSource, 64 * 1024, 10);  
  20.   
  21.         mConnectingDataSource.clear();  
  22.     } else {  
  23.         dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);  
  24.     }  
  25.   
  26.     if (dataSource == NULL) {  
  27.         return UNKNOWN_ERROR;  
  28.     }  
  29.   
  30.     <strong>sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);  
  31. </strong>  
  32.     if (extractor == NULL) {  
  33.         return UNKNOWN_ERROR;  
  34.     }  
  35.   
  36.     dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);  
  37.     if (mDecryptHandle != NULL  
  38.             && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {  
  39.         notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);  
  40.     }  
  41.   
  42.     if (dataSource->flags() & DataSource::kWantsPrefetching) {  
  43.         mPrefetcher = new Prefetcher;  
  44.     }  
  45.   
  46.    <strong> return setDataSource_l(extractor)</strong>;  
  47. }  
status_t AwesomePlayer::finishSetDataSource_l() {
    sp<DataSource> dataSource;

    if (!strncasecmp("http://", mUri.string(), 7)) {
        mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);

        mLock.unlock();
        status_t err = mConnectingDataSource->connect();
        mLock.lock();

        if (err != OK) {
            mConnectingDataSource.clear();

            LOGI("mConnectingDataSource->connect() returned %d", err);
            return err;
        }

        dataSource = new CachingDataSource(
                mConnectingDataSource, 64 * 1024, 10);

        mConnectingDataSource.clear();
    } else {
        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
    }

    if (dataSource == NULL) {
        return UNKNOWN_ERROR;
    }

    <strong>sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
</strong>
    if (extractor == NULL) {
        return UNKNOWN_ERROR;
    }

    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
    if (mDecryptHandle != NULL
            && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
    }

    if (dataSource->flags() & DataSource::kWantsPrefetching) {
        mPrefetcher = new Prefetcher;
    }

   <strong> return setDataSource_l(extractor)</strong>;
}


4.使用extractor对文件进行A/V分离:

[cpp] view plain copy
print ?
  1. status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {  
  2.     bool haveAudio = false;  
  3.     bool haveVideo = false;  
  4.     for (size_t i = 0; i < extractor->countTracks(); ++i) {  
  5.         sp<MetaData> meta = extractor->getTrackMetaData(i);  
  6.   
  7.         const char *mime;  
  8.         CHECK(meta->findCString(kKeyMIMEType, &mime));  
  9.   
  10.         if (!haveVideo && !strncasecmp(mime, “video/”, 6)) {  
  11.             setVideoSource(extractor->getTrack(i));  
  12.             haveVideo = true;  
  13.         } else if (!haveAudio && !strncasecmp(mime, “audio/”, 6)) {  
  14.             setAudioSource(extractor->getTrack(i));  
  15.             haveAudio = true;  
  16.         }  
  17.   
  18.         if (haveAudio && haveVideo) {  
  19.             break;  
  20.         }  
  21.     }  
  22.   
  23.     if (!haveAudio && !haveVideo) {  
  24.         return UNKNOWN_ERROR;  
  25.     }  
  26.   
  27.     mExtractorFlags = extractor->flags();  
  28.   
  29.     return OK;  
  30. }  
status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
    bool haveAudio = false;
    bool haveVideo = false;
    for (size_t i = 0; i < extractor->countTracks(); ++i) {
        sp<MetaData> meta = extractor->getTrackMetaData(i);

        const char *mime;
        CHECK(meta->findCString(kKeyMIMEType, &mime));

        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
            setVideoSource(extractor->getTrack(i));
            haveVideo = true;
        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
            setAudioSource(extractor->getTrack(i));
            haveAudio = true;
        }

        if (haveAudio && haveVideo) {
            break;
        }
    }

    if (!haveAudio && !haveVideo) {
        return UNKNOWN_ERROR;
    }

    mExtractorFlags = extractor->flags();

    return OK;
}

5.将解析后的音视频数据分别交给VideoTrack和AudioTrack:

[cpp] view plain copy
print ?
  1. void AwesomePlayer::setVideoSource(sp<MediaSource> source) {  
  2.     CHECK(source != NULL);  
  3.   
  4.     if (mPrefetcher != NULL) {  
  5.         source = mPrefetcher->addSource(source);  
  6.     }  
  7.   
  8.     mVideoTrack = source;  
  9. }  
  10.   
  11. void AwesomePlayer::setAudioSource(sp<MediaSource> source) {  
  12.     CHECK(source != NULL);  
  13.   
  14.     if (mPrefetcher != NULL) {  
  15.         source = mPrefetcher->addSource(source);  
  16.     }  
  17.   
  18.     mAudioTrack = source;  
  19. }  
void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
    CHECK(source != NULL);

    if (mPrefetcher != NULL) {
        source = mPrefetcher->addSource(source);
    }

    mVideoTrack = source;
}

void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
    CHECK(source != NULL);

    if (mPrefetcher != NULL) {
        source = mPrefetcher->addSource(source);
    }

    mAudioTrack = source;
}


6.根据mVideoTrck中的编码类型来选择 video decoder 同理根据mAudioTrack中的编码类型来选择 audio decoder:

[cpp] view plain copy
print ?
  1. status_t AwesomePlayer::initVideoDecoder() {  
  2.     mVideoSource = OMXCodec::Create(  
  3.             mClient.interface(), mVideoTrack->getFormat(),  
  4.             false// createEncoder  
  5.             mVideoTrack);  
  6.   
  7.     if (mVideoSource != NULL) {  
  8.         int64_t durationUs;  
  9.         if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {  
  10.             Mutex::Autolock autoLock(mMiscStateLock);  
  11.             if (mDurationUs < 0 || durationUs > mDurationUs) {  
  12.                 mDurationUs = durationUs;  
  13.             }  
  14.         }  
  15.   
  16.         CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));  
  17.         CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));  
  18.   
  19.         status_t err = mVideoSource->start();  
  20.   
  21.         if (err != OK) {  
  22.             mVideoSource.clear();  
  23.             return err;  
  24.         }  
  25.     }  
  26.   
  27.     return mVideoSource != NULL ? OK : UNKNOWN_ERROR;  
  28. }  
status_t AwesomePlayer::initVideoDecoder() {
    mVideoSource = OMXCodec::Create(
            mClient.interface(), mVideoTrack->getFormat(),
            false, // createEncoder
            mVideoTrack);

    if (mVideoSource != NULL) {
        int64_t durationUs;
        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
            Mutex::Autolock autoLock(mMiscStateLock);
            if (mDurationUs < 0 || durationUs > mDurationUs) {
                mDurationUs = durationUs;
            }
        }

        CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
        CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));

        status_t err = mVideoSource->start();

        if (err != OK) {
            mVideoSource.clear();
            return err;
        }
    }

    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
}


7.将mVideoEvent放入mQueue中,开始解码播放,并交由mvideoRenderer来画出   audio的数据则交由audioplayer来管理,它最终将解码的数据交给audioTrack并由audioTrack和audioFlinger进行交互,最终将数据交给audio hal层,这个我们以后会做讲解:

[cpp] view plain copy
print ?
  1. status_t AwesomePlayer::play() {  
  2.     Mutex::Autolock autoLock(mLock);  
  3.     return play_l();  
  4. }  
  5. status_t AwesomePlayer::play_l() {  
  6.     if (mFlags & PLAYING) {  
  7.         return OK;  
  8.     }  
  9.   
  10.     if (!(mFlags & PREPARED)) {  
  11.         status_t err = prepare_l();  
  12.   
  13.         if (err != OK) {  
  14.             return err;  
  15.         }  
  16.     }  
  17.   
  18.     mFlags |= PLAYING;  
  19.     mFlags |= FIRST_FRAME;  
  20.   
  21.     bool deferredAudioSeek = false;  
  22.   
  23.     if (mAudioSource != NULL) {  
  24.         if (mAudioPlayer == NULL) {  
  25.             if (mAudioSink != NULL) {  
  26.                 //音频数据由audioplayer进行管理  
  27.                 mAudioPlayer = new AudioPlayer(mAudioSink);  
  28.                 mAudioPlayer->setSource(mAudioSource);  
  29.   
  30.                 // We’ve already started the MediaSource in order to enable  
  31.                 // the prefetcher to read its data.  
  32.                   //调用audioPlayer的start方法则是调用audioSource对数据进行解码  
  33.                    //并将解码似得数据最终交给audioTrack,并调用audioTrack的start方法与audioFlinger进行交互  
  34.                    status_t err = mAudioPlayer->start(  
  35.                         true /* sourceAlreadyStarted */);  
  36.   
  37.                 if (err != OK) {  
  38.                     delete mAudioPlayer;  
  39.                     mAudioPlayer = NULL;  
  40.   
  41.                     mFlags &= ~(PLAYING | FIRST_FRAME);  
  42.   
  43.                     return err;  
  44.                 }  
  45.   
  46.                 delete mTimeSource;  
  47.                 mTimeSource = mAudioPlayer;  
  48.   
  49.                 deferredAudioSeek = true;  
  50.   
  51.                 mWatchForAudioSeekComplete = false;  
  52.                 mWatchForAudioEOS = true;  
  53.             }  
  54.         } else {  
  55.             mAudioPlayer->resume();  
  56.         }  
  57.   
  58.         postCheckAudioStatusEvent_l();  
  59.     }  
  60.   
  61.     if (mTimeSource == NULL && mAudioPlayer == NULL) {  
  62.         mTimeSource = new SystemTimeSource;  
  63.     }  
  64.   
  65.     if (mVideoSource != NULL) {  
  66.         // Kick off video playback  
  67.         //将mVideoEvent放入queue中  
  68.           postVideoEvent_l();  
  69.     }  
  70.   
  71.     if (deferredAudioSeek) {  
  72.         // If there was a seek request while we were paused  
  73.         // and we’re just starting up again, honor the request now.  
  74.         seekAudioIfNecessary_l();  
  75.     }  
  76.   
  77.     if (mFlags & AT_EOS) {  
  78.         // Legacy behaviour, if a stream finishes playing and then  
  79.         // is started again, we play from the start…  
  80.         seekTo_l(0);  
  81.     }  
  82.   
  83.     if (mDecryptHandle != NULL) {  
  84.         int64_t position;  
  85.         getPosition(&position);  
  86.         mDrmManagerClient->setPlaybackStatus(mDecryptHandle,  
  87.                 Playback::START, position / 1000);  
  88.     }  
  89.   
  90.     return OK;  
  91. }  
  92.   
  93.  void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {  
  94.     if (mVideoEventPending) {  
  95.         return;  
  96.     }  
  97.   
  98.     mVideoEventPending = true;  
  99.     mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);  
  100. }  
status_t AwesomePlayer::play() {
    Mutex::Autolock autoLock(mLock);
    return play_l();
}
status_t AwesomePlayer::play_l() {
    if (mFlags & PLAYING) {
        return OK;
    }

    if (!(mFlags & PREPARED)) {
        status_t err = prepare_l();

        if (err != OK) {
            return err;
        }
    }

    mFlags |= PLAYING;
    mFlags |= FIRST_FRAME;

    bool deferredAudioSeek = false;

    if (mAudioSource != NULL) {
        if (mAudioPlayer == NULL) {
            if (mAudioSink != NULL) {
                //音频数据由audioplayer进行管理
                mAudioPlayer = new AudioPlayer(mAudioSink);
                mAudioPlayer->setSource(mAudioSource);

                // We've already started the MediaSource in order to enable
                // the prefetcher to read its data.
                  //调用audioPlayer的start方法则是调用audioSource对数据进行解码
                   //并将解码似得数据最终交给audioTrack,并调用audioTrack的start方法与audioFlinger进行交互
                   status_t err = mAudioPlayer->start(
                        true /* sourceAlreadyStarted */);

                if (err != OK) {
                    delete mAudioPlayer;
                    mAudioPlayer = NULL;

                    mFlags &= ~(PLAYING | FIRST_FRAME);

                    return err;
                }

                delete mTimeSource;
                mTimeSource = mAudioPlayer;

                deferredAudioSeek = true;

                mWatchForAudioSeekComplete = false;
                mWatchForAudioEOS = true;
            }
        } else {
            mAudioPlayer->resume();
        }

        postCheckAudioStatusEvent_l();
    }

    if (mTimeSource == NULL && mAudioPlayer == NULL) {
        mTimeSource = new SystemTimeSource;
    }

    if (mVideoSource != NULL) {
        // Kick off video playback
        //将mVideoEvent放入queue中
          postVideoEvent_l();
    }

    if (deferredAudioSeek) {
        // If there was a seek request while we were paused
        // and we're just starting up again, honor the request now.
        seekAudioIfNecessary_l();
    }

    if (mFlags & AT_EOS) {
        // Legacy behaviour, if a stream finishes playing and then
        // is started again, we play from the start...
        seekTo_l(0);
    }

    if (mDecryptHandle != NULL) {
        int64_t position;
        getPosition(&position);
        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
                Playback::START, position / 1000);
    }

    return OK;
}

 void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
    if (mVideoEventPending) {
        return;
    }

    mVideoEventPending = true;
    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
}
[cpp] view plain copy
print ?
  1. void AwesomePlayer::onVideoEvent()  
  2. {  
  3.   mVideoSource->read(&mVideoBuffer, &options);  
  4.   mVideoRenderer->render(mVideoBuffer);  
  5.   
  6.   postVideoEvent_l();  
  7. }  
void AwesomePlayer::onVideoEvent()
{
  mVideoSource->read(&mVideoBuffer, &options);
  mVideoRenderer->render(mVideoBuffer);

  postVideoEvent_l();
}



转自:https://blog.csdn.net/itachi85/article/details/7216639


http://www.niftyadmin.cn/n/664539.html

相关文章

面试-双向链表

面试遇到一个题目&#xff0c;写一个双向链表&#xff0c;包括添加&#xff0c;删除&#xff0c;查找和遍历。当时写了一塌糊涂&#xff0c;后来自己都觉得想笑&#xff0c;双向写着写着被我写成了单向不像单向&#xff0c;双向不像双向了&#xff0c;真是不伦不类。之后 我把这…

Java虚拟机(一)结构原理与运行时数据区域

前言 本来计划要写Android内存优化的&#xff0c;觉得有必要在此之前介绍一下Java虚拟机的相关知识&#xff0c;Java虚拟机也并不是三言两语能够介绍完的&#xff0c;因此开了Java虚拟机系列&#xff0c;这一篇文章我们来学习Java虚拟机的结构原理与运行时数据区域。 1.Java虚拟…

[美食]台湾夜市空降上海 33元吃到饱

正宗的台湾夜市小吃搬到上海咯&#xff01;一家来自台 湾的自助式餐厅近日在上海长宁区延安西路近虹许路开张。大肠包小肠、蚵仔煎、牛肉面、担仔面、天妇罗、生炒花枝、台湾刨冰、台湾水果……食客在该店试营业 期间只需要花33元&#xff08;下午茶/宵夜价格&#xff09;&…

【codeforces 733F】 Drivers Dissatisfaction

http://codeforces.com/problemset/problem/733/F (题目链接) 题意 给出一张n个点的无向图&#xff0c;每一条变有两个特征值&#xff1a;${w&#xff0c;c}$&#xff1b;分别表示这条边的权值为${w}$&#xff0c;每将这条边的权值减小1需要充${c}$元钱。初始时有${S}$元钱&…

Java虚拟机(二)对象的创建与OOP-Klass模型

相关文章 Java虚拟机系列 前言 在前一篇文章中我们学习了Java虚拟机的结构原理与运行时数据区域&#xff0c;那么我们大概知道了Java虚拟机的内存的概况&#xff0c;那么内存中的数据是如何创建和访问的呢&#xff1f;这篇文章会给你答案。 1.对象的创建 对象的创建通常是通过…

IIS http 错误 401.3 - unauthorized

iis http 错误 401.3 - unauthorized 向物理目录添加iis_iusrs用户权限。转载于:https://www.cnblogs.com/zhanqun/p/5508954.html

Python 2.5 Quick Reference

Python 2.5 Quick Reference 收藏 <script type"text/javascript"> document.body.oncopy function() { if (window.clipboardData) { setTimeout(function() { var text clipboardData.getData(&quot;text&quot;); if (text &amp;&amp; t…

关于离职和领导交流完毕的感受

上回和段总聊了一下&#xff0c;聊完之后我真的是又坚定了离开的想法。我说我要离开时因为我的自学能力在逐步的下降&#xff0c;我自己学些的动力被一点一点的消磨掉了。早上我卡着点来是因为李萍老师&#xff0c;原因就是我不想听他放那些乱七八糟的音乐&#xff08;我认为这…