利用GPAC生成MP4文件

GPAC实战:MP4Box带你轻松解决MP4封装、修复与拼接难题 MP4作为一种常见的多媒体封装格式,其内部由ftyp、moov、mdat等box结构组成,其中moov保存时间戳与样本索引,一旦损坏或timescale设置不当,就会出现播放器打不开、mp4文件时间长度不对等问题。GPAC是一个开源多媒体框架,其命令行工具MP4Box能对MP4进行精细化的封装、拆封与修复。与ffmpeg相比,MP4Box更擅长处理容器结构问题,例如将m3u8分片转为MP4、修复时长偏差、重建moov索引等。本文从MP4基础结构出发,系统讲解用MP4Box完成裸流封装、多段拼接、损坏修复的实 阅读详情

        GPAC主要针对学生和内容创作者,代表了一个跨平台的多媒体框架,开发人员可以使用它在 LGPL 许可下制作开源媒体。GPAC多媒体框架兼容范围广泛的流行文件类型,从常见格式(如 AVI、MPEG 和 MOV)到复杂格式(如 MPEG-4 系统或 VRML/X3D)和 360 电影。

        一、MP4Writer类

MP4Writer.h文件

#ifndef _MP4WRITER_H_
#define _MP4WRITER_H_
 
#define GPAC_MP4BOX_MINI
#include "gpac/setup.h"
 
 
 
#define MP4_AUDIO_TYPE_INVALID      0
#define MP4_AUDIO_TYPE_AAC_MAIN     1
#define MP4_AUDIO_TYPE_AAC_LC       2
#define MP4_AUDIO_TYPE_AAC_SSR      3
#define MP4_AUDIO_TYPE_AAC_LD      23
 
 
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
void* MP4_Init();
s32  MP4_CreatFile(void *pCMP4Writer, char *strFileName);
s32  MP4_InitVideo265(void *pCMP4Writer, u32 TimeScale);
s32  MP4_Write265Sample(void *pCMP4Writer, u8 *pData, u32 Size, u64 TimeStamp);
s32  MP4_InitVideo264(void *pCMP4Writer, u32 TimeScale);
s32  MP4_Write264Sample(void *pCMP4Writer, u8 *pData, u32 Size, u64 TimeStamp);
s32  MP4_InitAudioAAC(void *pCMP4Writer, u8 AudioType, u32 SampleRate, u8 Channel, u32 TimeScale);
s32  MP4_WriteAACSample(void *pCMP4Writer, u8 *pData, u32 Size, u64 TimeStamp);
void MP4_CloseFile(void *pCMP4Writer);
void MP4_Exit(void *pCMP4Writer);
 
 
#ifdef __cplusplus
}
#endif
 
 
 
#endif

MP4Writer.cpp文件

#include "MP4Writer.h"
 
#include <Winsock2.h>
 
 
extern "C" {
#include "gpac/isomedia.h"
#include "gpac/constants.h"
#include "gpac/internal/media_dev.h"
}
 
 
#define INIT_STATUS    0
#define CONFIG_STATUS  1
#define CONFIG_FINISH  2
 
 
static s8 GetSampleRateID(u32 SamplRate)
{
    switch (SamplRate)
    {
         case 96000: return  0;
         case 88200: return  1;
         case 64000: return  2;
         case 48000: return  3;
         case 44100: return  4;
         case 32000: return  5;
         case 24000: return  6;
         case 22050: return  7;
         case 16000: return  8;
         case 12000: return  9;
         case 11025: return 10;
         case 8000 : return 11;
         case 7350 : return 12;
         default:    return -1;
    }
}
 
 
//gf_m4a_get_profile
static u8 GetAACProfile(u8 AudioType, u32 SampleRate, u8 Channel)
{
    switch (AudioType)
    {
        case 2: /* AAC LC */
        {
            if (Channel <= 2)  return (SampleRate <= 24000) ? 0x28 : 0x29; /* LC@L1 or LC@L2 */
            if (Channel <= 5)  return (SampleRate <= 48000) ? 0x2A : 0x2B; /* LC@L4 or LC@L5 */
                               return (SampleRate <= 48000) ? 0x50 : 0x51; /* LC@L4 or LC@L5 */
        }
        case 5: /* HE-AAC - SBR */
        {
            if (Channel <= 2)  return (SampleRate <= 24000) ? 0x2C : 0x2D; /* HE@L2 or HE@L3 */
            if (Channel <= 5)  return (SampleRate <= 48000) ? 0x2E : 0x2F; /* HE@L4 or HE@L5 */
                               return (SampleRate <= 48000) ? 0x52 : 0x53; /* HE@L6 or HE@L7 */
        }
        case 29: /*HE-AACv2 - SBR+PS*/
        {
            if (Channel <= 2)  return (SampleRate <= 24000) ? 0x30 : 0x31; /* HE-AACv2@L2 or HE-AACv2@L3 */
            if (Channel <= 5)  return (SampleRate <= 48000) ? 0x32 : 0x33; /* HE-AACv2@L4 or HE-AACv2@L5 */
                               return (SampleRate <= 48000) ? 0x54 : 0x55; /* HE-AACv2@L6 or HE-AACv2@L7 */
        }
        default: /* default to HQ */
        {
            if (Channel <= 2)  return (SampleRate <  24000) ? 0x0E : 0x0F; /* HQ@L1 or HQ@L2 */
                               return 0x10; /* HQ@L3 */
        }
    }
}
 
static void GetAudioSpecificConfig(u8 AudioType, u8 SampleRateID, u8 Channel, u8 *pHigh, u8 *pLow)
{
    u16 Config;
 
    Config = (AudioType & 0x1f);
    Config <<= 4;
    Config |= SampleRateID & 0x0f;
    Config <<= 4;
    Config |= Channel & 0x0f;
    Config <<= 3;
 
    *pLow  = Config & 0xff;
    Config >>= 8;
    *pHigh = Config & 0xff;
}
 
/* 返回的数据包括起始的4个字节0x00000001 */
static u8* FindNalu(u8 *pStart, u32 Size, u8 *pNaluType, u32 *pNaluSize)
{
    u8 *pEnd;
    u8 *pCur;
    u8 *pOut;
    u8  NaluType;
 
    if (4 >= Size)
        return NULL;
 
    /* 找第一个0x00000001 */
    pCur = pStart;
    pEnd = pStart + Size - 4;
    while (pCur < pEnd)
    {
        if ( (0 == pCur[0]) && (0 == pCur[1]) && (0 == pCur[2]) && (1 == pCur[3]) )
            break;
        pCur++;
    }
    if (pCur >= pEnd)
        return NULL;
 
    NaluType = (pCur[4] >> 1) & 0x3f;
    *pNaluType = NaluType;
    if (1 == NaluType || 19 == NaluType) /* P帧、I帧, 假设每一包里P帧I帧都是最后一个 */
    {
        *pNaluSize  = Size - (pCur - pStart);
        return pCur;
    }
 
    pOut = pCur;
 
    /* 找第二个0x00000001 */
    pCur += 5;
    while (pCur <= pEnd)
    {
        if ( (0 == pCur[0]) && (0 == pCur[1]) && (0 == pCur[2]) && (1 == pCur[3]) )
            break;
        pCur++;
    }
    if (pCur <= pEnd)
    {
        *pNaluSize  = pCur - pOut;
        return pOut;
    }
 
    *pNaluSize  = Size - (pOut - pStart);
    return pOut;
}
 
/* 返回的数据包括起始的4个字节0x00000001 */
static u8* FindNalu264(u8 *pStart, u32 Size, u8 *pNaluType, u32 *pNaluSize)
{
	u8 *pEnd;
	u8 *pCur;
	u8 *pOut;
	u8  NaluType;
 
	if (4 >= Size)
		return NULL;
 
	/* 找第一个0x00000001 */
	pCur = pStart;
	pEnd = pStart + Size - 4;
	while (pCur < pEnd)
	{
		if ((0 == pCur[0]) && (0 == pCur[1]) && (0 == pCur[2]) && (1 == pCur[3]))
			break;
		pCur++;
	}
	if (pCur >= pEnd)
		return NULL;
 
	NaluType = (pCur[4]) & 0x1f;
	*pNaluType = NaluType;
 
	if (1 == NaluType || 5 == NaluType) /* P帧、I帧, 假设每一包里P帧I帧都是最后一个 */
	{
		*pNaluSize = Size - (pCur - pStart);
		return pCur;
	}
 
	pOut = pCur;
 
	/* 找第二个0x00000001 */
	pCur += 5;
	while (pCur <= pEnd)
	{
		if ((0 == pCur[0]) && (0 == pCur[1]) && (0 == pCur[2]) && (1 == pCur[3]))
			break;
		pCur++;
	}
	if (pCur <= pEnd)
	{
		*pNaluSize = pCur - pOut;
		return pOut;
	}
 
	*pNaluSize = Size - (pOut - pStart);
	return pOut;
}
 
 
// aac数据时记得除掉adts头
static int AdtsDemux(unsigned char * data, unsigned int size, unsigned char** raw, int* raw_size)
{
	int ret = 1;
	if (size < 7) {
		ttf_human_trace("adts: demux size too small");
		return 0;
	}
	unsigned char* p = data;
	unsigned char* pend = data + size;
	//unsigned char* startp = 0;
 
	while (p < pend) {
 
		// decode the ADTS.
		// @see aac-iso-13818-7.pdf, page 26
		//      6.2 Audio Data Transport Stream, ADTS
		// @see https://github.com/ossrs/srs/issues/212#issuecomment-64145885
		// byte_alignment()
 
		// adts_fixed_header:
		//      12bits syncword,
		//      16bits left.
		// adts_variable_header:
		//      28bits
		//      12+16+28=56bits
		// adts_error_check:
		//      16bits if protection_absent
		//      56+16=72bits
		// if protection_absent:
		//      require(7bytes)=56bits
		// else
		//      require(9bytes)=
H 265/HEVC Codec 编解码 MP4 和 TS H 265/HEVC Codec 编解码 MP4 和 TS 阅读详情

相关推荐

海思MP4开发系列(一)GPAC交叉编译(Hi3559 + H265 + gpac + MP4)

参考 Hi3559AV100 下gpac交叉编译 海思3516A 运行mp4box工具,移植gpac 0.4.0 使用gpac封装mp4 无法解决R_AARCH64_ADR_PREL_PG_HI21重定向于符号__stack_chk_guard@GLIBC_2.17 背景 传统MP4封装,大部分都只是使用libmp4v2库,H264+libmp4v2网上教程也很多,但8012年和H265一起来了,技术应更好的兼容后续拓展,Mp4v2目前是无人维护的状态也不支持H265,所有我们选择了gpac作为新

一只海星的主页 2962

gpac在海思平台上编译适配指南

本文还有配套的精品资源,点击获取 简介:本文主要探讨gpac开源项目经过特定修改后,能够适应海思半导体硬件平台的编译和运行。gpac是一个包含多媒体处理工具如MP4Box和OMXPlayer的框架,广泛用于与ISO/IEC MPEG-4标准相关的多媒体应用开发。文章聚焦于gpac 0.4.0版本基础上的定制化改造,以解决在海思hisiv300工具链上的兼容性问题,使其适配于...

weixin_42600407的博客 1074

gpac开源库源代码压缩包:MP4与x264集成

本文还有配套的精品资源,点击获取 简介:gpac-master.zip包含了gpac开源库的源代码,该库支持MP4格式编码,并特别集成了x264编解码器。作为一个多媒体框架,gpac提供了处理多种多媒体格式的能力,包括解析、编码、解码及打包MP4和H.264视频。该压缩包包含了源代码、构建脚本、配置文件、文档以及示例和测试用例,为开发者提供了一个全面的资源集合,以实现高效多...

weixin_33205138的博客 1177

gpac库把H265与AAC封装成MP4的接口(新)

gpac库把H265与AAC封装成MP4的接口(新),https://blog.csdn.net/LLL347/article/details/85886975

使用gpac封装MP4源码

使用gpac库封装H264和H265格式的码流,输出mp4文件,原创资源,谢绝转载,如有疑问,欢迎到LiaoJunXiong的博客留言

mp4box.js, GPAC工具的MP4Box版本.zip

mp4box.js, GPAC工具的MP4Box版本 MP4Box.js JavaScript库,在浏览器( 在NodeJS中) 中处理MP4文件,支持渐进解析。 灵感来自于来自的 MP4Box 工具。 它可以用于:获得关于MP4文件的信息,一个MP4文件,用于与

如何在项目中集成bpmn-process-designer

文章目录一、bpmn-process-designer是什么?二、使用步骤1.将下面地址的代码下载到本地2.替换dependencies和devDependencies3.拷贝package目录4.在main.js引入代码5.拷贝src5.拷贝App.vue代码注意事项 一、bpmn-process-designer是什么? bpmn-process-designer是一个基于 bpmn.js,Vue 2.x 和 ElementUI 开发的流程设计器(前端部分),支持监听器,扩展属性,表单等配置,可自由扩展

weixin_43550766的博客 9447

EtherCAT同步模式实战:如何用TwinCAT配置DC-Synchronous模式(附时序图详解)

本文详细解析了如何在TwinCAT环境中配置EtherCAT的DC-Synchronous同步模式,实现纳秒级同步精度。通过硬件准备、参数配置和高级调优步骤,帮助工程师解决工业自动化中的同步挑战,提升运动控制性能。

gold的博客 1559

Linux中断子系统(二)—— 通用框架处理

1、数据结构分析 (1)中断描述符结构structirq_desc: 1)打开CONFIG_SPARSE_IRQ宏(中断编号不连续),中断描述符以radix- tree来组织,用户在初始化时进行动态分配,然后再插入radix-tree中; 2)关闭CONFIG_SPARSE_IRQ宏(中断编号连续),中断描述符以数组的 形式组织,并且已经分配好; 3)不管哪种形式,最终都可以通过linuxirq号来找到对应的中断描述符; (2)stru...

