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)=
2962




被折叠的 条评论
为什么被折叠?



