Explanation of the stagefright framework (-) Audio and video playback process (I)

Source: Internet
Author: User

From android
2.0. Google introduced stagefright and used stagefright in android2.3 to share
Library format (libstagefright. So), where awesomeplayer can be used to play video/audio. Awesomeplayer provides many APIs that allow upper-layer applications to use Java/JNI for calling. Here I will briefly describe the video playback process (using the android2.2 source code ).

In Java, to play a video, we usually write as follows:

MediaPlayer mp = new MediaPlayer();mp.setDataSource(PATH_TO_FILE);mp.prepare();mp.start();

In stagefright, you will see the following processing:

1. Specify the absolute path of the video file to Uri:

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. Start mqueue:

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 is triggered. Create a parser Based on the header of the sent file and initialize the audio/video decoder:

Void awesomeplayer: onprepareasyncevent () {sp <prefetcher> prefetcher; {mutex: autolock (mlock); If (mflags & prepare_cancelled) {Logi ("Prepare was canceled before doing anything"); abortprepare (unknown_error); return;} If (muri. size ()> 0) {// create a parser in this methodStatus_t err = finishsetperformance_l ();If (Err! = OK) {abortprepare (ERR); Return ;}} if (mvideotrack! = NULL & mvideosource = NULL) {// initialize the Video DecoderStatus_t err = initvideodecoder ();If (Err! = OK) {abortprepare (ERR); Return ;}} if (maudiotrack! = NULL & maudiosource = NULL) {// initialize the audio decoderStatus_t err = initaudiodecoder ();If (Err! = OK) {abortprepare (ERR); Return ;}} prefetcher = mprefetcher;} If (prefetcher! = NULL) {mutex: autolock (mlock); If (mflags & prepare_cancelled) {Logi ("Prepare was canceled 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 (mlock); check_eq (result,-eintr); Logi ("prefetcher-> prepare () was canceled early. "); abortprepare (unknown_error); Return ;}} mutex: autolock (mlock); If (misasyncprepare) {If (mvideowidth <0 | mvideoheight <0) {policylistener_l (media_set_video_size, 0, 0);} else {policylistener_l (media_set_video_size, mvideowidth, mvideoheight);} policylistener _ L (media_prepared);} mprepareresult = OK; mflags & = ~ (Preparing | prepare_cancelled); mflags | = prepared; masyncprepareevent = NULL; mpreparedcondition. Broadcast (); postbufferingevent_l ();}

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;    }    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);    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;    }    return setDataSource_l(extractor);}

4. Use the extractor to separate the File A/V:

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;}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.