Android Media Server - MediaPlayer - setDataSource

 

 

 

 

 

1.    MediaPlayer::MediaPlayer()

Frameworks/base/media/java/android/media/MediaPlayer.java

public MediaPlayer() {

 

        Looper looper;

 

// 得到当前线程的Looper, 并创建EventHandler对象

// 注意:EventHandler类重写了handleMessage消息处理函数

 

        if ((looper = Looper.myLooper()) !=null) {

            mEventHandler = newEventHandler(this, looper);

        } else if ((looper =Looper.getMainLooper()) != null) {

            mEventHandler = new EventHandler(this,looper);

        } else {

            mEventHandler = null;

        }

 

        /* Native setup requires a weakreference to our object.

         * It's easier to create it here thanin C++.

         */

        native_setup(new WeakReference<MediaPlayer>(this));

}

 

2.  android_media_MediaPlayer_native_setup()

Frameworks/base/media/jni/Android_media_MediaPlayer.cpp

 

// Thisfunction gets some field IDs, which in turn causes class initialization.

// It iscalled from a static block in MediaPlayer, which won't run until the

// firsttime an instance of this class is used.

staticvoid

android_media_MediaPlayer_native_init(JNIEnv*env)

{

    jclass clazz;

 

    clazz =env->FindClass("android/media/MediaPlayer");

    if (clazz == NULL) {

        return;

    }

 

    fields.context = env->GetFieldID(clazz,"mNativeContext", "I");

    if (fields.context == NULL) {

        return;

    }

 

    fields.post_event =env->GetStaticMethodID(clazz, "postEventFromNative",

                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");

    if (fields.post_event == NULL) {

        return;

    }

 

    fields.surface_texture =env->GetFieldID(clazz, "mNativeSurfaceTexture", "I");

    if (fields.surface_texture == NULL) {

        return;

    }

 

    clazz= env->FindClass("android/net/ProxyProperties");

    if (clazz == NULL) {

        return;

    }

 

    fields.proxyConfigGetHost =

        env->GetMethodID(clazz,"getHost", "()Ljava/lang/String;");

 

    fields.proxyConfigGetPort =

        env->GetMethodID(clazz,"getPort", "()I");

 

    fields.proxyConfigGetExclusionList =

        env->GetMethodID(clazz,"getExclusionList", "()Ljava/lang/String;");

}

 

staticvoid

android_media_MediaPlayer_native_setup(JNIEnv*env, jobject thiz, jobject weak_this)

{

    ALOGV("native_setup");

   sp<MediaPlayer> mp = new MediaPlayer();

    if (mp == NULL) {

        jniThrowException(env,"java/lang/RuntimeException", "Out of memory");

        return;

    }

 

    // create new listener and give it toMediaPlayer

    sp<JNIMediaPlayerListener> listener =new JNIMediaPlayerListener(env, thiz, weak_this);

// 将新建的MediaPlayerListener对象赋给本地 MediaPlayer对象

    mp->setListener(listener);

 

    // Stow our new C++ MediaPlayer in anopaque field in the Java object.

// 将本地MediaPlayer 对象保存在java env (context)

    setMediaPlayer(env, thiz, mp);

}

 

staticsp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, constsp<MediaPlayer>& player)

{

    Mutex::Autolock l(sLock);

    sp<MediaPlayer> old =(MediaPlayer*)env->GetIntField(thiz, fields.context);

    if (player.get()) {

       player->incStrong((void*)setMediaPlayer);

    }

    if (old != 0) {

       old->decStrong((void*)setMediaPlayer);

    }

    env->SetIntField(thiz, fields.context,(int)player.get());

    return old;

}

 

// 本地MediaPlayer对象创建完毕

 

// 下面是setDataSource分析

1.       MediaPlayer::setDataSource()

Frameworks/base/media/java/android/media/MediaPlayer.java

Ignored.

 

2.  android_media_MediaPlayer_setDataSourceAndHeaders()

Frameworks/base/media/jni/Android_media_MediaPlayer.cpp

static void

