使用FFMPEG库将YUV编码为H264

news2024/9/20 10:59:03

准备

ffmpeg 4.4

p准备一段yuv420p的格式的视频原始数据

这里我们使用命令直接提取

 ffmpeg -i .\beautlWorld.mp4 -pixel_format yuv420p  -s 1280x720 yuv420p_1280x720.yuv

编码流程

大致可以分为以下几步:

1.初始化编码器并设置参数

2.初始化AVPacket和AVFrame,设置参数

3.读取视频文件,进行编码

4.释放内存,结束

编码

以下是完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavutil/time.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
}

using namespace std;

const char* inFileName = "D:/测试工程/sound/yuv420p_1280x720.yuv";
const char* outFileName = "D:/测试工程/sound/3333encode_yuv420p_1280x720.h264";


int encode(AVCodecContext* codecContent, AVPacket * packet, AVFrame* frame, FILE* outFile)
{
	//解码

	int ret = avcodec_send_frame(codecContent, frame);
	if (ret < 0)
	{
		fprintf(stderr, "Error sending a frame for encoding\n");
		return -1;
	}

	while (ret == 0)
	{

		ret = avcodec_receive_packet(codecContent, packet);

		if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
			return 0;
		}
		else if (ret < 0) {
			fprintf(stderr, "Error encoding video frame\n");
			return -1;
		}

		if (ret == 0)
		{
			fwrite(packet->data, 1, packet->size, outFile);
		}

	}
}



int main(int argc, char* argv[])
{

	int ret = 0;

	AVCodec* codec = nullptr;
	AVCodecContext* codecContent = nullptr;
	AVPacket* packet = nullptr;
	AVFrame* frame = nullptr;

	FILE* inFile = nullptr;
	FILE* outFile = nullptr;

   

	//编码器初始化
	codec = avcodec_find_encoder(AV_CODEC_ID_H264);
	if (codec == nullptr)
	{
		printf("could not find h264 encoder!");
		return -1;
	}

	codecContent = avcodec_alloc_context3(codec);
	if (codecContent == nullptr)
	{
		printf("could not alloc h264 content!");
		return -1;
	}
	
	//必设参数
	codecContent->width = 1280;
	codecContent->height = 720;
	codecContent->time_base = AVRational{ 1, 25 };

	codecContent->pix_fmt = AV_PIX_FMT_YUV420P;
	codecContent->gop_size = 25; //关键帧间隔,默认250
	codecContent->framerate = AVRational{ 25, 1 };
	 

	ret = avcodec_open2(codecContent, codec, NULL);
	if (ret < 0) {
		fprintf(stderr, "Could not open codec: %d\n", ret);
		exit(1);
	}


	packet = av_packet_alloc();
	if (packet == nullptr)
	{
		printf("alloc packet error");
		return -1;
	}

	frame = av_frame_alloc();
	if (packet == nullptr)
	{
		printf("alloc frame error");
		return -1;
	}


	frame->width = codecContent->width;
	frame->height = codecContent->height;
	frame->format = codecContent->pix_fmt;

	ret =  av_frame_get_buffer(frame, 0);
	if (ret)
	{
		printf("alloc frame buffer error!");
		return -1;
	}

	inFile = fopen(inFileName, "rb");
	if (inFile == nullptr)
	{
		printf("error to open file: %s\n", inFileName);
		return -1;
	}

	outFile = fopen(outFileName, "wb");
	if (inFile == nullptr)
	{
		printf("error to open file: %s\n", outFileName);
		return -1;
	}

	int framecount = 0;

	frame->pts = 0;

	while (!feof(inFile))
	{
		ret = av_frame_is_writable(frame);
		if (ret < 0) 
		{
			ret = av_frame_make_writable(frame);
		}
		

		fread(frame->data[0], 1, frame->width * frame->height, inFile); //y
		fread(frame->data[1], 1, frame->width * frame->height / 4, inFile); //u
		fread(frame->data[2], 1, frame->width * frame->height / 4, inFile);  //v

		printf("encode frame num: %d\n", ++framecount);


		frame->pts += 1000 / (codecContent->time_base.den / codecContent->time_base.num);
		encode(codecContent, packet, frame, outFile);

	}

	encode(codecContent, packet, nullptr, outFile);
	

	
	av_packet_free(&packet);
	av_frame_free(&frame);

	avcodec_free_context(&codecContent);

	

	fclose(inFile);
	fclose(outFile);

	return 0;
}

小结

AVCodecContext

对于视频编码器而言必须设置以下参数:

AVRational time_base;

int width, height;

以下由用户设置,可选

gop_size: 默认250,也就是每250帧一个关键帧,可选设置

max_b_frames: 默认3, b帧最大连续个数

bit_rate: 平均比特率

avcodec_alloc_context3

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

为AVCodecContext结构申请空间,并使用默认值初始化!最后使用avcodec_free_context进行释放。

avcodec_open2

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

调用该函数前:time_base(也就是每帧显示的时间),width(帧宽), height(帧高)

av_frame_get_buffer

int av_frame_get_buffer(AVFrame *frame, int align);

为音视频分配数据存储空间。调用该函数前需要设置AVFRAME几个初始值。

音频:1.sample format  2.nb_samples 3.channel_layout

视频:1.pixel format 2.width 3.height  

align:直接对其,默认给0,根据当前CPU自行设置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/448987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java基础 1】Java 环境搭建

&#x1f34a; 欢迎加入社区&#xff0c;寒冬更应该抱团学习&#xff1a;Java社区 &#x1f4c6; 最近更新&#xff1a;2023年4月22日 文章目录 1 java发展史及特点1.1 发展史1.2 Java 特点1.2.1 可以做什么&#xff1f;1.2.2 特性 2 Java 跨平台原理2.1 两种核心机制2.2 JVM…

Activiti入门

目录 一、了解工作流 1、什么是工作流 2、工作流引擎 3、常见工作流引擎 4、Activiti7概述 4.1、Activiti介绍 4.2、建模语言BPMN 4.3、Activiti使用流程 一、了解工作流 1、什么是工作流 工作流&#xff08;Workflow&#xff09;&#xff0c;就是通过计算机对业务流…

SSeg总体思路

1&#xff1a;在train中加载train和test数据集。 2&#xff1a;指定数据集为kitti&#xff0c;确定训练验证的batchsize。 3&#xff1a;提前定义好数据预处理&#xff0c;首先是几何变换&#xff0c;包括随机裁切等。 4&#xff1a;然后是外观变换&#xff0c;包括高斯滤波…

计算同列排斥力的一种可能方法

假设神经网络同列数字之间有一种排斥力&#xff0c;且这种排斥力也与距离的平方成反比。设0是环境&#xff0c;1是粒子&#xff0c;则两个1之间的排斥力就是距离平方的倒数。 考虑任意遥远的两个粒子之间都有排斥力&#xff0c;可以得到同列排斥力的计算方法为 如计算"01…

移动硬盘数据恢复软件实用技巧

在我们日常生活中&#xff0c;移动硬盘已经成为了我们不可或缺的存储设备之一。但是&#xff0c;由于各种原因&#xff0c;移动硬盘中的数据有时会丢失或损坏&#xff0c;这时候我们就需要使用移动硬盘数据恢复软件来帮助恢复数据。那么&#xff0c;移动硬盘数据恢复软件有哪些…

Windows环境下实现设计模式——中介者模式(JAVA版)

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天总结一下Windows环境下如何编程实现中介者模式&#xff08;设计模式&#xff09;。 不知道大家有没有这样的感觉&#xff0c;看了一大堆编程和设计模式的书&#xff0c;却还是很难理解设计模式&#xff…

modbus指令测试

目录 一.抓包二.modbus与plc三.usb包分析四.编写modbus指令测试五.调试工具 一.抓包 1.串口抓包&#xff1f;wireshark&#xff01;: https://xuxeu.github.io/uart-catch/ 2.Windows&Linux USB抓包方法总结:https://zhuanlan.zhihu.com/p/267820933 3.USB The Setup Pack…

(“树” 之 前中后序遍历 ) 94. 二叉树的中序遍历 ——【Leetcode每日一题】

基础概念&#xff1a;前中后序遍历 1/ \2 3/ \ \ 4 5 6层次遍历顺序&#xff1a;[1 2 3 4 5 6]前序遍历顺序&#xff1a;[1 2 4 5 3 6]中序遍历顺序&#xff1a;[4 2 5 1 3 6]后序遍历顺序&#xff1a;[4 5 2 6 3 1] 层次遍历使用 BFS 实现&#xff0c;利用的就是 BFS…

一文搞懂Java中的异常问题

思考几个问题 1&#xff1a;JavaWeb系统中&#xff0c;我的代码未做任何处理&#xff0c;报错了还会往下执行吗&#xff1f; 2&#xff1a;JavaWeb系统中&#xff0c;我的代码做了 try catch finally, 报错了还会往下执行吗&#xff1f; 3&#xff1a;JavaWeb系统中&#xff0c…

软考高频考点--《项目采购管理》

现在离2023年上半年软考还有一个多月的时间&#xff0c;相信各位小伙伴们已经进入紧张的备考状态了。 小编今天为大家整理了软考的一些高频考点–《项目采购管理》&#xff0c;希望对正在备考软考的你有所帮助&#xff01; 采购是从项目团队外部获得产品、服务或成果的完整的购…

alsa_lib移植到IMX6ULL

简介 ALSA是Advanced Linux Sound Architecture的缩写&#xff0c;目前已经成为了linux下的主流音频体系架构&#xff0c;提供了音频和MIDI的支持。 交叉编译alsa_lib和alsa_utils 下载alsa_lib 在官网中下载AlsaProject 编译 先将文件解压&#xff0c;然后进入alsa_lib…

运筹说 第94期|论文速读之基于关键路径的置换流水车间调度问题

前几期的推送已经讲解了网络计划的基本知识、数学模型和相关算法&#xff0c;相信大家对网络计划已经有了充分的了解&#xff0c;这期小编将带大家一起来读一篇基于关键路径的置换流水车间调度问题的文章。 1.文章信息 题目&#xff1a;An efficient critical path based meth…

手把手教你分析解决MySQL死锁问题

在生产环境中出现MySQL死锁问题该如何排查和解决呢&#xff0c;本文将模拟真实死锁场景进行排查&#xff0c;最后总结下实际开发中如何尽量避免死锁发生。 一、准备好相关数据和环境 当前自己的数据版本是8.0.22 mysql> select version; ----------- | version | --------…

Arduino 多任务软件定时器:Simpletimer库的使用

Arduino 多任务软件定时器:Simpletimer库的使用 📌Simpletimer库Arduino官方介绍信息:https://playground.arduino.cc/Code/SimpleTimer/✨该库也是利用了millis()函数来实现任务轮询的。与之类似的还有ESP8266固件自带的Ticker库,但是Ticker库使用仅限于ESP8266内调用,Si…

Discourse Google Analytics 3 的升级提示

根据 Google 官方的消息&#xff1a; Google Analytics&#xff08;分析&#xff09;4 是我们的新一代效果衡量解决方案&#xff0c;即将取代 Universal Analytics。自 2023 年 7 月 1 日起&#xff0c;标准 Universal Analytics 媒体资源将停止处理新的命中数据。如果您仍在使…

linux-01-基础回顾

文章目录 Linux-Day01课程内容1. 前言1.1 什么是Linux1.2 为什么要学Linux1.3 学完Linux能干什么 2. Linux简介2.1 主流操作系统2.2 Linux发展历史2.3 Linux系统版本 3. Linux安装3.1 安装方式介绍3.2 安装VMware3.3 安装Linux TODO3.4 网卡设置3.5 安装SSH连接工具3.5.1 SSH连…

【Python】【进阶篇】1、Django是什么?

目录 1、Django是什么&#xff1f;1. Django的由来2. Django的命名3. Django的版本发布1) 功能版2) 补丁版3) LTS 版本 4. Django框架的特点 1、Django是什么&#xff1f; Django 是使用 Python 语言开发的一款免费而且开源的 Web 应用框架。由于 Python 语言的跨平台性&#…

IDA调试

IDA动态调试 有时候程序在运行过程中会生成一些关键的数值&#xff0c;而人力通过静态分析的结果模拟程序的运行来推出这些中间的数值可能很麻烦。简单重复的工作是计算机所擅长的而不是人&#xff0c;所以我们可以让这个程序运行起来&#xff0c;得到这些中间过程的数值。这就…

VLAN与access接口、hybrid接口实验

[r1]dhcp enable //开启DHC0功能P [r1-GigabitEthernet0/0/0]int g 0/0/0.1 [r1-GigabitEthernet0/0/0.1]ip add 192.168.1.1 24 [r1-GigabitEthernet0/0/0.1]dhcp select interface //接口地址池 [r1-GigabitEthernet0/0/0.1]dhcp server dns-list 8.8.8.8 [r1-GigabitEthern…

【Linux】输入系统详述 + 触摸屏应用实战(tslib)

目录简述 前言&#xff1a; 一、输入系统 二、Linux输入系统框架 &#xff08;1&#xff09;输入系统的驱动层 &#xff08;2&#xff09;输入系统核心层 &#xff08;3&#xff09;输入系统事件层 三、APP访问硬件的方式 &#xff08;1&#xff09;查询方式、休眠-唤醒…