[svn] / trunk / xvidextra / src / apps / miniconvert / filters.cpp Repository:
ViewVC logotype

View of /trunk/xvidextra/src/apps/miniconvert/filters.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2014 - (download) (annotate)
Tue May 31 08:55:11 2011 UTC (12 years, 10 months ago) by Irhall
File size: 21173 byte(s)
Xvid MiniConvert media converter (initial import)
/*****************************************************************************
 *
 *  Xvid MiniConvert
 *  - Helper filters -
 *
 *  Copyright(C) 2011 Xvid Solutions GmbH
 *
 *  This program is free software ; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation ; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY ; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program ; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * $Id$
 *
 ****************************************************************************/
/*
 *  Author(s): Ireneusz Hallmann
 *
 ****************************************************************************/

#include "stdafx.h"
#include "filters.h"
#include "mmreg.h"   // WAVE_FORMAT_MPEGLAYER3 format structure

//////////////////////////////////////////////////////////////////////////////////////////////////

CUnknown * WINAPI 
CProgressNotifyFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr, int Type)
{
  CUnknown *pNewFilter = new CProgressNotifyFilter(pUnk, phr, Type);
  
  if (phr) {
    if (pNewFilter == NULL) *phr = E_OUTOFMEMORY;
    else *phr = S_OK;
  }

  return pNewFilter;
}

CProgressNotifyFilter::CProgressNotifyFilter(LPUNKNOWN pUnk, HRESULT   *phr, int Type) :
  CTransInPlaceFilter("ProgressNotify", pUnk, CLSID_ProgressNotifyFilter, phr, false) 
{
  m_MessageWnd = 0;
  m_SampleCnt = 0;
  m_Pass = 1;
  m_Type = Type;
  m_startTime = 0;
  m_stopTime = 0;
  m_Width = 0, m_Height = 0;
  m_AvgTimeForFrame = 0;

  if (*phr) *phr = S_OK;
}


CProgressNotifyFilter::~CProgressNotifyFilter(void) 
{
}

HRESULT 
CProgressNotifyFilter::NonDelegatingQueryInterface(REFIID riid, void ** ppv) 
{
  if (riid == IID_IRecProgressNotify)
    return GetInterface((IRecProgressNotify*)this, ppv);

  return CBaseFilter::NonDelegatingQueryInterface (riid, ppv);
}

HRESULT 
CProgressNotifyFilter::CheckInputType(const CMediaType *mtIn) 
{
  if (mtIn->majortype != MEDIATYPE_Video && 
      mtIn->majortype != MEDIATYPE_Audio) {

    return VFW_E_TYPE_NOT_ACCEPTED;
  }

  if (mtIn->formattype != FORMAT_None) {

    if (mtIn->formattype == FORMAT_VideoInfo || 
		mtIn->formattype == FORMAT_MPEGVideo) {

      m_AvgTimeForFrame = ((VIDEOINFOHEADER *)mtIn->pbFormat)->AvgTimePerFrame;
	  m_Width = ((VIDEOINFOHEADER *)mtIn->pbFormat)->bmiHeader.biWidth;
	  m_Height = ((VIDEOINFOHEADER *)mtIn->pbFormat)->bmiHeader.biHeight;

    } 
	else if (mtIn->formattype == FORMAT_VideoInfo2 || 
             mtIn->formattype == FORMAT_MPEG2Video) {

      m_AvgTimeForFrame = ((VIDEOINFOHEADER2 *)mtIn->pbFormat)->AvgTimePerFrame;
	  m_Width = ((VIDEOINFOHEADER2 *)mtIn->pbFormat)->bmiHeader.biWidth;
	  m_Height = ((VIDEOINFOHEADER2 *)mtIn->pbFormat)->bmiHeader.biHeight;

    } 
	else if (mtIn->formattype == FORMAT_WaveFormatEx && m_Type == 2) {

      MPEGLAYER3WAVEFORMAT *pMp3 = (MPEGLAYER3WAVEFORMAT *)mtIn->pbFormat;
	  if (pMp3->wfx.nAvgBytesPerSec != 16000)
        return VFW_E_TYPE_NOT_ACCEPTED;

      // WAVEFORMATEX *pWaveFormat = (WAVEFORMATEX *)mtIn->pbFormat;
      // if (pWaveFormat->nChannels > 2)
	  //   return VFW_E_TYPE_NOT_ACCEPTED;

    } 
	else if (m_Type == 0) {
	  return VFW_E_TYPE_NOT_ACCEPTED;
	}
  }

  return S_OK;
}

