欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android万能视频播放器02-获取视频AVFrame的帧数据

程序员文章站 2022-07-01 23:26:34
...

解码

解码步骤:

步骤一:

AVPacket *avPacket = av_packet_alloc();
queue->getAvpacket(avPacket);
avcodec_send_packet(avCodecContext, avPacket);

步骤二:

AVFrame *avFrame = av_frame_alloc();
avcodec_receive_frame(avCodecContext, avFrame);

将前面得到的AVPacket发送到解码器进行解码:

void *playVideo(void *data){
    JfVideo *video = (JfVideo *)data;

    while (video->playStatus != NULL && !video->playStatus->exit){
        if (video->playStatus->seeking){
            av_usleep(1000 * 100);
            continue;
        }
        if (video->queue->getQueueSize() == 0){//加载状态
            if (!video->playStatus->loading){
                video->playStatus->loading = true;
                video->callJava->onCallLoading(CHILD_THREAD, true);
            }
            av_usleep(1000 * 100);
            continue;
        } else {
            if (video->playStatus->loading){
                video->playStatus->loading = false;
                video->callJava->onCallLoading(CHILD_THREAD, false);
            }
        }

        /*AVPacket *avPacket = av_packet_alloc();
        if (video->queue->getAVPacket(avPacket) == 0){
            //解码渲染
            LOGD("线程中获取视频AVPacket");
        }
        av_packet_free(&avPacket);//AVPacket中的第一个参数,就是引用,减到0才真正释放
        av_free(avPacket);
        avPacket = NULL;*/

        AVPacket *avPacket = av_packet_alloc();
        if (video->queue->getAVPacket(avPacket) != 0){

            av_packet_free(&avPacket);//AVPacket中的第一个参数,就是引用,减到0才真正释放
            av_free(avPacket);
            avPacket = NULL;
            continue;
        }
        
        if (avcodec_send_packet(video->pVCodecCtx,avPacket) != 0){

            av_packet_free(&avPacket);//AVPacket中的第一个参数,就是引用,减到0才真正释放
            av_free(avPacket);
            avPacket = NULL;
            continue;
        }
        AVFrame *avFrame = av_frame_alloc();
        if (avcodec_receive_frame(video->pVCodecCtx,avFrame) != 0){
            av_frame_free(&avFrame);
            av_free(avFrame);
            avFrame = NULL;
            av_packet_free(&avPacket);//AVPacket中的第一个参数,就是引用,减到0才真正释放
            av_free(avPacket);
            avPacket = NULL;
            continue;
        }

        if (LOG_DEBUG){
            LOGD("子线程解码一个AVFrame成功");
        }

        av_frame_free(&avFrame);
        av_free(avFrame);
        avFrame = NULL;
        av_packet_free(&avPacket);//AVPacket中的第一个参数,就是引用,减到0才真正释放
        av_free(avPacket);
        avPacket = NULL;
    }
    pthread_exit(&video->thread_play);
}

释放视频相关的资源文件

释放步骤

1、释放队列

delete(queue);

2、释放解码器上下文

avcodec_close(avCodecContext);
avcodec_free_context(&avCodecContext);

实现

void JfVideo::release() {
    if (queue != NULL){
        delete(queue);
        queue = NULL;
    }

    if (pVCodecCtx != NULL){
        avcodec_close(pVCodecCtx);
        avcodec_free_context(&pVCodecCtx);
        pVCodecCtx = NULL;
    }

    if (playStatus != NULL){
        playStatus = NULL;
    }

    if (callJava != NULL){
        callJava = NULL;
    }
}

void JfFFmpeg::release() 方法中调用!