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

📄 fssapmp4parser_audioop.cpp

📁 6410BSP1
💻 CPP
字号:
//------------------------------------------------------------------------------
// File: fSsapMp4Parser_AudioOp.cpp
//
// Desc: implement CMP4ParserAudioOp class
//
// Copyright (c) 2008, Samsung Electronics S.LSI.  All rights reserved.
//------------------------------------------------------------------------------

#include "stdafx.h"
#include "fSsapMp4Parser.h"
#include "fSsapMp4Parser_AudioOp.h"

#include <stdio.h>


//
// Constructor
//
CMP4ParserAudioOp::CMP4ParserAudioOp(HRESULT *phr, CMP4ParserFilter *pParent, LPCWSTR pPinName)
    : CSourceStream(NAME("CMP4ParserAudioOp"), phr, pParent, pPinName),
      CSourceSeeking(NAME("PinSeek"), (IPin*) this, phr, &m_cSharedState)
{
    CAutoLock cAutoLock(m_pFilter->pStateLock());

}


//
// Destructor
//
CMP4ParserAudioOp::~CMP4ParserAudioOp()
{
}


//
// GetMediaType
//
HRESULT CMP4ParserAudioOp::GetMediaType(CMediaType *pMediaType)
{
    CAutoLock lock(m_pFilter->pStateLock());

    ZeroMemory(pMediaType, sizeof(CMediaType));

    // TODO: modify this option
    *pMediaType = ((CMP4ParserFilter *)m_pFilter)->m_audio_mt;


    // m_rtDuration(Total playback time duration) & m_rtStop are used by WMP
    // for displaying the total playback time and progress bar.
    // Here is the most proper place to set.
    m_rtDuration = (REFERENCE_TIME) ((CMP4ParserFilter *)m_pFilter)->GetAudioMSecDuration();
    m_rtDuration = m_rtDuration * 10000i64;
    m_rtStop     = m_rtDuration;

    return S_OK;
}

//
// DecideBufferSize
//
HRESULT CMP4ParserAudioOp::DecideBufferSize(IMemAllocator *pMemAlloc, ALLOCATOR_PROPERTIES *pProperties)
{
    CAutoLock cAutoLock(m_pFilter->pStateLock());
    ASSERT(pMemAlloc);
    ASSERT(pProperties);

    HRESULT hr;

    pProperties->cbBuffer = ((CMP4ParserFilter *)m_pFilter)->GetAudioSampleMaxSize();
    pProperties->cBuffers = 3;
    pProperties->cbAlign  = 1;
    pProperties->cbPrefix = 0;

    // Ask the allocator to reserve us some sample memory, NOTE the function
    // can succeed (that is return NOERROR) but still not have allocated the
    // memory that we requested, so we must check we got whatever we wanted

    ALLOCATOR_PROPERTIES Actual;
    hr = pMemAlloc->SetProperties(pProperties, &Actual);
    if (FAILED(hr)) 
    {
        return hr;
    }

    // Is this allocator unsuitable
    if (Actual.cbBuffer < pProperties->cbBuffer) 
    {
        return E_FAIL;
    }

    return S_OK;
}

static void SaveData(unsigned char *pBuffer, int lSize)
{
    FILE *fp;

    fp = fopen("\\Storage Card\\hdr.tmp", "wb");
    if (fp == NULL)
        return;

    fwrite(pBuffer, 1, lSize, fp);
    fclose(fp);
}