android_media_MediaPlayer_setDataSourceAndHeaders(

       JNIEnv *env, jobject thiz, jstring path,

       jobjectArray keys, jobjectArray values) {

 

// 得到本地MediaPlayer对象

 

sp<MediaPlayer> mp = getMediaPlayer(env, thiz);

 

   if (mp == NULL ) {

       jniThrowException(env, "java/lang/IllegalStateException",NULL);

       return;

    }

 

   if (path == NULL) {

       jniThrowException(env, "java/lang/IllegalArgumentException",NULL);

       return;

    }

 

   const char *tmp = env->GetStringUTFChars(path, NULL);

   if (tmp == NULL) {  // Out ofmemory

       return;

    }

   ALOGV("setDataSource: path %s", tmp);

 

   String8 pathStr(tmp);

   env->ReleaseStringUTFChars(path, tmp);

   tmp = NULL;

 

   // We build a KeyedVector out of the key and val arrays

   KeyedVector<String8, String8> headersVector;

   if (!ConvertKeyValueArraysToKeyedVector(

           env, keys, values, &headersVector)) {

       return;

    }

 

   status_t opStatus =

        mp->setDataSource(

                pathStr,

                headersVector.size() > 0?&headersVector : NULL);

 

    process_media_player_call(

            env, thiz, opStatus,"java/io/IOException",

            "setDataSource failed.");

}

 

3.  MediaPlayer::setDataSource()

Frameworks/av/media/libmedia/MediaPlayer.cpp

 

status_tMediaPlayer::setDataSource(

        const char *url, constKeyedVector<String8, String8> *headers)

{

    ALOGV("setDataSource(%s)", url);

    status_t err = BAD_VALUE;

    if (url != NULL) {

 

// 从服务端得到MediaPlayerService

// 并创建本地对应的BpMediaPlayerService(BpBinder)

 

        constsp<IMediaPlayerService>& service(getMediaPlayerService());

        if (service != 0) {

 

// 依据BpMediaPlayerService(BpBinder)对象,

// 创建BpMediaPlayer(BpBinder) 对象

// player是一个BpMediaPlayer(BpBinder)对象

 

            sp<IMediaPlayer>player(service->create(this, mAudioSessionId));

 

            if ((NO_ERROR !=doSetRetransmitEndpoint(player)) ||

               (NO_ERROR != player->setDataSource(url, headers))) {

                player.clear();

            }

 

// 将这个BpMediaPlay(BpBinder)对象

// 保存在本地MediaPlayer对象的mPlayer成员变量中

 

            err = attachNewPlayer(player);

        }

    }

    return err;

}

 

 

status_tMediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)

{

    status_t err = UNKNOWN_ERROR;

    sp<IMediaPlayer> p;

    { // scope for the lock

        Mutex::Autolock _l(mLock);

 

        if ( !( (mCurrentState &MEDIA_PLAYER_IDLE) ||

                (mCurrentState ==MEDIA_PLAYER_STATE_ERROR ) ) ) {

            ALOGE("attachNewPlayer calledin state %d", mCurrentState);

            return INVALID_OPERATION;

        }

 

        clear_l();

        p = mPlayer;

 

// player是一个BpMediaPlayer(BpBinder)对象

// 这儿将player对象赋值给本地MediaPlayer对象的成员变量mPlayer

 

        mPlayer =player;

 

        if (player != 0) {

            mCurrentState =MEDIA_PLAYER_INITIALIZED;

            err = NO_ERROR;

        } else {

            ALOGE("Unable to to createmedia player");

        }

    }

 

    if (p != 0) {

        p->disconnect();

    }

 

    return err;

}

 

4.   BpMediaPlayerService::create()

Frameworks/av/media/libmedia/IMediaPlayerService.cpp

classBpMediaPlayerService: public BpInterface<IMediaPlayerService>

{

   virtual sp<IMediaPlayer> create(

           const sp<IMediaPlayerClient>& client, int audioSessionId) {

       Parcel data, reply;

       data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());

       data.writeStrongBinder(client->asBinder());

       data.writeInt32(audioSessionId);

 

// remote() 返回的是BpMediaPlayerService(BpBinder)中的BpBinder

// 这儿执行的是BpBinder->transact(),

// 将通过Binder机制执行BnMediaPlayerService::onTransact()

 

        remote()->transact(CREATE, data,&reply);

        returninterface_cast<IMediaPlayer>(reply.readStrongBinder());

}

}

 

template<typename INTERFACE>

class BnInterface :public INTERFACE, public BBinder

{

public:

   virtual sp<IInterface>     queryLocalInterface(const String16& _descriptor);

   virtual const String16&    getInterfaceDescriptor() const;

 

protected:

   virtual IBinder*           onAsBinder();

};

 

classIMediaPlayerService: public IInterface