HRESULT 
CProgressNotifyFilter::Transform(IMediaSample *pSample) 
{
  LONGLONG osTime, sTime, eTime;
  pSample->GetTime(&osTime, &eTime);
  sTime = osTime;
  int bSetTime = 0;

  if (m_Type == 0) { // Video

#if 0 // emms instruction - for debug
#ifdef __FUNCTION__
// Visual Studio
    __asm emms;
#else
    __asm ("emms");
#endif
#endif

    m_TotalDataSize += pSample->GetActualDataLength();
    m_SampleCnt++;
  
    int CurPos = (int) (m_TotalFrames ? (((double)(100 * m_SampleCnt/m_TotalFrames) + 0.5)) : 0);

	if (m_Pass == 0) {
	  CurPos /= 2;
	}
	else if (m_Pass == 2) {
	  CurPos = CurPos/2 + 50;
	}

	if (m_totalSize > 0) {
	  CurPos = ((CurPos*m_curSize) / m_totalSize);
      CurPos += ((100*m_elapsedSize) / m_totalSize);
	}

	if (m_MessageWnd)
	  PostMessage(m_MessageWnd, PBM_SETPOS, CurPos, 0);
  }
  else { // Audio
    MPEGLAYER3WAVEFORMAT *pMp3 = 0;

    if (m_MediaType.subtype == MEDIASUBTYPE_MP3) {
      pMp3 = (MPEGLAYER3WAVEFORMAT *)m_MediaType.pbFormat;

      DWORD ThisSamples = (pMp3->wfx.nSamplesPerSec >= 32000 ? 576 : 1152) * pMp3->nFramesPerBlock;
      m_SampleCnt += ThisSamples;

      LONGLONG sDuration =  eTime - sTime;
      if (((m_SampleCnt || sTime) && sTime <= m_stopTime)) {
        sTime = m_stopTime + 1;
        bSetTime = 1;
      }
      if (eTime <= sTime || sDuration != (ThisSamples * 10000000LL * m_FpsDen)/m_FpsNom) {
        sDuration = (ThisSamples * 10000000LL * m_FpsDen)/m_FpsNom - 1;
        eTime = sTime + sDuration;
        bSetTime = 1;
      }
      sTime = osTime; //!!

      pSample->SetSyncPoint(TRUE);
    }
  }

  if (bSetTime) 
    pSample->SetTime(&sTime, &eTime);

  m_startTime = sTime;
  m_stopTime = eTime;

  return S_OK;
}

