FFmpeg H264增加SEI

2023-11-18

先看使用场景:
https://blog.csdn.net/lsheevyfg/article/details/80951415
https://www.jianshu.com/p/4d9120dfcd69
参考文章:
https://blog.csdn.net/ab7936573/article/details/74135909

FFMPEG使用版本为3.2.2
直接上代码:
EvHeade.h

#ifdef __cplusplus
extern "C"
{
#endif
 
#include "libavcodec\avcodec.h"
#include "libavformat\avformat.h"
#include "libavutil\avutil.h"
 
#ifdef __cplusplus
}
#endif
 
 
#ifdef _WIN32
 
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avdevice.lib")
#pragma comment(lib,"avfilter.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"postproc.lib")
#pragma comment(lib,"swresample.lib")
#pragma comment(lib,"swscale.lib")
 
#endif

sei_packet.h

#ifndef SEI_PACKET_H
#define SEI_PACKET_H
 
#include <stdint.h>
 
uint32_t reversebytes(uint32_t value);
uint32_t get_sei_packet_size(uint32_t size);
int fill_sei_packet(unsigned char * packet, bool isAnnexb, const char * content, uint32_t size);
int get_sei_content(unsigned char * packet, uint32_t size, char * buffer, int *count);
#pragma once

#endif

sei_packet.cpp

#include "sei_packet.h"
#include <stdio.h>
#include <string.h>
 
#define min(X,Y) ((X) < (Y) ? (X) : (Y))
 
#define UUID_SIZE 16
 
//FFMPEG uuid
//static unsigned char uuid[] = { 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef };
//self UUID
static unsigned char uuid[] = { 0x54, 0x80, 0x83, 0x97, 0xf0, 0x23, 0x47, 0x4b, 0xb7, 0xf7, 0x4f, 0x32, 0xb5, 0x4e, 0x06, 0xac };
 
//开始码
static unsigned char start_code[] = {0x00,0x00,0x00,0x01};
 
