最简单的基于FFmpeg的编码器-纯净版(不包含libavformat)

=====================================================

最简单的基于FFmpeg的视频编码器文章列表:

最简单的基于FFMPEG的视频编码器(YUV编码为H.264)

最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))

最简单的基于FFmpeg的编码器-纯净版(不包括libavformat)

=====================================================

本文记录1个更加“纯净”的基于FFmpeg的视频编码器。此前记录过1个基于FFmpeg的视频编码器:

 《最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))》

这个视频编码器调用了FFmpeg中的libavformat和libavcodec两个库完成了视频编码工作。但是这不是1个“纯净”的编码器。上述两个库中libavformat完成封装格式处理,而libavcodec完成编码工作。1个“纯净”的编码器,理论上说只需要使用libavcodec就足够了,其实不需要使用libavformat。本文记录的编码器就是这样的1个“纯净”的编码器,它仅仅通过调用libavcodec将YUV数据编码为H.264/HEVC等格式的紧缩视频码流。

流程图

仅使用libavcodec(不使用libavformat)编码视频的流程以下图所示。

流程图中关键函数的作用以下所列:

avcodec_register_all():注册所有的编解码器。
avcodec_find_encoder():查找编码器。
avcodec_alloc_context3():为AVCodecContext分配内存。
avcodec_open2():打开编码器。
avcodec_encode_video2():编码1帧数据。

两个存储数据的结构体以下所列:

AVFrame:存储1帧未编码的像素数据。
AVPacket:存储1帧紧缩编码数据。

对照

简单记录1下这个只使用libavcodec的“纯净版”视频编码器和使用libavcodec+libavformat的视频编码器的不同。

PS:使用libavcodec+libavformat的编码器参考文章 《最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))》

(1) 以下与libavformat相干的函数在“纯净版”视频编码器中都不存在。

av_register_all():注册所有的编解码器,复用/解复用器等等组件。其中调用了avcodec_register_all()注册所有编解码器相干的组件。
avformat_alloc_context():创建AVFormatContext结构体。
avformat_alloc_output_context2():初始化1个输出流。
avio_open():打开输出文件。
avformat_new_stream():创建AVStream结构体。avformat_new_stream()中会调用avcodec_alloc_context3()创建AVCodecContext结构体。
avformat_write_header():写文件头。
av_write_frame():写编码后的文件帧。
av_write_trailer():写文件尾。

(2) 新增了以下几个函数

avcodec_register_all():只注册编解码器有关的组件。

avcodec_alloc_context3():创建AVCodecContext结构体。

可以看出,相比于“完全”的编码器,这个纯净的编码器函数调用更加简单,功能相对少1些,相对来讲更加的“轻量”。

源代码

/**
* 最简单的基于FFmpeg的视频编码器(纯净版)
* Simplest FFmpeg Video Encoder Pure
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
* 本程序实现了YUV像素数据编码为视频码流(H264,MPEG2,VP8等等)。
* 它仅仅使用了libavcodec(而没有使用libavformat)。
* 是最简单的FFmpeg视频编码方面的教程。
* 通过学习本例子可以了解FFmpeg的编码流程。
* This software encode YUV420P data to video bitstream
* (Such as H.264, H.265, VP8, MPEG2 etc).
* It only uses libavcodec to encode video (without libavformat)
* It’s the simplest video encoding software based on FFmpeg.
* Suitable for beginner of FFmpeg
*/

#include <stdio.h>

extern "C"
{
#include "libavutilopt.h"
#include "libavcodecavcodec.h"
#include "libavutilimgutils.h"
};

//test different codec
#define TEST_H264 0
#define TEST_HEVC 1

int main(int argc, char* argv[])
{
AVCodec *pCodec;
AVCodecContext *pCodecCtx= NULL;
int i, ret, x, y, got_output;
FILE *fp_in;
FILE *fp_out;
AVFrame *pFrame;
AVPacket pkt;
int y_size;
int framecnt=0;

char filename_in[]="../ds_480x272.yuv";

#if TEST_HEVC
AVCodecID codec_id=AV_CODEC_ID_HEVC;
char filename_out[]="ds.hevc";
#else
AVCodecID codec_id=AV_CODEC_ID_H264;
char filename_out[]="ds.h264";
#endif

int in_w=480,in_h=272;
int framenum=100;

avcodec_register_all();

pCodec = avcodec_find_encoder(codec_id);
if (!pCodec) {
printf("Codec not found
");
return ⑴;
}
pCodecCtx = avcodec_alloc_context3(pCodec);
if (!pCodecCtx) {
printf("Could not allocate video codec context
");
return ⑴;
}
pCodecCtx->bit_rate = 400000;
pCodecCtx->width = in_w;
pCodecCtx->height = in_h;
pCodecCtx->time_base.num=1;
pCodecCtx->time_base.den=25;
pCodecCtx->gop_size = 10;
pCodecCtx->max_b_frames = 1;
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;

if (codec_id == AV_CODEC_ID_H264)
av_opt_set(pCodecCtx->priv_data, "preset", "slow", 0);

if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec
");
return ⑴;
}

pFrame = av_frame_alloc();
if (!pFrame) {
printf("Could not allocate video frame
");
return ⑴;
}
pFrame->format = pCodecCtx->pix_fmt;
pFrame->width = pCodecCtx->width;
pFrame->height = pCodecCtx->height;

ret = av_image_alloc(pFrame->data, pFrame->linesize, pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, 16);
if (ret < 0) {
printf("Could not allocate raw picture buffer
");
return ⑴;
}
//Input raw data
fp_in = fopen(filename_in, "rb");
if (!fp_in) {
printf("Could not open %s
", filename_in);
return ⑴;
}
//Output bitstream
fp_out = fopen(filename_out, "wb");
if (!fp_out) {
printf("Could not open %s
", filename_out);
return ⑴;
}

y_size = pCodecCtx->width * pCodecCtx->height;
//Encode
for (i = 0; i < framenum; i++) {
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
//Read raw YUV data
if (fread(pFrame->data[0],1,y_size,fp_in)< 0|| // Y
fread(pFrame->data[1],1,y_size/4,fp_in)< 0|| // U
fread(pFrame->data[2],1,y_size/4,fp_in)< 0){ // V
return ⑴;
}else if(feof(fp_in)){
break;
}

pFrame->pts = i;
/* encode the image */
ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_output);
if (ret < 0) {
printf("Error encoding frame
");
return ⑴;
}
if (got_output) {
printf("Succeed to encode frame: %5d size:%5d
",framecnt,pkt.size);
framecnt++;
fwrite(pkt.data, 1, pkt.size, fp_out);
av_free_packet(&pkt);
}
}
//Flush Encoder
for (got_output = 1; got_output; i++) {
ret = avcodec_encode_video2(pCodecCtx, &pkt, NULL, &got_output);
if (ret < 0) {
printf("Error encoding frame
");
return ⑴;
}
if (got_output) {
printf("Flush Encoder: Succeed to encode 1 frame! size:%5d
",pkt.size);
fwrite(pkt.data, 1, pkt.size, fp_out);
av_free_packet(&pkt);
}
}

fclose(fp_out);
avcodec_close(pCodecCtx);
av_free(pCodecCtx);
av_freep(&pFrame->data[0]);
av_frame_free(&pFrame);

return 0;
}

运行结果

通过设定定义在程序开始的宏,肯定需要使用的编码器。

//test different codec
#define TEST_H264 0
#define TEST_HEVC 1

当TEST_H264设置为1的时候,编码H.264文件“ds.h264”。
当TEST_HEVC设置为1的时候,解码HEVC文件“ds.hevc”。
输入文件是“ds_480x272.yuv”。

程序运行的截图以下所示。

输入的YUV文件以下图所示。

输出的HEVC文件以下图所示。

下载

Simplest ffmpeg encoder pure工程被作为子工程添加到了simplest ffmpeg video encoder工程中。新版的simplest ffmpeg video encoder的信息以下。

Simplest ffmpeg video encoder

SourceForge主页:https://sourceforge.net/projects/simplestffmpegvideoencoder/
CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/8322003

本程序实现了YUV像素数据编码为视频码流(H.265,H264,MPEG2,VP8等等)。

是最简单的FFmpeg视频编码方面的教程。

它包括以下两个子项目:

simplest_ffmpeg_video_encoder:最简单的基于FFmpeg的视频编码器。使用libavcodec和libavformat编码并且封装视频。
simplest_ffmpeg_video_encoder_pure:最简单的基于FFmpeg的视频编码器-纯净版。仅使用libavcodec编码视频,不使用libavformat。

波比源码 – 精品源码模版分享 | www.bobi11.com
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!

波比源码 » 最简单的基于FFmpeg的编码器-纯净版(不包含libavformat)

发表评论

Hi, 如果你对这款模板有疑问,可以跟我联系哦!

联系站长
赞助VIP 享更多特权,建议使用 QQ 登录
喜欢我嘛?喜欢就按“ctrl+D”收藏我吧!♡