HRESULT 
CProgressNotifyFilter::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin) 
{
  HRESULT hr = pReceivePin->ConnectionMediaType(&m_MediaType);
  m_MinSampleSize = 0;

  if (hr == S_OK) {
    if (m_MediaType.formattype == FORMAT_VideoInfo 
        || m_MediaType.formattype == FORMAT_MPEGVideo) {

      m_AvgTimeForFrame = ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->AvgTimePerFrame;

	  if (direction == PINDIR_INPUT) {
        if (m_MediaType.bTemporalCompression || m_MediaType.lSampleSize <=1) {
          m_MinSampleSize = ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->bmiHeader.biHeight * 
                             ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->bmiHeader.biWidth * 4;
        }
	  }
    } 
	else if (m_MediaType.formattype == FORMAT_VideoInfo2 || 
             m_MediaType.formattype == FORMAT_MPEG2Video) {
      m_AvgTimeForFrame = ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->AvgTimePerFrame;

	  if (direction == PINDIR_INPUT) {
        if (m_MediaType.bTemporalCompression || m_MediaType.lSampleSize <=1) {
          m_MinSampleSize = ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->bmiHeader.biHeight * 
                             ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->bmiHeader.biWidth * 4;
        }
	  }
    } 
	else if (m_Type == 0) {
      hr = VFW_E_TYPE_NOT_ACCEPTED;
	}

    if (m_AvgTimeForFrame) {
  
      switch (m_AvgTimeForFrame) {
        case 416666: // 24.0 FPS
          m_FpsNom = 24; 
          m_FpsDen = 1; 
          break;

        case 417083: // 23.97 FPS
          m_FpsNom = 24000;
          m_FpsDen = 1001;
          break;

        case 333333: // 30.0 FPS
          m_FpsNom = 30;
          m_FpsDen = 1;
          break;

        case 333666: // 29.97 FPS
          m_FpsNom = 30000;
          m_FpsDen = 1001;
          break;

        default: 
          m_FpsNom = (int) (10000000 / m_AvgTimeForFrame);
          m_FpsDen = 1;
      }
    } 
	else if (m_Type == 1 || m_Type == 2) {
      WAVEFORMATEX *pWave = (WAVEFORMATEX *)m_MediaType.pbFormat;
      m_FpsNom = pWave->nSamplesPerSec;
      m_FpsDen = 1;
    }
  }

  return hr;
}

HRESULT 
CProgressNotifyFilter::DecideBufferSize(IMemAllocator *pAlloc, 
                                        ALLOCATOR_PROPERTIES *pProperties)
{
  ALLOCATOR_PROPERTIES Request, Actual;
  HRESULT hr;

  // If we are connected upstream, get his views
  if (m_pInput->IsConnected()) {
    // Get the input pin allocator, and get its size and count.
    // we don't care about his alignment and prefix.

    hr = InputPin()->PeekAllocator()->GetProperties(&Request);

    if (FAILED(hr)) {
      // Input connected but with a secretive allocator - enough!
      return hr;
    }

    if (m_MinSampleSize && (m_Type == 0)) {
      if (Request.cbBuffer < m_MinSampleSize) {
        Request.cbBuffer = m_MinSampleSize;
      }
    }
  } 
  else {
    // We're reduced to blind guessing.  Let's guess one byte and if
    // this isn't enough then when the other pin does get connected
    // we can revise it.

    ZeroMemory(&Request, sizeof(Request));
    Request.cBuffers = 1;
    Request.cbBuffer = 1;
  }

#ifdef _DEBUG
  DbgLog((LOG_MEMORY,1,TEXT("Setting Allocator Requirements")));
  DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d"), Request.cBuffers, Request.cbBuffer));
#endif

  // Pass the allocator requirements to our output side
  // but do a little sanity checking first or we'll just hit
  // asserts in the allocator.

  pProperties->cBuffers = Request.cBuffers;
  pProperties->cbBuffer = Request.cbBuffer;
  pProperties->cbAlign = Request.cbAlign;

  if (pProperties->cBuffers<=0) {
    pProperties->cBuffers = 1; 
  }
  
  if (pProperties->cbBuffer<=0) {
    pProperties->cbBuffer = 1; 
  }
  
  hr = pAlloc->SetProperties(pProperties, &Actual);
  if (FAILED(hr)) {
    return hr;
  }

#ifdef _DEBUG
  DbgLog((LOG_MEMORY,1,TEXT("Obtained Allocator Requirements")));
  DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d, Alignment %d"), 
	      Actual.cBuffers, Actual.cbBuffer, Actual.cbAlign));
#endif

  // Make sure we got the right alignment and at least the minimum required
  if ((Request.cBuffers > Actual.cBuffers) || 
      (Request.cbBuffer > Actual.cbBuffer) || 
      (Request.cbAlign  > Actual.cbAlign)) 
  {
    return E_FAIL;
  }
  
  return NOERROR;
}

