zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ",__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
    ",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文件信息如下,用播放器播放可以正常显示图像.

  • 相关阅读:
    四种访问权限修饰符的区别
    安全框架Shiro和Spring Security比较
    POJ 1873 The Fortified Forest 凸包 二进制枚举
    POJ 2007 Scrambled Polygon 极角排序
    POJ 1113 Wall 凸包
    hdu 2276 Kiki & Little Kiki 2 矩阵快速幂
    UVA 10689 Yet another Number Sequence 矩阵快速幂 水呀水
    UVa 10655 Contemplation! Algebra 矩阵快速幂
    直线与直线相交 直线与线段相交 线段与线段相交
    hdu 4686 Arc of Dream 自己推 矩阵快速幂
  • 原文地址:https://www.cnblogs.com/streammm/p/6099327.html
Copyright © 2011-2022 走看看