FFmpeg普及率高,相对易于使用,资料也多,甚至还有视频学习课程,FFmpeg属于GPL开源的,有助于学习,如果商业应用,切记GPL条款,几个著名的视频播放软件因编译改变了FFmpeg源代码而没有开源,作者光荣的登上了耻辱名单。

在学习FFmpeg过程中,遇到了点困难,因为直接下载使用了最新4.1版的,很多函数被否决,网上的资料行不通,自带的例程难以理解,所以又找到最低3.2版的,还是行不通,还好部分函数被否决,网上的资料大部分是2.x版的,所以试着找3.x版的和2.x不同的部分,结果成功了。需要说明的是2.x版的方便易用,好理解,3.x版变得臃肿不易理解。既然3.x版的成功了,为何不4.1版的,所以将4.1版的替换进去,结果成功了,4.1版相对3.2版改变不多,av_register_all()被否决了,需要替换。使用4.1版的意义在于当前大部分视频都可以轻松搞定。

1. Visual C++ 2017 创建控制台程序。

2. 到http://ffmpeg.org/下载Windods文件,通过以下选项下载:

Version:4.1

Architecture:Windods32-bit

Linking:下载Shared和Dev两个压缩文件,Shared需要DLL,Dev需要库和头文件。分别解压,将ffmpeg-4.1-win32-shared->bin目录内的.dll考入解决方案的Debug目录中。在解决方案目录中新建FFmpeg目  录,拷入ffmpeg-4.1-win32-dev内的include和lib两个目录。

3. 创建开发环境:

3.1 包含编译文件

3.1.1 包含头目录:项目->属性->VC++目录->包含目录:F:\FFmpegTest\FFmpeg\include。

3.1.2 包含库目录:项目->属性->VC++目录->库目录:F:\FFmpegTest\FFmpeg\lib。

3.1.3 包含链接库文件:项目->属性->链接器->输入->附加依赖项:avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;postproc.lib;swresample.lib;swscale.lib。

4. 输入代码:

