温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Qt ffmpeg解码处理方法是什么

发布时间:2021-12-15 10:33:06 来源:亿速云 阅读:218 作者:iii 栏目:互联网科技

本篇内容主要讲解“Qt ffmpeg解码处理方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Qt ffmpeg解码处理方法是什么”吧!

一、前言

采用ffmpeg解码,是所有视频监控开发人员必备的技能,绕不过去的一个玩意,甚至可以说是所有音视频开发人员的必备技能。FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它包括了目前领先的音/视频编码库libavcodec。 FFmpeg是在 Linux 下开发出来的,但它可以在包括 Windows 在内的大多数操作系统中编译。这个项目是由 Fabrice Bellard 发起的,现在由 Michael Niedermayer 主持。可以轻易地实现多种视频格式之间的相互转换,例如可以将摄录下的视频avi等转成现在视频网站所采用的flv格式。

关于ffmpeg解码,网上搜索到的代码绝对是一大堆一大堆,而且很多都讲得很详细,解码的函数流程图非常清晰,关于ffmpeg这块的学习本人推荐雷神的博客,分析的相当细致,我在很久以前刚用Qt+ffmpeg解码的时候,参考的就是雷神的例子,当然这些demo其实在ffmpeg的开发包dev下的examples也是非常详细的,只不过没有什么分析过程,参考雷神的博客可以看到很多分析过程。

本人总结的解码过程:

  1. 注册解码库相关(av_register_all、avformat_network_init等)

  2. 初始化各种参数比如缓存大小等(av_dict_set)

  3. 打开视频流或者文件(avformat_alloc_context、avformat_open_input)

  4. 获取流信息(avformat_find_stream_info)

  5. 获取视频流并初始化视频解码器(av_find_best_stream、avcodec_find_decoder)

  6. 获取音频流并初始化音频解码器(av_find_best_stream、avcodec_find_decoder、avcodec_open2)

  7. 预分配帧内存(av_frame_alloc)

  8. 循环读取音视频帧(av_read_frame、av_packet_unref)

  9. 解码视频(avcodec_decode_video2或者avcodec_send_packet、avcodec_receive_frame)

  10. 解码音频(avcodec_decode_audio4)

  11. 处理结束释放资源(sws_freeContext、av_frame_free、av_free)

二、功能特点

  1. 多线程实时播放视频流和本地视频。

  2. 支持windows+linux+mac,支持ffmpeg3和ffmpeg4,支持32位和64位。

  3. 多线程显示图像,不卡主界面。

  4. 自动重连网络摄像头。

  5. 可设置边框大小即偏移量和边框颜色。

  6. 可设置是否绘制OSD标签即标签文本或图片和标签位置。

  7. 可设置两种OSD位置和风格。

  8. 可设置是否保存到文件以及文件名。

  9. 可直接拖曳文件到ffmpegwidget控件播放。

  10. 支持h365视频流+rtmp等常见视频流。

  11. 可暂停播放和继续播放。

  12. 支持回调模式和句柄两种模式。

  13. 支持线程读取进度等信息和事件回调两种处理模式。

  14. 自动将当前播放位置和音量大小是否静音以信号发出去。

  15. 提供接口设置播放位置和音量及设置静音。

  16. 支持存储单个视频文件和定时存储视频文件。

  17. 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。

  18. 支持qsv、dxva2、d3d11va等硬解码。

  19. 支持opengl绘制视频数据,极低CPU占用。

  20. 支持嵌入式linux。

三、效果图

Qt ffmpeg解码处理方法是什么

四、核心代码

bool FFmpegThread::init()
{
    //判断该摄像机是否能联通
    if (checkConn && isRtsp) {
        if (!checkUrl(url, checkTime)) {
            return false;
        }
    }

    //初始化参数
    this->initOption();
    //初始化输入
    if (!initInput()) {
        return false;
    }
    //初始化视频
    if (!initVideo()) {
        return false;
    }
    //初始化音频
    if (!initAudio()) {
        return false;
    }
    //初始化帧
    this->initFrame();

    //输出视频信息
    //av_dump_format(formatCtx, 0, url.toStdString().data(), 0);
    //qDebug() << TIMEMS << "init ffmpeg finsh";
    return true;
}

void FFmpegThread::initOption()
{
    //在打开码流前指定各种参数比如:探测时间/超时时间/最大延时等
    //设置缓存大小,1080p可将值调大
    av_dict_set(&options, "buffer_size", "8192000", 0);
    //以tcp方式打开,如果以udp方式打开将tcp替换为udp
    av_dict_set(&options, "rtsp_transport", transport.toLatin1().constData(), 0);
    //设置超时断开连接时间,单位微秒,3000000表示3秒
    av_dict_set(&options, "stimeout", "3000000", 0);
    //设置最大时延,单位微秒,1000000表示1秒
    av_dict_set(&options, "max_delay", "1000000", 0);
    //自动开启线程数
    av_dict_set(&options, "threads", "auto", 0);

    //设置USB摄像机分辨率
    if (url.startsWith("video")) {
        QString size = QString("%1x%2").arg(videoWidth).arg(videoHeight);
        av_dict_set(&options, "video_size", size.toLatin1().constData(), 0);
    }
}

bool FFmpegThread::initInput()
{
    //实例化格式处理上下文
    formatCtx = avformat_alloc_context();

    //先判断是否是本地设备(video=设备名字符串),打开的方式不一样
    int result = -1;
    if (url.startsWith("video")) {
#if defined(Q_OS_WIN)
        AVInputFormat *ifmt = av_find_input_format("dshow");
#elif defined(Q_OS_LINUX)
        AVInputFormat *ifmt = av_find_input_format("video4linux2");
#elif defined(Q_OS_MAC)
        AVInputFormat *ifmt = av_find_input_format("avfoundation");
#endif
        result = avformat_open_input(&formatCtx, url.toStdString().data(), ifmt, &options);
    } else {
        result = avformat_open_input(&formatCtx, url.toStdString().data(), NULL, &options);
    }

    if (result < 0) {
        qDebug() << TIMEMS << "open input error" << url;
        return false;
    }

    //释放设置参数
    if (options != NULL) {
        av_dict_free(&options);
    }

    //获取流信息
    result = avformat_find_stream_info(formatCtx, NULL);
    if (result < 0) {
        qDebug() << TIMEMS << "find stream info error";
        return false;
    }

    return true;
}

到此,相信大家对“Qt ffmpeg解码处理方法是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI