【视频编码】调用x264库文件实现编码

news2024/12/24 11:31:25

调用x264库文件实现编码

整理前面记录的文章时发现还没有记录过如何实际操作x264编码器实现编码的功能,过去是通过FFmpeg调用libx264的接口来实现编码功能,这里记录一下直接调用x264的接口来实现编码的功能,同时存储编码之后的码流和重建的yuv。

代码整体的框架参考example.c文件,文件的存储参考encoder.c中的frame_dump函数。在进行文件存储时需要注意uv分量的存储是按照interleave的方式进行的

// x264_encode.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#pragma warning(disable:4996)

#include <stdio.h>
#include <malloc.h>
#include <stdint.h>
#include <inttypes.h>
#include <memory.h>

#include "x264.h"
#include "x264_config.h"

#define	BUF_SIZE	32 * 1024 * 1024

#define ENCODE_STREAM_SAVE	1
#define RECON_YUV_SAVE 1


void plane_copy_deinterleave(uint8_t* dsta, intptr_t i_dsta, uint8_t* dstb, intptr_t i_dstb,
	uint8_t* src, intptr_t i_src, int w, int h)
{
	for (int y = 0; y < h; y++, dsta += i_dsta, dstb += i_dstb, src += i_src)
		for (int x = 0; x < w; x++)
		{
			dsta[x] = src[2 * x];
			dstb[x] = src[2 * x + 1];
		}

}

int main(int argc, int** argv)
{
	FILE* fp_in_yuv;
	FILE* fp_out_h264;
	FILE* fp_out_recon;
	int width, height;
	int frames_to_encode;
	x264_param_t param;
	x264_picture_t pic_in;
	x264_picture_t pic_out;
	x264_t* h;
	int i_frame = 0;
	int i_frame_size;
	x264_nal_t* nals;
	x264_nal_t* nal;
	int i_nal;

	// set default param
	x264_param_default(&param);

	/* Get default params for preset/tuning */
	if (x264_param_default_preset(&param, "ultrafast", "zerolatency") < 0)
	{
		printf("set preset failed\n");
		return -1;
	}

	width = 1280;
	height = 720;

	/* Configure non-default params */
	param.i_bitdepth = 8;
	param.i_csp = X264_CSP_I420;
	param.i_width = width;
	param.i_height = height;
	param.b_vfr_input = 0;
	param.b_repeat_headers = 1;
	param.b_annexb = 1;
	param.b_full_recon = 1;

	/* Apply profile restrictions. */
	if (x264_param_apply_profile(&param, "high") < 0)
	{
		printf("apply profile failed\n");
		return -1;
	}

	h = x264_encoder_open(&param);
	if (!h)
	{
		printf("open encoder failed\n");
		return -1;
	}

	if (x264_picture_alloc(&pic_in, param.i_csp, param.i_width, param.i_height) < 0)
	{
		printf("alloc picture failed\n");
		return -1;
	}

	uint8_t* data_buf = (uint8_t*)malloc(BUF_SIZE * sizeof(uint8_t));
	if (!data_buf)
	{
		printf("malloc data buf failed\n");
		return -1;
	}

	fp_in_yuv = fopen("crew.yuv", "rb");
	if (!fp_in_yuv)
	{
		printf("open file failed\n");
		return -1;
	}

#if ENCODE_STREAM_SAVE
	fp_out_h264 = fopen("crew.h264", "wb");
	if (!fp_out_h264)
	{
		printf("open output file failed\b");
		return -1;
	}
#endif
#if RECON_YUV_SAVE
	fp_out_recon = fopen("crew_recon.yuv", "wb");
	if (!fp_out_recon)
	{
		printf("open recon file failed\n");
		return -1;
	}
#endif
	int rsz = 0; // read size
	int size = width * height;
	uint8_t* p = data_buf;
	int frame_cnt = 0;
	/* Encode frames */
	for (;; i_frame++)
	{
		rsz = fread(p, 1, width * height * 3 / 2, fp_in_yuv);
		printf("read size:%d\n", rsz);
		if (!rsz)
		{
			printf("end of file\n");
			goto end;
		}

		// read input data
		memcpy(pic_in.img.plane[0], p, size);
		memcpy(pic_in.img.plane[1], p + size, size / 4);
		memcpy(pic_in.img.plane[2], p + size + size / 4, size / 4);
		pic_in.i_pts = i_frame;

		i_frame_size = x264_encoder_encode(h, &nals, &i_nal, &pic_in, &pic_out);
		if (i_frame_size < 0)
		{
			printf("x264 encode failed\n");
			goto end;
		}
		else if (i_frame_size)
		{
#if ENCODE_STREAM_SAVE
			for (nal = nals; nal < nals + i_nal; nal++) 
			{
				fwrite(nal->p_payload, sizeof(uint8_t), nal->i_payload, fp_out_h264);
			}
#endif
			
#if RECON_YUV_SAVE
			// write recon yuv
			for (int y = 0; y < height; y++)
			{
				fwrite(&pic_out.img.plane[0][y * pic_out.img.i_stride[0]], sizeof(uint8_t), width, fp_out_recon);
			}

			/*
			img.plane[1]中存储uv分量的方式为交错存储,即UV UV UV....的方式
					0		1		2		3...	w_uv - 1
			0		uv		uv		uv		uv		uv
			1		uv		uv		uv		uv		uv
			2		uv		uv		uv		uv		uv
			3		uv		uv		uv		uv		uv
			...
			h_uv - 1	uv	uv		uv		uv		uv
			*/
			int cw = width >> 1;
			int ch = height >> 1;
			uint8_t* planeu = (uint8_t*)malloc(2 * (cw * ch * sizeof(uint8_t) + 32));
			if (planeu)
			{
				uint8_t* planev = planeu + cw * ch + 32 / sizeof(uint8_t);
				plane_copy_deinterleave(planeu, cw, planev, cw, pic_out.img.plane[1], pic_out.img.i_stride[1], cw, ch);
				fwrite(planeu, 1, cw * ch * sizeof(uint8_t), fp_out_recon);
				fwrite(planev, 1, cw * ch * sizeof(uint8_t), fp_out_recon);
				free(planeu);
			}
#endif
		}
		printf("frame_cnt:%d\n", frame_cnt++);
	}

end:
	x264_encoder_close(h);
	x264_picture_clean(&pic_in);
	
	fclose(fp_in_yuv);
#if ENCODE_STREAM_SAVE
	fclose(fp_out_h264);
#endif
#if RECON_YUV_SAVE
	fclose(fp_out_recon);
#endif
	free(data_buf);
	return 0;
}

编码前后yuv对比
原始yuv(crew.yuv)
在这里插入图片描述

重建yuv(crew_recon.yuv)在这里插入图片描述
编码后码流
在这里插入图片描述

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

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

相关文章

线上预约陪诊平台医院陪诊系统源码就医陪护小程序APP开发

项目分析 随着医疗行业的数字化转型和人们对健康需求的日益增长&#xff0c;线上预约陪诊系统作为一种新兴的医疗服务模式&#xff0c;正逐渐受到市场的关注和认可。本文将从市场前景、使用人群、盈利模式以及竞品分析等多个角度&#xff0c;全面探讨线上预约陪诊系统的技术性…

Windows长文件名支持

Windows 长文件名支持 &#x1f354;打开注册表&#x1f957;激活 &#x1f354;打开注册表 &#x1f957;激活 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem双击进入编辑模式 把0改成1&#xff0c;确定

【高校主办 | 快录用,稳定EI检索 !ACM独立出版】2024智能物联与计算国际学术会议(AITC 2024,8月30-9月1)

为探讨智能物联与计算技术所涉领域的最新研究和发展趋势&#xff0c;2024智能物联与计算学术大会&#xff08;AITC 2024&#xff09;将于2024年8月30日-9月1日在中国 贵阳举行。 AITC 2024由中国计算机学会、中国人工智能学会、浙江省科学技术协会、浙江工业大学、浙江省人工智…

Moba案例帧同步

1.设置环境光 2.搭建客户端框架 a.对上述的模块基类&#xff08;都是单例类&#xff0c;都有初始化方法&#xff09; b.隐藏登录页面&#xff08;得到Canvas的子对象失活&#xff09; c.设置根对象过场景不被移除 tip&#xff1a;模块都是继承mono的&#xff0c;不能直接ne…

AI写作进阶 运用思维链CoT让AI写出来的东西更有“人味儿“

嗨&#xff0c;大家好&#xff0c;我是大象。 AI 写作今年可谓是大放光芒&#xff0c;从年初的 AI 自动摘要生成工具到年中的 AI 情感分析引擎&#xff0c;再到现在备受推崇的 AI 故事创作助手&#xff0c;一次次让 AI 写作成为众人热议的焦点。 大家惊叹 AI 写作的神奇能力&am…

DockerCompose中使用自定义网络的方式实现部署SpringBoot+Mysql+Redis

场景 Docker中Docker网络-理解Docker0与自定义网络的使用示例&#xff1a; Docker中Docker网络-理解Docker0与自定义网络的使用示例_docker 配置 docker0-CSDN博客 Docker中使用自定义网络方式实现Redis集群部署与测试流程&#xff1a; Docker中使用自定义网络方式实现Redi…

【工具测评】腾讯云 AI 代码助手——你的下一位编码“伙伴”

文章目录 引言一、VS Code下安装腾讯云 AI 代码助手插件二、腾讯云AI代码助手使用实例2.1 通过对话生成代码2.2 通过注释生成代码2.3 规范、修复代码错误2.4 人工智能技术对话&#xff0c;有求必应2.5 智能代码分析&#xff0c;快速上手历史代码 三、获得的帮助与提升四、建议五…

