使用FFMPEG将YUV编码为H.264

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

本文介绍一个如何使用FFmpeg实现YUV420P的像素数据编码为H.264的压缩编码数据。

项目十分简单,没有多少代码在其中。弄清楚了该项目的代码也就基本弄清楚了FFMPEG的编码流程。

本程序使用的FFmpeg版本为2.2.2(版本较新),开发平台为VC2008(VC2010估计很多人都用不了)。

相关配置已经完成,只需下载源码运行即可。

下面直接上代码:

/* 
 *将YUV420P进行H264编码压缩
 *码术 codemanship
 *邮箱: f.chen1989@gmail.com
 *http://blog.csdn.net/codemanship
 *微信公众号: codemanship
 *本程序实现了YUV420P的像素数据编码为H.264的压缩编码数据
 *是最简单的FFmpeg视频编码方面的教程。
 *通过学习本例子可以了解FFmpeg的图片压缩过程。
*/
#ifndef INT64_C
#define INT64_C
#define UINT64_C
#endif
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavutil/imgutils.h"
#include "libavutil/parseutils.h"
#include "libswscale/swscale.h"
#include "libavformat/avformat.h"
};
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"swscale.lib")
#pragma comment(lib,"avutil.lib")

#define  FrameCount 50
static void fill_yuv_image(uint8_t *data[4], int linesize[4],
                           int width, int height, int frame_index)
{
    int x, y;

    /* Y */
    for (y = 0; y < height; y++)
        for (x = 0; x < width; x++)
            data[0][y * linesize[0] + x] = x + y + frame_index * 3;

    /* Cb and Cr */
    for (y = 0; y < height / 2; y++) {
        for (x = 0; x < width / 2; x++) {
            data[1][y * linesize[1] + x] = 128 + y + frame_index * 2;
            data[2][y * linesize[2] + x] = 64 + x + frame_index * 5;
        }
    }
}



int main(int argc, char **argv)
{
	AVFormatContext* pFormatCtx;
	AVOutputFormat* fmt;
	AVStream* video_st;
	AVCodecContext* pCodecCtx;
	AVCodec* pCodec;
	AVFrame* srcFrame;
	int size;

	int width=640,height=480;
	const char* outfilename = "out_640x480.h264";

	av_register_all();
	pFormatCtx = avformat_alloc_context();
	fmt = av_guess_format(NULL, outfilename, NULL);
	pFormatCtx->oformat = fmt;

	if (avio_open(&pFormatCtx->pb,outfilename, AVIO_FLAG_READ_WRITE) < 0)
	{
		printf("open file failed.");
		exit(1);
	}

	video_st = av_new_stream(pFormatCtx, 0);
	if (video_st==NULL)
	{
		exit(1);
	}
	pCodecCtx = video_st->codec;
	pCodecCtx->codec_id = fmt->video_codec;
	pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
	pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
	pCodecCtx->width = width;  
	pCodecCtx->height = height;
	pCodecCtx->time_base.num = 1;  
	pCodecCtx->time_base.den = 25;  
	pCodecCtx->bit_rate = 40000;  
	pCodecCtx->gop_size=10;
	pCodecCtx->qmin = 10;
	pCodecCtx->qmax = 30;

	//输出格式信息
	av_dump_format(pFormatCtx, 0, outfilename, 1);

	pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
	if (!pCodec)
	{
		fprintf(stderr, "Codec not found\n");
		exit(1);
	}
	//设置X264编码的参数,减小延迟
	AVDictionary *opts = NULL;
	av_dict_set(&opts, "profile", "baseline", 0); 
	av_dict_set(&opts, "preset", "fast", 0);
	av_dict_set(&opts, "tune", "zerolatency", 0);
	if (avcodec_open2(pCodecCtx, pCodec,&opts) < 0)
	{
		fprintf(stderr, "Could not open codec\n");
		exit(1);
	}
	srcFrame = av_frame_alloc();
	size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
	/* allocate source and destination image buffers */
	if ((av_image_alloc(srcFrame->data, srcFrame->linesize,
		width, height, PIX_FMT_YUV420P, 16)) < 0) {
			fprintf(stderr, "Could not allocate source image\n");
			exit(1);
	}
	//写文件头
	avformat_write_header(pFormatCtx,NULL);

	AVPacket pkt;
	int y_size = pCodecCtx->width * pCodecCtx->height;
	av_new_packet(&pkt,y_size*3);

	for (int i=0; i<FrameCount; i++){
		/* generate synthetic video */
		fill_yuv_image(srcFrame->data,srcFrame->linesize,width,height,i);
		/*设置pts*/
		srcFrame->pts=i;
		int got_picture=0;
		/*编码*/
		int ret = avcodec_encode_video2(pCodecCtx, &pkt,srcFrame, &got_picture);
		if(ret < 0)
		{
			fprintf(stderr, "Error encoding frame\n");
			return -1;
		}
		if (got_picture==1)
		{
			printf("Write frame %3d (size=%5d)\n", i, pkt.size);
			pkt.stream_index = video_st->index;
			ret = av_write_frame(pFormatCtx, &pkt);
			av_free_packet(&pkt);
		}
	}

	//写文件尾
	av_write_trailer(pFormatCtx);
	//清理
	if (video_st)
	{
		avcodec_close(video_st->codec);
		av_freep(srcFrame);
	}
	avio_close(pFormatCtx->pb);
	avformat_free_context(pFormatCtx);
	return 0;
}

程序截图


编码前YUV数据


编码后H264码流


ffmpeg-4.2.2:视频编码流程(yuv编码h.264 这是基于FFMPEG的视频编码器,可以将yuv视频元数据编码h264压缩编码数据。 主要是记录一下自己学习FFMPEG时总结的视频编码流程。 ffmpeg版本:ffmpeg-4.2.2 libx264版本:x264-snapshot-20191023-2245-stable 流程图 简单介绍下各个函数的功能: avcodec_find_encoder_by_name():通过编码器的名字查找编码... 阅读详情

相关推荐

FFmpeg编码实战】(1)将YUV420P图片集编码成H.264视频文件

FFmpeg编码实战】(1)将YUV420P图片集编码H264视频文件 在前文《【FFmpeg编程实战】(2)分离视频文件中的视频流每一张图片(进阶)》中, 我们实现了,将一个H264编码的视频文件,解码成一张张的YUV420P 图片。 本文,我们来实现一下,将这些解码后的YUV420P图片,重新编码成一个新的H.264视频文件。 YUV420P图片如下: 好,开始Code吧^_^ 《ffmpeg将视频编码H264格式》 《ffmpeg视频编解码实例》 《FFmpeg解码处理3-视频编码

|~~~热爱生活、努力学习的小伙汁~~~| 1864

FFMPEGYUV420P格式数据编码成H.264

FFMPEG系列笔记记录 第一章 FFMPEG编译 第二章 FFMPEG学习 从USB摄像头捕获YUV数据 第三章 FFMPEG学习 将YUV420P格式数据编码成H.264 FFMPEG学习 将YUV420P格式数据编码成H.264FFMPEG系列笔记记录前言一、编码流程二、代码实现三、实现效果四、总结 前言 在学习FFMPEG过程中,我们需要获取到H264码流,但是我们采集到的一般都是YUV格式的数据,这里记录一下,用FFMPEG将采集到的YUV数据编码成H.264码流的学习过程, 并把遇到的问题

qq_38750519的博客 4083

FFmpeg编码实战】(2)将YUV420P图片集编码成H.264视频文件(方法二)

FFmpeg编码实战】(2)将YUV420P图片集编码成H.264视频文件(方法二) 在前文《【FFmpeg编码实战】(1)将YUV420P图片集编码成H.264视频文件》中,我们实现了将一些YUV420P图片集编码成H.264视频。 其方法是通过 AVFormatContext 这个已经封装好的接口来实现的, 打开文件时使用的是 avio_open,写视频内容时通过的是av_interleaved_write_frame,这些都是已经封装的非常好的方法。 但我们学习,不能局限于此,为学习更详细的原理,

|~~~热爱生活、努力学习的小伙汁~~~| 1940

FFMpeg视频开发与应用基础】五、调用FFMpeg SDK封装音频和视频为视频文件

FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK》视频教程已经在“CSDN学院”上线,视频中包含了从0开始逐行代码实现FFMpeg视频开发的过程,欢迎观看!链接地址:FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK工程代码地址:FFmpeg_Tutorial音频和视频的封装过程为解封装的逆过程,即将独立的音频数据和视频数据按照容器文件所规定的格式封装为一个完整的视频文件

Workshop of Wenjie.Yin 7415

使用ffmpeg接口将YUV编码为h.264

目录 1. 第一步: 解析数据参数 2. 第二步: 按要求初始化ffmpeg结构2.1. 第一步: 根据编解码器ID,获取编解码器指针 2.2. 第二步: 获取AVCodecContext实例。通过编解码器AVCodec指针,获取编解码器上下文 2.3. 第三步: 设置编码器参数 2.4. 第四步: 根据AVCodec和AVCodecContext实例,打开编码器 2.5. 第五步:配置编码的输入数

timesir的博客 1551

使用ffmpeg3.x进行YUV420P->H.264的简单转码

本文代码是基于雷霄骅的《最简单的基于FFMPEG的视频编码器(YUV编码为H.264)》一文修改得来的。由于雷霄骅原文中采用的API在新版本ffmpeg中,关健的编码API发生了变化,我在此基础上,参考了ffmpeg3.x的sample和header修改后得到。主要的变化是在编码API上,原来是通过avcodec_encode_video2()来完成编码的,现在编码API变为avcodec_send

我的玻璃盒子 2552

.ffmpegyuv数据进行h264编码

我检查了编码器的配置,发现并没有问题,那就是编码的过程中,最后是第二天早上仔细看了一下,原来我编码的代码里面第一行打印了frame的参数,但是最后冲刷编码器的时候,传入的是NULL,导致最后冲刷解码器崩溃了,不过并没有报错,只是停止了编码并卡顿了一下,这是我在windows上的情况,已解决。(2)yuv420p的数据格式:四个y分量和一个u、一个v分量共占6个字节,同上,6/4=1.5,所以每个yuv420p像素占的字节数为1.5,得到每个yuv420p帧的字节数为:w*h*1.5。

Ricardo的博客 610

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

本文介绍一个最简单的基于FFMPEG的视频编码器。该编码器实现了YUV420P的像素数据编码为H.264压缩编码数据。编码器代码十分简单,但是每一行代码都很重要,适合好好研究一下。弄清楚了本代码也就基本弄清楚了FFMPEG编码流程。目前我虽然已经调通了程序,但是还是有些地方没有完全搞明白,需要下一步继续探究然后补充内容。 本程序使用最新版的类库(编译时间为2014.5.6),开发平台为VC2

雷霄骅(leixiaohua1020)的专栏 18万+

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

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

ProgramNovice的博客 1403

FFmpegYUV420P格式数据编码成H.264

一、编码流程 H264 二、代码实现 /*--------------------------------------------------------- * 文件名:transfer.c * 文件说明:实现YUV数据编码成H.264文件 * 作者:hzg * 修改记录: * 1、修改了申请

m0_60259116的博客 1671

致敬雷神【最简单的基于FFMPEG的视频编码器(YUV编码为H.264)】最新ffmpeg编译

最近开始学习ffmpeg.学到 雷神的 最简单的基于FFMPEG的视频编码器(YUV编码为H.264) https://blog.csdn.net/leixiaohua1020/article/details/25430425 发觉2020.5月的版本编译使用时已经运行不正确。后来修改了一点东西才成功yuvb编码出mp4. 首先是yuv文件。我没下他对应的工程文件,用的是640x360_yuv420p.yuv 对应要修改下 int in_w=640,in_h=360; ...

smwhotjay的专栏 656

浅显易懂 FFmpeg学习(05)— QT+FFmpeg编码YUV编H.264

本篇,作者将分享如何使用FFmpeg解码后的YUV数据编码成H.246格式视频。

孤生i的博客 1594
上一篇: windows平台下使用ffmpeg对视频进行H264编码总结
下一篇: 学习Golang语言(6):类型--切片
codemanship
博客等级 码龄12年 31粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值