mp4v2保存H264裸码流

  本文通过调用OpenCV库采集摄像头视频,再经过libx264库将视频帧转化成h264格式的裸码流,随后再利用mp4v2库的相关接口将264裸码流保存成mp4格式的视频文件。

头文件:

#ifndef _MP4_ENCODER_H
#define _MP4_ENCODER_H

#include "mp4v2/mp4v2.h"  
  
class MP4Encoder  
{  
public:  
    MP4Encoder(void);

    MP4Encoder(const char* fileName, int width, int height, int timeScale = 90000, int frameRate = 25);

    ~MP4Encoder(void);  

    // open or creat a mp4 file.  
    bool CreateMP4File(const char *fileName, int width, int height, int timeScale = 90000, int frameRate = 25);  
     
    // wirte 264 data, data can contain  multiple frame.  
    bool WriteH264Data(const unsigned char* pData,int size);   
    
    // close mp4 file.  
    void CloseMP4File();

private:

    void Init();
   
private:  
    int m_nWidth;  
    int m_nHeight;  
    int m_nFrameRate;  
    int m_nTimeScale;  
    MP4TrackId m_videoId;
    MP4FileHandle m_fileHandle;
};

#endif
MP4Encoder.h

实现文件:

#include "MP4Encoder.h"  
#include <string.h>  
  

MP4Encoder::MP4Encoder(void)  
{
    Init();
}  

MP4Encoder::MP4Encoder(const char* fileName, int width, int height, int timeScale /* = 90000 */, int frameRate /* = 25 */)
{
    Init();
    CreateMP4File(fileName, width, height, timeScale, frameRate);
}
  
MP4Encoder::~MP4Encoder(void)  
{
    CloseMP4File();
}

void MP4Encoder::Init()
{
    m_nWidth = 0;
    m_nHeight = 0;
    m_nFrameRate = 0;
    m_nTimeScale = 0;
    m_videoId = MP4_INVALID_TRACK_ID;
    m_fileHandle = MP4_INVALID_FILE_HANDLE;
}
  
bool MP4Encoder::CreateMP4File(const char *fileName, int width, int height, int timeScale /* = 90000 */, int frameRate /* = 25 */)
{  
    if(fileName == NULL){
        return false;
    }

    // create mp4 file
    m_fileHandle = MP4CreateEx(fileName);
    if (m_fileHandle == MP4_INVALID_FILE_HANDLE){
        printf("ERROR:Open file fialed.
");  
        return false;  
    }
    m_nWidth = width;
    m_nHeight = height;
    m_nTimeScale = timeScale;
    m_nFrameRate = frameRate;

    MP4SetTimeScale(m_fileHandle, m_nTimeScale);

    m_videoId = MP4AddH264VideoTrack(m_fileHandle, 
        m_nTimeScale, m_nTimeScale / m_nFrameRate, 
        m_nWidth, m_nHeight,
        0x64,    //sps[1] AVCProfileIndication
        0x00,    //sps[2] profile_compat
        0x1f,    //sps[3] AVCLevelIndication
        3);        // 4 bytes length before each NAL unit
    if (m_videoId == MP4_INVALID_TRACK_ID){
        printf("add video track fialed.
");
        CloseMP4File();
        return false;
    }

    return true;  
}

bool MP4Encoder::WriteH264Data(const unsigned char* buf, int bufsize)
{
    if (MP4_INVALID_FILE_HANDLE == m_fileHandle ||
        MP4_INVALID_TRACK_ID == m_videoId){
        return false;
    }
    return MP4WriteSample(m_fileHandle, m_videoId, buf, bufsize, MP4_INVALID_DURATION, 0, 1);
}

void MP4Encoder::CloseMP4File()
{
    if (m_fileHandle != MP4_INVALID_FILE_HANDLE){
        MP4Close(m_fileHandle, 0);
        m_fileHandle = MP4_INVALID_FILE_HANDLE;
        m_videoId = MP4_INVALID_TRACK_ID;
    }
}
MP4Encoder.cpp

主函数:

#include <stdio.h>
#include "x264_encoder.h"
#include "MP4Encoder.h"
#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
  
int main(int argc, char** argv)  
{  
    cv::VideoCapture cap(0);
    cv::Mat frame;
    x264Encoder x264;
    MP4Encoder mp4Enc;
    uint8_t* buf;
    int bufsize;
    int count = 0;

    cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);

    x264.Create(640, 480, 3, 25);
    mp4Enc.CreateMP4File("..\test.mp4", 640, 480);

    while (count++ < 1000)
    {
        cap >> frame;
        if (!frame.empty()){
            bufsize = x264.EncodeOneFrame(frame);
            if (bufsize > 0){
                buf = x264.GetEncodedFrame();
                mp4Enc.WriteH264Data(buf, bufsize);
            }
        }
    }

    return 0;
}
main.cpp

有关 x264Encoder 类的相关实现见:OpenCV采集的视频流转化成H264格式裸码流

 
 
原文地址:https://www.cnblogs.com/ziyu-trip/p/7074922.html