ffmpeg视频解码原理和实战-(4)硬件加速解码并每秒打印帧率

源文件:

#include <iostream>
#include <fstream>
#include <string>
#include"xsdl.h"
using namespace std;
extern "C" { //指定函数是c语言函数,函数名不包含重载标注
//引用ffmpeg头文件
#include <libavcodec/avcodec.h>
}
//预处理指令导入库
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
int main(int argc, char* argv[])
{
    auto view = XVideoView::Create();
    //1 分割h264 存入AVPacket
    
    string filename = "test.h264";
    ifstream ifs(filename, ios::binary);
    if (!ifs)return -1;
    unsigned char inbuf[4096] = { 0 };//用于存储h264编码流
    AVCodecID codec_id = AV_CODEC_ID_H264;

    //1 找解码器
    auto codec = avcodec_find_decoder(codec_id);

    //2 创建解码器上下文
    auto c = avcodec_alloc_context3(codec);


    //硬件加速格式 DXVA2
    auto hw_type = AV_HWDEVICE_TYPE_DXVA2;
    
    /// 打印所有支持的硬件加速方式
    for (int i = 0;; i++)
    {
        auto config = avcodec_get_hw_config(codec, i);
        if (!config)break;
        if (config->device_type)
            cout << av_hwdevice_get_type_name(config->device_type) << endl;
    }
    //初始化硬件加速上下文
    AVBufferRef* hw_ctx = nullptr;
    av_hwdevice_ctx_create(&hw_ctx, hw_type, NULL, NULL, 0);
    //设定硬件GPU加速
    c->hw_device_ctx = av_buffer_ref(hw_ctx);
    c->thread_count = 16;



    //3 打开上下文
    avcodec_open2(c, NULL, NULL);

    //分割上下文
    auto parser = av_parser_init(codec_id);
    auto pkt = av_packet_alloc();
    auto frame = av_frame_alloc();
    auto begin = NowMs();
    int count = 0;//解码统计
    bool is_init_win = false;
    while (!ifs.eof())
    {
        ifs.read((char*)inbuf, sizeof(inbuf));//将h264编码的流读入inbuf中,一次读4096
        int data_size = ifs.gcount();// 读取的字节数,inbuf中的字节数
        if (data_size <= 0)break;
        if (ifs.eof())
        {
            ifs.clear();
            ifs.seekg(0, ios::beg);
        }
        auto data = inbuf;
        while (data_size > 0) //一次有多帧数据
        {
         
            //通过0001 截断输出到AVPacket 返回帧大小
            int ret = av_parser_parse2(parser, c,
                &pkt->data, &pkt->size, //截断后输出到AVpacket的data中
                data, data_size,        //h264编码流,待处理数据
                AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0
            );//返回消耗的输入数据字节数ret。如果所有输入数据都被消耗,则返回值等于 buf_size。如果解析过程中出现错误,则返回负数。
            data += ret;//data指针向前移动 ret个字节,继续处理inbuf未处理的数据
            data_size -= ret; //待处理的数据大小
            if (pkt->size)
            {
                //cout << pkt->size << " "<<flush;
                //发送packet到解码线程
                ret = avcodec_send_packet(c, pkt);//把avpacket给解码器进行解码
                if (ret < 0)
                    break;
                //获取多帧解码数据
                while (ret >= 0)
                {
                    //每次回调用av_frame_unref 
                    ret = avcodec_receive_frame(c, frame);//拿到解码后的数据存储到frame中
                    if (ret < 0)
                        break;
                   // cout << frame->format << " " << flush;
                    //
                 /// 第一帧初始化窗口
                    if (!is_init_win)
                    {
                        is_init_win = true;
                       // view->Init(frame->width, frame->height, (XVideoView::Format)frame->format);
                    }
                   // view->DrawFrame(frame);

                    count++;//每有一帧被渲染count+1
                    auto cur = NowMs();
                    if (cur - begin >= 1000)// 1秒钟计算一次
                    {
                        cout << "\nfps = " << count  << endl;
                        count = 0;
                        begin = cur;
                    }
                }
            }
        }
    }
    ///取出缓存数据,防止丢帧
    int ret = avcodec_send_packet(c, NULL);
    while (ret >= 0)
    {
        ret = avcodec_receive_frame(c, frame);
        if (ret < 0)
            break;
        cout << frame->format << "-" << flush;
    }
    av_parser_close(parser);
    avcodec_free_context(&c);
    av_frame_free(&frame);
    av_packet_free(&pkt);

    getchar();
    return 0;
}

运行结果:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值