ffplayer——主线程StartPlayer

这里写图片描述
主线程StartPlayer(prepare prepareAsync)
prepare方法是将资源同步缓存到内存中,一般加载本地较小的资源可以用这个,如果是较大的资源或者网络资源建议使用prepareAsync方法,异步加载。
在异步中,若想让资源start()起来,必须设置监听,否则拿不到这个资源。如果让线程睡眠一段时间,则可以取得资源,因为这个时候,异步线程已经取得资源,但不可能使用线程睡眠的方式来获取资源啊.所以就需要设置监听事件setOnPreparedListener()来通知MediaPlayer资源已经获取到了,然后实现onPrepared(MediaPlayermp)方法.在里面启动MediaPlayer。
http://blog.csdn.net/qq_24223073/article/details/69315856

status_t FFMPlayer::prepareAsync()
{//从initialized和stopped状态进入prepared状态
    int status = getCurrentStatus();//得到mCurrentState
    if ((status == PLAYER_INITIALIZED) || (status == PLAYER_STOPPED)) {
        status = doPrepareAsync();
        ALOGD("prepareAsync ok");
        return status;
    }
    return UNKNOWN_ERROR;
}

status_t FFMPlayer::doPrepareAsync()
{
    if (mCancelThreadStatus >= 0) {//若mCancelThreadStatus,需要等待线程mCancelThread结束(该线程在stop_l中创建)
        if (pthread_join(mCancelThread, NULL) != 0) {
            ALOGE("doPrepareAsync:Couldn't cancel CancelThread");
        }
        mCancelThreadStatus = -1;
    }
    setCurrentStatus(PLAYER_PREPARING); //将mCurrentState设置为PLAYER_PREPARING
    mPlayer_sistarted = true;
    mReadThreadStatus = pthread_create(&mReadThread, NULL, StartPlayer, (void*)this);  //创建线程StartPlayer
    mReadThreadCond.wait(mReadThreadLock);
    return NO_ERROR;
}

void* FFMPlayer::StartPlayer(void* ptr)
{
    //dump information for ffplayer
    rkffplay_info::getInstance()->dumpFFPlayerInfo();//获得ffplayer的一些消息
    prctl(PR_SET_NAME, (unsigned long)"FFParser", 0, 0, 0);
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_URGENT_DISPLAY);
    FFMPlayer *player = (FFMPlayer *)ptr;
    //1.prepare
    if ( player->prepareDataSource(ptr) != NO_ERROR) {//会调用 AVFormatContext *s = getContext();  AVFormatContext为ffmpeg中的
        ALOGD("startPlayer(): prepareDataSource error");
        player->setCurrentStatus(PLAYER_STATE_ERROR);
        player->notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, UNKNOWN_ERROR);
        return NULL;
    }
    //2.readpacket
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
    player->decodeMovie(ptr);
    return NULL;
}

status_t FFMPlayer::doPrepareDataSource(const char *url, const char *fileurl)
{
    AVFormatContext *s = getContext();//AVFormatContext为ffmpeg中的
    enqueueMessage(new MessagePrepare(NULL, NULL));//创建一个类型CMD_PREPARE的meg,会调用doPrepare()
}

void FFMPlayer::decodeMovie(void* ptr)
{
    //set the current thread to foreground
    setFgCurrentThread();

    while (mPlayer_sistarted) {
        if ((getCurrentStatus() == PLAYER_DECODED)
                || (getCurrentStatus() == PLAYER_STOPPED)
                || (getCurrentStatus() == PLAYER_STATE_ERROR)
                || (getCurrentStatus() == PLAYER_IDLE)) {
            break;
        }
        {
            timeUs = readpacket();//主要内容
        }
        if (timeUs > 0) {
            usleep(timeUs);
        }
    }
}

int64_t FFMPlayer::readpacket()
{
    AVFormatContext* s = getContext();//得到AVFormatContext* FFMediaSource::mContext;

    //1. Check end of stream
    if (isPlayerEndOfStream() && (!isSeeking())) {
        return completePlay();
    }
    //2. Do seek operation
    if (isSeeking()&& !mHaveSeek) {
        int result = doSeek();
        if (result < 0) {
            return 20;
        }
    }
    //3. Check Buffer Size
    cret = checkDecoderBuffer();
    if (cret>0) return cret;
    return doReadAVFrame(s);
}

int64_t FFMPlayer::doReadAVFrame(AVFormatContext* s)
{
    AVPacket pPacket;
    int ret = 0;
    int64_t ret_time = readAVPacket(&pPacket, ret);
    AVStream* stream_audio = getAudioStream();
    AVStream* stream_video = getVideoStream();//得到AVFormatContext* s->streams[strmIdx];
    // Is this a packet from the video stream?
    if (isVideoStream(pPacket.stream_index)) {
        //enqueue video packet
        mReadVideoCounter ++;
//主要调用了mDecoderVideo->enqueue(&pPacket);   将pPacket放入PacketQueue* mQueue;
        enqueueRet = enqueueVideoPacket(s, pPacket, stream_video);
        if (enqueueRet >= 0) return enqueueRet;
    } else if (isAudioStream(pPacket.stream_index)) {
        //enqueue audio packet
        mReadAudioCounter ++;
        enqueueRet = enqueueAudioPacket(s, pPacket, stream_audio);
        if (enqueueRet>=0) return enqueueRet;
    } else if (isSubtitleStream(pPacket.stream_index)) {
        //enqueue subtitle packet
        if (mDecoderSub) {
            mDecoderSub->enqueue(&pPacket);
        } else {
            av_free_packet(&pPacket);
            return 20;
        }
    } else {
        // Free the packet that was allocated by av_read_frame
        pushOtherPacket(&pPacket);
        av_free_packet(&pPacket);
    }
    return 20;
}

int64_t FFMediaSource::readAVPacket(AVPacket *pkt, int &ret)
{
    if (mContext) {   
            ret = av_read_frame(mContext, pkt); //es   //avpacket es==>pkt->data pts==>pkt->pts dts==>pkt->dts
                                                       // keyframe ==> pkt->key_frame
                                                                         // pkt videostre //黑盒子   链接到ffmpeg中
    }
    return -1;
}

pkt是一帧的数据,已进行过分帧了。mpp中的分帧没有必要。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值