目录

1、视频解码流程分析

2、FFmpeg相关解码函数

3、创建一个类专门用来视频解码

.h文件

构造函数

打开视频文件

获取视频文件流信息并查找是否有视频流

查找视频流对应的解码器

打开解码器

循环读取每一帧并生成.h264、.yuv文件

关闭解码用到的组件

主函数测试

4、测试效果

运行效果

查看h264文件

查看yuv文件


一个视频包含有音频流、视频流、字幕流等信息,下面为视频流的解码过程以及代码实现。

1、视频解码流程分析

/*解码流程分析:* 1.注册所有组件* 2.打开文件* 3.获取文件信息* 4.看看有没有相关视频信息* 5.有视频信息,找他对应的解码器* 6.打开解码器* 7.获取一帧视频流(码流)信息* 8.读取,解码的动作* 9.得到像素数据* 重复7、8、9的动作,直到没有码流数据* 10.关闭解码器* 11.关闭视频流文件** */

2、FFmpeg相关解码函数

av_register_all():注册所有组件。avformat_open_input():打开输入视频文件。avformat_find_stream_info():获取视频文件信息。avcodec_find_decoder():查找解码器。avcodec_open2():打开解码器。av_read_frame():从输入文件读取一帧压缩数据。avcodec_decode_video2():解码一帧压缩数据。avcodec_close():关闭解码器。avformat_close_input():关闭输入视频文件。

3、创建一个类专门用来视频解码

.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 fDecode
{
public:fDecode();void openMvFile(QString mvPath);//打开视频文件void findVideoStream();//查找视频流void findDecoder();//查找对应的解码器void openDecoder();//打开解码器void readFrame();//读取每一帧void closeAll();//关闭用到的组件private:AVFrame *in_frame,*out_frame;//保存解码后的像素数据int avcodec_index;//视频流所在输入视频的AVStream []数组的索引AVFormatContext* avformat_context;//封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息AVCodecContext* avcodec_context;//编码器上下文结构体,保存了视频(音频)编解码相关信息AVCodec* avcodec;//每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体
};

构造函数

fDecode::fDecode()
{    //注册组件avcodec_register_all();qDebug()<<"————注册所有组件————";qDebug()<<"注册成功!";
}

打开视频文件

void fDecode::openMvFile(QString mvPath)
{qDebug()<<"————打开视频文件————";avformat_context = avformat_alloc_context();//封装格式上下文结构体开空间int res = avformat_open_input(&avformat_context,mvPath.toStdString().c_str(),NULL,NULL);//return 0 on successif (res != 0){qDebug()<<"打开失败";exit(0);}else{qDebug()<<"打开成功!";}
}

获取视频文件流信息并查找是否有视频流

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

查找视频流对应的解码器

void fDecode::findDecoder()
{qDebug()<<"————查找对应的解码器————";//avcodec_index为视频流所在输入视频的AVStream []数组的索引,通过上一步查找视频流得到的//avcodec_context 编码器上下文结构体,保存了视频(音频)编解码相关信息avcodec_context = avformat_context->streams[this->avcodec_index]->codec;//根据解码器id查找解码器对应的结构体avcodec = NULL;avcodec = avcodec_find_decoder(avcodec_context->codec_id);if (NULL == avcodec){qDebug()<<"没有找到视频解码器";exit(0);}else{qDebug()<<"找到对应的解码器为:"<<avcodec->name;}
}

打开解码器

void fDecode::openDecoder()
{qDebug()<<"————打开解码器————";//avcodec_context、 avcodec 为上一步得到的int res = avcodec_open2(avcodec_context,avcodec,NULL);//zero on success, a negative value on errorif (0 != res){qDebug()<<"打开解码器失败";exit(0);}else{qDebug()<<"打开解码器成功!";}
}

循环读取每一帧并生成.h264、.yuv文件

