使用FFmpeg库实现视频编码
1.FFmpeg进行视频编解码所需要的结构
.AVCodec :AVCodec结构保存了一个编解码器的实例,实现实际的编码功能。通常我们在程序中定义一个指向AVCodec 结构的指针指向该实例。
.AVCodecContext :AVCodecContext表示AVCodec所代表的上下文信息,保存了AVCodec所需要的一些参数。对于实现 编码功能,我们可以在这个结构体中设置我们指定的编码参数。通常也是定义一个指针指向AVCodecContext.
.AVFrame :AVFrame结构保存编码之前的像素数据,并作为编码器的输入数据。其在程序中也是一个指针的形式
.AVPacket :AVPacket表示码流包结构,包含编码之后的码流数据。该结构可以不定一指针,以一个对象的形式定义。
2.FFmpeg编码的主要步骤
1.解析输入参赛
2.按要求初始化需要的FFmpeg结构
3.编码过程循环
4.写出码流数据
5.收尾工作
3.源代码
#include "stdio.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;//要打开的yuv文件名
const char *outputFileName = NULL;//编码后的输出的文件名
int frameWidth = 0, frameHeight = 0;//视频的宽和高
int bitRate = 0;//视频的比特率
int frameToEncode = 0;//需要转换编码的帧数
FILE *pFin = NULL,*pFout = NULL; //打开输入和输出的文件描述符
AVCodec *codec = NULL; //代表一个编解码器
AVCodecContext *codecCtx = NULL; //编解码器上下文
AVFrame *frame = NULL; //待编码的像素数据
AVPacket pkt; //保存编码之后的码流int read_yuv_data(int color);
int parse_input_paramaters(int argc, char **argv)
{inputFileName = argv[1]; //输入文件名称in.yuvoutputFileName = argv[2]; //输出文件名称out.h264frameWidth = atoi(argv[3]); //视频的宽frameHeight = atoi(argv[4]);//视频的高bitRate = atoi(argv[5]); //比特率frameToEncode = atoi(argv[6]);//要编码的帧数fopen_s(&pFin, inputFileName, "rb+");//打开输入文件if (!pFin){printf("fopen_s inputFile failed\n");return FILE_ERROR_OPEN_FAILED;}fopen_s(&pFout, outputFileName, "wb+");//打开输出文件if (!pFout){printf("fopen_s outputFile failed\n");return FILE_ERROR_OPEN_FAILED;}return HPR_OK;
}
int main(int argc, char **argv)
{ int got_packet;//是否已经完成编码出一个完整的数据包printf("Hello world \n");/*解析输入参数*/if (HPR_OK == parse_input_paramaters(argc,argv)){printf("inputFileName:%s\n outputFileName:%s\n frameWidth:%d\n frameHeight:%d\n bitRate:%d\n frameToEncode:%d\n",inputFileName,outputFileName,frameWidth,frameHeight,bitRate,frameToEncode);}else{printf("parse_input_paramaters error\n");return HPR_ERROR;}/*注册编解码器*/avcodec_register_all();/*查找AVCodec编码器*/codec = avcodec_find_encoder(AV_CODEC_ID_H264);if (!codec){return FF_ERROR_INIT_FAILED;}/*分配AVCodecContext实例*/codecCtx = avcodec_alloc_context3(codec);if (!codecCtx){return FF_ERROR_INIT_FAILED;}/*设置编码器参数*/codecCtx->width = frameWidth; //视频帧宽codecCtx->height = frameHeight;//视频帧高codecCtx->bit_rate = bitRate;//比特率AVRational r = { 1, 25 }; //每秒25帧codecCtx->time_base = r;codecCtx->gop_size = 12;//GOP即Group of picture(图像组),指两个I帧之间的距离codecCtx->max_b_frames = 1;//两个非B帧之间的最大B帧数目codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;//像素格式//priv_data 属于每个编码器特有的设置域,用av_opt_set 设置//preset 与编码速度和质量相关av_opt_set(codecCtx->priv_data, "preset", "slow", 0);/*打开编码器*/if(avcodec_open2(codecCtx, codec, NULL) < 0){return FF_ERROR_INIT_FAILED;}/*分配AVFrame以及像素存储空间*/frame = av_frame_alloc();//分配的AVFrame结构体空间if (!frame){return FF_ERROR_INIT_FAILED;}frame->width = codecCtx->width;//像素的宽frame->height = codecCtx->height;//像素的高frame->format = codecCtx->pix_fmt;//像素的格式//分配实际存储像素的存储空间// frame->linesize:frame->data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。if (av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, (AVPixelFormat)frame->format, 32) < 0){return FF_ERROR_INIT_FAILED;}/*读取像素数据到AVFrame*/for (int frameIdx = 0; frameIdx < frameToEncode;frameIdx++){//初始化AVPacketav_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;//读取像素数据(YUV三个分量)到AVFrameread_yuv_data(0);read_yuv_data(1);read_yuv_data(2);frame->pts = frameIdx;//显示时间戳,这一帧要显示的时间/*编码*///AVFrame的像素数据编码为AVPacket的码流数据//got_packet:是否已经完成编码出一个完整的数据包if(avcodec_encode_video2(codecCtx, &pkt, frame, &got_packet) < 0){return FF_ERROR_ENCODING_FAILED;}if (got_packet){printf("write packet of frame %d,size = %d\n", frameIdx, pkt.size);//写入out.h264文件fwrite(pkt.data, 1, pkt.size,pFout);//释放pktav_packet_unref(&pkt);}}/*编码器可能还保留着没有输出的数据*/for (got_packet = 1; got_packet;){//frame传入NULL,不从frame里面读取数据,编码自己内部缓存的数据if (avcodec_encode_video2(codecCtx, &pkt, NULL, &got_packet) < 0){return FF_ERROR_ENCODING_FAILED;}if (got_packet){printf("write cached packet size = %d\n",pkt.size);//写入out.h264文件fwrite(pkt.data, 1, pkt.size, pFout);//释放pktav_packet_unref(&pkt);}}/*收尾工作*///关闭输入输出文件fclose(pFin);fclose(pFout);avcodec_close(codecCtx);//关闭AVCodecConetxtav_free(codecCtx);//释放codecCtxav_freep(&frame->data[0]);//释放frame保存像素数据的地址空间av_frame_free(&frame);//释放framereturn 0;
}int read_yuv_data(int color)
{//color = 0; Y分量//color = 1; U分量//color = 2; V分量//色度分量的采样分辨率是亮度分量的1/2,宽和高分别为1/2int color_height = color == 0 ? frameHeight : frameHeight / 2;int color_width = color == 0 ? frameWidth : frameWidth / 2;int color_size = color_height*color_width;//图片大小int color_stride = frame->linesize[color];//缓存的宽度:为像素的宽度加上外边框//像素分量在AVFrame中连续存放的,内存边缘没有填充的数据if (color_width == color_stride){fread_s(frame->data[color], color_size, 1, color_size, pFin);}else{//一行一行读取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;
}
使用FFmpeg库实现视频编码相关推荐
- Linux实现ffmpeg H.265视频编码
Linux实现ffmpeg H.265视频编码 几乎所有观看的视频,数字地面电视,电缆,卫星或互联网上的压缩.原始的,未压缩的视频太大,会浪费太多的带宽.在DVD和Blu-ray之前,有视频CD(VC ...
- FFmpeg系列(二)-Android项目引入FFmpeg库播放视频
在系列一中讲述了如何编译FFmpeg的源码,现在就在Android项目中引入我们编译出来的库,并实现播放一个在线视频的功能 新建Android工程 新建一个支持ndk的Android工程,在AS中新建 ...
- 音视频基础+ffmpeg原理(视频编码)
H264: H264压缩比 条件:1.YUV格式YUV420 2.分辨率:640x480 3.帧率15 源码流:640x480x1.5x15,建议码流:500kpbs, 结 ...
- 视频教程-FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-C/C++
FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK 夏曹俊:南京捷帝科技有限公司创始人,南京大学计算机硕士毕业,有15年c++跨平台项目研发的经验,领导开发过大量的c++虚拟 ...
- FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-夏曹俊-专题视频课程...
FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-3798人已学习 课程介绍 本课程讲解的是基于流行的直播技术 FFMpeg3.3音视频处理框架,和应用广的 ...
- 【Python】ffmpeg模块查询视频、音频信息
FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.采用LGPL或GPL许可证.它提供了录制.转换以及流化音视频的完整解决方案. 它包含了非常先进的音频/视频编解码库 ...
- MediaCodec 、x264、faac 实现音视频编码并通过 rtmp 协议实现推流
前言 咱们回顾一下前面 2 篇文章,主要讲解了如何搭建 rtmp 直播服务器,和如何开发一款具有拉流功能的 Android 播放器.那么现在有了播放端和直播服务器还缺少推流端.该篇文章我们就一起来实现 ...
- 视频编码中为什么须要进行变换编码?
绝大多数图像都有一个共同的特征:平坦区域和内容缓慢变化区域占领一幅图像的大部分,而细节区域和内容突变区域则占小部分.也能够说,图像中直流和低频区占大部分,高频区占小部分.这样,空间域的图像变换到频域或 ...
- FFMPEG采集摄像头图像SDL渲染+MP4格式视频编码
FFMPEG采集摄像头图像SDL渲染+MP4格式视频编码 FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.采用LGPL或GPL许可证.它提供了录制.转换以及流化音 ...
最新文章
- 2018年终总结之摄影作品展
- 【Python基础】python使用python-docx操作word
- WebRTC基本介绍
- 存根类 测试代码 java_有关为旧版代码创建存根的更多信息–测试技术7
- word python api_WordNet Python API (整理总结)
- MSU 出品的 H.264 编码器比较 (2011.5)
- atitit 软件框架类库设计的艺术.docx 目录 1. index	1 2. 第2章 设计api的动力之源 14	2 2.1. .1 分布式开发 14	2 2.2. 2.2 模块化应用程序 16
- 记redis的一个测试
- Hystrix原理介绍:服务雪崩、断路器、服务降级、资源隔离-《Spring Cloud微服务架构进阶》读书笔记
- ASP.Net Core 发布在IIS部署出现502.5错误的解决办法
- Namenode处于安全模式时,对hadoop进行查看操作,edits_inprogress_txid中没有事物事件的增加,txid没有增加?
- runOnUiThread简单应用
- php 极光短信发送 api
- 键盘输入,键盘输入结束符。
- 三、硬盘分类与操作系统的启动流程
- 年后跳槽如何准备?(转)
- 感知器算法(PLA)
- mahout 详解
- 学校计算机职业技能鉴定总结,职业技能鉴定个人工作总结精选 .doc
- 【汇正财经】股票集合竞价时间内可以撤单吗?