ffmpeg视频编码分析
2016-10-20 10:24
351 查看
使用visual studio 2013 ,首先配置项目环境。下载ffmpeg:win64位:https://ffmpeg.zeranoe.com/builds/win64/。下载share与dev,版本需要一致。
在自己工程项目的.sln文件路径下新建include与lib文件夹,将ffmpeg shared项目的bin目录下.dll拷贝到自己创建的lib中,将dev项目中的lib目录下.lib文件拷贝到自己创建的lib目录中,将dev项目中的include目录下的所有文件拷贝到自己创建的include中并将如下三个头文件拷入include中
设置include与lib的引用
最后将需要用到的.dll文件拷贝到生成.exe的目录下,至此环境搭建完成。
详细编码流程如下:
1.首先解析、处理输入参数,如编码器的参数、图像的参数、输入输出文件;
2.建立整个FFMpeg编码器的各种组件工具,顺序依次为:avcodec_register_all -> avcodec_find_encoder ->avcodec_alloc_context3
-> avcodec_open2 -> av_frame_alloc -> av_image_alloc;
3.编码循环:av_init_packet -> avcodec_encode_video2(两次) -> av_packet_unref
4.关闭编码器组件:avcodec_close,av_free,av_freep,av_frame_free
详细编码代码如下:
1:定义错误码头文件Error.h
2:main函数代码与注释
最终将yuv格式数据编码为h264格式。
备注:博客内容来源于《FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK》
视频地址:http://edu.csdn.net/course/detail/2515
在自己工程项目的.sln文件路径下新建include与lib文件夹,将ffmpeg shared项目的bin目录下.dll拷贝到自己创建的lib中,将dev项目中的lib目录下.lib文件拷贝到自己创建的lib目录中,将dev项目中的include目录下的所有文件拷贝到自己创建的include中并将如下三个头文件拷入include中
设置include与lib的引用
最后将需要用到的.dll文件拷贝到生成.exe的目录下,至此环境搭建完成。
详细编码流程如下:
1.首先解析、处理输入参数,如编码器的参数、图像的参数、输入输出文件;
2.建立整个FFMpeg编码器的各种组件工具,顺序依次为:avcodec_register_all -> avcodec_find_encoder ->avcodec_alloc_context3
-> avcodec_open2 -> av_frame_alloc -> av_image_alloc;
3.编码循环:av_init_packet -> avcodec_encode_video2(两次) -> av_packet_unref
4.关闭编码器组件:avcodec_close,av_free,av_freep,av_frame_free
详细编码代码如下:
1:定义错误码头文件Error.h
#ifndef _ERROR_H_ #define _ERROR_H_ #define IO_FILE_ERROR_OPEN_FAIL -1 #define FF_ERROR_INITIALIZATION_FAILED -10 #define FF_ERROR_ENCODING_FAILED -11 #endif
2:main函数代码与注释
#include "stdio.h" #include "stdlib.h" #include "stdint.h" #include "Error.h" extern "C"{ #include "libavutil/imgutils.h" #include "libavutil/samplefmt.h" #include "libavformat/avformat.h" #include "libavutil/opt.h" } //文件输入路径 const char *inputFileName = NULL; //文件输出路径 const char *outPutFileName = NULL; //输入输出文件指针 FILE *pFin = NULL, *pFout = NULL; //输入的视频文件宽高 int frameWidth = 0, frameHeight = 0; //编码的比特率和编码帧数 int bitRate = 0, frameToCode = 0; //编码器对象 AVCodec *codec = NULL; //编码器对象的上下文环境 AVCodecContext *codecCtx = NULL; AVFrame *frame = NULL; AVPacket pkt; /** *从命令行中解析出命令行参数 */ static int parse_input_paramaters(int argc, char **argv){ inputFileName = argv[1]; outPutFileName = argv[2]; fopen_s(&pFin,inputFileName,"rb+"); if (!pFin){ return IO_FILE_ERROR_OPEN_FAIL; } fopen_s(&pFout, outPutFileName, "wb+"); if (!pFout){ return IO_FILE_ERROR_OPEN_FAIL; } frameWidth = atoi(argv[3]); frameHeight = atoi(argv[4]); bitRate = atoi(argv[5]); frameToCode = atoi(argv[6]); return 1; } /** *从命令行中解析出命令行参数 *YUV_420_P格式的数据 */ static int read_yuv_data(int color){ //color = 0; y分量 亮度分量 占4份 //color = 1; u分量 色度分量 占2份 //color = 2; v分量 色度分量 占2份 int color_width = color == 0 ? frameWidth : frameWidth / 2; int color_height = color == 0 ? frameHeight : frameHeight / 2; int color_size = color_width * color_height; int color_stride = frame->linesize[color]; //由于视频边缘可能有填充像素,所以frame的width与linesize可能不相等 if (color_width == color_stride){ //frame的width与linesize相等时像素数据是连续的 fread_s(frame->data[color], color_size, 1, color_size, pFin); } else { //frame的width与linesize不相等时候读取像素数据 for (int row_idx = 0; row_idx < color_height; row_idx++){ fread_s(frame->data[color] + row_idx * color_stride, color_width, 1, color_width, pFin); } } return color_size; } int main(int argc, char **argv){ int got_packet = 0; if (parse_input_paramaters(argc, argv) > 0){ printf("InputFile: %s\nOutPutFile: %s\nFile:Frame resolution: (%d x %d)\nBitrate: %d\nFrame num to code: %d\n" ,inputFileName,outPutFileName,frameWidth,frameHeight,bitRate,frameToCode); } else{ printf("Error:connamd line error\n"); return -1; } { //注册需要的ffmpeg编解码组件 avcodec_register_all(); //查找编解码器 codec = avcodec_find_encoder(AV_CODEC_ID_H264); if (!codec){ return FF_ERROR_INITIALIZATION_FAILED; } //分配AVCodecContext codecCtx = avcodec_alloc_context3(codec); if (!codecCtx){ return FF_ERROR_INITIALIZATION_FAILED; } //设置编码参数 codecCtx->width = frameWidth; codecCtx->height = frameHeight; codecCtx->bit_rate = bitRate; AVRational r = { 1, 25 }; codecCtx->time_base = r; codecCtx->gop_size = 12; codecCtx->max_b_frames = 1; codecCtx->pix_fmt = AV_PIX_FMT_YUV420P; //av_opt_set(codecCtx->priv_data,"preset","superfast",0); av_opt_set(codecCtx->priv_data, "tune", "zerolatency", 0); //打开编码器 if(avcodec_open2(codecCtx, codec, NULL) < 0){ return FF_ERROR_INITIALIZATION_FAILED; } //分配AVFrame以及像素存储空间 frame = av_frame_alloc(); if (!frame){ return FF_ERROR_INITIALIZATION_FAILED; } frame->width = codecCtx->width; frame->height = codecCtx->height; frame->format = codecCtx->pix_fmt; if (av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, (AVPixelFormat)frame->format, 32) < 0){ return FF_ERROR_INITIALIZATION_FAILED; } } for (int frameIdx = 0; frameIdx < frameToCode; frameIdx++) { //初始化AVPacket av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; //读取像素数据到AVFrame中 read_yuv_data(0); read_yuv_data(1); read_yuv_data(2); //设置视频的显示时间戳 frame->pts = frameIdx; //开始编码 if (avcodec_encode_video2(codecCtx,&pkt,frame,&got_packet) < 0){ printf("Error: encoding failed!"); return FF_ERROR_ENCODING_FAILED; } //将编码后的数据写入输出文件中 if (got_packet){ printf("write packet of frame %d,size = %d\n",frameIdx,pkt.size); fwrite(pkt.data,1,pkt.size,pFout); av_packet_unref(&pkt); } } //在编码器中可能还有一些缓存数据需要进行编码 for (got_packet = 1; got_packet;) { //编码 if (avcodec_encode_video2(codecCtx, &pkt, NULL, &got_packet) < 0){ printf("Error: encoding failed!"); return FF_ERROR_ENCODING_FAILED; } if (got_packet){ printf("write cached packet,size = %d\n", pkt.size); fwrite(pkt.data, 1, pkt.size, pFout); av_packet_unref(&pkt); } } //收尾工作,清理内存 fclose(pFin); fclose(pFout); avcodec_close(codecCtx); av_free(codecCtx); av_freep(&frame->data[0]); av_frame_free(&frame); return 0; }
最终将yuv格式数据编码为h264格式。
备注:博客内容来源于《FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK》
视频地址:http://edu.csdn.net/course/detail/2515
相关文章推荐
- ffmpeg转码MPEG2-TS的音视频同步机制分析
- 从ffmpeg源代码分析如何解决ffmpeg编码的延迟问题
- H.264视频编码传输的QoS特性分析(二)
- ffmpeg视频编码(2)-建立VC环境
- FFMpeg中apiexample.c例子分析——编码分析
- H.264视频编码传输的QoS特性分析(二)
- ffmpeg转码MPEG2-TS的音视频同步机制分析
- 使用FFmpeg类库实现YUV视频序列编码为视频
- 图像视频编码和FFmpeg(6)-----用FFmpeg编码和解码的例子
- ffmpeg转换参数和对几种视频格式的转换分析
- 视频格式与编码问题分析
- windows平台下使用ffmpeg对视频进行H264编码总结
- 关于H.264视频编码传输的QoS特性分析
- X264视频编码分析(3):视频帧的存取
- H.264视频编码传输的QoS特性分析(一)
- ffmpeg编码YUV420视频序列
- x264源码分析与应用示例(一)——视频编码基本流程
- 用FFmpeg编码h264视频介绍
- H.264视频编码传输的QoS特性分析(三)
- 关于H.264视频编码传输的QoS特性分析(转载)