First, H264 video encoded into MP4 file
See: H264 video encoded into MP4 file
See: Compilation of Mp4v2 under VS2010 and its use in projects
Recently do the project needs to be H264 file encapsulated as MP4 file, from the Internet to find the MP4V2 library, downloaded down do not know where to start, the official website https://code.google.com/p/mp4v2/in the compilation process under Windows is very brief, For those who have just started using VS2010 to do large-scale projects, it is a bit weak. So from the Internet to find the following several blog posts, pro-test available, left to prepare for viewing.
(1) compilation process of Mp4v2 library under VS2017
Note: The content of this paragraph
Reference: Compiling mp4v2
Mp4v2 was bundled with Mpeg4ip, the open source project, and is now separated from Mpeg4ip in a separate library. The MP4V2 library provides some APIs for creating modified MP4 files.
Source code in http://mp4v2.googlecode.com/svn/trunk/, first create a new folder to import the source code, creating a folder right after the SVN checkout (need to pre-install TortoiseSVN client on the computer), in the URL of Repository fill in the http://mp4v2.googlecode.com/svn/trunk/this URL, click OK to import
code, and then put vstudio9.0\libmp4v2\version.rc into the src folder.
The above content is actually to obtain MP4V2 source code. The above two Google sites do not enter, the reason you understand. Available for download from CSDN.
Download: mp4v2 Latest Source
Then, enter the vs2013 directory and open the Mp4v2.sln with vs2017. Select Configure as release Win32, after success, compile libmp4v2. 4 files are generated under Mp4v2-master\buildwin\lib.vs2013\win32\release, Lbmp4v2.lib, Libmp4v2.dll, libmp4v2.pdb, Libmp4v2.exp. So it's done.
Remark: 1. Mp4v2 source download needs to use the SVN client TortoiseSVN, the official website can download the code under the Linux platform. Linux installation before the compilation is said,
See: Mp4v2 Re-learning-mp4v2 Installation Instructions
2. This process opens in VS2017 no problem.
3. In the future, you will use the two files of Lbmp4v2.lib and Libmp4v2.dll in your project.
Here are a few things to keep in mind:
(1) First select Configure as release Win32, this is how to configure.
Configuration method: Build Configuration Manager, and then change the libmp4v2 configuration to Release
(2) Problem analysis
The include file cannot be opened: "Corecrt.h"
workaround, see: VS2015 cannot open include files Corecrt.h
To put it simply, make a copy of the 10.0.15063.0 file in the image below and rename it to 10.0.10240.0
(2) Use of Mp4v2 library in VS2010
Note: Test the code here
Reference: H264 video encoded into MP4 file, the author code is very good, praise one. This is just a detailed look at the configuration process. The original text reads as follows:
It is recently necessary to encode H264 video into MP4 format. Research, one method is to use the FFmpeg library, you can first decode the H264 file, and then encode the generation of MP4 files, but this method is less efficient, 10M video may take a few seconds to complete. Another way is to encapsulate the H264 package directly into the MP4 format according to the MP4 file protocol, which is highly efficient because it is directly based on the MP4 package. H264 can be easily packaged into FLV files, but the MP4 format is relatively complex and can be cumbersome to package. Since there is no time to study the MP4 protocol, find an open source MP4 codec library mp4v2 (https://code.google.com/p/mp4v2/) on Google Code, mp4v2 can easily encode H264 format files. For ease of use, a Mp4encoder class is encapsulated based on the library, and the interface for the Mp4encoder package is as follows. Currently only supports encoding H264 files or data frames into a MP4 file.
[CPP]
class MP4Encoder
{
public:
MP4Encoder(void);
~MP4Encoder(void);
public:
// open or creat a mp4 file.
MP4FileHandle CreateMP4File(const char *fileName,int width,int height,int timeScale = 90000,int frameRate = 25);
// wirte 264 metadata in mp4 file.
bool Write264Metadata(MP4FileHandle hMp4File,LPMP4ENC_Metadata lpMetadata);
// wirte 264 data, data can contain multiple frame.
int WriteH264Data(MP4FileHandle hMp4File,const unsigned char* pData,int size);
// close mp4 file.
void CloseMP4File(MP4FileHandle hMp4File);
// convert H264 file to mp4 file.
// no need to call CreateMP4File and CloseMP4File,it will create/close mp4 file automaticly.
bool WriteH264File(const char* pFile264,const char* pFileMp4);
// Prase H264 metamata from H264 data frame
static bool PraseMetadata(const unsigned char* pData,int size,MP4ENC_Metadata &metadata);
};
The client calls the sample code:
[cpp] view plain copy
#include <stdio.h>
#include "MP4Encoder.h"
int main (int argc, char ** argv)
{Noun
Mp4Encoder mp4Encoder;
/// convert H264 file to mp4 file
Mp4Encoder.WriteH264File ("test.264", "test.mp4");
}
The complete code of MP4Encoder is as follows:
[cpp] view plain copy
/ ************************************************* *******************
filename: MP4Encoder.h
created: 2013-04-16
author: firehood
purpose: MP4 encoder, based on the open source library mp4v2 (https://code.google.com/p/mp4v2/). Zh
********************************************** ******************* /
#pragma once
#include "mp4v2 \ mp4v2.h"
// NALU unit
typedef structure_MP4ENC_NaluUnit
{Noun
Int type;
Int; size;
Unsigned char * data;
} MP4ENC_NaluUnit;
typedef structure_MP4ENC_Metadata
{Noun
// video, must be h264 type
Unsigned intSpnsLen;
Unsigned char Sps [1024];
Unsigned intnPpsLen;
Unsigned char Pps [1024];
} MP4ENC_Metadata, * LPMP4ENC_Metadata;
class MP4Encoder
{Noun
public:
MP4Encoder (void);
~ MP4Encoder (void);
public:
Http: //open.or.creator.mp4 file.
MP4FileHandle CreateMP4File (const charchar * fileName, int width, int height, int timeScale = 90000, int frameRate = 25);
/// wirte 264 metadata in mp4 file.
BoolWrite264Metadata (MP4FileHandle hMp4File, LPMP4ENC_Metadata lpMetadata);
/// wirte 264 data, data can contain multiple frames.
WriteH264Data (MP4FileHandle hMp4File, const unsigned char * pData, int size);
// close mp4 file.
Close MP4File (MP4FileHandle hMp4File);
/// convert H264 file to mp4 file.
/// need to call CreateMP4File and CloseMP4File, it will create / close mp4 file automatically.
BoolWriteH264File (const char * pFile264, const char * pFileMp4);
// Prase H264 metamata from H264 data frame
StaticPraseMetadata (const unsigned char * pData, int size, MP4ENC_Metadata & metadata);
private:
Http: //read.one.nalu.from H264 data buffer.
ReadOneNaluFromBuf (const unsigned char * buffer, unsigned intBufferSize, unsigned intOffSet, MP4ENC_NaluUnit & nalu);
private:
Int m_nWidth;
Int m_nHeight;
Int m_nFrameRate;
Int m_nTimeScale;
MP4TrackId m_videoId;
};
MP4Encoder.cpp
[cpp] view plain copy
/ ************************************************* *******************
filename: MP4Encoder.cpp
created: 2013-04-16
author: firehood
purpose: MP4 encoder, based on the open source library mp4v2 (https://code.google.com/p/mp4v2/). Zh
********************************************** ******************* /
#include "MP4Encoder.h"
#include <string.h>
#define BUFFER_SIZE (1024 * 1024)
MP4Encoder :: MP4Encoder (void):
m_videoId (NULL),
m_nWidth (0),
m_nHeight (0),
m_nTimeScale (0),
m_nFrameRate (0)
{Noun
}
MP4Encoder :: ~ MP4Encoder (void)
{Noun
}
MP4FileHandle MP4Encoder :: CreateMP4File (const char * pFileName, int width, int height, int timescale / * = 90000 * /, int frameRate / * = 25 * /)
{Noun
If (pFileName == NULL)
^ {
To return false;
}
Http: //create.mp4 file.
MP4FileHandle hMp4file = MP4Create (pFileName);
(HMp4file == MP4_INVALID_FILE_HANDLE)
^ {
Printf ("ERROR: Open file fialed. \ N");
To return false;
}
M_nWidth = width;
M_nHeight = height;
_M_nTimeScale = 90000;
M_nFrameRate = 25;
MP4SetTimeScale (hMp4file, m_nTimeScale);
Return hMp4file;
}
bool MP4Encoder :: Write264Metadata (MP4FileHandle hMp4File, LPMP4ENC_Metadata lpMetadata)
{Noun
M_videoId = MP4AddH264VideoTrack
(HMp4File, hMp4File,
Mm_nTimeScale,
M_nTimeScale / m_nFrameRate,
M m_nWidth, // width
^ M_nHeight, // height
LpMetadata-> Sps [1], // sps [1] AVCProfileIndication
LpMetadata-> Sps [2], // sps [2] profile_compat
LpMetadata-> Sps [3], // sps [3] AVCLevelIndication
(3); the number of bytes // length of each byte before the NAL unit
(M_videoId == MP4_INVALID_TRACK_ID)
^ {
Printf ("add video video track failed. \ N");
To return false;
}
MP4SetVideoProfileLevel (hMp4File, 0x01); // Simple Profile @ Level
/// write writesps
MP4AddH264SequenceParameterSet (hMp4File, m_videoId, lpMetadata-> Sps, lpMetadata-> nSpsLen);
/// write writes pps
MP4AddH264PictureParameterSet (hMp4File, m_videoId, lpMetadata-> Pps, lpMetadata-> nPpsLen);
Return true;
}
int MP4Encoder :: WriteH264Data (MP4FileHandle hMp4File, const unsigned char * pData, int size)
{Noun
If (hMp4File == NULL)
^ {
... return -1;
}
If (pData == NULL)
^ {
... return -1;
}
MP4ENC_NaluUnit nalu;
Intint = = 0, len = = 0;
while (len = ReadOneNaluFromBuf (pData, size, pos, nalu))
^ {
(Nalu.type == 0x07) // // sps
... {{
... // Add h264 to track h264
_M_videoId = MP4AddH264VideoTrack
(HMp4File, hMp4File,
The time scale, nTimeScale,
_M_nTimeScale / m_nFrameRate,
The width of the _m_nWidth, // the width
_M_nHeight, // height
Lunalu.data [1], // sps [1] AVCProfileIndication
Lunalu.data [2], // sps [2] profile_compat
Nanalu.data [3], // sps [3] AVCLevelIndication
(3); (3); the length of the bytes of each byte before the NAL unit
(M_videoId == MP4_INVALID_TRACK_ID)
……
Printf ("add video video track failed. \ N");
0; return; 0;
}}
MP4SetVideoProfileLevel (hMp4File, 1); // Simple Profile @ Level
MP4AddH264SequenceParameterSet (hMp4File, m_videoId, nalu.data, nalu.size);
}}}}
... else if (nalu.type == 0x08) // // pps
... {{
MP4AddH264PictureParameterSet (hMp4File, m_videoId, nalu.data, nalu.size);
}}}}
Elelse
... {{
Data int datalen = nalu.size + 4;
Unsigned char * data = new unsigned char [datalen];
// MP4 The first four bytes of Nalu indicate the length of Nalu
Data [0] = nalu.size >> 24;
Data [1] = nalu.size >> 16;
Data [2] = nalu.size >> 8;
Data [3] = nalu.size & 0xff;
Mcmemcpy (data + 4, nalu.data, nalu.size);
(! MP4WriteSample (hMp4File, m_videoId, data, datalen, MP4_INVALID_DURATION, 0, 1))
……
0; return; 0;
}}
Data; [delete] [data]
}}}}
…
Pos + + = len;
}
Return return pos;
}
int MP4Encoder :: ReadOneNaluFromBuf (const unsigned char * buffer, unsigned intBufferSize, unsigned intOffSet, MP4ENC_NaluUnit & nalu)
{Noun
Int i = offSet;
While (i <nBufferSize)
^ {
If (buffer [i ++] == 0x00 &&
Buffer [i ++] == 0x00 &&
Buffer [i ++] == 0x00 &&
Buffer [i ++] == 0x01
().))
... {{
To int pos = i;
(While pos <nBufferSize)
……
(Buffer [pos ++] == 0x00 &&)
The buffer [pos ++] == 0x00 &&
The buffer [pos ++] == 0x00 &&
The buffer [pos ++] == 0x01
(Because of)
…………
To break; break;
To be able to do so
}}
(If pos == nBufferSize)
……
The size of nalu.size = pos-i;
}}
... else
……
Lu nalu.size = (pos-4) -i;
}}
Na nalu.type = buffer [i] & 0x1f;
Nalu.data = (unsigned char *) & buffer [i];
Return (nalu.size + i-offSet); (nalu.size + i-offSet);
}}}}
}
Return 0; return
}
void MP4Encoder :: CloseMP4File (MP4FileHandle hMp4File)
{Noun
If (hMp4File)
^ {
MP4Close (hMp4File);
HMp4File = NULL;
}
}
bool MP4Encoder :: WriteH264File (const char * pFile264, const char * pFileMp4)
{Noun
(PFile264 == NULL NULL || pFileMp4 == NULL)
^ {
To return false;
}
MP4FileHandle hMp4File = CreateMP4File (pFileMp4,352,288);
If (hMp4File == NULL)
^ {
Printf ("ERROR: Create file failed!");
To return false;
}
FILE * fp = fopen (pFile264, "rb");
If (! Fp)
{{{
Printf ("ERROR: open file failed!");
To return false;
}
Fseek (fp, 0, SEEK_SET);
Unsigned char * buffer = new unsigned char [BUFFER_SIZE];
Int pos = = 0;
Whi while (1)
^ {
Int readread = fread (buffer + pos, sizeof (unsigned char), BUFFER_SIZE-pos, fp);
If (readlen <= 0)
... {{
To break; break;
}}}}
Readlen + = = pos;
Int writelen = = 0;
For (int = ireadlen-1; i> = 0; i--)
... {{
(Buffer [i--] == 0x01 &&
The buffer [i--] == 0x00 &&
The buffer [i--] == 0x00 &&
The buffer [i--] == 0x00
(Because of)
…………
(1) Writelen = i + 5;
To break; break;
To be able to do so
}}}}
…
Writelen = WriteH264Data (hMp4File, buffer, writelen);
If (writelen <= 0)
... {{
To break; break;
}}}}
Memcpy (buffer, buffer + writelen, readlen-writelen + 1);
Possibility = readlen-writelen + 1;
}
Fclose (fp);
Delete [] buffer;
CloseMP4File (hMp4File);
Return true;
}
bool
P4Encoder :: PraseMetadata (const unsigned char * pData, int size, MP4ENC_Metadata & metadata)
{Noun
If (pData == NULL NULL || size <4)
^ {
To return false;
}
MP4ENC_NaluUnit nalu;
Int pos = = 0;
Bool bRet1 = false, bRet2 = false;
(While int len = ReadOneNaluFromBuf (pData, size, pos, nalu))
^ {
(Nalu.type == 0x07)
... {{
Mcmemcpy (metadata.Sps, nalu.data, nalu.size);
Metadata.nSpsLen = nalu.size;
^ BRet1 = true;
}}}}
Else if ((nalu.type == 0x08))
... {{
Mcmemcpy (metadata.Pps, nalu.data, nalu.size);
The metadata.nPpsLen = nalu.size;
Reb2 = true;
}}}}
Pos + + = len;
}
If (bRet1 && bRet2)
^ {
Return; true;
}
Return false;
}
In fact, when talking about ffmpeg, we already talked about the VS development environment setup. See: ffmpeg relearn-Installation instructions for Windows
Well, let me repeat it. .
(1) New project
Open VS;
File-> New-> Project-> Win32 Console Application-> Select Empty Project and click Finish.
Note that it is best not to have spaces or Chinese characters in the selected position.
(2) Copy the test documents
Header files (* .h) are copied to the include subfolder of the project folder
Copy the import library file (* .lib) to the lib subfolder of the project folder
Copy the dynamic library files (* .dll) to the project folder
The three sets of files are specifically the include folder under the mp4v2-master folder and libmp4v2.lib and libmp4v2.dll under the mp4v2-master \ buildwin \ lib.vs2013 \ Win32 \ Release folder
Right-click and select Open Folder in Explorer to go to the project directory.
(Note that if I manually enter the folder location, I just did n’t find a good location. After trying for a long time, I found out that I copied the above files to the wrong folder)
After the placement is completed, the following figure:
(3) Add code
Right click on the MP4Encoder project and add-> Class
Double-click the C ++ class to enter the general C ++ class wizard, write the class name as CMP4Encoder, and then copy the above MP4Encoder.h and MP4Encoder.cpp codes to the corresponding files.
Right-click the project MP4Encoder-> Add-> New Item
Select the C ++ file, write the name as main.cpp, the default location is OK, and then copy the above "client call sample code" to this file.
(4) Configuration development files
Open the properties panel
Solution Explorer-> Right-click Project-> Properties
Header configuration
Configuration properties-> C / C ++-> General-> Add include directory, enter "include" (the directory where the header file was just copied)
Import library configuration
Configuration properties-> linker-> general-> additional library directory, enter "lib" (the directory where the library file was just copied)
Configuration properties-> linker-> input-> additional dependencies, enter libmp4v2.lib;
No configuration for dynamic libraries
(5) Test
First copy a H264 test file (.264 extension) to the MP4Encoder folder.
The test file can be downloaded from here: [Open Source World] Share H.264 Video File Download Address
Note that you need to rename the 264 file to test.h264, otherwise the MP4 file size will be 1K.
Or you change the main function:
Then click on the local Windows debugger. This item has expired. Select Yes.
The test.mp4 file can be generated and can be opened with VLC player.
However, it appears when the file is generated, and the PDB file cannot be found or opened. As shown below:
It has no effect on the generated files. If you are uncomfortable, see: Cannot find or open the PDB file.
This is the project file I wrote: MP4Encoder project file
Project files (available)
Having said so much, you find that without the above example, you just encode the H264 video into an MP4 file, and the audio is missing.
The following is an example of audio and video encoding to MP4 file download: MP4v2-h264 to MP4