目录

1、转码流程分析

2、创建一个类专门用来转码

.h文件

构造函数

打开对应的码流数据

转码得到最终的封装格式

主函数测试

转码运行结果


1、转码流程分析

/*转码流程分析:
* 1、注册组件
* 2、打开视频文件
* 3、查找视频流
* 4、找到了视频流,猜测需要的封装格式是否存在
* 5、打开目标文件流
* 6、新建目标视频流
* 7、编码器参数设置
* 8、开始写入头部信息
* 9、一帧一帧的读取视频码流数据,并进行转码
* 10、转码结束写入尾巴帧,结束本次的转码,并把需要释放的资源回收
* */

2、创建一个类专门用来转码

.h文件

#include <QString>extern "C"
{#include <libavcodec/avcodec.h>#include <libavdevice/avdevice.h>#include <libavformat/avformat.h>#include <libavutil/avconfig.h>#include <libswscale/swscale.h>#include <libswresample/swresample.h>
}class transCoding
{
public:transCoding();//打开对应的码流数据void openH264file(QString fileName);//转码得到最终的封装格式:格式是不固定的void coverTovideo(QString fileName);private:AVStream *newStream;//新建视频流AVOutputFormat *avoutput_format;//输出封装格式上下文结构体int avcodec_index;//视频流所在输入视频的AVStream []数组的索引AVFormatContext *in_avformat_context,*out_avformat_context;//封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息};

构造函数

transCoding::transCoding()
{//注册所有组件av_register_all();in_avformat_context = avformat_alloc_context();out_avformat_context = avformat_alloc_context();
}

打开对应的码流数据

void transCoding::openH264file(QString fileName)
{//打开视频文件int res = avformat_open_input(&in_avformat_context, fileName.toStdString().c_str(), nullptr, nullptr);if (res != 0){qDebug()<<"打开失败";exit(0);}else{qDebug()<<"打开成功!";qDebug()<<fileName;}this->avcodec_index = -1;res = avformat_find_stream_info(in_avformat_context, NULL);//return >=0 if OKif (res < 0){qDebug()<<"获取文件信息失败";exit(0);}else{qDebug()<<"获取文件信息成功!";qDebug()<<"视频时长为:"<<in_avformat_context->duration/1000000.0<<"秒";qDebug()<<"视频平均混合码率为:"<<in_avformat_context->bit_rate/1000<<"Kbps";qDebug()<<"————获取文件视频流信息————";//nb_streams :输入视频的AVStream 个数for (int i = 0; i < in_avformat_context->nb_streams; i++)//遍历流{//找到视频流if (in_avformat_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){this->avcodec_index = i;qDebug()<<"获取文件视频流信息成功!";break;}}if (-1 == this->avcodec_index){qDebug()<<"没有找到视频流";exit(0);}else{qDebug()<<"找到视频流";}}qDebug()<<"输入准备完成!";
}

转码得到最终的封装格式

可以转码生成mp4、mov、flv、avi等视频格式。

void transCoding::coverTovideo(QString fileName)
{qDebug()<<"猜测编码器";//猜测编码器//猜测avoutput_format = av_guess_format(nullptr, fileName.toStdString().c_str(), nullptr);//判断有没有匹配到格式if(avoutput_format == nullptr){qDebug()<<"没有匹配到!";return;}else{qDebug()<<"匹配到!";}//输出封装格式文件的格式设置out_avformat_context->oformat = avoutput_format;//打开视频流/*参数一:AVIOContent:输入输出上下文对象参数二:文件流的路径参数三:文件打开的方式,以写入的方式打开@return >= 0 in case of success, a negative value corresponding to an*/int res = avio_open(&out_avformat_context->pb, fileName.toStdString().c_str(), AVIO_FLAG_WRITE);if(res < 0){qDebug()<<"avio_open error!";return;}else{qDebug()<<"avio_open success!";}//新建视频流 参数一:保存视频信息的结构体newStream = avformat_new_stream(out_avformat_context, nullptr);if(newStream == nullptr){qDebug()<<"新建视频流失败!";return;}else{qDebug()<<"新建视频流成功!";}//编码器参数的设置res = avcodec_parameters_copy(newStream->codecpar, in_avformat_context->streams[avcodec_index]->codecpar);if(res < 0){qDebug()<<"copy error!";return;}else{qDebug()<<"copy success!";}newStream->codecpar->codec_tag = 0;qDebug()<<"————写入头部信息————";//写入头部信息res = avformat_write_header(out_avformat_context, nullptr);if(res < 0){qDebug()<<"write header error!";return;}else{qDebug()<<"write header success!";}//一帧一帧读取码流数据,转码AVPacket *pkt = nullptr;pkt = (AVPacket *)malloc(sizeof(AVPacket));int size = newStream->codecpar->width*newStream->codecpar->height;av_new_packet(pkt, size);int frame_count = 0;qDebug()<<"————循环去读一帧一帧的数据————";while(av_read_frame(in_avformat_context, pkt) == 0){if(pkt->stream_index == avcodec_index){frame_count++;//转码//查看是否有做时间基的设置if(pkt->pts == AV_NOPTS_VALUE)//没有设置{//qDebug()<<"时间基的转换";//时间基的转换AVRational time_base1 = in_avformat_context->streams[avcodec_index]->time_base;//计算两帧码流数据之间的长度int64_t duration = (double)AV_TIME_BASE/av_q2d(in_avformat_context->streams[avcodec_index]->r_frame_rate);//计算显示的时间基(当前帧数*两帧之间的长度)/(输入时间基*AV_TIME_BASE)pkt->pts = (double)(frame_count * duration)/(double)(av_q2d(time_base1) * AV_TIME_BASE);pkt->dts = pkt->pts;//没有B帧pkt->duration = duration/(double)(av_q2d(time_base1) * AV_TIME_BASE);}else if(pkt->pts < pkt->dts){continue;}pkt->pts = av_rescale_q_rnd(pkt->pts, in_avformat_context->streams[avcodec_index]->time_base,newStream->time_base, (AVRounding)(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));pkt->dts = av_rescale_q_rnd(pkt->dts, in_avformat_context->streams[avcodec_index]->time_base,newStream->time_base, (AVRounding)(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));pkt->duration = av_rescale_q(pkt->duration, in_avformat_context->streams[avcodec_index]->time_base, newStream->time_base);//准备写入pkt->pos = -1;pkt->flags |= AV_PKT_FLAG_KEY;pkt->stream_index = 0;av_interleaved_write_frame(out_avformat_context, pkt);}//清空av_packet_unref(pkt);}//写入尾巴帧qDebug()<<"写入尾巴帧";av_write_trailer(out_avformat_context);//关闭编码器avcodec_close(out_avformat_context->streams[avcodec_index]->codec);//删掉编码器av_freep(out_avformat_context->streams[avcodec_index]->codec);//关闭各种流qDebug()<<"关闭各种流";avio_close(out_avformat_context->pb);av_free(out_avformat_context);avformat_close_input(&in_avformat_context);av_free(in_avformat_context);qDebug()<<"释放包";//av_packet_free(&pkt);qDebug()<<"转码成功";
}

主函数测试

工程目录下的fileOut文件夹下有个2022_2_7_0_41.h264文件,通过转码生成test.mp4。

#include "transcoding.h"
#include <QApplication>
#include <QString>int main(int argc, char *argv[])
{QApplication a(argc, argv);transCoding transCode;transCode.openH264file(QString("fileOut/2022_2_7_0_41.h264"));//打开视频文件transCode.coverTovideo(QString("fileOut/test.mp4"));//转码生成对应的封装格式视频return a.exec();
}

也可以将mp4格式的视频转换成其他格式的视频,如下为将上一步转码得到的test.mp4转换成test.mov。

int main(int argc, char *argv[])
{QApplication a(argc, argv);transCoding transCode;transCode.openH264file(QString("fileOut/test.mp4"));//打开视频文件transCode.coverTovideo(QString("fileOut/test.mov"));//转码生成对应的封装格式视频return a.exec();
}

转码运行结果

原创不易,转载请标明出处。

Qt结合FFmpeg转码码流数据(h264)生成不同视频格式(mp4、mov、flv、avi等)相关推荐

  1. 开发游戏陪玩app源码前,需要掌握的音视频格式知识

    为了让用户拥有更好的聊天体验,游戏陪玩app源码在开发时,采用了音视频连麦技术,通过语音或视频的方式快速拉近彼此的距离,哪怕在游戏过程中也不耽误彼此聊天.而且音视频连麦技术的应用还为游戏陪玩app源码 ...

  2. Node.js脚本项目合集(一):Node.js+FFmpeg实现批量从B站导出离线缓存视频到mp4格式,mp4转mp3,实现听歌自由

    Node.js脚本项目合集(一):Node.js+FFmpeg实现批量从B站导出离线缓存视频到mp4格式,mp4转mp3,实现听歌自由 前言 一.准备工作以及介绍 1.什么是FFmpeg 2.FFmp ...

  3. 利用FFmpeg实现录屏、直播推流、音频视频格式转换、剪裁等功能

    一.FFmpeg简介. 二.FFmpeg常用参数及命令. 三.FFmpeg在Unity 3D中的使用. 1.FFmpeg 录屏. 2.FFmpeg 推流. 3.FFmpeg 其他功能简述. 一.FFm ...

  4. Qt基于FFmpeg播放本地 H.264(H264)文件

    最近在弄H264的硬件编解码,基于DM3730,但是为了调试方便,在小红帽上用FFmpeg实现了H264的软件编解码.现在弄了一个Windows的例子,给需要的同学参考一下,如果大家觉得有帮助,可以小 ...

  5. PCM裸流数据的16进制格式以及左右声道分离c语言程序

    前言 本文讲解PCM裸流数据的存储格式. 本文PCM音频参数 声道数: 2采样位数: little endian signed 16 bits,小端有符号字 = short,表示范围 -32768~3 ...

  6. 使用 ffmpeg 转换视频格式 mp4 webm

    ffmpeg 是 *nix 系统下最流行的音视频处理库,功能强大,并且提供了丰富的终端命令,实是日常视频处理的一大利器! 实例 flac 格式转 mp3 音频格式转换非常简单:. ffmpeg -i ...

  7. 使用 FFmpeg 批量转换视频格式 mp4转ts(bat命令行)

    第一步:官网下载 FFmpeg 打开 http://ffmpeg.org/ 点 download 按钮,找到自己的系统对应格式(比如我的Windows 64位下载之后是个压缩包ffmpeg-20181 ...

  8. php二维码存放json数据_PHP生成及获取JSON文件的方法

    本文实例讲述了PHP生成及获取JSON文件的方法.分享给大家供大家参考,具体如下: 首先定义一个数组,然后遍历数据表,把相应的数据放到数组中,最后通过json_encode()转化数组 json_en ...

  9. ffmpeg C语言实现视频从MP4转成AVI

    这是一个通过c代码实现视频格式的转换. #include <libavutil/log.h> #include <libavformat/avformat.h> #includ ...

最新文章

  1. 基于 HTML5 的工业互联网云平台监控机房 U 位
  2. 《Java并发编程实践》学习笔记之一:基础知识
  3. python中的reduce、lambda函数
  4. phpmyadmin忘记mysql密码_忘记phpmyadmin登录密码怎么办
  5. Android WebView获取网页中JavaScript弹框内容
  6. Gnosis发起提案就是否推出Gnosis协议v2版本展开讨论
  7. servlet精华讲解
  8. python爬虫——批量爬取百度图片
  9. iOS 面试题整理(带答案)二
  10. 2023年计算机网络考研真题详解
  11. mysql 查看校对集,MySQL校对集
  12. 在unity中,模型自动旋转
  13. 2016年安防上市公司年报披露情况
  14. CSDN上传资源无法设置积分了吗
  15. 产品经理也能动手实践的AI(四)- 多标签识别,图像分割
  16. 《IT老外在中国》第29期:这位美籍华裔兜兜转转又回到了心心念念的故乡
  17. JVM系列之JDK、JRE、JVM的区别是什么?(二)
  18. linux主分区扩容
  19. 股权和更高的薪资应该选那个呢?
  20. 个人计算机专业报告,计算机专业个人实习报告

热门文章

  1. mysql悲观锁和乐观优缺点_乐观锁、悲观锁和MVCC各是什么?各自优缺点是什么?...
  2. python orange3汉化_Python 3.5 in win10 pip install Orange3
  3. 日常工作中的几个excel小技巧
  4. Java实现经典八锁问题
  5. Apache DolphinScheduler 大数据工作流调度系统
  6. 手机云顶之弈谷歌账号换服务器,云顶之弈手游谷歌账号怎么充值 云顶之弈手游谷歌账号充值流程一览...
  7. 墨菲定律:一个参数Drop_caches导致集群数据库实例崩溃
  8. uber onsite interview reviews
  9. 【计算机图形学】深入浅出讲解光线追踪(Ray Tracing)
  10. FFmpeg常用推流命令