nvidia系列教程-AGX-Orin系统启动异常解决(eeprom: Failed to read I2C slave device)

目录 前言 一、问题描述 二、问题解决 总结 前言 在使用 NVIDIA Jetson 系列开发板时&#xff0c;可能会遇到启动时的错误提示&#xff0c;例如 eeprom: Failed to read I2C slave device。这个错误通常出现在设备启动日志中&#xff0c;可能会导致设备无法正常启动或功能受限…

vue3 input加一个回车,直接进行查询的事件,然后提示v-on event ‘@pressEnter‘ must be hyphenated.

1、加个回车的事件&#xff0c;直接就有个提示&#xff0c;没有报错 2、v-on事件“pressEnter”必须连字符这个是中文意思&#xff0c;也就是说不要写成个驼峰的形式&#xff0c;要改为-的形式。 3、稍改下&#xff0c;就可以解决&#xff1a; 4、其实不改也没有事的&#xff…

星际牛仔1998年SUNRISE制作的原创电视动画

《星际牛仔》是日本SUNRISE动画公司制作的原创电视动画。于1998年4月3日-1999年4月23日在东京电视台和WOWOW播出&#xff0c;同年夺得第三回神户动画奖的年度最佳电视动画奖&#xff0c;2000年获得日本科幻大会星云奖。 动画剧场版《星际牛仔&#xff1a;天国之扉》2001年9月1…

Vue快速入门(二)——选项式 API介绍

当前 Vue 的最新稳定版本是 v3.4.35&#xff0c;而Vue 2 已于 2023 年 12 月 31 日停止维护。 Vue2的书写风格是选项式 API &#xff0c;而Vue3的书写风格同时支持选项式API和组合式 API。那我们选哪一种风格的API来学习呢&#xff1f;我建议先学习选项式API&#xff0c;然后再…

yolov5更换MobileNetV3的主干网络

目录 1.定义网络 2.将test_MobileNetV3.py上面的代码复制粘贴到如下文件里面 2.1复制需要更改的原来的网络如何改结构 3.更改yolo.py注册网络 1.定义网络 1. 宽度为0.5的mobilenetv2网络的结构图 在主干网络上面可以重新定义成三层&#xff0c;编号从0开始 如图是MobileNet…

如何在不同阶段选择合适的项目管理软件?

作为一个资深的产品经理&#xff0c;我有幸在过去的20多年里&#xff0c;接触过很多不同行业&#xff0c;从互联网行业、软件行业&#xff0c;到金融行业、制造行业&#xff0c;所积累的丰富经验让我对项目管理软件的选择有了更深入的了解和认识。 不同行业的项目管理痛点 每个…

如果要做一个重要的决定, 有什么好的方法可以让我做出正确的选择

做出重要决定时&#xff0c;以下方法可以帮助你做出更正确的选择&#xff1a; 文章目录 1. 收集信息和数据2. 制定明确的目标和标准3. 分析和评估选项4. 考虑长远利益5. 制定备选方案和应急计划6. 寻求意见和建议7. 直觉和情感的平衡8. 制定决策计划并执行 分析和评估选项1. 决…

【JavaEE】初步认识多线程

​ &#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 &#x1f3b7; 一.线程 1.概念 线程&#xff08;Thread&#xff09;是在计算机科学中&#xff0c;特别是操作系统领域里的一个关键概念。它是操作系统能够进…

极狐GitLab 走进合肥,受邀参与合肥市政府举办的“开源聚力,合创未来”第一期活动

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

惊爆!英伟达那神秘的视频基础模型「Cosmos」竟然浮出水面,然而其数据居然是靠窃取得来!

&#x1f431; 个人主页&#xff1a;TechCodeAI启航&#xff0c;公众号&#xff1a;TechCodeAI &#x1f64b;‍♂️ 作者简介&#xff1a;2020参加工作&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab; 优质专…

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——5Webscoket节点的使用

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——5Webscoket节点的使用 ​ 有了前面几篇文章的铺垫&#xff0c;现在已经可以实现我到手测试那一步的 1.解读usb_websocket_display.launch.py ​ 首先进入这个目录/root/dev_ws/src/origincar/originca…

WPF-MVVM架构

在WPF&#xff08;Windows Presentation Foundation&#xff09;开发中&#xff0c;MVVM&#xff08;Model-View-ViewModel&#xff09;是一种非常流行的设计模式&#xff0c;它旨在将应用程序的UI逻辑与业务逻辑和数据模型分离&#xff0c;从而提高代码的可维护性、可测试性和…

4.12.束搜索

束搜索 ​ 为了量化解码器的计算代价&#xff0c;用 y y y表示输出词表&#xff0c;其中包含 < e o s > <eos> <eos>&#xff0c;词表大小则为 ∣ y ∣ |y| ∣y∣&#xff0c;指定输出序列的最大词元数为 T ′ T T′&#xff0c;则我们的目标是从所有 O ( ∣…