#include <iostream>
#include <stdio.h>#define __STDC_CONSTANT_MACROSextern "C"
{#include "libavutil/imgutils.h"   //av_image使用#include "libavcodec/avcodec.h"   //编解码处理#include "libavformat/avformat.h" //文件封装处理#include "libswscale/swscale.h"//图像变换#include "libavdevice/avdevice.h"
};void PrintErrStr(const char *str)
{printf(str);printf("\n\n");system("pause");
}int Decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt)//解码
{int ret = avcodec_send_packet(dec_ctx, pkt);// 先发送包数据到解码上下文中if (ret < 0){PrintErrStr("发送数据包进行解码时出错.");return ret;}return avcodec_receive_frame(dec_ctx, frame);// 然后从解码上下文中读取帧数据到frame对象中
}int main()
{AVFormatContext *pFormatCtx = NULL;//主要用于处理封装格式(FLV/MKV/RMVB等)AVCodecContext *pVideoCodecCtx = NULL;AVCodecContext *pAudioCodecCtx = NULL;AVCodec *pVideoCodec = NULL;AVCodec *pAudioCodec = NULL;AVFrame *pFrame;   //存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)AVPacket packet;   //存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)int iHour, iMinute, iSecond, iTotalSeconds;//HH:MM:SSint videoStreamIndex, audioStreamIndex; //音视频流索引int ret, FrameBytes;const char In_FileName[] = "F:\\TestMov\\Titanic.ts";//输入文件const char Out_h264_FileName[] = "F:\\TestMov\\output.h264";//输出h264文件const char Out_rgb24_FileName[] = "F:\\TestMov\\output.rgb24";//输出h264文件FILE *fp_Out_h264_File = fopen(Out_h264_FileName, "wb+");FILE *fp_Out_rgb24_File = fopen(Out_rgb24_FileName, "wb+");int OutImgW = 640;int OutImgH = 272;int OutImg_linesize[3] = {OutImgW * 3,0,0};avdevice_register_all();//注册所有组件if (avformat_open_input(&pFormatCtx, In_FileName, NULL, NULL) != 0)//打开输入视频文件{PrintErrStr("打开输入文件失败。");return -1;}if (avformat_find_stream_info(pFormatCtx, NULL) < 0)//获取文件信息{PrintErrStr("没有发现流信息。");return -1;}videoStreamIndex = -1;audioStreamIndex = -1;for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)//寻找流索引{if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)//查找视频流索引{videoStreamIndex = i;}elseif (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)//查找音频流索引{audioStreamIndex = i;}}if ((videoStreamIndex == -1)||(audioStreamIndex == -1)){PrintErrStr("没有发现视频或音频流。");return -1;}pVideoCodec = avcodec_find_decoder(pFormatCtx->streams[videoStreamIndex]->codecpar->codec_id);//查找视频解码器if (pVideoCodec == NULL){PrintErrStr("没有找到视频解码器。");return -1;}pAudioCodec = avcodec_find_decoder(pFormatCtx->streams[audioStreamIndex]->codecpar->codec_id);//查找音频解码器if (pVideoCodec == NULL){PrintErrStr("没有找到音频解码器。");return -1;}pVideoCodecCtx = avcodec_alloc_context3(pVideoCodec);//申请视频解码空间if (pVideoCodecCtx == NULL){PrintErrStr("无法分配视频解码器。");return -1;}pAudioCodecCtx = avcodec_alloc_context3(pAudioCodec);//申请音频解码空间if (pAudioCodecCtx == NULL){PrintErrStr("无法分配音频解码器。");return -1;}avcodec_parameters_to_context(pVideoCodecCtx, pFormatCtx->streams[videoStreamIndex]->codecpar);avcodec_parameters_to_context(pAudioCodecCtx, pFormatCtx->streams[audioStreamIndex]->codecpar);if (avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL) < 0) //打开视频解码器{  PrintErrStr("没有打开视频解码器。");return -1;}if (avcodec_open2(pAudioCodecCtx, pAudioCodec, NULL) < 0) //打开音频解码器{PrintErrStr("没有打开音频解码器。");return -1;}pFrame = av_frame_alloc();//申请解压帧缓存if (pFrame == NULL){PrintErrStr("申请解压帧缓存失败。");return -1;}FrameBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pVideoCodecCtx->width, pVideoCodecCtx->height, 1);//获取视频帧字节数uint8_t *pFrameBuffer = (uint8_t *)av_malloc(FrameBytes);//创建动态视频帧数组while (av_read_frame(pFormatCtx, &packet) >= 0)//从文件中读取一个packet {if (packet.stream_index == videoStreamIndex)//如果是视频帧 {fwrite(packet.data, packet.size, 1, fp_Out_h264_File);//写视频包文件ret = Decode(pVideoCodecCtx, pFrame, &packet);//解码 packet->pFrameif (ret == 0) //已得到解码的图像在pFrame里{struct SwsContext *pSwsCtx = NULL;pSwsCtx = sws_getContext( pVideoCodecCtx->width, pVideoCodecCtx->height, pVideoCodecCtx->pix_fmt,//源宽度高度和格式YUV420 OutImgW, OutImgH, AV_PIX_FMT_RGB24,//转换到目标的宽度高度和格式1,//缩放算法 SWS_FAST_BILINEARNULL, NULL, NULL);//初始化转换if (!pSwsCtx){PrintErrStr("无法初始化转换Frame帧。");return -1;} sws_scale(pSwsCtx, pFrame->data, pFrame->linesize, 0, pVideoCodecCtx->height, &pFrameBuffer, OutImg_linesize);fwrite(pFrameBuffer, FrameBytes, 1, fp_Out_rgb24_File);//写RGB视频文件sws_freeContext(pSwsCtx);//释放转换}}av_packet_unref(&packet);}//输出信息puts("[文件信息]");iTotalSeconds = (int)pFormatCtx->duration / 1000000; //SiHour = iTotalSeconds / 3600;//小时iMinute = iTotalSeconds % 3600 / 60;//分钟iSecond = iTotalSeconds % 60;//秒printf("播放时间:%02d:%02d:%02d\n", iHour, iMinute, iSecond);printf("流 个 数:%d\n", pFormatCtx->nb_streams);printf("封装格式:%s\n", pFormatCtx->iformat->long_name);printf("\n");puts("[视频信息]");printf("编码格式:%s\n", pVideoCodec->long_name);printf("视频码率:%I64d kb/s\n", pVideoCodecCtx->bit_rate / 1000);printf("分 辨 率:%d * %d\n", pVideoCodecCtx->width, pVideoCodecCtx->height);printf("\n");puts("[音频信息]");printf("编码格式:%s\n", pAudioCodec->long_name);printf("音频码率:%I64d kb/s\n", pAudioCodecCtx->bit_rate / 1000);printf("通 道 数:%d\n", pAudioCodecCtx->channels);printf("采 样 率:%d\n", pAudioCodecCtx->sample_rate);printf("\n");fclose(fp_Out_h264_File);fclose(fp_Out_rgb24_File);av_free(pFrameBuffer);av_frame_free(&pFrame);avcodec_close(pVideoCodecCtx);avcodec_close(pAudioCodecCtx);avformat_close_input(&pFormatCtx);printf("\n\n");system("pause");
}

5. 编译运行:得到两个文件,一个是output.h264未解压的视频包文件,另一个是output.rgb24已解压的RGB24图像文件。  

5.1 用ESEyE播放output.h264未解压的原始裸流视频文件,我下载的是Elecard StreamEye Tools绿色直接运行版,内有ESEyE播放软件,内还有pyuv用于播放yuv文件。

5.2 用RawPlayer播放output.rgb24,因属于裸流视频文件,打开文件时需要手动输入图像信息。