{

public:

   DECLARE_META_INTERFACE(MediaPlayerService);

 

   virtual sp<IMediaRecorder> createMediaRecorder() = 0;

   virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;

    virtual sp<IMediaPlayer> create(constsp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;

 

   virtual sp<IMemory>        decode(const char* url, uint32_t *pSampleRate, int* pNumChannels,audio_format_t* pFormat) = 0;

virtualsp<IMemory>         decode(int fd,int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels,audio_format_t* pFormat) = 0;

 

…………………………………………………………………….

}

 

5.  BnMediaPlayerService::onTransact()

Frameworks/av/media/libmedia/IMediaPlayerService.cpp

status_t BnMediaPlayerService::onTransact(

   uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

   switch (code) {

       case CREATE: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

            sp<IMediaPlayerClient> client =

               interface_cast<IMediaPlayerClient>(data.readStrongBinder());

            int audioSessionId =data.readInt32();

 

// create生成一个MediaPlayerService::Client对象

// 它是一个BnMediaPlayer对象

// 因此player是一个BnMediaPlayer对象

 

            sp<IMediaPlayer> player =create(client, audioSessionId);

           reply->writeStrongBinder(player->asBinder());

 

           return NO_ERROR;

       } break;

………………………………………………………………………………………………….

}

 

 

6.   MediaPlayerService::create()

Frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

 

因为

class MediaPlayerService : publicBnMediaPlayerService

{

}

因此上述            sp<IMediaPlayer> player =create(client, audioSessionId);

就是调用

sp<IMediaPlayer>MediaPlayerService::create(const sp<IMediaPlayerClient>& client,

       int audioSessionId)

{

   pid_t pid = IPCThreadState::self()->getCallingPid();

   int32_t connId = android_atomic_inc(&mNextConnId);

 

//  生成一个MediaPlayerService::Client对象

 

   sp<Client> c = new Client(

           this, pid, connId, client, audioSessionId,

           IPCThreadState::self()->getCallingUid());

 

   ALOGV("Create new client(%d) from pid %d, uid %d, ", connId,pid,

        IPCThreadState::self()->getCallingUid());

 

   wp<Client> w = c;

    {

       Mutex::Autolock lock(mLock);

       mClients.add(w);

    }

   return c;

}

 

MediaPlayerService::Client::Client(

       const sp<MediaPlayerService>& service, pid_t pid,

       int32_t connId, const sp<IMediaPlayerClient>& client,

       int audioSessionId, uid_t uid)

{

   ALOGV("Client(%d) constructor", connId);

   mPid = pid;

   mConnId = connId;

    mService = service;

    mClient = client;

   mLoop = false;

   mStatus = NO_INIT;

   mAudioSessionId = audioSessionId;

   mUID = uid;

   mRetransmitEndpointValid = false;

 

#if CALLBACK_ANTAGONIZER

   ALOGD("create Antagonizer");

   mAntagonizer = new Antagonizer(notify, this);

#endif

}

 

7.   BpMediaPlayer::setDataSource ()

Frameworks/av/media/libmedia/IMediaPlayerService.cpp

Follow 3 中语句

            if ((NO_ERROR !=doSetRetransmitEndpoint(player)) ||

               (NO_ERROR != player->setDataSource(url, headers))) {

                player.clear();

            }

执行该调用

   status_t setDataSource(const char* url,

           const KeyedVector<String8, String8>* headers)

    {

       Parcel data, reply;

       data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());

       data.writeCString(url);

       if (headers == NULL) {

           data.writeInt32(0);

       } else {

           // serialize the headers

           data.writeInt32(headers->size());

           for (size_t i = 0; i < headers->size(); ++i) {

               data.writeString8(headers->keyAt(i));

                data.writeString8(headers->valueAt(i));

           }

       }

       remote()->transact(SET_DATA_SOURCE_URL, data, &reply);

       return reply.readInt32();

}

 

 

 

 

 

 

 

 

 

8.   BnMediaPlayer::onTransact ()

Frameworks/av/media/libmedia/IMediaPlayerService.cpp

status_tBnMediaPlayer::onTransact(

    uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)