uint32_t reversebytes(uint32_t value) {
	return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
		(value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;
}
 
uint32_t get_sei_nalu_size(uint32_t content)
{
	//SEI payload size
	uint32_t sei_payload_size = content + UUID_SIZE;
	//NALU + payload类型 + 数据长度 + 数据
	uint32_t sei_size = 1 + 1 + (sei_payload_size / 0xFF + (sei_payload_size % 0xFF != 0 ? 1 : 0)) + sei_payload_size;
	//截止码
	uint32_t tail_size = 2;
	if (sei_size % 2 == 1)
	{
		tail_size -= 1;
	}
	sei_size += tail_size;
 
	return sei_size;
}
 
uint32_t get_sei_packet_size(uint32_t size)
{
	return get_sei_nalu_size(size) + 4;
}
 
int fill_sei_packet(unsigned char * packet,bool isAnnexb, const char * content, uint32_t size)
{
	unsigned char * data = (unsigned char*)packet;
	unsigned int nalu_size = (unsigned int)get_sei_nalu_size(size);
	uint32_t sei_size = nalu_size;
	//大端转小端
	nalu_size = reversebytes(nalu_size);
 
	//NALU开始码
	unsigned int * size_ptr = &nalu_size;
	if (isAnnexb)
	{
		memcpy(data, start_code, sizeof(unsigned int));
	}
	else
	{
		memcpy(data, size_ptr, sizeof(unsigned int));
	}
	data += sizeof(unsigned int);
 
	unsigned char * sei = data;
	//NAL header
	*data++ = 6; //SEI
	//sei payload type
	*data++ = 5; //unregister
	size_t sei_payload_size = size + UUID_SIZE;
	//数据长度
	while (true)
	{
		*data++ = (sei_payload_size >= 0xFF ? 0xFF : (char)sei_payload_size);
		if (sei_payload_size < 0xFF) break;
		sei_payload_size -= 0xFF;
	}
 
	//UUID
	memcpy(data, uuid, UUID_SIZE);
	data += UUID_SIZE;
	//数据
	memcpy(data, content, size);
	data += size;
 
	//tail 截止对齐码
	if (sei + sei_size - data == 1)
	{
		*data = 0x80;
	}
	else if (sei + sei_size - data == 2)
	{
		*data++ = 0x00;
		*data++ = 0x80;
	}
 
	return true;
}
 
int get_sei_buffer(unsigned char * data, uint32_t size, char * buffer, int *count)
{
	unsigned char * sei = data;
	int sei_type = 0;
	unsigned sei_size = 0;
	//payload type
	do {
		sei_type += *sei;
	} while (*sei++ == 255);
	//数据长度
	do {
		sei_size += *sei;
	} while (*sei++ == 255);
 
	//检查UUID
	if (sei_size >= UUID_SIZE && sei_size <= (data + size - sei) &&
		sei_type == 5 && memcmp(sei, uuid, UUID_SIZE) == 0)
	{
		sei += UUID_SIZE;
		sei_size -= UUID_SIZE;
 
		if (buffer != NULL && count != NULL)
		{
			if (*count > (int)sei_size)
			{
				memcpy(buffer, sei, sei_size);
			}
		}
		if (count != NULL)
		{
			*count = sei_size;
		}
		return sei_size;
	}
	return -1;
}
 
int get_sei_content(unsigned char * packet, uint32_t size,char * buffer,int *count)
{
	unsigned char ANNEXB_CODE_LOW[] = { 0x00,0x00,0x00,0x01 };
	unsigned char ANNEXB_CODE[] = { 0x00,0x00,0x00,0x01 };
 
	unsigned char *data = packet;
	bool isAnnexb = false;
	if ((size > 3 && memcmp(data, ANNEXB_CODE_LOW,3) == 0) ||
		(size > 4 && memcmp(data, ANNEXB_CODE,4) == 0)
		)
	{
		isAnnexb = true;
	}
	//暂时只处理MP4封装,annexb暂为处理
	if (isAnnexb)
	{
		while (data < packet + size) {
			if ((packet + size - data) > 4 && data[0] == 0x00 && data[1] == 0x00)
			{
				int startCodeSize = 2;
				if (data[2] == 0x01)
				{
					startCodeSize = 3;
				}
				else if(data[2] == 0x00 && data[3] == 0x01)
				{
					startCodeSize = 4;
				}
				if (startCodeSize == 3 || startCodeSize == 4)
				{
					if ((packet + size - data) > (startCodeSize + 1) && 
						(data[startCodeSize] & 0x1F) == 6)
					{
						//SEI
						unsigned char * sei = data + startCodeSize + 1;
 
						int ret = get_sei_buffer(sei, (packet + size - sei), buffer, count);
						if (ret != -1)
						{
							return ret;
						}
					}
					data += startCodeSize + 1;
				}
				else
				{
					data += startCodeSize + 1;
				}
			}
			else
			{
				data++;
			}
		}
	}
	else
	{
		//当前NALU
		while (data < packet + size) {
			//MP4格式起始码/长度
			unsigned int *length = (unsigned int *)data;
			int nalu_size = (int)reversebytes(*length);
			//NALU header
			if ((*(data + 4) & 0x1F) == 6)
			{
				//SEI
				unsigned char * sei = data + 4 + 1;
 
				int ret = get_sei_buffer(sei, min(nalu_size,(packet + size - sei)),buffer,count);
				if (ret != -1)
				{
					return ret;
				}
			}
			data += 4 + nalu_size;
		}
	}
	return -1;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FFmpeg H264增加SEI 的相关文章

  • FFmpeg 支持哪些编解码器和格式? [关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我需要 FFmpeg 支持的编解码器和格式列表 我在哪里可以找到它 正确的编解码器 ffmpeg codecs Formats ffm
  • 一段时间后终止由 exec() 启动的进程并将帧存储在数组中

    首先我要说的是我对 Java 完全陌生 我有 PHP 背景 但碰巧我的一项 PHP 任务需要转换为 Java 该任务是使用 ffmpeg 将视频分割为帧 然后处理这些帧 我已经用 PHP 完成了这个过程 现在我可以将它转换成Java 我浏览
  • 如何将 FFmpeg 命令行转换为 ffmpeg-python 代码?

    我有这个命令行代码 ffmpeg i 0 mp4 c v libx265 preset fast crf 28 tag v hvc1 c a aac bitexact map metadata 1 out mkv 我想将其转换为Python
  • 如何在 laravel 4 中使用 php-FFMpeg?

    我是 Laravel 4 的新手 我已经安装了php ffmpeg在我本地的 Laravel 设置中 但我需要有关如何在 Laravel 4 中使用此 ffmpeg 的帮助 假设你已经拥有ffmpeg安装在本地主机服务器上 然后在 Lara
  • FFMPEG - 以特定时间间隔在视频上叠加多个视频

    我想以指定的时间间隔将多个视频叠加在单个视频上 尝试过不同的解决方案 但它不会像我一样工作 我使用下面的命令将视频叠加在视频上 String cmdWorking3 new String i yourRealPath i gifVideoF
  • 使用 FFmpeg 在特定时间将一个视频叠加在另一个视频上

    我正在尝试将一个视频与另一个视频叠加 我按照OP发布的原始命令进行操作here https stackoverflow com questions 35269387 ffmpeg overlay one video onto another
  • FFmpeg 转换错误

    我正在尝试使用 FFmpeg 将视频转换为 webm 格式 我已经安装了此处列出的所有依赖项 http www videochat scripts com install ffmpeg mplayer flvtool2 yamdi x264
  • 如何将 ffplay 作为无窗口进程运行?

    我正在运行 ffplay 作为后台进程 它向我的主 UI 进程提供图像数据 我已经设定 SDL VIDEODRIVER dummy 抑制 SDL 窗口中显示的 ffplay 视频 问题是 即使不显示视频输出窗口 ffplay 进程仍然显示为
  • OpenCV 3.0.0 使用 FFMPEG 时出错

    我使用 OpenCV 一段时间了 但是 我最近将系统更改为没有任何管理员权限的集群 问题是这样的 在我的主文件夹中 我安装了 FFMPEG ffmpeg 网站上提供的最新稳定版本 我将它安装在 HOME 中 因此在 HOME lib 中安装
  • 使用 Python 从原始帧创建 MPEG4 视频文件

    我有一个原始视频帧源 我可以在 Python 中访问它 我想用它创建一个 MPEG4 视频 并带有 MP3 背景音乐 Python 中有哪些类型的工具和库可用于此类任务 最好我想要一个 API 我可以为其提供输出文件名 然后将各个帧作为 2
  • ffmpeg drawtext如何设置从右到左的方向

    i write arabic text to videos and it works fine but the issue is that the arabic language is written from right to left
  • 为 iOS6.0 ARMv7 处理器构建 FFMPEG 库

    WARNING 我刚刚被另一位用户告知 在 iOS 上使用 FFMPEG 存在一些法律问题 请在此处留下链接http multinc com 2009 08 24 compatibility Between the iphone app s
  • 使用 ffmpeg 转换真实媒体

    我有许多旧的硬壳真实媒体文件需要转换 并希望编写一个脚本来批量处理它们 我可以使用 FFMpegX 进行 Real Media gt AVI 转换 但是当我尝试使用 ffmpeg 复制转换时 它总是会出现如下错误 avi 0x10084fa
  • pictureBox 图片处理异常

    我最近想尝试一下锻造网 http www aforgenet com framework 因为我发现它非常简单 所以我决定使用 Video FFMPEG 命名空间进行一些简单的视频播放 这样我就可以将每个帧直接放在 pictureBox 上
  • 在 R 中导入 png 文件并转换为动画(.mp4)

    我正在尝试用 R 中的几个 png 文件创建一个简短的动画 我尝试了 packagemagick但只有当我将它们保存为 gif 时它才有效 当我尝试另存为 mp4 时 它将生成一个 mp4 文件 但一旦打开它 只会显示第一张图像 我的代码是
  • YUV420p 上的大量绿色 --> iOS 上 OpenGL 2.0 着色器中的 RGB

    我想使用 ffmpeg 和 OpenGL ES 2 0 为 iOS 制作一个电影播放器 但我有一些问题 输出 RGB 图像有很多绿色 这是代码和图像 480x320 宽度和高度 512x512 纹理宽度和高度 我从 ffmpeg AVFra
  • 使用 MediaRecorder 录制屏幕特定视图

    我想录制特定的屏幕视频View链接只想记录里面执行的动作LinearLayout 现在 MediaRecorder正在录制整个屏幕 如何录制屏幕的特定部分 MediaRecorder 通过媒体投影API 记录整个屏幕 至少从 Android
  • 访问 AVFrame 的每个像素

    我需要访问 FFMPEG 的 AVFrame 对象的每个像素信息 如果是 RGB 则每个像素的每种颜色 R G 和 B 我怎样才能做到这一点 如果您已经前进到正确的框架 类似于 img convert ctx ffmpeg sws getC
  • 无法在 Windows 7 机器中使用 OpenCV 2.4.3、Python 2.7 打开“.mp4”视频文件

    我目前正在进行一个涉及读取 mp4 视频文件的项目 我遇到的问题是它在Windows 7机器上使用Python 2 7 32位 OpenCV 2 4 3 cv2 pyd 代码片段如下 try video cv2 VideoCapture v
  • 使用 ffmpeg 或 OpenCV 处理原始图像

    看完之后维基百科页面 http en wikipedia org wiki Raw image format原始图像格式 是任何图像的数字负片 为了查看或打印 相机图像传感器的输出具有 进行处理 即转换为照片渲染 场景 然后以标准光栅图形格

随机推荐

  • 枚举类的value方法

    枚举类的value 方法可以将枚举类转变为一个枚举类型的数组 是由编译器添加的 官网 如图
  • 【Logback】<logger>、<root>标签详解

    文章目录 背景 一
  • linux自学群565589971欢迎加入

    作为一个linux爱好者 从自学一步步走上linux运维的工作岗位 对这个行业深深的热爱 也知道自学的不易 学习过程中也走了不少弯路 我现在在一家网络公司任职运维高级经理 也算积累一定的linux实战经验 所以我打算建一个自学群 跟想要学习
  • 近期遇到的两个SQL盲注与云盾绕过的一个小tips

    文章目录 前言 一 数字型盲注 二 order by注入 前言 最近在测试过程中遇到两个SQL注入 一个是数字型的盲注 一个是order by盲注 云盾绕过 一 数字型盲注 凭借印象 搭了个环境 大概长这样 前面170会拼接到查询语句 后面
  • 从zygote到onCreate应用启动过程分析

    在之前的文章讲了app进程大概的启动过程 https blog csdn net qq 36063677 article details 125638137 这篇文章细致的分析一下app进程从zygote进程fork出来到onCreate等
  • java和电脑编程_计算机初学者学习编程语言C#和Java哪个更有前途?

    如果同时接触到Java和C 这两门语言 确实是会容易让人纠结 毕竟目前这两门语言都是世界使用人数排名前五的语言 要说哪个更有前途 真的很难判定 因此 个人认为是有必要分析一下两门语言的一些特点和应用领域 语法 在语法上 如果是接触过Java
  • Function Score 多个function java写法

    背景 我们在使用 ES 查询的时候 除了 bool 查询 还会经常用到 function score 查询 简单来说 function score 就是对打分结果进行算法重排 鉴于网上基本上都是DSL写法 我找了好久没有找到JAVA应该怎么
  • 新版sonar代码审查问题总结

    主要问题列表 格式 问题名字 问题出现的次数 Resources should be closed2 资源未关闭 打开发现有两处用到的IO流没有关闭 Conditions should not unconditionally evaluat
  • 选择单选‘固定时间’,那么单选灵活时间输入框被禁用

    预计效果 1 disable isSee radio flexible 不能编辑 选择另一个单选的单选框 短路或 一边为真即为真 2 method方法 如果e 固定时间 那么 灵活时间输入框为空 相反 如果e 灵活时间 那么 固定时间输入框
  • 【3D点云】分割算法总结(一)

    文章目录 前言 Related work 一 PointNet 分类 分割2018 1 关键代码 1 点云采样 2 卷积下采样 升维 3 上采样 self fp4 l3 xyz l4 xyz l3 points l4 points 二 MV
  • Android 蓝牙开发基本流程

    http blog csdn net q610098308 article details 45248423 此例子基于 Android demo 对于一般的软件开发人员来说 蓝牙是很少用到的 尤其是Android的蓝牙开发 国内的例子很少
  • Mysql 报错注入方式总结

    floor 注入语句 id 1 and select 1 from select count concat user floor rand 0 2 x from information schema tables group by x a
  • 解密aes加密的m3u8片段的方法

    现在一些m3u8是有aes加密的 解密方法也简单 只要找到m3u8指定的密码文件就行了 一般都在 EXT X KEY METHOD AES 128 URI xxx 这里 下面的代码显示了在下载ts片段和密码文件后如何解密 假设已下载的m3u
  • Qt实战-聊天界面案例

    Qt实战 聊天界面案例 本项目模仿某平台 实现类似的聊天案例 喜欢的朋友可以在此基础上进行添加功能 1 原理 使用udp通信接收本地服务器的消息 ui gt setupUi this 初始化操作 udpSocket new QUdpSock
  • C语言:结构体中(.)和(->)的区别

    首先 要了解 a b 等价于 a gt b 概念上 一般情况下用 只需要声明一个结构体 格式是 结构体类型名 结构体名 然后用结构体名加 加域名就可以引用域 了 因为自动分配了结构体的内存 如同 int a 一样 而用 gt 则要声明一个结
  • 会议通知

    全国高校Python数据分析与实训课程 高级研修班 通 知 各高校教务处 各相关院系负责人 依据 教育部高等学校教学指导委员会章程 规定 教育部高等学校教学指导委员会的任务之一是 组织师资培训 沟通信息 交流教学建设和教学改革经验 宣传推广
  • 2022 Java面试题

    Java面向对象有哪些特征 如何应用 面向对象编程是利用类和对象编程的一种思想 万物可归类 类是对于世界事物的高度抽象 不同的事物之间有不同的关系 一个类自身与外界的封装关系 一个父类和子类的继承关系 一个类和多个类的多态关系 万物皆对象
  • 基于MATLAB GUI的LSB语音信号数字水印

    基于MATLAB GUI的LSB语音信号数字水印 数字水印是一种在数字媒体中嵌入信息的技术 它可以用于版权保护 身份验证以及数据完整性验证等应用 在本文中 我们将介绍如何使用MATLAB GUI和最低有效位 Least Significan
  • Vue2.0知识点

    Vue2 0指令 v text指令 内容渲染指令 它会覆盖元素内部原有的内容 语法 插值表达式 专门用来解决v text会覆盖默认文本内容的问题 v text和插值表达式只能渲染纯文本内容 插值表达式不能用到属性节点 v html指令 可以
  • FFmpeg H264增加SEI

    先看使用场景 https blog csdn net lsheevyfg article details 80951415 https www jianshu com p 4d9120dfcd69 参考文章 https blog csdn