5.3 output.h264为h264压缩,属于原始裸流视频文件,因原始压缩包中含有播放用信息,所以可以播放。找了几个短视频文件均不是,所以用了雷霄骅博士的资源包,内有Titanic.ts为h264压缩,作为输入视频文件,分解出两个可播放的裸流视频文件。

转载于:https://www.cnblogs.com/hbg200/p/10353354.html

FFmpeg入门测试相关推荐

  1. FFmpeg入门详解之117:视频监控的架构和流程

    几张架构图带您快速了解视频监控 图一 图二 图三 图四 视频监控系统的简介 视频监控 视频监控是安全防范系统的重要组成部分,英文Cameras and Surveillance.传统的监控系统包括前端 ...

  2. FFmpeg入门详解之124:Qt5 FFmpeg单路网络摄像头采集预览

    Qt5+FFmpeg单路网络摄像头采集预览 源码工程:S26_Test4 RTSP协议简介 RTSP(Real Time Streaming Protocol),RFC2326 RTSP(Real T ...

  3. FFmpeg入门详解之111:RTSP协议2

    rtsp消息详解 1.RTSP的消息有两大类,一是请求消息(request),一是回应消息(response),两种消息的格式不同. 请求消息格式: 方法 URI RTSP版本 CR LF 消息头 C ...

  4. FFmpeg入门详解之119:FFmpeg的SDK编程回顾总结并操练

    3.FFmpeg的SDK编程回顾总结并操练 参考课程:"FFmpeg4.3--系列5--SDK二次开发详解与实战" FFmpeg主要框架 FFmpeg骨架:"八大金刚&q ...

  5. FFmpeg入门详解之104:Win10快速安装OpenSSL(不用编译源码)

    win10x64安装OpenSSL:不用编译源码 网上一堆的教程教你去下载opensll源代码并用vs进行编译,虽然我有安装vs2015,但是看到那么长的编译步骤,太心累了. 懒人只得找简单的方法,最 ...

  6. FFmpeg入门详解之87:HLS直播协议详解

    引言与效果演示 ----------------------------------------- FFmpeg431的官方地址已经无法打开, 我将ffmepg4.3.1的开发包和源码上传到了百度云: ...

  7. FFmpeg入门详解之102:HLS直播协议详解

    引言与效果演示 ----------------------------------------- FFmpeg431的官方地址已经无法打开, 我将ffmepg4.3.1的开发包和源码上传到了百度云: ...

  8. FFmpeg入门详解之89:HTTP-FLV讲解

    HTTP-FLV简介 HTTP-FLV,即将音视频数据封装成 FLV,然后通过 HTTP 协议传输给客户端. HLS 其实是一个 "文本协议",而并非流媒体协议.那么,什么样的协议 ...

  9. FFmpeg入门详解之84:RTSP协议讲解

    RTSP亲手搭建直播点播 测试工具:VLC 数据源:  文件或本地摄像头 测试功能:RTSP直播点播 播放地址:rtsp://127.0.0.1:8554/rtspa001 服务端:推流 客户端:拉流 ...

最新文章

  1. Fortinet宣布收购AccelOps
  2. 关于软件外包的一些看法(转)
  3. Windows Azure Storage (4) Windows Azure Storage Service存储服务之Blob Share Access Signature
  4. Scrapy框架实现爬虫
  5. Epos消费管理系统复制迁移SQL SERVER 2005数据库
  6. SVN提示: File or directory '*' is out of date; try updating 解决方案
  7. 【零基础学Java】—Collections集合工具类(四十二)
  8. Ehcahe spring
  9. tensorflow实现残差网络(mnist数据集)
  10. Excel员工考勤表模板,这三套送给您
  11. 华为USG6000V防火墙学习
  12. java转换成kotlin语言教程_#7 Kotlin教程 | 把Java转换为Kotlin
  13. java groovy 乱码_解决Groovy复制文件的乱码
  14. linux下查看U盘文件
  15. 台式计算机usb口不能用,电脑usb接口没反应是什么原因?电脑usb接口没反应解决方法...
  16. SQL Server排序规则
  17. Actor模型和CSP模型的区别
  18. Codeforces Round #835 (Div. 4) - D. Challenging Valleys
  19. Proxyee-down 3.x的下载与安装
  20. 某程序员哀叹:做码农真的很悲哀,有的35岁就没人要了

热门文章

  1. (转)C# Winform应用程序占用内存较大解决方法整理
  2. (原创)sqlite封装库SmartDB1.3发布
  3. 接收list参数_Python 犄角旮旯--List
  4. 你可能没听过的 Java 8 中的 10 个特性
  5. SFS2X客户端全部事件详细
  6. myeclipse中的项目如何切换svn地址
  7. html事件中写js,html标签中绑定触发事件与js中绑定触发事件写法上的区别
  8. pfx导入后仍然打不开加密文件_天正CAD图纸加密和解密方法
  9. MFC三大dll使用总结
  10. 可以打开md_大祥MD型耐磨卧式多级离心泵现货出售中大泵业