{

    switch (code) {

        case DISCONNECT: {

            CHECK_INTERFACE(IMediaPlayer, data,reply);

            disconnect();

            return NO_ERROR;

        } break;

        case SET_DATA_SOURCE_URL: {

            CHECK_INTERFACE(IMediaPlayer, data,reply);

            const char* url =data.readCString();

            KeyedVector<String8, String8>headers;

            int32_t numHeaders = data.readInt32();

            for (int i = 0; i < numHeaders;++i) {

                String8 key =data.readString8();

                String8 value =data.readString8();

                headers.add(key, value);

            }

           reply->writeInt32(setDataSource(url,numHeaders > 0 ? &headers : NULL));

            return NO_ERROR;

        } break;

………………………………………………………………………………………………….

}

 

9.   MediaPlayerService::Client::setDataSource()

Frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

 

status_t MediaPlayerService::Client::setDataSource(

        const char *url, constKeyedVector<String8, String8> *headers)

{

    ALOGV("setDataSource(%s)", url);

    if (url == NULL)

        return UNKNOWN_ERROR;

 

    if ((strncmp(url, "http://", 7)== 0) ||

        (strncmp(url, "https://", 8)== 0) ||

        (strncmp(url, "rtsp://", 7)== 0)) {

        if(!checkPermission("android.permission.INTERNET")) {

            return PERMISSION_DENIED;

        }

    }

 

    if (strncmp(url, "content://",10) == 0) {

        // get a filedescriptor for the contentUri and

        // pass it to the setDataSource(fd)method

 

        String16 url16(url);

        int fd =android::openContentProviderFile(url16);

        if (fd < 0)

        {

            ALOGE("Couldn't open fd for%s", url);

            return UNKNOWN_ERROR;

        }

        setDataSource(fd, 0, 0x7fffffffffLL);// this sets mStatus

        close(fd);

        return mStatus;

    } else {

        player_typeplayerType = MediaPlayerFactory::getPlayerType(this, url);

       sp<MediaPlayerBase> p = setDataSource_pre(playerType);

        if (p == NULL){

            returnNO_INIT;

        }

 

// p 赋值给mPlayer成员变量,它是一个StagefrightPlayer()对象

// 而这个StageFrightPlayer对象中的mPlayer成员变量

// 是一个AwesomePlayer对象

 

       setDataSource_post(p, p->setDataSource(url, headers));

        return mStatus;

    }

}

 

sp<MediaPlayerBase>MediaPlayerService::Client::setDataSource_pre(

        player_type playerType)

{

    ALOGV("player type = %d",playerType);

 

    // create the right type of player

   sp<MediaPlayerBase> p = createPlayer(playerType);

    if (p == NULL) {

        return p;

    }

 

    if (!p->hardwareOutput()) {

        mAudioOutput = newAudioOutput(mAudioSessionId);

       static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);

    }

 

    return p;

}

 

sp<MediaPlayerBase>MediaPlayerService::Client::createPlayer(player_type playerType)

{

    // determine if we have the right playertype

    sp<MediaPlayerBase> p = mPlayer;

    if ((p != NULL) &&(p->playerType() != playerType)) {

        ALOGV("delete player");

        p.clear();

    }

    if (p == NULL) {

        p =MediaPlayerFactory::createPlayer(playerType, this, notify);

    }

 

    if (p != NULL) {

        p->setUID(mUID);

    }

 

    return p;

}

 

10.  sp<MediaPlayerBase> MediaPlayerFactory::createPlayer ()

Frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp

sp<MediaPlayerBase>MediaPlayerFactory::createPlayer(

        player_type playerType,

        void* cookie,

        notify_callback_f notifyFunc) {

    sp<MediaPlayerBase> p;

    IFactory* factory;

    status_t init_result;

    Mutex::Autolock lock_(&sLock);

 

    if (sFactoryMap.indexOfKey(playerType) <0) {

        ALOGE("Failed to create playerobject of type %d, no registered"

              " factory",playerType);

        return p;

    }

 

    factory = sFactoryMap.valueFor(playerType);

    CHECK(NULL != factory);

    p =factory->createPlayer();

 

    if (p == NULL) {

        ALOGE("Failed to create playerobject of type %d, create failed",

               playerType);

        return p;

    }

 

    init_result = p->initCheck();

    if (init_result == NO_ERROR) {

        p->setNotifyCallback(cookie,notifyFunc);

    } else {

        ALOGE("Failed to create playerobject of type %d, initCheck failed"

              " (res = %d)",playerType, init_result);

        p.clear();

    }

 

    return p;

}

 