void fDecode::readFrame()
{qDebug()<<"————读取每一帧————";AVPacket *pkt = (AVPacket *)malloc(sizeof(AVPacket));//存储一帧压缩编码数据in_frame= av_frame_alloc();//保存解码后的像素数据out_frame = av_frame_alloc();//保存解码后剔除损坏数据后的像素数据//一帧码流数据解码后得到的像素数据有多大int numByte = avpicture_get_size(AV_PIX_FMT_YUV420P, avcodec_context->width, avcodec_context->height);//开的空间用来保存像素数据uint8_t *buf = (uint8_t *)av_malloc(numByte * sizeof(uint8_t));//像素数据的填充avpicture_fill((AVPicture *)out_frame, buf, AV_PIX_FMT_YUV420P, avcodec_context->width, avcodec_context->height);//保存转换规则SwsContext *sws_content = nullptr;//转换规则的设置sws_content = sws_getContext(avcodec_context->width, avcodec_context->height ,avcodec_context->pix_fmt,avcodec_context->width, avcodec_context->height ,AV_PIX_FMT_YUV420P,SWS_BICUBIC,nullptr,nullptr,nullptr);FILE *fp_H264=NULL;FILE *fp_yuv=NULL;//以二进制格式创建或打开文件fp_H264=fopen("test.h264","wb+");fp_yuv=fopen("test.yuv","wb+");if(fp_H264 == NULL || fp_yuv == NULL){qDebug()<<"file open fail!";exit(0);}int size = avcodec_context->width * avcodec_context->height;av_new_packet(pkt,size);//循环读取每一帧while (av_read_frame(avformat_context,pkt) == 0) //return 0 if OK, < 0 on error or end of file{if(pkt->stream_index == this->avcodec_index)  //如果这一帧是视频流{fwrite(pkt->data,pkt->size,1,fp_H264);//写入h264文件//解码——>得到yuv AVFrame//got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero.int got_picture_ptr = -1;avcodec_decode_video2(avcodec_context, in_frame, &got_picture_ptr, pkt);if(got_picture_ptr != 0)//做解码的操作{//把解码得到的损坏的数据剔除sws_scale(sws_content, in_frame->data, in_frame->linesize, 0, in_frame->height,  //原数据out_frame->data, out_frame->linesize);  //输出数据fwrite(out_frame->data[0], size, 1, fp_yuv);//写入y数据fwrite(out_frame->data[1], size/4, 1, fp_yuv);//写入u数据fwrite(out_frame->data[2], size/4, 1, fp_yuv);//写入v数据}}}av_packet_unref(pkt);//清空}//关闭h264、yuv文件fclose(fp_H264);fclose(fp_yuv);qDebug()<<"写入成功";
}

关闭解码用到的组件

void fDecode::closeAll()
{qDebug()<<"————关闭所有组件————";av_frame_free(&in_frame);av_frame_free(&out_frame);avcodec_close(avcodec_context);avformat_free_context(avformat_context);qDebug()<<"关闭成功";
}

主函数测试

int main(int argc, char *argv[])
{QApplication a(argc, argv);qDebug()<<"ffmpeg版本号:"<<avcodec_version();fDecode mvDecode;mvDecode.openMvFile("mv/Warcraft3_End.avi");//打开视频文件mvDecode.findVideoStream();//查找视频流mvDecode.findDecoder();//查找对应的解码器mvDecode.openDecoder();//打开解码器mvDecode.readFrame();//读取每一帧mvDecode.closeAll();//关闭用到的组件return 0;
}

4、测试效果

运行效果

当前目录下会生成test.h264文件和test.yuv文件

H.264压缩方法比较复杂。包含了帧内预测、帧间预测、熵编码、环路滤波等环节构成。可以将图像数据压缩100倍以上,所以可以发现未压缩的像素数据yuv文件比压缩后的码流数据h624文件大非常多。

查看h264文件

查看yuv文件