//
// FillBuffer
//
HRESULT CMP4ParserAudioOp::FillBuffer(IMediaSample *pSample)
{
    CMP4ParserFilter *pFilter;

    CAutoLock lock(m_pFilter->pStateLock());

    // End of Stream?
    if (m_rtMediaTime >= m_rtStop)
        return S_FALSE;

    HRESULT hr;
    BYTE *pBuffer;
    long lSize;

    // Get the pointer of MP4 Parser Filter
    pFilter = (CMP4ParserFilter *)m_pFilter;


    // If the current position was moved,
    // the 'm_bDiscontinuity' flag was set.
    if (m_bDiscontinuity) {

    }

    // Get the pointer for output buffer
    hr = pSample->GetPointer(&pBuffer);
    if (FAILED(hr))
        return S_FALSE;
    lSize = ((CMP4ParserFilter *)m_pFilter)->GetAudioSampleMaxSize();

    // Get the Audio frame of 'm_nSampleId'.
    if (pFilter->GetAudioFrame(pBuffer, (unsigned int *) &lSize, m_nSampleId) <= 0)
        return S_FALSE;

/*
    if (m_nSampleId == 1) {
        SaveData(pBuffer, lSize);
    }
*/

    pSample->SetActualDataLength(lSize);

    // Put the timestamp on the sample
    REFERENCE_TIME    rtStart, rtStop;
    rtStart = (REFERENCE_TIME) (m_rtSampleTime / m_dRateSeeking);
    rtStop  = rtStart + (REFERENCE_TIME) (m_rtRepeatTime / m_dRateSeeking);
    pSample->SetTime(&rtStart, &rtStop);

    pSample->SetSyncPoint(TRUE);    // Every audio frame is sync frame.


    m_rtSampleTime  += m_rtRepeatTime;
    m_rtMediaTime   += m_rtRepeatTime;

    m_nSampleId++;


    // If the current position was moved,
    // the 'm_bDiscontinuity' flag was set
    // and therefore the sample needs to be set as discontinuity.
    if (m_bDiscontinuity) {
        pSample->SetDiscontinuity(TRUE);
        m_bDiscontinuity = FALSE;
    }


    return S_OK;
}

//
// OnThreadCreate
//
HRESULT CMP4ParserAudioOp::OnThreadCreate(void)
{
    double  frame_time = ((CMP4ParserFilter *)m_pFilter)->GetAudioFrameTime();    // in seconds


    // SEEKING: Reset the sample time to zero
    CAutoLock lock(&m_cSharedState);

    m_rtSampleTime = 0;
    m_rtMediaTime  = m_rtStart;
    m_nSampleId    = 1;

    // we need to also reset the repeat time in case the system
    // clock is turned off after m_iRepeatTime gets very big
    m_rtRepeatTime = (REFERENCE_TIME) (UNITS * frame_time);

    return CSourceStream::OnThreadCreate();
}


//
// OnThreadDestroy
//
HRESULT CMP4ParserAudioOp::OnThreadDestroy(void)
{
    return CSourceStream::OnThreadDestroy();
}


//
// OnThreadStartPlay
//
HRESULT CMP4ParserAudioOp::OnThreadStartPlay(void)
{
    {
        CAutoLock lock(CSourceSeeking::m_pLock);
        m_bDiscontinuity = TRUE;
    }

    return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
}


//
// ChangeStart
//
HRESULT CMP4ParserAudioOp::ChangeStart(void)
{
    // Reset stream time to zero and the source time to m_rtStart.
    {
        CAutoLock lock(CSourceSeeking::m_pLock);
        m_rtSampleTime = 0;
        m_rtMediaTime  = m_rtStart;
        m_nSampleId    = ((int) (m_rtStart / m_rtRepeatTime)) + 1;

        m_bDiscontinuity = TRUE;
    }

    // Change the start time then flush the graph.
    UpdateFromSeek();

    return S_OK;
}


//
// OnThreadDestroy
//
HRESULT CMP4ParserAudioOp::ChangeStop(void)
{
    CAutoLock lock(CSourceSeeking::m_pLock);
    if (m_rtMediaTime < m_rtStop)
        return S_OK;


    // We've already past the new stop time. Flush the graph.
    UpdateFromSeek();

    return S_OK;
}