//////////////////////////////////////////////////////////////////////////////////////////

HRESULT 
CIRecProgressNotify::GetDimensions(DWORD &Width, DWORD &Height) 
{
  Width = m_Width;
  Height = m_Height;

  return S_OK;
}

HRESULT 
CIRecProgressNotify::GetBitrate(DWORD &OutFramesCount, 
                                LONGLONG &OutTotalDataSize) 
{
  OutFramesCount = m_SampleCnt;
  OutTotalDataSize = m_TotalDataSize;

  return S_OK;
}

HRESULT 
CIRecProgressNotify::SetPass(int in_Pass) 
{
  m_Pass = in_Pass;
  m_SampleCnt = 0;

  return S_OK;
}

HRESULT
CIRecProgressNotify::SetTotalFrames(DWORD in_TotalFrames)
{
  m_TotalFrames = in_TotalFrames;

  return S_OK;
}

HRESULT 
CIRecProgressNotify::SetNotifyWnd(HWND in_hWnd) 
{
  m_MessageWnd = in_hWnd;

  return S_OK;
}

STDMETHODIMP 
CIRecProgressNotify::SetTotalSize(int nbTotal) 
{
  m_totalSize = nbTotal;

  return S_OK;
}

STDMETHODIMP 
CIRecProgressNotify::SetCurSize(int nbCur) 
{
  m_curSize = nbCur;

  return S_OK;
}

STDMETHODIMP 
CIRecProgressNotify::SetElapsedSize(int nbElapsed) 
{
  m_elapsedSize = nbElapsed;

  return S_OK;
}

CIRecProgressNotify::CIRecProgressNotify() 
{
  m_Pass = -1;
  m_MessageWnd = 0;
  m_TotalFrames = 0;
  m_SampleCnt = 0;
  m_TotalDataSize = 0;
  m_totalSize = 0;
  m_curSize = 0;
  m_elapsedSize = 0;
}

//////////////////////////////////////////////////////////////////

CUnknown * WINAPI 
ChangeSubtypeT::CreateInstance(IUnknown *pUnk, HRESULT *phr) 
{
  CUnknown *pNewFilter = new ChangeSubtypeT(pUnk, phr );

  if (phr) {
    if (pNewFilter == NULL) *phr = E_OUTOFMEMORY;
    else *phr = S_OK;
  }

  return pNewFilter;
}

ChangeSubtypeT::ChangeSubtypeT(LPUNKNOWN pUnk, HRESULT   *phr) :
  CTransformFilter("ChangeSubtypeT", pUnk, CLSID_ChangeSubtypeT) 
{
  m_OutFcc = 'DIVX';  // == FCC('xvid')
  m_SubtypeID = FOURCCMap('divx');  // FCC('XVID')
  m_SampleCnt = 0;

  if (*phr) *phr = S_OK;

  m_pMpeg4Sequence = 0;
  m_Mpeg4SequenceSize = 0;
}

ChangeSubtypeT::~ChangeSubtypeT(void)
{
}

HRESULT 
ChangeSubtypeT::NonDelegatingQueryInterface(REFIID riid, void ** ppv) 
{
  if (riid == IID_IRecProgressNotify)
    return GetInterface((IRecProgressNotify*)this, ppv);

  return CBaseFilter::NonDelegatingQueryInterface (riid, ppv);
}

HRESULT 
ChangeSubtypeT::CheckInputType(const CMediaType *pmt) 
{
  if (!pmt) 
    return E_POINTER;

  if (pmt->majortype != MEDIATYPE_Video)
    return S_FALSE;

  return S_OK;
}

