ffplayer——消息线程sched_thread(setDataSource)

本文详细探讨了FFmpeg中ffplayer的消息线程`sched_thread`及其在设置数据源`setDataSource`时的角色。通过分析源码,解释了线程如何处理解码和播放过程中的消息调度,以及如何加载和处理不同类型的数据源,为理解和优化FFmpeg播放器的性能提供关键洞见。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里写图片描述

status_t FFMPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{   
    startMessageQueue();//消息队列

    mFd = fd;//int FFMPlayer::mFd;
    mUri = &path[0];
    mOffsetLength = length;
    mOffsetPosition = offset;
    int status = getCurrentStatus();  
    if (status == PLAYER_IDLE) {
//首先新建了一个类型为CMD_CURRENTSTATUS的meg,当前状态设置为PLAYER_INITIALIZED 
//然后将该meg放入Vector <RkMessage*>  RkMessageQueue::mQueue
        enqueueMessage(new MessageCurrentStatus(NULL, PLAYER_INITIALIZED));
        return NO_ERROR;
    } else {
        return UNKNOWN_ERROR;
    }
}

//1.以下为startMessageQueue()

//1.1启动mMessageQ,若没有mMessageQ,则新建,若有,则调用start()    sp<RkMessageQueue> FFMPlayer::mMessageQ;
void FFMPlayer::startMessageQueue()
{//sp<RkMessageQueue>  FFMplayer::mMessageQ;
    if (mMessageQ == NULL || mMessageQ.get() == NULL) {
        mMessageQ = new RkMessageQueue(this);
    }
    if (mMessageQ.get() != NULL && !mMessageQ->isRunning()) {
        mMessageQ->start();
    }
}

//1.2主要为创建sched_thread线程
int RkMessageQueue::start()
{
    if (mExcuting) {
        return NO_ERROR;
    }
    mExcuting = true;
    mThreadStatus = pthread_create(&mQueueThread, NULL, sched_thread, (void *)this);//创建sched_thread线程
    mThreadCond.wait(mLock);
    ALOGD("start:create thread ok,mThreadStatus=%d",mThreadStatus);
    return mThreadStatus;
}


//1.3以下是对线程sched_thread
void* RkMessageQueue::sched_thread(void* cookie)
{
    RkMessageQueue *QueueManager = (RkMessageQueue *)cookie;
    return QueueManager->run();
}

//1.4从mMessageQ中的mQueue中得到mCurMessage
void* RkMessageQueue::run()
{//从mQueue得到一个msg到mCurMessage
    while (mExcuting) {
        {
            if (mQueue.empty()) //Vector<RkMessage*>  RkMessageQueue::mQueue;       
            ALOGD("deliverMessage ");
            mCurMessage = mQueue.top();//mCurMessage为mQueue的队首
            mQueue.pop();//mQueue出队列,得到mCurMessage
        }

        ALOGD("run : dequeueMessage Message %d", mCurMessage->getMessageType());
        ret = dequeueMessage(mCurMessage);//会调用onRkMessageReceived
        ALOGD("run : dequeueMessage Message %d OK", mCurMessage->getMessageType());
        /* notice: free the Message there! */
        mCurMessage->setMessageRet(ret);
        Messagecomplete(mCurMessage);
        ALOGD("run : Message %d complete", mCurMessage->getMessageType());
        delete mCurMessage;
        mCurMessage= NULL;
    }//end while

    ALOGD("signal thread out");
    //notify the desctruct: the thread is out
    {
        Mutex::Autolock l(mLock);
        mThreadCond.signal();
    }
    ALOGD("sched_thread out");
    return 0;
}


//2.以下为enqueueMessage()

//2.1新建一个meg
MessageCurrentStatus(complete_cb cb,int status):RkMessage(CMD_CURRENTSTATUS,cb),mCurrentStatus(status) {};
RkMessage(int t,complete_cb cb,void* userdata=0):mType(t),mCb(cb),mUserData(userdata),mWhenUs(0) {}

int FFMPlayer::enqueueMessage(RkMessage* msg)
{
    if (mMessageQ.get()) {
        return mMessageQ->enqueueMessage(msg);
    } else {
        if(msg != NULL) {
            delete msg;
            msg = NULL;
        }
        ALOGD("Message queue is Null");
    }
    return -1;
}

//2.2将上一步新建的meg放入mQueue
int RkMessageQueue::enqueueMessage(RkMessage* meg)
{//meg进入mQueue
    meg->setMessageId(mMessageId++);
    /* set the default callback for sync cmd */
    if (NULL == meg->getMessageCb()) {
        meg->setMessageCb(RkMessageQueue::syncComplete);
        sync = true;
    }

    ALOGD("enqueueMessage:****1");
    {
        Mutex::Autolock l(mLock);
        // after destroy operation is in queue,do not deal any operation.maybe command is enqueued
        // from hiPlayerEventCallback thread
        if (mIsPlayerDestroyed) {//删除meg
            ALOGE("Player is destroyed,do not deal any operation,operation is type %d", meg->getMessageType());
            delete meg;
            meg = NULL;
            return NO_ERROR;
        }

        ALOGD("enqueueMessage:****2");
        if (RkMessage::CMD_DESTROYPLAYER == meg->getMessageType()) {//meg的类型为CMD_DESTROYPLAYER时
            ALOGE("enque destroy player cmd");
            mIsPlayerDestroyed = true;
        }

        ALOGD("enqueueMessage:****3");
        mQueue.insertAt(meg, 0);//meg进入mQueue
        /*wake up sched_thread */
        if (mQueue.size() >= 1) {
            ALOGD("enqueueMessage:Message 1,set signal");
            mThreadCond.signal();
        }
        /* sync cmd, need wait */
        if (sync) {
            ALOGD("enqueueMessage:sync wait");
            mSyncCond.wait(mLock);
            ALOGD("enqueueMessage:sync wait ok");
            return mSyncStatus;
        }
    }
    return NO_ERROR;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值