weixin_38428439的博客 4869

测站坐标系、地心非惯性系、经纬高互转

目录 一、经纬高转直角坐标系互转 1.1 python代码 二、wgs84转cgcs2000的转换矩阵如下 虽然cgcs2000与wgs84差别很小,但是我比较较真,还是做了两个坐标系的转换。 一、经纬高转直角坐标系互转 此处可参考链接(百度文库用手机浏览器可以打开看全部的): (1)第四章地球椭球及其数学详解 (2)第四章椭球数学变换16节 (3)大地测量学基础[1](7)(控制) 转换公式如下: LBH转XYZ: a为半长轴,e为偏心率 XYZ转LBH: a为半长轴

${王小贱}的博客 2万+

关于获取CISP-PTE一些避坑经历

考场内是不允许携带外设键盘的,现场会至少有一个360安全专业人员监考.所有人电脑都会提前装一个奇安信的一个考试exe,刚开始的时候会让你连接一个WIFI,我们将会通过WIFI进行做题,做题期间你的电脑将被全程监控并且一些退出快捷键也是全部锁死(有点像勒索病毒那种界面),想要重启必须直接拔电源。中途可以上厕所,需要监考官陪同

6312

HyperMesh实战:5种复杂载荷场景下的field映射技巧(附TCL脚本)

本文详细介绍了HyperMesh在5种复杂载荷场景下的field映射技巧,包括轴承载荷的圆柱坐标系映射、粉末压力中的切向力处理、实验数据到有限元模型的场映射、多工况载荷的组合映射以及局部细化网格的边界条件传递。通过实战案例和TCL脚本,帮助工程师高效解决有限元分析中的载荷映射难题,提升工作效率。

fanta的博客 287

【大模型工程局】告别单打独斗:手把手带你构建多智能体系统(MetaGPT 启示录)

想象一下,不再是只有一个全知全能的 AI,而是有一群各有所长、能够独立思考和行动的“智能体”(Agent)。它们生活在一个共同的环境中,可以相互交流、协作完成共同目标,也可能为了有限资源而相互竞争。这就是多智能体系统(MAS)的核心图景。MAS 的关键特征:自治性 (Autonomy):每个智能体都能独立感知环境、做出决策并执行动作,无需外部直接控制。交互性 (Interaction):智能体之间可以通过某种通信机制(显式或隐式)交换信息、协调行为。

高校图书馆高级系统架构师/研究馆员,推动高校AI从概念演示到可评审、可交付、可运维:路线图与立项评审、PoC交付、评测回归与上线运维(Baseline/Eval/Ops)。 1175

innovus中如何设置cts参数

上面是设置cts的一般设置,如果需要对某些skew group或者某些clock tree设置不一样的参数,如需要对clk1这个clock设置不一样的inverter,可以使用。需要查询已经设置过的ccopt参数,可以使用get_ccopt_property去查询,方法和set_ccopt_property一致。言归正传,cts的设置命令是set_ccopt_property,获取命令是get_ccopt_property。另外,set_ccopt_property提供一套命令查询方法。

芯冰乐 528

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

上一篇: nvidia显卡编码并发session限制破解
下一篇: librtmp使用方法
byxdaz
byxdaz 领域专家: C/C++技术领域 领域专家: C/C++技术领域
博客等级 码龄23年 3万+粉丝 1272原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byxdaz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值