//
// OnThreadStartPlay
//
HRESULT CMP4ParserAudioOp::ChangeRate(void)
{
    // Now ChangeRate won't ever be called,
    // but it's pure virtual, so it needs a dummy implementaion
    return S_OK;
}

//
// SetRate
//
STDMETHODIMP CMP4ParserAudioOp::SetRate(double dRate)
{
    if (dRate <= 1.0)
        return E_INVALIDARG;

    {
        CAutoLock lock(CSourceSeeking::m_pLock);
        m_dRateSeeking = dRate;
    }

    // Change rate then flush the graph
    UpdateFromSeek();

    // Now ChangeRate won't ever be called,
    // but it's pure virtual, so it nneds a dummy implementaion
    return S_OK;
}


//
// UpdateFromSeek
//
void CMP4ParserAudioOp::UpdateFromSeek(void)
{
    if (ThreadExists()) 
    {
        // next time around the loop, the worker thread will
        // pick up the position change.
        // We need to flush all the existing data - we must do that here
        // as our thread will probably be blocked in GetBuffer otherwise
        DeliverBeginFlush();

        // make sure we have stopped pushing
        Stop();

        // complete the flush
        DeliverEndFlush();

        // restart
        Run();
    }
}


STDMETHODIMP CMP4ParserAudioOp::SetTimeFormat(const GUID* pFormat)
{
    CAutoLock cAutoLock(m_pFilter->pStateLock());
    CheckPointer(pFormat, E_POINTER);

    if (m_pFilter->IsActive())
    {
        // Cannot switch formats while running
        return VFW_E_WRONG_STATE;
    }

    if (S_OK != IsFormatSupported(pFormat))
        return E_INVALIDARG;    // We don't support this time format.

    return S_OK;
}

STDMETHODIMP CMP4ParserAudioOp::GetTimeFormat(GUID* pFormat)
{
    CAutoLock cAutoLock(m_pFilter->pStateLock());
    CheckPointer(pFormat, E_POINTER);

    *pFormat = TIME_FORMAT_MEDIA_TIME;
    return S_OK;
}

STDMETHODIMP CMP4ParserAudioOp::IsUsingTimeFormat(const GUID* pFormat)
{
    return IsFormatSupported(pFormat);
}


STDMETHODIMP CMP4ParserAudioOp::IsFormatSupported(const GUID* pFormat)
{
    CheckPointer(pFormat, E_POINTER);

    if (*pFormat == TIME_FORMAT_MEDIA_TIME)
        return S_OK;
//    else if (*pFormat == TIME_FORMAT_FRAME)
//        return S_OK;
    else
        return S_FALSE;
}

STDMETHODIMP CMP4ParserAudioOp::QueryPreferredFormat(GUID* pFormat)
{
    CheckPointer(pFormat, E_POINTER);

    *pFormat = TIME_FORMAT_MEDIA_TIME;
    return S_OK;
}

STDMETHODIMP CMP4ParserAudioOp::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat)
{
    return E_NOTIMPL;
}

STDMETHODIMP CMP4ParserAudioOp::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
{
    return CSourceSeeking::SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
}

STDMETHODIMP CMP4ParserAudioOp::GetDuration(LONGLONG* pDuration)
{
    CheckPointer(pDuration, E_POINTER);
    *pDuration = m_rtDuration;

    return S_OK;
}

STDMETHODIMP CMP4ParserAudioOp::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop)
{

    if (pCurrent)    *pCurrent = m_rtMediaTime;
    if (pStop)        *pStop    = m_rtStop;
    return S_OK;
}


STDMETHODIMP CMP4ParserAudioOp::GetCapabilities(DWORD* pCapabilities)
{
    return pCapabilities ? *pCapabilities = 
        AM_SEEKING_CanGetStopPos|
        AM_SEEKING_CanGetDuration|
        AM_SEEKING_CanSeekAbsolute|
        AM_SEEKING_CanSeekForwards|
        AM_SEEKING_CanSeekBackwards, S_OK : E_POINTER;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -