2023年6月27日发(作者:)
移植mp4v2开源库,h264+g711ag711u编码mp41、mp4v2移植 step2、编译 简单配置参数: ./configure --host=arm-linux CXX=arm-hisiv100nptl-linux-g++ CC=arm-hisiv100nptl-linux-gcc --prefix=/home/mp4v2-2.0.0/Demo --enable-shared 减少库⼤⼩配置参数: ./configure --host=arm-linux CXX=arm-hisiv100nptl-linux-g++ CC=arm-hisiv100nptl-linux-gcc --prefix=/home/mp4v2-2.0.0/Demo --enable-shared --disable-option-checking --disable-debug --disable-fvisibility --disable-largefile --disable-util --disable-dependency-tracking --disable-libtool-lock 如果编译出来的库在调⽤ MP4AddH264VideoTrack 函数时发⽣崩溃现象,加上以下选项可以解决,具体原因我也不清楚。 --disable-optimize make make install2、mp4v2 API简介
MP4FileHandle MP4Create (const char* fileName,uint32_t flags)功能:创建MP4⽂件句柄。 返回:MP4⽂件句柄。 参数:fileName 要录制的MP4⽂件名;flags 创建⽂件类型,如果要创建普通⽂件⽤默认值0就可以,如要录制⼤于4G的MP4⽂件此处要设置MP4_CREATE_64BIT_DATA。
bool MP4SetTimeScale( MP4FileHandle hFile, uint32_t value )功能:设置时间标度。返回:成功返回true,失败返回false。参数:hFile MP4⽂件句柄,value 要设置的值(每秒的时钟ticks数)。
MP4TrackId MP4AddH264VideoTrack(MP4FileHandle hFile, uint32_t timeScale, MP4Duration sampleDuration, uint16_t width, uint16_t height, uint8_t AVCProfileIndication, uint8_t profile_compat, uint8_t AVCLevelIndication, uint8_t sampleLenFieldSizeMinusOne)功能:添加h264视频track。返回:返回track id号。参数:hFile MP4⽂件句柄,timeScale 视频每秒的ticks数(如90000),sampleDuration 设置为MP4_INVALID_DURATION,width height 视频的宽⾼,AVCProfileIndication profile (baseline profile, main profile, ),profile_compat compatible profile,AVCLevelIndication levels,sampleLenFieldSizeMinusOne 设置为3.注意: AVCProfileIndication,profile_compat, AVCLevelIndication,这三个参数值是在h264流中得到的。 MP4TrackId MP4AddAudioTrack( MP4FileHandle hFile, uint32_t timeScale, MP4Duration sampleDuration, uint8_t audioType) 功能:添加⾳频(aac)track。 返回:返回track id号。 参数:hFile MP4句柄,timeScale⾳频每秒的ticks数,默认使⽤采样率(如16000),下⾯两参数设置为MP4_INVALID_DURATION和MP4_MPEG4_AUDIO_TYPE。sampleDuration[翻译:样例持续时长]:⾳频这中这个参数是指每⼀帧⾳频的专多少个采样点MP4TrackId MP4AddALawAudioTrack( MP4FileHandle hFile, uint32_t timeScale)这个接⼝是初始化添加⾳频为APCM(G711_A)的接⼝,接⼝的问题是其中默认⼀帧的持续时间是20ms,见下⾯的源码。我们可以根据⾃⼰的实际情况来更改这个值。MP4TrackId MP4File::AddALawAudioTrack( uint32_t timeScale ){ uint32_t fixedSampleDuration = (timeScale * 20)/1000; // 20mSec/Sample MP4TrackId trackId = AddTrack(MP4_AUDIO_TRACK_TYPE, timeScale); m_pTracks[FindTrackIndex(trackId)]->SetFixedSampleDuration(fixedSampleDuration); return trackId;}所以建议修改库源码为以下接⼝:MP4TrackId MP4AddALawAudioTrack( MP4FileHandle hFile, uint32_t timeScale, uint32_t pointPerFrame)视频或者⾳画同步的主要参数是:SampleDuration。G711_U的⽅式和G711_A做同样修改。bool MP4SetTrackESConfiguration( MP4FileHandle hFile, MP4TrackId trackId, const uint8_t* pConfig, uint32_t configSize ); 功能:设置⾳频解码信息(如果设置错误会导致没有声⾳)。 返回:成功返回true,失败返回false。 参数:hFile ⽂件句柄,trackId ⾳频的track id,pConfig 记录解码信息的⼆进制流,configSize 解码串的长度。 注意:mpeg4ip 使⽤faac进⾏aac⾳频编码的,在编码时可以调⽤相应的函数得到⼆进制串pConfig和长度configSize,但是如果aac不是⽤faac编码的,这是需要⾃⼰填充pConfig,可以参考faac的实现,下⾯是⼀个填充结构例⼦:
前五个字节为 AAC object types LOW 2接着4个字节为 码率index 16000 8接着4个字节为 channels 个数 1应打印出的正确2进制形式为 00010 | 1000 | 0001 | 000 2 8 1bool MP4WriteSample( MP4FileHandle hFile, MP4TrackId trackId, const uint8_t* pBytes, uint32_t numBytes, MP4Duration duration DEFAULT(MP4_INVALID_DURATION), MP4Duration renderingOffset DEFAULT(0), bool isSyncSample DEFAULT(true) );功能:写⼀帧视频数据或写⼀段⾳频数据。返回:成功返回true,失败返回false。参数:hFile ⽂件句柄,trackId ⾳频或视频的track id,pBytes为要写的数据流指针,numBytes为数据字节长度,duration为前⼀视频帧与当前视频帧之间的ticks数,或这是前⼀段⾳频数据和当前⾳频数据之间的ticks。isSyncSample 对视频来说是否为关键帧。注意:1,duration这个参数是⽤来实现⾳视频同步⽤的,如果设置错了会造成⾳视频不同步,甚⾄会出现crash现象(⼀般出现在调⽤MP4Close是crash)。 2,对于视频流MP4WriteSample函数每次调⽤是录制前⼀帧数据,⽤当前帧的时间戳和前⼀帧的时间戳计算duration值,然后把当前帧保存下来⽤做下次调⽤MP4WriteSample时⽤,写⾳频数据⼀样。
void MP4AddH264SequenceParameterSet( MP4FileHandle hFile, MP4TrackId trackId, const uint8_t* pSequence, uint16_t sequenceLen );和void MP4AddH264PictureParameterSet( MP4FileHandle hFile, MP4TrackId trackId, const uint8_t* pPict, uint16_t pictLen );功能:添加序列参数集,添加图像参数集。参数:hFile ⽂件句柄,trackId 视频track id,pSequence和pPict为要写⼊的序列图像参数集的数据指针,sequenceLen和pictLen为串长度。注意:当检测到序列参数集或图像参数集更新时要调⽤MP4AddH264SequenceParameterSet或MP4AddH264PictureParameterSet进⾏更新。
void MP4Close( MP4FileHandle hFile, uint32_t flags DEFAULT(0) );功能:关闭以打开的MP4⽂件。参数:hFile ⽂件句柄,flags 是否允许在关闭MP4⽂件前做⼀些额外的优化处理。注意:在录制较⼩的MP4⽂件时可以把flags设置为默认值,如果录制较⼤的⽂件最好把flags设置为MP4_CLOSE_DO_NOT_COMPUTE_BITRATE否则调⽤MP4Close函数会⽤掉很长的时间。3、h264编码mp4⽂件伪代码
1. {
2. rtp_s* p_rtp = (rtp_s*) arg;
3. if (p_rtp == NULL)
4. { 5. printf("ERROR!n");
6. return;
7. }
8.
9. MP4FileHandle file = MP4Create("4", 0);10. if (file == MP4_INVALID_FILE_HANDLE)
11. {
12. printf("open file fialed.n");
13. return;
14. }
15.
16. MP4SetTimeScale(file, 90000);
17.
18. //添加h264 track
19. MP4TrackId video = MP4AddH264VideoTrack(file, 90000, 90000 / video rate(25), width, height,
20. sps[1], //sps[1] AVCProfileIndication
21. sps[1], //sps[2] profile_compat
22. sps[3]f, //sps[3] AVCLevelIndication
23. 3); // 4 bytes length before each NAL unit
24. if (video == MP4_INVALID_TRACK_ID)
25. {
26. printf("add video track failed.n");
27. return;
28. }
29. MP4SetVideoProfileLevel(file, 0x7F);
30.
31. //添加aac⾳频
32. MP4TrackId audio = MP4AddAudioTrack(file, 48000, 1024, MP4_MPEG4_AUDIO_TYPE);
33. if (video == MP4_INVALID_TRACK_ID)
34. {
35. printf("add audio track failed.n");
36. return;
37. }
38. MP4SetAudioProfileLevel(file, 0x2);
39.
40. //添加g711-u41. m_audioId = MP4AddULawAudioTrack(hMp4File, 8000, 320); //8K采⽤率42. if(m_audioId == MP4_INVALID_TRACK_ID)43. {44. return 0;45. }46. bool a = MP4SetTrackIntegerProperty( hMp4File, m_audioId,"ls", 1); //单通道47. MP4SetAudioProfileLevel(hMp4File, 0x02);48.
49. //添加g711-a50. m_audioId = MP4AddALawAudioTrack(hMp4File, 8000, 320); //8K采⽤率51. if(m_audioId == MP4_INVALID_TRACK_ID)52. {53. return 0;54. }55. bool a = MP4SetTrackIntegerProperty( hMp4File, m_audioId,"ls", 1); //单通道56. MP4SetAudioProfileLevel(hMp4File, 0x02);57.
58. int ncount = 0;
59. while (1)
60. {
61. frame_t* pf = NULL; //frame
62. pthread_mutex_lock(&p_rtp->mutex);
63. pf = p_rtp->p_frame_header;
64. if (pf != NULL)
65. {
66. if (pf->i_type == 1)//video
67. {
68. MP4WriteSample(file, video, pf->p_frame, pf->i_frame_size, MP4_INVALID_DURATION, 0, 1);
69. }
70. else if (pf->i_type == 2)//audio
71. {
72. MP4WriteSample(file, audio, pf->p_frame, pf->i_frame_size , MP4_INVALID_DURATION, 0, 1);
73. }
74.
75. ncount++;
76.
77. //clear frame.
78. p_rtp->i_buf_num--;
79. p_rtp->p_frame_header = pf->p_next;
80. if (p_rtp->i_buf_num <= 0)
81. {
82. p_rtp->p_frame_buf = p_rtp->p_frame_header;
83. }
84. free_frame(&pf);
85. pf = NULL;
86.
87. if (ncount >= 1000)
88. {
89. break;
90. } 91. }
92. else
93. {
94. //printf("BUFF EMPTY, p_rtp->i_buf_num:%dn", p_rtp->i_buf_num);
95. }
96. pthread_mutex_unlock(&p_rtp->mutex);
97. usleep(10000);
98. }
99.
100. MP4Close(file);
101. }
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1687821592a48107.html
评论列表(0条)