视频安防平台-MP4文件的封装

来源:互联网 发布:淘宝卖家怎么参返利 编辑:程序博客网 时间:2024/05/22 02:02
视频安防平台-MP4文件的封装

一般客户端存储录像文件会采用mp4的格式进行封装,下面针对mp4文件封装了一层,支持语音流的写入、语音流的读出、支持视频流的写入、支持视频流的读出,支持按帧读、按时间读取、支持倒放、随机读取等各种历史视频控制功能,支持文件加密等功能。
下面粘贴一下mp4文件的封装头文件:
#ifndef __LIBMP4_H_#define __LIBMP4_H_#ifndef _MP4V2_H_#define _MP4V2_H_#include "mp4v2/mp4v2.h"#include <vector>#endifusing namespace std;typedef struct sps_pps_header{unsigned char start_code_prefix[5];}sps_pps_header_t;#define MP4ENCODER_ERROR(err) ((MP4EncoderResult)(-(err)))#define DEFAULT_RECORD_TIME 0U#define MAX_FRAME_LEN2*1024*1024UL#define MAX_AUDIO_SIZE100*1024UL//#define AUDIO_STEP_SIZE160#define AUDIO_STEP_SIZE160 * 2//双声道数据加倍#define H264_VIDEO_TYPE"H264"#define MPEG4_VIDEO_TYPE"MPEG4"#define MPEG2_VIDEO_TYPE"MPEG2"#define PRIVATE_VIDEO_TYPE"PRIVATE"#define ALAW_AUDIO_TYPE"ALAW"typedef enum{MP4ENCODER_ENONE = 0,MP4ENCODER_E_CREATE_FAIL,MP4ENCODER_E_ADD_VIDEO_TRACK,MP4ENCODER_E_ADD_AUDIO_TRACK,MP4ENCODER_WARN_RECORD_OVER,MP4ENCODER_E_WRITE_VIDEO_DATA,MP4ENCODER_E_WRITE_AUDIO_DATA,MP4ENCODER_E_ALLOC_MEMORY_FAILED,MP4ENCODER_E_UNKONOWN}MP4EncoderResult;enum StreamTypes{E_STREAM_UNKNOWN = -1,E_STREAM_PRAVITE,E_STREAM_H264,E_STREAM_MPEG4,E_STREAM_MPEG2,E_STREAM_ALAW};class MP4Encoder{public:MP4Encoder(void);~MP4Encoder(void);MP4EncoderResult MP4CreateFile(const char *sFileName,unsigned uRecordTime = DEFAULT_RECORD_TIME,bool bEnc = false);MP4EncoderResult MP4AddH264Track(const uint8_t *sData, int nSize,int nWidth, int nHeight, int nFrameRate = 25);MP4EncoderResult MP4AddAACTrack(const uint8_t *sData, int nSize);MP4EncoderResult MP4AddALAWTrack(const uint8_t *sData, int nSize);MP4EncoderResult MP4AddMPEGTrack(int nWidth, int nHeight, int nFrameRate = 25,uint8_t nVdeoType = MP4_MPEG4_VIDEO_TYPE);MP4EncoderResult MP4WriteH264Data(uint8_t *sData, int nSize, uint64_t u64PTS);MP4EncoderResult MP4WriteAACData(const uint8_t *sData, int nSize,uint64_t u64PTS);MP4EncoderResult MP4WriteALAWData(uint8_t *sData, int nSize,uint64_t u64PTS);MP4EncoderResult MP4WriteMPEGData(uint8_t *sData, int nSize, uint64_t u64PTS);    MP4EncoderResult MP4ModifyFile(const char *sFileName);    MP4EncoderResult MP4OptimizeFile(const char *sFileName);void MP4ReleaseFile();private:unsigned m_uSecond;MP4FileHandle m_hFile;bool m_bFirstVideo,m_bFirstAudio;MP4TrackId m_videoTrack, m_audioTrack;uint64_t m_u64VideoPTS,m_u64AudioPTS, m_u64FirstPTS, m_u64LastPTS;bool m_IsPrivateStream;char*m_pAudioBuf;intm_AudioSize;boolm_bEnc;};struct MP4SampleData{MP4SampleData(void){pData = NULL;nLen = 0;nPts = 0;IsKeyFrame = false;}uint8_t *pData;uint32_t nLen;uint64_t nPts;bool IsKeyFrame;};typedef vector<MP4SampleData>  MP4SampleVector;//回调接口class IMP4Notify{public:virtual void OnReadVideoData(uint8_t *pData,uint32_t nLen,uint64_t nPts,bool IsKeyFrame) = 0; };struct MP4_FRAME{    unsigned short Sn;                    //    int bVideo;                           //int PayLoadType;                      //payload typeint Manuf;                            //视频厂家StreamTypes eType;MP4SampleVector vmp4buf;      //存放多帧数据};class MP4Decoder{public:MP4Decoder();MP4Decoder(IMP4Notify* pNotify);~MP4Decoder(void);int MP4ReadFileExt(const char *sFileName,uint64_t *msFileDuration,uint64_t msStartTime = 0,uint64_t msEndTime = 0,bool FirstKeyFrame = false,bool bInitDirection = false);//读取时需要给定一个初始方向,默认0正向int MP4ReadSampleByFrame(uint64_t *CurSampleID,MP4_FRAME &mp4frame,bool wantKeyFrame = false,bool bDirection = false);//首次调用时,方向必须与打开文件时设置的初始方向一致int MP4ReadSampleByDuration(uint64_t msDuration,MP4_FRAME &mp4frame,bool wantKeyFrame = false,bool bDirection = false);//首次调用时,方向必须与打开文件时设置的初始方向一致int MP4ReadSampleByTime(uint64_t msStartTime,uint64_t msEndTime,MP4_FRAME &mp4frame);int MP4ReadAudioByFrame(uint64_t *CurSampleID,MP4_FRAME &mp4audio);int MP4ReadAudioByDuration(uint64_t msDuration,MP4_FRAME &mp4audio);int MP4ReadAudioByTime(uint64_t msStartTime,uint64_t msEndTime,MP4_FRAME &mp4audio);void MP4ReleaseFile();uint64_t MP4GetTotalSampleNum(){return m_TotalSample;}uint64_t MP4GetCurSampleID(){if(m_bDirection == false){return m_ReadIndex;}else{return m_ReverseReadIndex;}}float MP4GetPos(){float nPos = 0;if(m_bDirection == false){nPos = (float)m_ReadIndex * 100.00 / (float)m_FileAllSample;}else{nPos = (float)m_ReverseReadIndex * 100.00 / (float)m_FileAllSample;}return nPos;}void MP4SetPos(uint64_t msStartTime){MP4SampleId StartSampleID;MP4Timestamp StartStamp =  MP4ConvertToTrackTimestamp(m_hFile,m_videoTrack,msStartTime,MP4_MSECS_TIME_SCALE);StartSampleID = MP4GetSampleIdFromTime(m_hFile,m_videoTrack,StartStamp,false);if(StartSampleID == MP4_INVALID_SAMPLE_ID){return ;}if(StartSampleID > m_FinalSample){return;}m_ReadIndex = StartSampleID;}//通知接口IMP4Notify* m_pMP4Notify;private:MP4FileHandle m_hFile;MP4TrackId m_videoTrack, m_audioTrack;uint64_t m_u64VideoPTS,m_u64AudioPTS;uint64_tm_msTotalDuration;//单位msStreamTypes eStreamType;uint8_t m_video_data[MAX_FRAME_LEN];unsigned int m_video_len;uint8_t m_audio_data[MAX_AUDIO_SIZE];unsigned int m_audio_len;uint64_t m_msStartTime;uint64_t m_msEndTime;uint32_t m_ReadIndex;int32_t m_ReverseReadIndex;uint64_t m_FileAllSample;uint64_t m_TotalSample;uint64_t m_StartSample;uint64_t m_FinalSample;bool m_bDirection;//false 正向 true反向int MP4ReadSampleByFrameForward(uint64_t *CurSampleID,MP4_FRAME &mp4frame,bool wantKeyFrame = false);int MP4ReadSampleByDurationForward(uint64_t msDuration,MP4_FRAME &mp4frame,bool wantKeyFrame = false);int MP4ReadSampleByFrameReverse(uint64_t *CurSampleID,MP4_FRAME &mp4frame);int MP4ReadSampleByDurationReverse(uint64_t msDuration,MP4_FRAME &mp4frame);int MP4ReadChangeDirection(void);void MP4FreeSample(uint8_t** pSample);boolm_bEnc;};#endif




原创粉丝点击