MP4v2 基本使用(二)

时间:2024-02-22 17:43:38

MP4转H264文件

本文最目标是基本的MP4v2接口的使用,并且实现一个简单的提取mp4文件里面264流的功能;

1.264文件基本知识 

下看看H264文件的基本常识 
NAL 头 0x00 0x00 0x00 0x01 
sps :nal+0x67开头 
pps :nal+0x68开头

I帧 0x65 开头 
P帧… 
具体的参考别人的解析 
http://blog.csdn.net/jefry_xdz/article/details/8461343

2.mp4v2提取264文件的代码

  1 #include <stdlib.h>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <sys/types.h>
  5 #include <dirent.h>
  6 #include <time.h> 
  7 #include <sys/time.h>
  8 #include <mp4v2/mp4v2.h>
  9 
 10 unsigned char sps[64],pps[64];
 11 int spslen = 0,ppslen = 0;
 12 
 13 int get264stream(MP4FileHandle oMp4File,int VTrackId,int totalFrame)
 14 {
 15     if(!oMp4File) return -1;
 16     char NAL[5] = {0x00,0x00,0x00,0x01};    
 17     unsigned char *pData = NULL;
 18     unsigned int nSize = 0;
 19     MP4Timestamp pStartTime;
 20     MP4Duration pDuration;
 21     MP4Duration pRenderingOffset;
 22     bool pIsSyncSample = 0;
 23 
 24     int nReadIndex = 0;
 25     FILE *pFile = NULL;
 26     pFile = fopen("out.h264","wb"); 
 27 
 28     while(nReadIndex < totalFrame)
 29     {   
 30         nReadIndex ++;
 31         //printf("nReadIndex:%d\n",nReadIndex);
 32         MP4ReadSample(oMp4File,VTrackId,nReadIndex,&pData,&nSize,&pStartTime,&pDuration,&pRenderingOffset,&pIsSyncSample);
 33 
 34         //IDR֡ 帧,写入sps pps先
 35         if(pIsSyncSample)
 36         {
 37             fwrite(NAL,4,1,pFile);
 38             fwrite(sps,spslen,1,pFile);
 39 
 40             fwrite(NAL,4,1,pFile);
 41             fwrite(pps,ppslen,1,pFile);
 42 
 43         }
 44         //264frame
 45         if(pData && nSize > 4)
 46         {
 47             //标准的264帧,前面几个字节就是frame的长度.
 48             //需要替换为标准的264 nal 头.
 49             pData[0] = 0x00;
 50             pData[1] = 0x00;
 51             pData[2] = 0x00;
 52             pData[3] = 0x01;
 53             fwrite(pData,nSize,1,pFile);
 54         }
 55 
 56         //如果传入MP4ReadSample的视频pData是null
 57         // 它内部就会new 一个内存
 58         //如果传入的是已知的内存区域,
 59         //则需要保证空间bigger then max frames size.
 60         free(pData);
 61         pData = NULL;
 62     }       
 63     fflush(pFile);
 64     fclose(pFile);  
 65 
 66     return 0;
 67 }
 68 int openmp4file(char *sMp4file)
 69 {
 70     MP4FileHandle oMp4File;
 71     int i;
 72 
 73     //unsigned int oStreamDuration;
 74     unsigned int oFrameCount;
 75 
 76     oMp4File = MP4Read(sMp4file);
 77     int videoindex = -1,audioindex = -1;
 78     uint32_t numSamples;
 79     //uint32_t timescale;
 80     //uint64_t duration;        
 81 
 82     if (!oMp4File)
 83     {
 84         printf("Read error....%s\r\n",sMp4file);
 85         return -1;
 86     }
 87 
 88     MP4TrackId trackId = MP4_INVALID_TRACK_ID;
 89     uint32_t numTracks = MP4GetNumberOfTracks(oMp4File,NULL,0);
 90     printf("numTracks:%d\n",numTracks);
 91 
 92     for (i = 0; i < numTracks; i++)
 93     {
 94         trackId = MP4FindTrackId(oMp4File, i,NULL,0);
 95         const char* trackType = MP4GetTrackType(oMp4File, trackId);
 96         if (MP4_IS_VIDEO_TRACK_TYPE(trackType))
 97         {
 98             //printf("[%s %d] trackId:%d\r\n",__FUNCTION__,__LINE__,trackId);
 99             videoindex= trackId;
100 
101             //duration = MP4GetTrackDuration(oMp4File, trackId );
102             numSamples = MP4GetTrackNumberOfSamples(oMp4File, trackId);
103             //timescale = MP4GetTrackTimeScale(oMp4File, trackId);          
104             //oStreamDuration = duration/(timescale/1000);          
105             oFrameCount = numSamples;
106 
107             // read sps/pps 
108             uint8_t **seqheader;
109             uint8_t **pictheader;
110             uint32_t *pictheadersize;
111             uint32_t *seqheadersize;
112             uint32_t ix;
113             MP4GetTrackH264SeqPictHeaders(oMp4File, trackId, &seqheader, &seqheadersize, &pictheader, &pictheadersize);
114 
115             for (ix = 0; seqheadersize[ix] != 0; ix++)
116             {
117                 memcpy(sps, seqheader[ix], seqheadersize[ix]);
118                 spslen = seqheadersize[ix];
119                 free(seqheader[ix]);
120             }
121             free(seqheader);
122             free(seqheadersize);
123 
124             for (ix = 0; pictheadersize[ix] != 0; ix++)
125             {
126                 memcpy(pps, pictheader[ix], pictheadersize[ix]);
127                 ppslen = pictheadersize[ix];
128                 free(pictheader[ix]);
129             }
          free(
pictheader);
free(pictheadersize);
130 }
131         else if (MP4_IS_AUDIO_TRACK_TYPE(trackType))
132         {
133             audioindex = trackId;
134             printf("audioindex:%d\n",audioindex);
135         }   
136     }
137 
138     //解析完了mp4,主要是为了获取sps pps 还有video的trackID
139     if(videoindex >= 0)
140         get264stream(oMp4File,videoindex,oFrameCount);  
141 
142     //需要mp4close 否则在嵌入式设备打开mp4上多了会内存泄露挂掉.
143     MP4Close(oMp4File,0);   
144     return 0;
145 }
146 
147 int main(void)
148 {
149     openmp4file("test.mp4");    
150     return 0;
151 }

3.测试文件ffproe的信息如下.

测试的mp4文件和生成的264文件信息如下,用播放器播放可以正常显示图像.

 

相关文章