linux下利用MP4v2封装H264 aac为mp4

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 <stdio.h>
#include "mp4v2/mp4v2.h"
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#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;i<len;i++)
    {
        switch(Vframe_state)
        {
            //============find head 00 00 00 01 ====================
            case FRAME_HD_00_1:
                if(src_buff[i]==0x00)
                {
                    ptr->first_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;i<len;i++)
    {
        switch(Aframe_state)
        {
            //============find head FF F9 4C 80 ====================
            case FRAME_HD_00_1:
                if(src_buff[i]==0xFF)
                {
                    ptr->first_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;
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值