2,543
社区成员
发帖
与我相关
我的任务
分享
main.cpp
#include "Mp4Muxer.h"
static int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
{
int info;
int i;
info = 1;
for (i = 0; i < zeros_in_startcode; i++)
{
if(Buf[i] != 0)
info = 0;
}
if(Buf[i] != 1)
info = 0;
return info;
}
static bool Check_StartCode(unsigned char *Buf, int pos)
{
int info3 = 0;
info3 = FindStartCode(&Buf[pos-4], 3);
return info3 == 1;
}
static int getNextNal(FILE* inpf, unsigned char* Buf)
{
int pos = 0;
int StartCodeFound = 0;
int info2 = 0;
int info3 = 0;
int nCount = 0;
while(!feof(inpf) && ++nCount <= 4)
{
Buf[pos++]=fgetc(inpf);
}
if(!Check_StartCode(Buf, pos))
{
return 0;
}
while(!feof(inpf) && (Buf[pos++]=fgetc(inpf))==0);
while (!StartCodeFound)
{
if (feof (inpf))
{
return pos-1;
}
Buf[pos++] = fgetc (inpf);
StartCodeFound = Check_StartCode(Buf, pos);
}
fseek(inpf, -4, SEEK_CUR);
return pos - 4;
}
int main()
{
CMp4Muxer mp4("1.mp4");
unsigned char *p_In_Frame = new unsigned char[1280 * 720 * 3/2];
FILE *pFile = NULL;
pFile = fopen("1.h264", "rb");
while(!feof(pFile))
{
int nCount = getNextNal(pFile, p_In_Frame);
if(nCount == 0)
{
continue;
}
mp4.Start_Pack_Video((char *)p_In_Frame, nCount);
}
mp4.Finish_Pack_Video();
delete[] p_In_Frame;
return 1;
}
Mp4Muxer.h
#pragma once
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
};
#include <string>
using namespace std;
class CMp4Muxer
{
public:
CMp4Muxer(const char *pstrFileName = NULL,
AVCodecID type = AV_CODEC_ID_H264,
const int nWidth = 1280,
const int nHeight= 720
);
~CMp4Muxer(void);
public:
int AddStreamToVideo();
int PrePackVideo();
int Start_Pack_Video(const char *pVideoData, int nDataSize);
void Finish_Pack_Video();
int MuxingVideo();
private:
AVFormatContext *m_pFormatCtx;
AVOutputFormat *m_pOutputFormat;
AVCodecContext *m_pOutputCodecCtx;
AVStream *m_pOutputStream;
AVCodec *m_pOutputCodec;
public:
int m_nFrameCount;
string m_strOutputFileName;
private:
int m_nWidth;
int m_nHeight;
AVCodecID m_codecType;
bool m_bMuxing;
bool m_bPrepared;
bool m_bWritedHeader;
bool m_bStreamAdded;
uint8_t *m_pInputVideoData;
int m_nInputVideoSize;
uint8_t *m_pInputAudioData;
int m_nInputAudioSize;
};
Mp4Muxer.cpp
#include "Mp4Muxer.h"
#include <afx.h>
int CMp4Muxer::Start_Pack_Video(const char *pVideoData, int nDataSize)
{
if(!pVideoData || IsBadReadPtr(pVideoData, nDataSize) || nDataSize < 1)
{
return 0;
}
m_nInputVideoSize = nDataSize;
m_pInputVideoData = (uint8_t *)pVideoData;
if(0 > PrePackVideo())
{
return -1;
}
if(0 > AddStreamToVideo())
{
return -2;
}
if(0 > MuxingVideo())
{
return -3;
}
return 1;
}
void CMp4Muxer::Finish_Pack_Video()
{
av_write_trailer(m_pFormatCtx);
}
int CMp4Muxer::PrePackVideo()
{
if(m_bPrepared)
{
return 1;
}
if(m_strOutputFileName.empty())
{
return -1;
}
int nRet = 0;
nRet = avformat_alloc_output_context2(&m_pFormatCtx, NULL, NULL, m_strOutputFileName.c_str());
if(nRet < 0 || !m_pFormatCtx)
{
av_free(m_pFormatCtx);
return -2;
}
m_pFormatCtx->oformat->video_codec = GetCodecType();
m_pOutputFormat = m_pFormatCtx->oformat;
av_dump_format(m_pFormatCtx, 0, m_strOutputFileName.c_str(), 1);
m_bPrepared = true;
return 1;
}
int CMp4Muxer::AddStreamToVideo()
{
if(m_bStreamAdded)
{
return 1;
}
m_pOutputCodec = avcodec_find_decoder(GetCodecType());
if(!m_pOutputCodec)
{
return -2;
}
m_pOutputStream = avformat_new_stream(m_pFormatCtx, m_pOutputCodec);
if(!m_pOutputStream)
{
return -1;
}
m_pOutputStream->id = m_pFormatCtx->nb_streams - 1;
m_pOutputCodecCtx = m_pOutputStream->codec;
m_pOutputCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
m_pOutputCodecCtx->codec_id = GetCodecType();
m_pOutputCodecCtx->time_base.den= 25;
m_pOutputCodecCtx->time_base.num= 1;
m_pOutputCodecCtx->width = m_nWidth;
m_pOutputCodecCtx->height = m_nHeight;
if(m_pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
m_pOutputCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
int nRet = 0;
nRet = avcodec_open2(m_pOutputCodecCtx, m_pOutputCodec, NULL);
if(nRet < 0)
{
return -3;
}
if(!(m_pOutputFormat->flags & AVFMT_NOFILE))
{
nRet = avio_open(&m_pFormatCtx->pb, m_strOutputFileName.c_str(), AVIO_FLAG_READ_WRITE);
if(nRet < 0)
{
return -4;
}
}
m_bStreamAdded = true;
return 1;
}
int CMp4Muxer::MuxingVideo()
{
if(!m_bWritedHeader)
{
avformat_write_header(m_pFormatCtx, NULL);
m_bWritedHeader = true;
}
if(!WriteFrameFromData())
{
return -1;
}
return 1;
}
int CMp4Muxer::WriteFrameFromData()
{
AVPacket h264Pkt;
av_init_packet(&h264Pkt);
AVRational base1 = {1, 25};
AVRational base2 = {1, 12800};
h264Pkt.dts = av_rescale_q(m_nFrameCount, m_pOutputCodecCtx->time_base, m_pOutputStream->time_base);
h264Pkt.pts = h264Pkt.dts;
h264Pkt.flags |= AV_PKT_FLAG_KEY;
h264Pkt.stream_index = m_pOutputStream->index;
h264Pkt.data = m_pInputVideoData;
h264Pkt.size = m_nInputVideoSize;
double dTime = h264Pkt.pts * av_q2d(m_pOutputStream->time_base);
m_nFrameCount++;
int nRet = 0;
nRet = av_interleaved_write_frame(m_pFormatCtx, &h264Pkt);
if(nRet < 0)
{
return -1;
}
avio_flush(m_pFormatCtx->pb);
av_free_packet(&h264Pkt);
return 1;
}