⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fssapmp4parser.cpp

📁 6410BSP1
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
// 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 + -