MP4v2 基本使用(二)

摘要:
oMp4File)返回-1;16charNAL[5]={0x00,0x00,0x00,0x01};17unsignedchar*pData=NULL;18未签名尺寸=0;19MP4时间戳开始时间;20MP4工期;21MP4工期渲染偏移;22boolpIsSyncSample=0;2324intnReadIndex=0;25FILE*pFile=NULL;26pFile=fopen;2728当29{30nReadIndex++;31//printf;32MP4ReadSample;3334//IDR帧时,写入sppps 35if36{37fwrite;38fwrite,3940write;41fwrite:4243}44//264frame45if46{47//标准264帧,并且前几个字节是帧的长度。48//您需要替换标准264nal标头。49pData[0]=0x00;50pData[1]=0x00,51pData[2]=0x00//如果MP4ReadSample的视频pData为空57//它将在内部创建一个新的存储器58//如果MP4ReadSample的视频p Data被导入到一个已知的存储器区域,59//则需要保证最大帧大小为60free;61pData=空;62}63英尺;64fc关闭;6566返回0;67}68到penmp4file 69{70MP4FileHandleoMp4File;71inti;7273//未签名到StreamDuration;74未签名到FrameCount;7576oMp4File=MP4Read;77intvideoindex=-1,audioindex=-1;78uint32_tnumSamples;79//uint32.timescale;80//uint64_tduration;8182if(!
MP4转H264文件

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

1.264文件基本知识 

MP4v2 基本使用(二)第1张

下看看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的信息如下.

MP4v2 基本使用(二)第2张

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

免责声明:文章转载自《MP4v2 基本使用(二)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇四个好看的CSS样式表格axios 封装及取消请求下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

AntDesignVue中关于Table组件的使用

--下面这整个div都是设置每一列搜索的样式图标--˃searchInput=c":placeholder="`Search${column.dataIndex}`":value="selectedKeys[0]"@change="e=˃setSelectedKeys(e.target.value?...

20、EVE-NG华丽登场Openstack镜像,体验私有云!

EVE-NG华丽登场Openstack镜像,体验私有云!为了推动Cloud技术在国内更快速的发展,本人决定为EVE-NG定制一个Openstack私有云系统的镜像,来提升工程师个人的技术实力,横向拓宽技术知识面,以应对IT技术高速迭代,快速发展的现状。当然,您可以将Openstack设备连接到其他拓补中,但设备所在的网络必须是10.0.0.0/24,并且网关...

IDEA的设置打不开,点了没反应解决办法

把它去掉用回英文d就可以了。...

ubuntu的ufw如何开放特定端口?

ubuntu的ufw是如何打开特定端口的?1.安装sudoapt getinstallufw2.启用sudoufwenable以默认情况下禁用外部访问sudoufwdefaultdeny 3.查看状态sudoufwstatus4.添加端口sudoufwallow80805。删除端口sudoufwdeleteallow808080806。允许特定源的IP地址从...

Nginx反向代理缓冲区优化

为了为不同域名的业务需求设置代理_ bufferingproxy_缓冲参数用于控制是否打开后端响应内容的缓冲区_缓冲区将缓冲到硬盘(缓冲区目录由_temp_path命令指定),...

为什么运行CMD后,一闪就不见了 解决方案

方法1:如果您中毒,系统中的一个进程正在监视您的命令。如果您看到CMD,可以关闭它。您可以检查任务管理中是否有流程。如果你关闭它,你应该可以打开它。如果没有,则说明已注入系统进程。很难杀死病毒。方法2:注册表:HKEY_LOCAL__清除MACHINE Software Microsoft CommandProcessor AutoRun中的值,即删除带有d...