classStagefrightPlayerFactory :

    public MediaPlayerFactory::IFactory {

  public:

    virtual float scoreFactory(constsp<IMediaPlayer>& client,

                               int fd,

                               int64_t offset,

                               int64_t length,

                               float curScore){

        char buf[20];

        lseek(fd, offset, SEEK_SET);

        read(fd, buf, sizeof(buf));

        lseek(fd, offset, SEEK_SET);

 

        long ident = *((long*)buf);

 

        // Ogg vorbis?

        if (ident == 0x5367674f) // 'OggS'

            return 1.0;

 

        return 0.0;

    }

 

    virtual sp<MediaPlayerBase>createPlayer() {

        ALOGV(" createStagefrightPlayer");

        return newStagefrightPlayer();

    }

};

 

11.  MediaPlayerService::Client::setDataSource_post ()

Frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

Follow 9 中语句

       setDataSource_post(p, p->setDataSource(url, headers));

调用该函数

voidMediaPlayerService::Client::setDataSource_post(

        const sp<MediaPlayerBase>& p,

        status_t status)

{

    ALOGV(" setDataSource");

    mStatus = status;

    if (mStatus != OK) {

        ALOGE("  error: %d", mStatus);

        return;

    }

 

    // Set the re-transmission endpoint if onewas chosen.

    if (mRetransmitEndpointValid) {

        mStatus =p->setRetransmitEndpoint(&mRetransmitEndpoint);

        if (mStatus != NO_ERROR) {

            ALOGE("setRetransmitEndpointerror: %d", mStatus);

        }

    }

 

    if (mStatus == OK){

        mPlayer = p;

    }

}

 

上面p-> setDataSource(url, headers)将调用StageFrightPlayersetDataSource

 

status_tStagefrightPlayer::setDataSource(

        const char *url, constKeyedVector<String8, String8> *headers) {

    returnmPlayer->setDataSource(url, headers);

}

mPlayer-> setDataSource(url, headers); 将调用AwesomePlayersetDataSource

 

status_t AwesomePlayer::setDataSource(

        const char *uri, constKeyedVector<String8, String8> *headers) {

    Mutex::Autolock autoLock(mLock);

    returnsetDataSource_l(uri, headers);

}

 

status_tAwesomePlayer::setDataSource_l(

        const char *uri, const KeyedVector<String8,String8> *headers) {

    reset_l();

 

    mUri = uri;

 

    if (headers) {

        mUriHeaders = *headers;

 

        ssize_t index =mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));

        if (index >= 0) {

            // Browser is in"incognito" mode, suppress logging URLs.

 

            // This isn't something that shouldbe passed to the server.

            mUriHeaders.removeItemsAt(index);

 

            modifyFlags(INCOGNITO, SET);

        }

    }

 

    ALOGI("setDataSource_l(URLsuppressed)");

 

    // The actual work will be done duringpreparation in the call to

    // ::finishSetDataSource_l to avoidblocking the calling thread in

    // setDataSource for any significant time.

 

    {

        Mutex::Autolock autoLock(mStatsLock);

        mStats.mFd = -1;

        mStats.mURI = mUri;

    }

 

    return OK;

}

 

 

12.  StagefrightPlayer::StagefrightPlayer ()

Frameworks/av/media/libmediaplayerservice/StageFrightPlayer.cpp

Follow 10 return newStagefrightPlayer();

StagefrightPlayer::StagefrightPlayer()

   : mPlayer(new AwesomePlayer) {

    ALOGV("StagefrightPlayer");

 

   mPlayer->setListener(this);

}

 

13.  StagefrightPlayer::StagefrightPlayer ()

Frameworks/av/media/libstagefright/AwesomePlayer.cpp

 

AwesomePlayer::AwesomePlayer()

    : mQueueStarted(false),

      mUIDValid(false),

      mTimeSource(NULL),

      mVideoRenderingStarted(false),

      mVideoRendererIsPreview(false),

      mAudioPlayer(NULL),

      mDisplayWidth(0),

      mDisplayHeight(0),

      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),

      mFlags(0),

      mExtractorFlags(0),

      mVideoBuffer(NULL),

      mDecryptHandle(NULL),

      mLastVideoTimeUs(-1),

      mTextDriver(NULL) {

    CHECK_EQ(mClient.connect(), (status_t)OK);

 

    DataSource::RegisterDefaultSniffers();

 

    mVideoEvent = new AwesomeEvent(this,&AwesomePlayer::onVideoEvent);

    mVideoEventPending = false;

    mStreamDoneEvent = new AwesomeEvent(this,&AwesomePlayer::onStreamDone);

    mStreamDoneEventPending = false;

    mBufferingEvent = new AwesomeEvent(this,&AwesomePlayer::onBufferingUpdate);

    mBufferingEventPending = false;

    mVideoLagEvent = new AwesomeEvent(this,&AwesomePlayer::onVideoLagUpdate);

    mVideoEventPending = false;

 

    mCheckAudioStatusEvent = new AwesomeEvent(

            this,&AwesomePlayer::onCheckAudioStatus);

 

    mAudioStatusEventPending = false;

 

    reset();

}

 

 

voidAwesomePlayer::reset() {

    Mutex::Autolock autoLock(mLock);

    reset_l();

}

 

voidAwesomePlayer::reset_l() {

    mVideoRenderingStarted = false;

    mActiveAudioTrackIndex = -1;

    mDisplayWidth = 0;

    mDisplayHeight = 0;

 

    if (mDecryptHandle != NULL) {

           mDrmManagerClient->setPlaybackStatus(mDecryptHandle,

                    Playback::STOP, 0);

            mDecryptHandle = NULL;

            mDrmManagerClient = NULL;

    }

 

    if (mFlags & PLAYING) {

        uint32_t params =IMediaPlayerService::kBatteryDataTrackDecoder;

        if ((mAudioSource != NULL) &&(mAudioSource != mAudioTrack)) {

            params |=IMediaPlayerService::kBatteryDataTrackAudio;

        }

        if (mVideoSource != NULL) {

            params |=IMediaPlayerService::kBatteryDataTrackVideo;

        }

        addBatteryData(params);

    }

 

    if (mFlags & PREPARING) {

        modifyFlags(PREPARE_CANCELLED, SET);

        if (mConnectingDataSource != NULL) {

            ALOGI("interrupting theconnection process");

           mConnectingDataSource->disconnect();

        }

 

        if (mFlags & PREPARING_CONNECTED) {

            // We are basically done preparing,we're just buffering

            // enough data to start playback,we can safely interrupt that.

            finishAsyncPrepare_l();

        }

    }

 

    while (mFlags & PREPARING) {

        mPreparedCondition.wait(mLock);

    }

 

    cancelPlayerEvents();

 

    mWVMExtractor.clear();

    mCachedSource.clear();

    mAudioTrack.clear();

    mVideoTrack.clear();

    mExtractor.clear();

 

    // Shutdown audio first, so that therespone to the reset request

    // appears to happen instantaneously as faras the user is concerned

    // If we did this later, audio wouldcontinue playing while we

    // shutdown the video-related resources andthe player appear to

    // not be as responsive to a reset request.

    if ((mAudioPlayer == NULL || !(mFlags &AUDIOPLAYER_STARTED))

            && mAudioSource != NULL) {

        // If we had an audio player, it wouldhave effectively

        // taken possession of the audio sourceand stopped it when

        // _it_ is stopped. Otherwise this isstill our responsibility.

        mAudioSource->stop();

    }

    mAudioSource.clear();

 

    mTimeSource = NULL;

 

    delete mAudioPlayer;

    mAudioPlayer = NULL;

 

    if (mTextDriver != NULL) {

        delete mTextDriver;

        mTextDriver = NULL;

    }

 

    mVideoRenderer.clear();

 

    if (mVideoSource != NULL) {

        shutdownVideoDecoder_l();

    }

 

    mDurationUs = -1;

    modifyFlags(0, ASSIGN);

    mExtractorFlags = 0;

    mTimeSourceDeltaUs = 0;

    mVideoTimeUs = 0;

 

    mSeeking = NO_SEEK;

    mSeekNotificationSent = true;

    mSeekTimeUs = 0;

 

    mUri.setTo("");

    mUriHeaders.clear();

 

    mFileSource.clear();

 

    mBitrate = -1;

    mLastVideoTimeUs = -1;

 

    {

        Mutex::Autolock autoLock(mStatsLock);

        mStats.mFd = -1;

        mStats.mURI = String8();

        mStats.mBitrate = -1;

        mStats.mAudioTrackIndex = -1;

        mStats.mVideoTrackIndex = -1;

        mStats.mNumVideoFramesDecoded = 0;

        mStats.mNumVideoFramesDropped = 0;

        mStats.mVideoWidth = -1;

        mStats.mVideoHeight = -1;

        mStats.mFlags = 0;

        mStats.mTracks.clear();

    }

 

    mWatchForAudioSeekComplete = false;

    mWatchForAudioEOS = false;

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值