HRESULT 
ChangeSubtypeT::CheckTransform (const CMediaType *pmtIn, const CMediaType *pmtOut) 
{
  if (!m_pInput->IsConnected())
    return E_UNEXPECTED;

  if (pmtIn->majortype != MEDIATYPE_Video)
    return VFW_E_TYPE_NOT_ACCEPTED;

  BITMAPINFOHEADER *pBmp = 0;

  if (pmtOut->majortype == MEDIATYPE_Video) {

    if (m_SubtypeID != pmtOut->subtype)
      return VFW_E_TYPE_NOT_ACCEPTED;
    
	if (!pmtOut->pbFormat)
      return S_OK;

    if (pmtOut->formattype == FORMAT_VideoInfo || 
		pmtOut->formattype == FORMAT_MPEGVideo) 
	{
      pBmp = &((VIDEOINFOHEADER *)pmtOut->pbFormat)->bmiHeader;
    } 
	else if (pmtOut->formattype == FORMAT_VideoInfo2 || 
		     pmtOut->formattype == FORMAT_MPEG2Video) 
	{
      pBmp = &((VIDEOINFOHEADER2 *)pmtOut->pbFormat)->bmiHeader;
    } 
	else 
      return VFW_E_TYPE_NOT_ACCEPTED;

    if (m_OutFcc == pBmp->biCompression)
      return S_OK;
  } 

  return VFW_E_TYPE_NOT_ACCEPTED;
}

