ffmpeg+sdl播放H264/H265文件

一、概述

  上一篇写了使用windows录屏+ffmpeg生成H264/H265数据,并存储成文件。本节就写下如何使用ffmpeg+sdl播放H264/H265裸数据文件。

  界面如下:

  1.播放前界面  

  

   2.播放后界面

  

 

二、代码示例

void H264OrH265FilePlayWindow::Draw()
{

    //找打解码器
    auto codec = avcodec_find_decoder((AVCodecID)codecId);
    if (!codec)
    {
        qDebug() << "无法找到解码器->avcodec_find_decoder";
        return;
    }
    //创建解码器上下文
    auto codecCtx = avcodec_alloc_context3(codec);
    if (!codecCtx)
    {
        qDebug() << "解码器山下文创建失败->avcodec_alloc_context3";
        return;
    }
    codecCtx->thread_count = 16;//16线程解码
    //打开解码器
    int ret = avcodec_open2(codecCtx, NULL, NULL);
    if (ret != 0)
    {
        qDebug() << "解码器打开失败->avcodec_open2";
        return;
    }

    //创建文件分割上下文
    auto parser = av_parser_init(codecId);
    //申请packet空间
    auto pkt = av_packet_alloc();
    //申请frame空间
    auto frame = av_frame_alloc();
    while (isRunning)
    {
        bool flag = reader->Read((char*)inbuf, sizeof(inbuf));
        if (!flag)
        {
            qDebug() << "文件读取结束";
            break;
        }
        int data_size = reader->getBytesCount();
        if (data_size <= 0) {
            qDebug() << "没有读到数据退出循环";
            break;
        }
        auto data = inbuf;
        while (data_size > 0) //一次有多帧数据
        {
            //通过0001 截断输出到AVPacket 返回帧大小
            int ret = av_parser_parse2(parser, codecCtx,
                &pkt->data, &pkt->size, //输出
                data, data_size,        //输入
                AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0
            );
            data += ret;
            data_size -= ret; //已处理
            if (pkt->size)
            {
                //cout << pkt->size << " "<<flush;
                //发送packet到解码线程
                ret = avcodec_send_packet(codecCtx, pkt);
                if (ret < 0)
                    break;
                //获取多帧解码数据
                while (ret >= 0)
                {
                    //每次回调用av_frame_unref 
                    ret = avcodec_receive_frame(codecCtx, frame);
                    if (ret < 0)
                        break;
                    qDebug() << frame->format << " ";
                    renderView->DrawFrame(frame);
                    std::this_thread::sleep_for(std::chrono::milliseconds(1000/25));
                }
            }
        }
        
    }
    ///取出缓存数据
    ret = avcodec_send_packet(codecCtx, NULL);
    while (ret >= 0)
    {
        ret = avcodec_receive_frame(codecCtx, frame);
        if (ret < 0)
            break;
        qDebug() << frame->format << "-";
    }

    av_parser_close(parser);
    avcodec_free_context(&codecCtx);
    av_frame_free(&frame);
    av_packet_free(&pkt);
}

 

posted on 2025-05-22 16:59  飘杨......  阅读(69)  评论(0)    收藏  举报