mp4文件格式:https://wenku.baidu.com/view/673482284b73f242336c5f4c.html
MP4v2开源库:https://download.csdn.net/download/lq496387202/10515621
mp4v2简介记录:https://blog.csdn.net/yuan1125/article/details/51051683
方法都是在网上查找的通用方法,目前实现了将h264文件封装成了mp4文件,可以播放成功。但是buf设置有点问题,导致转码有点错误,会有花屏的现象,如果直接取流,一帧一帧的取就会没问题,以下代码只是最简单的读h264文件的进行封装mp4,sps_pps可以将h264文件通过ue打开查看,(例如:00 00 00 01 67,,,,,这些就是sps,00 00 00 01 68。。这就是pps)为了图方便直接使用最简单的操作数组写死sps_pps(ps:这个是我的h264文件的sps和pps)。目前将aac文件和h264文件封装成mp4文件,但是音视频不同步,还需好好调试。aac的MP4SetTrackESConfiguration(mp4File,audio,audioconfig, 2);中的audioconfig配置请看https://www.cnblogs.com/zhangxuan/p/8809245.html
主要是5个bit的profile4个bit的采样率4个bit的通道,以及三个字节的0,这些配置可以从adts头中找到,adts分析可以看上述链接
源代码:
#include
#include "mp4v2/mp4v2.h"
#include
#include
#include
#include
#include
#define BUF_SIZE 1024*1024*2
uint16_t width=1920;
uint16_t height=1080;
unsigned char sps_pps[] = {0x67,0x4D,0x40,0x28,0x8D,0x8D,0x40,0x3C,0x01,0x13, 0xF2,0xE0,0x2D,0xC0,0x40,0x40,0x50,0X00,0X00,0X3E,0X90,0X00,0X0E,0XA6,0X0E,
0X86,0X00,0X3D,0X08,0X00,0X01,0X7D,0X78,0X2E,0XF2,0XE3,0X43,0X00,0X1E,0X84,0X00,0X00,0XBE,0XBC,0X17,0X79,0X70,0XA0,0X68,0XEE,0X38,0X80}; //48(sps)+4(pps)
//unsigned char sps_pps[] = {0x67, 0x42, 0xC0, 0x2A, 0xD9 ,0x00, 0x78, 0x02, 0x27, 0xE5, 0xC0, 0x44, 0x00, 0x00, 0x03, 0x00, 0x04,0X00,0X00,0X03,0X01,0XE2,0X3C,0X60,0XC9,
//0X20,0X68,0XCB,0X8C,0XB2};//26(sps)+4(pps)
uint8_t audioconfig[2] = {0x11,0x90}; //0x11 0x90/*low 48000 2*/ 0x11 0x10/*low 64000 2*/ 0x12 0x08/*low 44100 1*/ 0x11 0x88/*low 48000 1*/ 0x12 0x10/*low 44100 2*/
#define FRAME_HD_00_1 0
#define FRAME_HD_00_2 1
#define FRAME_HD_00_3 2
#define FRAME_HD_01 3
#define FRAME_END_00_1 4
#define FRAME_END_00_2 5
#define FRAME_END_00_3 6
#define FRAME_END_01 7
#define AUDIO 1
int Vframe_state=FRAME_HD_00_1;
int Aframe_state=FRAME_HD_00_1;
typedef struct _FRAME_PARA{
long first_byte;
long last_byte;
long data_total;
}FRAME_PARA;
int buff_len=1;
int buff_len1=1;
int Aflag=0;
int Vflag=0;
long Vdat_cnt=-1;
long Adat_cnt=-1;
FRAME_PARA gPara_video;
FRAME_PARA gPara_audio;
char *frame_buff;
char *frame_buff1;
int Get_VFrame_Data(char *src_buff,long len,char *dst_buff,long offset, FRAME_PARA *ptr)
{
int i;
//long dat_cnt=-1;
Vflag=0;
for(i=offset;ifirst_byte=i;
Vdat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Vdat_cnt]=src_buff[i];
Vframe_state=FRAME_HD_00_2;
//printf("-HEAD-find1-\n");
}
break;
case FRAME_HD_00_2:
if(src_buff[i]==0x00)
{
Vdat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Vdat_cnt]=src_buff[i];
Vframe_state=FRAME_HD_00_3;
//printf("-HEAD-find2-\n");
}
else
{
Vdat_cnt--;
Vframe_state=FRAME_HD_00_1;
}
break;
case FRAME_HD_00_3:
if(src_buff[i]==0x00)
{
Vdat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Vdat_cnt]=src_buff[i];
Vframe_state=FRAME_HD_01;
//printf("-HEAD-find3-\n");
}
else
{
Vdat_cnt--;
Vdat_cnt--;
Vframe_state=FRAME_HD_00_1;
}
break;
case FRAME_HD_01:
if(src_buff[i]==0x01)
{
Vdat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Vdat_cnt]=src_buff[i];
Vframe_state=FRAME_END_00_1;
printf("-HEAD-find4-dat_cnt=%d\n",Vdat_cnt);
}
else
{
Vdat_cnt--;
Vdat_cnt--;
Vdat_cnt--;
Vframe_state=FRAME_HD_00_1;
}
break;
//============find tail 00 00 00 01 ====================
case FRAME_END_00_1:
Vdat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Vdat_cnt]=src_buff[i];
if(src_buff[i]==0x00)
Vframe_state=FRAME_END_00_2;
//printf("-END-find1-\n");
break;
case FRAME_END_00_2:
Vdat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Vdat_cnt]=src_buff[i];
if(src_buff[i]==0x00)
{
Vframe_state=FRAME_END_00_3;
//printf("-END-find2-\n");
}
else
Vframe_state=FRAME_END_00_1;
break;
case FRAME_END_00_3:
Vdat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Vdat_cnt]=src_buff[i];
if(src_buff[i]==0x00)
{
Vframe_state=FRAME_END_01;
//printf("-END-find3-\n");
}
else
Vframe_state=FRAME_END_00_1;
break;
case FRAME_END_01:
Vdat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Vdat_cnt]=src_buff[i];
if(src_buff[i]==0x01)
{
Vframe_state=FRAME_HD_00_1;
ptr->last_byte=i-3;
//ptr->data_total=ptr->data_total+dat_cnt-4;
ptr->data_total=Vdat_cnt-3;
printf("-END-find4-dat_cnt=%d\n",Vdat_cnt-3);
Vdat_cnt=-1;
Vflag=1;
return 1;
}
else
Vframe_state=FRAME_END_00_1;
break;
}
}
return 0;
}
int count=0;
int Get_One_VFrame(int fp)
{
char buff[101];
int ret=-1;
for(;;)
{
if(Vflag==0)
buff_len=read(fp,buff,100);
if(buff_len<=0)
{
printf("read data over\n");
return 0;
}
ret=Get_VFrame_Data(buff,buff_len,frame_buff,gPara_video.last_byte,(FRAME_PARA *)&gPara_video);
if(ret==1) // 读到完整的帧尾,frame_buff前四个字节放帧长度
{
frame_buff[0]=((gPara_video.data_total-4)&0xff000000)>>24;
frame_buff[1]=((gPara_video.data_total-4)&0x00ff0000)>>16;
frame_buff[2]=((gPara_video.data_total-4)&0x0000ff00)>>8;
frame_buff[3]=((gPara_video.data_total-4)&0x000000ff);
count++;
break;
}
else
{
gPara_video.first_byte=0;
gPara_video.last_byte=0;
}
}
return 1;
}
int Get_AFrame_Data(char *src_buff,long len,char *dst_buff,long offset, FRAME_PARA *ptr)
{
int i;
//long dat_cnt=-1;
Aflag=0;
for(i=offset;ifirst_byte=i;
Adat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Adat_cnt]=src_buff[i];
Aframe_state=FRAME_HD_00_2;
//printf("-HEAD-find1-\n");
}
break;
case FRAME_HD_00_2:
if(src_buff[i]==0xF9)
{
Adat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Adat_cnt]=src_buff[i];
Aframe_state=FRAME_HD_00_3;
//printf("-HEAD-find2-\n");
}
else
{
Adat_cnt--;
Aframe_state=FRAME_HD_00_1;
}
break;
case FRAME_HD_00_3:
if(src_buff[i]==0x4C)
{
Adat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Adat_cnt]=src_buff[i];
Aframe_state=FRAME_HD_01;
//printf("-HEAD-find3-\n");
}
else
{
Adat_cnt--;
Adat_cnt--;
Aframe_state=FRAME_HD_00_1;
}
break;
case FRAME_HD_01:
if(src_buff[i]==0x80)
{
Adat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Adat_cnt]=src_buff[i];
Aframe_state=FRAME_END_00_1;
printf("-HEAD-find4-dat_cnt=%d\n",Adat_cnt);
}
else
{
Adat_cnt--;
Adat_cnt--;
Adat_cnt--;
Aframe_state=FRAME_HD_00_1;
}
break;
//============find tail FF F9 4C 80 ====================
case FRAME_END_00_1:
Adat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Adat_cnt]=src_buff[i];
if(src_buff[i]==0xFF)
Aframe_state=FRAME_END_00_2;
//printf("-END-find1-\n");
break;
case FRAME_END_00_2:
Adat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Adat_cnt]=src_buff[i];
if(src_buff[i]==0xF9)
{
Aframe_state=FRAME_END_00_3;
//printf("-END-find2-\n");
}
else
Aframe_state=FRAME_END_00_1;
break;
case FRAME_END_00_3:
Adat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Adat_cnt]=src_buff[i];
if(src_buff[i]==0x4C)
{
Aframe_state=FRAME_END_01;
//printf("-END-find3-\n");
}
else
Aframe_state=FRAME_END_00_1;
break;
case FRAME_END_01:
Adat_cnt++;
//dst_buff[offset+dat_cnt]=src_buff[i];
dst_buff[Adat_cnt]=src_buff[i];
if(src_buff[i]==0x80)
{
Aframe_state=FRAME_HD_00_1;
ptr->last_byte=i-3;
//ptr->data_total=ptr->data_total+dat_cnt-4;
ptr->data_total=Adat_cnt-3;
printf("-END-find4-dat_cnt=%d\n",Adat_cnt-3);
Adat_cnt=-1;
Aflag=1;
return 1;
}
else
Aframe_state=FRAME_END_00_1;
break;
}
}
return 0;
}
int number=0;
int Get_One_AFrame(int fp)
{
char buff[101];
int ret=-1;
for(;;)
{
if(Aflag==0)
buff_len1=read(fp,buff,100);
if(buff_len1<=0)
{
printf("read data over\n");
return 0;
}
ret=Get_AFrame_Data(buff,buff_len1,frame_buff1,gPara_audio.last_byte,(FRAME_PARA *)&gPara_audio);
if(ret==1) // 读到完整的帧尾,frame_buff前四个字节放帧长度
break;
else
{
gPara_audio.first_byte=0;
gPara_audio.last_byte=0;
}
}
return 1;
}
int main(int argc,char *argv[])
{
int fd_audio,fd_video;
frame_buff=(char *)malloc(BUF_SIZE);
memset(frame_buff,0,BUF_SIZE);
if(frame_buff==NULL)
{
fprintf(stderr,"malloc fail!\n");
exit(1);
}
frame_buff1=(char *)malloc(BUF_SIZE);
memset(frame_buff1,0,BUF_SIZE);
if(frame_buff1==NULL)
{
fprintf(stderr,"malloc fail!\n");
exit(1);
}
if (argc < 4)
{
fprintf(stderr,"usage fail!\n");
exit(1);
}
u_int32_t verbosity = 0 /* MP4_DETAILS_ALL */;
fd_video=open(argv[1],O_RDWR);
if(fd_video<0)
{
fprintf(stderr,"open fail!\n");
exit(1);
}
fd_audio=open(argv[2],O_RDWR);
if(fd_audio<0)
{
fprintf(stderr,"open fail!\n");
exit(1);
}
MP4FileHandle mp4File = MP4Create(argv[3],verbosity);
#if 1
//MP4FileHandle mp4File = MP4CreateEx(argv[2],MP4_DETAILS_ALL, 0, 1, 1, 0, 0, 0, 0);//创建mp4文件
if (mp4File==MP4_INVALID_FILE_HANDLE)
exit(1);
MP4SetTimeScale(mp4File,90000);
MP4TrackId video = MP4AddH264VideoTrack(mp4File,90000,90000/29.97, width, height,
0x4D, //sps[1] AVCProfileIndication
0x40, //sps[2] profile_compat
0x28, //sps[3] AVCLevelIndication
3); // 4 bytes length before each NAL unit
//MP4TrackId audio = MP4AddAudioTrack(mp4File,16000, 1024,MP4_MPEG2_AAC_LC_AUDIO_TYPE);
if (video == MP4_INVALID_TRACK_ID)
{
perror("add video track fialed.\n");
return 1;
}
MP4AddH264SequenceParameterSet(mp4File,video,sps_pps,48);
MP4AddH264PictureParameterSet(mp4File,video,sps_pps+48,4);
MP4SetVideoProfileLevel(mp4File, 0x7F);
//MP4SetVideoProfileLevel(mp4File, 0x1);
#if AUDIO
//MP4TrackId audio = MP4AddAudioTrack(mp4File,44100,1024,MP4_MPEG4_AAC_LC_AUDIO_TYPE);
MP4TrackId audio = MP4AddAudioTrack(mp4File,48000,1024,MP4_MPEG2_AAC_LC_AUDIO_TYPE);
//MP4TrackId audio = MP4AddAudioTrack(mp4File,48000,1024,MP4_MPEG4_AUDIO_TYPE);
if (audio == MP4_INVALID_TRACK_ID)
{
perror("add audio track fialed.\n");
return 1;
}
MP4SetAudioProfileLevel(mp4File, 0x2 );
// 设置编码信息
MP4SetTrackESConfiguration(mp4File,audio,audioconfig, 2);
#endif
#endif
int ret,ret1;
int i=0;
while(1)
{
ret=Get_One_VFrame(fd_video);
if(ret==1)
MP4WriteSample(mp4File,video,frame_buff,gPara_video.data_total,90000/29.97, 0, 1);
#if AUDIO
ret1=Get_One_AFrame(fd_audio);
if(ret1==1)
MP4WriteSample(mp4File,audio,&frame_buff1[7],gPara_audio.data_total-7,MP4_INVALID_DURATION, 0, 1); // MP4_INVALID_DURATION
#endif
if(ret==0)
#if AUDIO
if(ret1==0)
#endif
break;
memset(frame_buff,0,gPara_video.data_total);
memset(frame_buff1,0,gPara_audio.data_total);
}
printf("-----------------encode sucess!-------------\n");
printf("count=%d\n",count);
free(frame_buff);
free(frame_buff1);
close(fd_video);
close(fd_audio);
MP4Close(mp4File,0);
return 0;
}