HRESULT 
ChangeSubtypeT::DecideBufferSize(IMemAllocator * pAlloc, 
                                 ALLOCATOR_PROPERTIES * ppropInputRequest) 
{
  if (!m_pInput->IsConnected())
    return E_UNEXPECTED;

  HRESULT hr = NOERROR;
  BITMAPINFOHEADER *pBmp = 0;

  if (!m_OutMediaType.pbFormat) 
    return VFW_E_TYPE_NOT_ACCEPTED;

  if (m_OutMediaType.formattype == FORMAT_VideoInfo || 
	  m_OutMediaType.formattype == FORMAT_MPEGVideo)
  {
    pBmp = &((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->bmiHeader;
  } 
  else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || 
           m_OutMediaType.formattype == FORMAT_MPEG2Video)
  {
    pBmp = &((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->bmiHeader;
  } 
  else 
    return VFW_E_TYPE_NOT_ACCEPTED;

  ppropInputRequest->cBuffers = 1;
  ppropInputRequest->cbBuffer = pBmp->biHeight*pBmp->biWidth * (pBmp->biBitCount+7)/8;

  ALLOCATOR_PROPERTIES Actual;
  hr = pAlloc->SetProperties(ppropInputRequest,&Actual);
  if (FAILED(hr))
    return hr;

  if (ppropInputRequest->cBuffers > Actual.cBuffers || 
	  ppropInputRequest->cbBuffer > Actual.cbBuffer)
    return E_FAIL;

  return S_OK;
}

HRESULT 
ChangeSubtypeT::GetMediaType(int iPosition, CMediaType *pMediaType) 
{
  if (!m_pInput->IsConnected()) {
    return E_UNEXPECTED;
  }
  else if (iPosition < 0) {
    return E_INVALIDARG;
  }
  else if (iPosition > 0) {
    return VFW_S_NO_MORE_ITEMS;
  }
  else { //if (iPosition == 0) 
    *pMediaType = m_OutMediaType;
    return S_OK;
  }
}

HRESULT 
ChangeSubtypeT::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin) 
{
  CMediaType mt;
  BITMAPINFOHEADER *pBmp = 0;
  pReceivePin->ConnectionMediaType(&mt);

  if (mt.majortype == MEDIATYPE_Video) {
    if (direction == PINDIR_INPUT) {

      // if (m_pOutput->IsConnected()) {
      //   m_pInput->BreakConnection();
      // }

      m_InMediaType = mt;
      m_OutMediaType = mt;
      m_OutMediaType.subtype = m_SubtypeID;

      int NewSequenceSize = 0;

      if (m_InMediaType.formattype == FORMAT_VideoInfo || 
		  m_InMediaType.formattype == FORMAT_MPEGVideo)
	  {
        pBmp = &((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->bmiHeader;
        m_AvgTimeForFrame = (DWORD) ((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->AvgTimePerFrame;
      } 
	  else {
        if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || 
		    m_OutMediaType.formattype == FORMAT_MPEG2Video) 
        {
          pBmp = &((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->bmiHeader;
          m_AvgTimeForFrame = (DWORD) ((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->AvgTimePerFrame;
	    } 
        else 
          return VFW_E_TYPE_NOT_ACCEPTED;
	  }

	  if (*m_InMediaType.FormatType() == FORMAT_MPEG2Video) {
        MPEG2VIDEOINFO *mpeg2info=(MPEG2VIDEOINFO*)m_InMediaType.Format();

        if (mpeg2info->hdr.bmiHeader.biCompression!=0 && mpeg2info->cbSequenceHeader>0) {

          if (m_pMpeg4Sequence) 
            free(m_pMpeg4Sequence);

          m_Mpeg4SequenceSize = mpeg2info->cbSequenceHeader;

          if (m_Mpeg4SequenceSize > 0) {
            m_pMpeg4Sequence = (BYTE *)malloc(m_Mpeg4SequenceSize*sizeof(BYTE));
            memcpy(m_pMpeg4Sequence, (const BYTE *)mpeg2info->dwSequenceHeader, m_Mpeg4SequenceSize);
          }
        }
      }

      VIDEOINFOHEADER * pVih = (VIDEOINFOHEADER*)m_OutMediaType.ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));
      if (pVih==NULL) {
        return E_OUTOFMEMORY;
      }

      ZeroMemory(pVih, sizeof (VIDEOINFOHEADER));
      CopyMemory(&pVih->bmiHeader, pBmp, sizeof(BITMAPINFOHEADER));

      /* set output format */
      m_OutMediaType.SetType(&MEDIATYPE_Video);
      m_OutMediaType.SetFormatType(&FORMAT_VideoInfo); 

      m_OutMediaType.SetSubtype(&m_SubtypeID);
      pVih->bmiHeader.biCompression = m_OutFcc;
	  
      pVih->AvgTimePerFrame = m_AvgTimeForFrame;
      pVih->dwBitErrorRate = 0;
      pVih->dwBitRate = 8 * (DWORD)(((float)pVih->bmiHeader.biSizeImage * 10000000) / m_AvgTimeForFrame);

      m_OutMediaType.SetTemporalCompression(TRUE);
      m_OutMediaType.SetVariableSize();

      if (m_AvgTimeForFrame) {
        switch (m_AvgTimeForFrame) {

          case 416666: // 24.0 FPS
            m_FpsNom = 24; 
            m_FpsDen = 1; 
            break;

		  case 417083: // 23.97 FPS
            m_FpsNom = 24000;
            m_FpsDen = 1001;
            break;

          case 333333: // 30.0 FPS
            m_FpsNom = 30;
            m_FpsDen = 1;
            break;

          case 333666: // 29.97 FPS
            m_FpsNom = 30000;
            m_FpsDen = 1001;
            break;

          default: 
            m_FpsNom = (int) (10000000 / m_AvgTimeForFrame);
            m_FpsDen = 1;
        }
      }

      m_SampleCnt = 0;
      return S_OK;
    }
    else { // if (direction == PINDIR_OUTPUT) {
      if (!m_pInput->IsConnected())
        return E_UNEXPECTED;

      if (m_SubtypeID != mt.subtype)
        return VFW_E_TYPE_NOT_ACCEPTED;

      if (!mt.pbFormat)
        return VFW_E_TYPE_NOT_ACCEPTED;

      if (mt.formattype == FORMAT_VideoInfo || 
          mt.formattype == FORMAT_MPEGVideo) 
	  {
        pBmp = &((VIDEOINFOHEADER *)mt.pbFormat)->bmiHeader;
      } 
      else if (mt.formattype == FORMAT_VideoInfo2 || 
               mt.formattype == FORMAT_MPEG2Video) 
	  {
        pBmp = &((VIDEOINFOHEADER2 *)mt.pbFormat)->bmiHeader;
      }
      else
        return VFW_E_TYPE_NOT_ACCEPTED;

      if (m_OutFcc == pBmp->biCompression)
        return S_OK;
    }
  } 

  return VFW_E_TYPE_NOT_ACCEPTED;
}

HRESULT 
ChangeSubtypeT::Transform(IMediaSample *pIn, IMediaSample *pOut) 
{
  BITMAPINFOHEADER *pBmpIn=0, *pBmpOut=0;
  HRESULT hr = S_FALSE;

  if (m_InMediaType.formattype == FORMAT_VideoInfo || 
      m_InMediaType.formattype == FORMAT_MPEGVideo) 
  {
    pBmpIn = &((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->bmiHeader;
  } 
  else if (m_InMediaType.formattype == FORMAT_VideoInfo2 || 
           m_InMediaType.formattype == FORMAT_MPEG2Video) 
  {
    pBmpIn = &((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->bmiHeader;
  }

  if (m_OutMediaType.formattype == FORMAT_VideoInfo || 
      m_OutMediaType.formattype == FORMAT_MPEGVideo) 
  {
    pBmpOut = &((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->bmiHeader;
  } 
  else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || 
           m_OutMediaType.formattype == FORMAT_MPEG2Video) 
  {
    pBmpOut = &((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->bmiHeader;
  }

  if (pBmpIn && pBmpOut && m_InMediaType.lSampleSize == m_OutMediaType.lSampleSize) 
  {
    BYTE *pBufIn, *pBufOut;
    pIn->GetPointer(&pBufIn);
    pOut->GetPointer(&pBufOut);
    DWORD lSize = pIn->GetActualDataLength();

    DWORD OutOffset = 0;
    if (*((int *)pBufIn) != 0xB0010000 && m_pMpeg4Sequence) {
	  if (pIn->IsSyncPoint() == S_OK) { // I-VOP
        memcpy(pBufOut, m_pMpeg4Sequence, m_Mpeg4SequenceSize);
        OutOffset = m_Mpeg4SequenceSize;
      }
    }

    pOut->SetActualDataLength(lSize + OutOffset);
    memcpy(&pBufOut[OutOffset], pBufIn, lSize);
    LONGLONG UnitDuration = (10000000LL * m_FpsDen)/m_FpsNom;
    LONGLONG NormalStart = (m_SampleCnt * 10000000LL * m_FpsDen)/m_FpsNom;
    LONGLONG NormalEnd = ((m_SampleCnt + 1) * 10000000LL * m_FpsDen)/m_FpsNom;

    LONGLONG sTime, eTime;
    pOut->GetTime(&sTime, &eTime);
    int bSetTime = 0;
    LONGLONG sDuration =  eTime - sTime;

    // simply set correct end time - seems to work here...
    if (eTime <  sTime + UnitDuration) {
      eTime = sTime + UnitDuration;
      bSetTime = 1;
	}

    if (bSetTime) pOut->SetTime(&sTime, &eTime);

#if 0
    LONGLONG sTime=0, eTime=0;
    sTime = (m_SampleCnt * 10000000LL * m_FpsDen)/m_FpsNom;
    eTime = ((m_SampleCnt + 1) * 10000000LL * m_FpsDen)/m_FpsNom - 1;
    pOut->SetTime(&sTime, &eTime);
#endif

    m_startTime = sTime;
    m_stopTime = eTime;
    m_SampleCnt ++;
    
	int CurPos = (int) ((double)(100.0 * m_SampleCnt/m_TotalFrames) + 0.5);
    if (m_Pass == 0)
      CurPos /= 2;
    else if (m_Pass == 2)
      CurPos = CurPos /2 + 50;

    if (m_MessageWnd)
      PostMessage(m_MessageWnd, PBM_SETPOS, CurPos, 0);

    hr = S_OK;
  } 

  return hr;
}

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4