zoukankan      html  css  js  c++  java
  • 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格式裸码流

     
     
  • 相关阅读:
    avalon如何用年月日的方式输出..
    做一个倒计时的功能,天,时,分 /时,分,秒
    avalon用background-image不起作用,怎么来选取前几个的图片进行渲染
    获取地址栏的参数的两种方法?
    mac屏幕录制
    数据可视化
    vscode 插件
    git 命令 总结
    jest
    react admin
  • 原文地址:https://www.cnblogs.com/ziyu-trip/p/7074922.html
Copyright © 2011-2022 走看看