📄 fssapmp4parser.cpp
字号:
//------------------------------------------------------------------------------
// File: fFrameExtractFilter.cpp
//
// Desc: implement CMP4ParserFilter class
//
// Copyright (c) 2008, Samsung Electronics S.LSI. All rights reserved.
//------------------------------------------------------------------------------
#include "stdafx.h"
#include <stdio.h>
#include "SsapMp4Parser.h"
#include "fSsapMp4Parser.h"
#include "fSsapMp4Parser_AudioOp.h"
#include "fSsapMp4Parser_VideoOp.h"
#include "mp4.h"
#include "get_videoinfo.h"
static unsigned char h264_delimiter[4] = {0x00, 0x00, 0x00, 0x01};
static int GetVideoStreamHeader(MP4FileHandle mp4File, MP4TrackId video_trId, int video_codec,
unsigned char *strm_hdr_buf, int *strm_hdr_leng);
static int GetAudioStreamHeader(MP4FileHandle mp4File, MP4TrackId audio_trId, int audio_codec,
unsigned char *strm_hdr_buf, int *strm_hdr_leng);
static int GetVideoProfileAndSize(MP4FileHandle mp4File, MP4TrackId video_trId, int video_codec,
int *profile, int *width, int *height);
#define NAL_UNIT_TYPE_TYPE(n) ((0x1F) & (n))
//
// Constructor
//
CMP4ParserFilter::CMP4ParserFilter(LPUNKNOWN pUnk, HRESULT *phr)
: CSource(NAME("CMP4ParserFilter"), pUnk, CLSID_SSAP_MP4Parser_Filter),
m_pwFileName(NULL)
{
CAutoLock cAutoLock(&m_cStateLock);
// Initializing Member variables
m_hMP4File = NULL;
m_video_codec = 0;
m_video_trId = MP4_INVALID_TRACK_ID;
m_video_num_samples = 0;
m_video_timescale = 0;
m_video_duration = 0;
m_video_profile = 0;
m_audio_codec = 0;
m_audio_trId = MP4_INVALID_TRACK_ID;
m_audio_num_samples = 0;
m_audio_timescale = 0;
m_audio_duration = 0;
m_h264_bufleng_size = 4;
m_h264_tmp_buf = NULL;
//
// CSource::AddPin() is automatically called
// by creating a source stream (CSourceStream)
//
// Add one source stream (output pin)!
// TODO: add source stream here
}
//
// Destructor
//
CMP4ParserFilter::~CMP4ParserFilter()
{
if (m_pwFileName)
delete[] m_pwFileName;
if (m_h264_tmp_buf) {
free(m_h264_tmp_buf);
m_h264_tmp_buf = NULL;
}
if (m_hMP4File)
MP4Close(m_hMP4File);
}
//
// Load
//
STDMETHODIMP CMP4ParserFilter::Load(LPCOLESTR pwszFileName, const AM_MEDIA_TYPE *pmt)
{
// IFileSourceFilter::Load()
// Any calls to this method after the first call will fail!
if (m_pwFileName)
return E_FAIL;
CheckPointer(pwszFileName, E_POINTER);
// lstrlenW is one of the few Unicode functions that works on win95
DWORD dwSize = lstrlenW(pwszFileName) + 1;
#ifndef UNICODE
TCHAR *pszFileName = 0;
pszFileName = new char[dwSize * 2];
if (!pszFileName)
return E_OUTOFMEMORY;
WideCharToMultiByte(GetACP(), 0, pwszFileName, -1,
pszFileName, dwSize * 2, NULL, NULL);
#else
TCHAR pszFileName[MAX_PATH] = {0};
lstrcpy(pszFileName, pwszFileName);
#endif
CAutoLock lck(&m_cStateLock);
// file checking and identify the video & audio codec
HRESULT hr = CheckFile(pszFileName);
#ifndef UNICODE
delete[] pszFileName;
#endif
if (FAILED(hr))
return E_FAIL;
///////////////////////////////////////////
// Add Output Pin for Video Stream
int b;
switch (m_video_codec) {
case RAW_STRM_TYPE_M4V: // MPEG4
case RAW_STRM_TYPE_H263:
// 恐 MPEG4俊辑 profile阑 啊廉坷搁 俊矾啊 唱蠢衬... (throw Exception 锭巩俊...)
// video_profile = MP4GetVideoProfileLevel(m_hMP4File, m_video_trId);
printf("\n[VIDEO] MPEG4, profile = 0x%02X", m_video_profile);
MakeVideoMediaType(&m_video_mt);
new CMP4ParserVideoOp(&hr, this, L"Video Out");
break;
case RAW_STRM_TYPE_H264RAW: // H264
printf("\n[VIDEO] H.264, profile = 0x%02X", m_video_profile);
if (m_video_profile == 66) { // It supports H.264 Baseline only..
MakeVideoMediaType(&m_video_mt);
new CMP4ParserVideoOp(&hr, this, L"Video Out");
}
else
m_video_codec = MP4_INVALID_TRACK_ID;
break;
default:
break;
}
///////////////////////////////////////////
// Add Output Pin for Audio Stream
switch (m_audio_codec) {
case RAW_STRM_TYPE_M4A: // MPEG4-AAC
MakeAudioMediaType(&m_audio_mt);
new CMP4ParserAudioOp(&hr, this, L"Audio Out");
break;
case RAW_STRM_TYPE_AMR_NB: // AMR-NB
MakeAudioMediaType(&m_audio_mt);
new CMP4ParserAudioOp(&hr, this, L"Audio Out");
break;
default:
break;
}
// Restore the current file name
m_pwFileName = new WCHAR[dwSize];
if (m_pwFileName != NULL)
CopyMemory(m_pwFileName, pwszFileName, dwSize * sizeof(WCHAR));
return S_OK;
}
//
// GetCurFile
//
STDMETHODIMP CMP4ParserFilter::GetCurFile(LPOLESTR *ppwszFileName, AM_MEDIA_TYPE *pmt)
{
CheckPointer(ppwszFileName, E_POINTER);
*ppwszFileName = NULL;
if (m_pwFileName != NULL)
{
DWORD dwSize = sizeof(WCHAR) * (1 + lstrlenW(m_pwFileName));
*ppwszFileName = (LPOLESTR)CoTaskMemAlloc(dwSize);
if (*ppwszFileName != NULL)
{
CopyMemory(*ppwszFileName, m_pwFileName, dwSize);
}
}
return S_OK;
}
int CMP4ParserFilter::GetVideoFrame(unsigned char *pFrameBuf, unsigned int *pSize, unsigned int *isIframe, int sample_id)
{
int nRead;
int n_video_hdr;
u_int8_t *p_video_sample;
u_int32_t n_video_sample;
int b, ret;
if ((m_video_codec == RAW_STRM_TYPE_H264RAW) && (m_h264_bufleng_size != 4))
p_video_sample = (u_int8_t *) m_h264_tmp_buf;
else
p_video_sample = (u_int8_t *) pFrameBuf;
n_video_sample = *pSize;
if ((sample_id <= 0) || (sample_id > m_video_num_samples)) {
RETAILMSG(1, (L"\n[CMP4ParserFilter::GetVideoFrame] \'sample_id\' is invalid. (sample_id = %d", sample_id));
*pSize = 0;
return -1;
}
// if (sampleId == 1),
// then "video stream header" is extracted and it is put in the buffer.
if (sample_id == 1) {
ret = GetVideoStreamHeader(m_hMP4File, m_video_trId, m_video_codec,
pFrameBuf, &n_video_hdr);
pFrameBuf += n_video_hdr;
p_video_sample += n_video_hdr;
n_video_sample -= n_video_hdr;
}
else
n_video_hdr = 0;
/////////////////////
// MP4ReadSample //
/////////////////////
b = MP4ReadSample(m_hMP4File, m_video_trId, sample_id,
&p_video_sample, &n_video_sample,
NULL, NULL, NULL, NULL);
if (!b) {
*pSize = 0;
return -1;
}
// if (codec == h.264), the first 4 bytes are the length octets.
// They need to be changed to H.264 delimiter (00 00 00 01).
if (m_video_codec == RAW_STRM_TYPE_H264RAW) {
int h264_nal_leng;
int nal_leng_acc = 0;
if (m_h264_bufleng_size == 4) {
do {
h264_nal_leng = p_video_sample[0];
h264_nal_leng = (h264_nal_leng << 8) | p_video_sample[1];
h264_nal_leng = (h264_nal_leng << 8) | p_video_sample[2];
h264_nal_leng = (h264_nal_leng << 8) | p_video_sample[3];
memcpy(p_video_sample, h264_delimiter, 4);
nal_leng_acc += (h264_nal_leng + 4);
p_video_sample += (h264_nal_leng + 4);
} while (nal_leng_acc < n_video_sample);
}
else {
do {
if (m_h264_bufleng_size == 1)
h264_nal_leng = p_video_sample[0];
else { // m_h264_bufleng_size == 2
h264_nal_leng = p_video_sample[0];
h264_nal_leng = (h264_nal_leng << 8) | p_video_sample[1];
}
memcpy(pFrameBuf, h264_delimiter, 4);
memcpy(pFrameBuf + 4, p_video_sample + m_h264_bufleng_size, h264_nal_leng);
nal_leng_acc += (h264_nal_leng + m_h264_bufleng_size);
p_video_sample += (h264_nal_leng + m_h264_bufleng_size);
pFrameBuf += (h264_nal_leng + 4);
} while (nal_leng_acc < n_video_sample);
}
}
*pSize = nRead = (n_video_hdr + n_video_sample);
*isIframe = MP4GetSampleSync(m_hMP4File, m_video_trId, sample_id);
return nRead;
}
int CMP4ParserFilter::GetAudioFrame(unsigned char *pFrameBuf, unsigned int *pSize, int sample_id)
{
int nRead;
u_int8_t *p_audio_sample;
u_int32_t n_audio_sample;
int b, ret;
p_audio_sample = (u_int8_t *) pFrameBuf;
n_audio_sample = *pSize;
if ((sample_id <= 0) || (sample_id > m_audio_num_samples)) {
RETAILMSG(1, (L"\n[CMP4ParserFilter::GetAudioFrame] \'sample_id\' is invalid. (sample_id = %d", sample_id));
*pSize = 0;
return -1;
}
/////////////////////
// MP4ReadSample //
/////////////////////
b = MP4ReadSample(m_hMP4File, m_audio_trId, sample_id,
&p_audio_sample, &n_audio_sample,
NULL, NULL, NULL, NULL);
if (!b) {
*pSize = 0;
return -1;
}
//printf("\n --- MP4ReadSample=%d", n_audio_sample);
*pSize = nRead = n_audio_sample;
return nRead;
}
double CMP4ParserFilter::GetVideoFrameTime()
{
double frame_time;
frame_time = 1.0 / GetVideoFrameRate(); // in seconds
return frame_time;
}
double CMP4ParserFilter::GetAudioFrameTime()
{
double frame_time=0.0;
switch (m_audio_codec) {
case RAW_STRM_TYPE_M4A: // AAC-LC
frame_time = 1024.0 / GetAudioTimescale(); // in seconds
break;
case RAW_STRM_TYPE_AMR_NB: // AMR-NB
frame_time = 160.0 / GetAudioTimescale(); // in seconds
break;
}
return frame_time;
}
unsigned int CMP4ParserFilter::IsSyncSample(int sample_id)
{
return MP4GetSampleSync(m_hMP4File, m_video_trId, sample_id);
}
static void wchar_t2char(const wchar_t *str_wchar, char *str_char)
{
int i, j;
int leng;
wchar_t c;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -