To use mp4v2 for MP4 video recording, prepare the following information:
1. Obtain the mp4v2 source code and compile it into a library file. For mp4v2 compilation, see the previous article.Android compiles mp4v2 2.0.0 to generate a dynamic library
;
2. Obtain the SPS and PPS data in h264 data. If not, you can view the previous article.
Click the open link;
3. Obtain audio decoding information, which is used when mp4settrackesconfiguration is called. The specific method is obtained through faac. faacencgetdecoderspecificinfo (hencoder, & (ASC), & (asclength )); // obtain the decoding information. view the AAC audio source code and analyze it against the AAC ADTs Header Format:
The first five bytes are AAC object types low 2 and then 4 bytes are bit rate index 16000 8 and then 4 bytes are the number of channels 1 the correct binary format should be printed is 00010 | 1000 | 0001 | 000 2 8 1
So for (20, 8)
4. For the specified time scale, generally 90000 is set on the Internet. This 90000 refers to the number of tick in one second, which is to divide the second into 90000 copies. In the function of adding audio and video
Durationmp4_invalid_duration
Bool mp4writesample (mp4filehandle hfile, mp4trackid trackID, u_int8_t * pbytes, u_int32_t numbytes, mp4duration duration = duration, mp4duration renderingoffset = 0, bool issyncsample = true // if the video is, this indicates whether the current video frame is a key frame. If it is a key frame, it is 1. If not, it is 0 );
The duration parameter indicates the time when the video frame exists, and the time on the scale of 90000. If the user determines that the audio video frame is at a fixed rate, you can set mp4_invalid_duration here. Then, mp4v2 will use the time scale in the following function.
Video:
Values (mp4filehandle hfile, uint32_t timescale, mp4duration sampleduration, uint16_t width, uint16_t height, uint8_t distance, distance profile_compat, uint8_t distance, uint8_t hour)Sampleduration is the display time of a fixed video frame. The calculation method is timescale (90000) * during (this value is the collection time of the current video frame-The video collection time of the previous frame) /1000, the formula can also be changed to timescale (90000)/FPs (bit rate such as 20f)
Audio:
Sampleduration
Mp4trackid mp4addaudiotrack (mp4filehandle hfile, u_int32_t timescale, u_int32_t sampleduration, u_int8_t audiotype = mp4_mpeg4_audio_type)Sampleduration is the time when the audio frame exists on the time scale. Here, the timescale is the audio sampling time, for example, 44100,32000. The calculation method is the same for the video above.Sampleduration is mainly used for audio and video synchronization.
5. The h264 format in the mp4v2 video must be nal Length + nal data. If the transmitted data does not contain 0x00000001, it is pure data.
(1) The Nal in the h264 stream. The first four bytes are 0x00000001;
(2) hsf-track in MP4. The first four bytes must be of the nal length and are of a large order;
(3) mp4v2 may not be processed in this case, so the four bytes of each nal header written to the MP4 file are still 0x00000001.
Therefore, if the passed h264 data is pure data, you need to modify it as follows:
int nalsize = frameSize; buf[0] = (nalsize&0xff000000)>>24; buf[1] = (nalsize&0x00ff0000)>>16; buf[2] = (nalsize&0x0000ff00)>>8; buf[3] = nalsize&0x000000ff;
If there are other headers, offset them to the pure data position according to the above method.
6. AAC format requirements in mp4v2 Video Recording: Sometimes the AAC data format remotely transmitted is ADTs + AAC pure data, you need to remove the ADTs part, that is, the unit that needs to be offset by 7 bytes.
The following describes how to call the mp4v2 Library:
# Include <stdio. h> # include <string. h> # include ".. /mp4v2/mp4v2. H "# include" appcamerashooting. H "mp4trackid video; mp4trackid audio; mp4filehandle filehandle; unsigned char sps_pps_640 [17] = {0x67, 0x42, 0x40, 0x1f, 0x96, 0x54, 0x05, 0x01, 0xed, 0x00, 0xf3, 0x9e, 0xa0, 0x68, 0xce, 0x38, 0x80 }; // store SPS and ppsint video_width = 640; int video_height = 480; // call video recording to initialize jniexport bool jnicall initialize (jnienv * ENV, jclass clz, jstring title, jint type) {const char * local_title = (* env)-> getstringutfchars (ENV, title, null); // create the MP4 File filehandle = mp4create (local_title, 0 ); if (filehandle = mp4_invalid_file_handle) {return false;} memcpy (sps_pps, sps_pps_640, 17); video_width = 640; video_height = 480; // set the time unit of the MP4 File mp4settimescale (filehandle, 90000); // create a video track // according to ISO/IEC 14496-10, we can see the second and third of SPs, the fourth byte is avcprofileindication, profile_compat, avclevelindication. Among them, 20> is fpsvideo = watermark (filehandle, 90000/20 90000,900, video_width, video_height, sps_pps [1], sps_pps [2]. sps_pps [3], 3); If (Video = mp4_invalid_track_id) {mp4close (filehandle, 0); Return false;} audio = mp4addaudiotrack (filehandle, 16000,102 4, audio ); if (audio = mp4_invalid_track_id) {mp4close (filehandle, 0); Return false ;}// you can specify SPS and SPS (filehandle, video, sps_pps, 13); mp4addh1_pictureparameterset (filehandle, video, sps_pps + 13, 4); mp4setvideoprofilelevel (filehandle, 0x7f); audio (filehandle, 0x02); mp4settrackesconfiguration (filehandle, audio, & ubuffer [0], 2 ); (* env)-> releasestringutfchars (ENV, title, local_title); Return true;} // Method for adding video frames jniexport void jnicall encode (jnienv * ENV, jclass clz, jbytearray data, jint size, jint keyframe) {unsigned char * Buf = (unsigned char *) (* env)-> getbytearrayelements (ENV, Data, jni_false ); if (video_type = 1) {int nalsize = size; Buf [0] = (nalsize & 0xff000000)> 24; Buf [1] = (nalsize & 0x00ff0000)> 16; Buf [2] = (nalsize & 0x0000ff00)> 8; Buf [3] = nalsize & 0x000000ff; mp4writesample (filehandle, video, Buf, size, mp4_invalid_duration, 0, keyframe);} (* env)-> releasebytearrayelements (ENV, data, (jbyte *) BUF, 0 );} // Method for adding audio frames jniexport void jnicall audio (jnienv * ENV, jclass clz, jbytearray data, jint size) {uint8_t * bufaudio = (uint8_t *) (* env) -> getbytearrayelements (ENV, Data, jni_false); mp4writesample (filehandle, audio, & bufaudio [7], size-7, mp4_invalid_duration, 0, 1 ); // subtract 7 to delete the seven bytes (* env) of the ADTs header-> releasebytearrayelements (ENV, data, (jbyte *) bufaudio, 0 );} // call jniexport void jnicall java_com_seuic_jni_appcamerashooting_mp4close (jnienv * ENV, jclass clz) {mp4close (filehandle, 0) when the video recording ends );}