Qt结合FFmpeg解码本地视频生成.h264文件和.yuv文件相关推荐

  1. 【Qt+FFmpeg】FFmpeg解码本地视频流程

    目录 一.视频播放器的实现框架 1.解封装(Demuxing) 2.解码(Decode) 3.音视频同步 二.FFmpeg解码视频流程 1.FFmpeg解码视频流程图 2. 代码实现 一.视频播放器的 ...

  2. android全平台基于ffmpeg解码本地MP4视频推流到RTMP服务器

    音视频实践学习 android全平台编译ffmpeg以及x264与fdk-aac实践 ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器 android全平台编译ffm ...

  3. ffmpeg 解码本地裸视频流

    解码本地视频流基本和解码音频流一致 视频解码过程 FFmpeg流程 关键函数啥的就不多说了 直接看我之前解码音频的文章 代码如下 #include <stdio.h> #include & ...

  4. ffmpeg读取本地视频,获取视频帧

    本文转自:https://blog.csdn.net/yinsui1839/article/details/80519742 /******** *本代码参考自雷神博客 * **********/ # ...

  5. Windows上搭建Nginx RTMP服务器并使用FFmpeg实现本地视频推流

    场景 RTMP RTMP协议 (1)是流媒体协议. (2)RTMP协议是 Adobe 的私有协议,未完全公开. (3)RTMP协议一般传输的是 flv,f4v 格式流. (4)RTMP一般在 TCP ...

  6. FFmpeg进阶: 截取视频生成gif动图

    文章目录 1.封装视频滤镜 2.截取视频生成gif 3.gif优化 4.示例效果 现在互联网上很多人都通过表情包来表达自己的情绪,常用的表情包很多都是视频文件的一部分.这里就介绍一下如何通过ffmpe ...

  7. ffmpeg推本地视频到rtmp服务器

    ffmpeg -re -i <视频文件名> -vcodec copy -f flv <rtmp://服务器地址> -re表示按帧率发送(保持视频按照时间戳发送,否则视频文件将很 ...

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

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

  9. android推流局域网,android全平台基于ffmpeg解码本地MP4视频推流到RTMP服务器

    音视频实践学习 本文目录 概述 还是先从最简单的搞起来,先从最基本的视频推流开始,要知道在电脑上使用ffmpeg完成推流,简直不要太简单,直接使用ffmpeg的推流命令即可,今天想在android平台 ...

  10. ffmpeg 解码本地无封装裸音频流 AAC MP3 复制代码就可以运行

    ⾳频解码过程 FFmpeg对应流程 关键函数说明: avcodec_find_decoder:根据指定的AVCodecID查找注册的解码器. av_parser_init:初始化AVCodecPars ...

最新文章

  1. 关于Action返回结果类型的事儿(下)
  2. 砥砺前行,比特币现金周年国际峰会正式召开
  3. RecyclerView添加头条目显示空白的解决方案
  4. Calendar类的常用成员方法
  5. python可以下载百度文库_百度文库随便下载,解除限制
  6. 鸿蒙os硬件要求,华为公布鸿蒙OS 2.0硬件安装要求:只要128K内存就能跑
  7. Android 渗透测试学习手册 翻译完成!
  8. pycharm创建django项目界面解释
  9. JQuery的Alert插件介绍
  10. 使用docker compose 测试集群网络连接性
  11. http状态码大全整理
  12. 【递归入门】组合的输出
  13. NAT hairpin,端口回流,回环NAT
  14. 计算机使用技巧爆文,自媒体原创(伪原创)爆文的写作技巧
  15. 2022081班李亚楠20220902
  16. git找回删除的stash
  17. CSAPP第五章家庭作业参考答案
  18. 成功人士分析问题的11种思维方式
  19. python画爱心原理_如何理解python一行代码实现一个爱心字符画?
  20. “闪婚”的代价:亿晶光电控股权陷“罗生门”

热门文章

  1. 影视App下载页源码
  2. Java中StringBuffer类的常用方法
  3. ubuntu vscode 配置字体_配置vscode终端字体,vscode终端字体
  4. android studio jdy08,JDY-08模块 蓝牙4.0 BLE CC2541 airsync iBeacon 兼容arduino
  5. 指纹机和计算机无法连接,指纹考勤系统常见问题及解决办法
  6. matlab色差,计算CMC色差公式的matlab程序
  7. Excel将数据内容导出为数据库DBF文件的操作
  8. dbf转成excel_dbf转excel工具(DbfToExcel) v1.2 免费版
  9. 屏幕取词编程学习总结
  10. 神经网络预测python_bp神经网络预测python