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库实现视频编码相关推荐

  1. Linux实现ffmpeg H.265视频编码

    Linux实现ffmpeg H.265视频编码 几乎所有观看的视频,数字地面电视,电缆,卫星或互联网上的压缩.原始的,未压缩的视频太大,会浪费太多的带宽.在DVD和Blu-ray之前,有视频CD(VC ...

  2. FFmpeg系列(二)-Android项目引入FFmpeg库播放视频

    在系列一中讲述了如何编译FFmpeg的源码,现在就在Android项目中引入我们编译出来的库,并实现播放一个在线视频的功能 新建Android工程 新建一个支持ndk的Android工程,在AS中新建 ...

  3. 音视频基础+ffmpeg原理(视频编码)

    H264: H264压缩比 条件:1.YUV格式YUV420        2.分辨率:640x480        3.帧率15 源码流:640x480x1.5x15,建议码流:500kpbs, 结 ...

  4. 视频教程-FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-C/C++

    FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK 夏曹俊:南京捷帝科技有限公司创始人,南京大学计算机硕士毕业,有15年c++跨平台项目研发的经验,领导开发过大量的c++虚拟 ...

  5. FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-夏曹俊-专题视频课程...

    FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-3798人已学习 课程介绍         本课程讲解的是基于流行的直播技术 FFMpeg3.3音视频处理框架,和应用广的 ...

  6. 【Python】ffmpeg模块查询视频、音频信息

    FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.采用LGPL或GPL许可证.它提供了录制.转换以及流化音视频的完整解决方案. 它包含了非常先进的音频/视频编解码库 ...

  7. MediaCodec 、x264、faac 实现音视频编码并通过 rtmp 协议实现推流

    前言 咱们回顾一下前面 2 篇文章,主要讲解了如何搭建 rtmp 直播服务器,和如何开发一款具有拉流功能的 Android 播放器.那么现在有了播放端和直播服务器还缺少推流端.该篇文章我们就一起来实现 ...

  8. 视频编码中为什么须要进行变换编码?

    绝大多数图像都有一个共同的特征:平坦区域和内容缓慢变化区域占领一幅图像的大部分,而细节区域和内容突变区域则占小部分.也能够说,图像中直流和低频区占大部分,高频区占小部分.这样,空间域的图像变换到频域或 ...

  9. FFMPEG采集摄像头图像SDL渲染+MP4格式视频编码

    FFMPEG采集摄像头图像SDL渲染+MP4格式视频编码 FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.采用LGPL或GPL许可证.它提供了录制.转换以及流化音 ...

最新文章

  1. 2018年终总结之摄影作品展
  2. 【Python基础】python使用python-docx操作word
  3. WebRTC基本介绍
  4. 存根类 测试代码 java_有关为旧版代码创建存根的更多信息–测试技术7
  5. word python api_WordNet Python API (整理总结)
  6. MSU 出品的 H.264 编码器比较 (2011.5)
  7. atitit 软件框架类库设计的艺术.docx 目录 1. index 1 2. 第2章 设计api的动力之源 14 2 2.1. .1 分布式开发 14 2 2.2. 2.2 模块化应用程序 16
  8. 记redis的一个测试
  9. Hystrix原理介绍:服务雪崩、断路器、服务降级、资源隔离-《Spring Cloud微服务架构进阶》读书笔记
  10. ASP.Net Core 发布在IIS部署出现502.5错误的解决办法
  11. Namenode处于安全模式时,对hadoop进行查看操作,edits_inprogress_txid中没有事物事件的增加,txid没有增加?
  12. runOnUiThread简单应用
  13. php 极光短信发送 api
  14. 键盘输入,键盘输入结束符。
  15. 三、硬盘分类与操作系统的启动流程
  16. 年后跳槽如何准备?(转)
  17. 感知器算法(PLA)
  18. mahout 详解
  19. 学校计算机职业技能鉴定总结,职业技能鉴定个人工作总结精选 .doc
  20. 【汇正财经】股票集合竞价时间内可以撤单吗?

热门文章

  1. 什么是PEPPOL BIS?
  2. mySql 简单 多表 联查
  3. SAP公司间外协业务流程以及配置说明
  4. 软件项目管理-项目人力资源管理
  5. 【概率论与数理统计】猴博士 笔记 p26-28 F、f的性质、一、二维连续型求期望、方差
  6. RKMEDIA--VP使用
  7. 用KNN分类器进行猫狗分类
  8. 红米 Redmi 6A 在 HbuilderX 上进行真机调试
  9. 3D地图+智能导航,用微信小程序轻松实现校园内导航
  10. tree结构穿梭 vue_结合el-tree和el-transfer搞一个树形穿梭框