MP4v2 基本使用(二)


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文件信息如下,用播放器播放可以正常顯示圖像.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM