Skip to content
Snippets Groups Projects
Commit d5d18816 authored by Hidenori Takeshima's avatar Hidenori Takeshima Committed by Alexandre Julliard
Browse files

Added some stubs.

Started implementing MPEG parser.
parent 5f5a05fb
No related branches found
No related tags found
No related merge requests found
......@@ -636,8 +636,8 @@ qcap/qcap.dll$(DLLEXT): dummy ntdll.dll$(DLLEXT)
@cd qcap && $(MAKE) qcap.dll$(DLLEXT)
quartz/quartz.dll$(DLLEXT): dummy oleaut32.dll$(DLLEXT) ole32.dll$(DLLEXT) \
msvfw32.dll$(DLLEXT) winmm.dll$(DLLEXT) user32.dll$(DLLEXT) gdi32.dll$(DLLEXT) \
advapi32.dll$(DLLEXT) kernel32.dll$(DLLEXT) ntdll.dll$(DLLEXT)
msvfw32.dll$(DLLEXT) msacm32.dll$(DLLEXT) winmm.dll$(DLLEXT) user32.dll$(DLLEXT) \
gdi32.dll$(DLLEXT) advapi32.dll$(DLLEXT) kernel32.dll$(DLLEXT) ntdll.dll$(DLLEXT)
@cd quartz && $(MAKE) quartz.dll$(DLLEXT)
rasapi32/rasapi32.dll$(DLLEXT): dummy kernel32.dll$(DLLEXT) ntdll.dll$(DLLEXT)
......
......@@ -9,6 +9,7 @@ LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
acmwrap.c \
amundoc.c \
asyncsrc.c \
audioutl.c \
......@@ -35,6 +36,7 @@ C_SRCS = \
iunk.c \
main.c \
memalloc.c \
mpgparse.c \
mtype.c \
parser.c \
regsvr.c \
......
/*
* Implements ACM Wrapper(CLSID_ACMWrapper).
*
* FIXME - stub
*
* Copyright (C) 2002 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "msacm.h"
#include "strmif.h"
#include "control.h"
#include "amvideo.h"
#include "vfwmsgs.h"
#include "uuids.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "xform.h"
static const WCHAR ACMWrapper_FilterName[] =
{'A','C','M',' ','W','r','a','p','p','e','r',0};
typedef struct CACMWrapperImpl
{
HACMSTREAM has;
} CACMWrapperImpl;
/***************************************************************************
*
* CACMWrapperImpl methods
*
*/
static void ACMWrapper_Close( CACMWrapperImpl* This )
{
if ( This->has != (HACMSTREAM)NULL )
{
acmStreamReset( This->has, 0 );
acmStreamClose( This->has, 0 );
This->has = (HACMSTREAM)NULL;
}
}
static HRESULT ACMWrapper_Init( CTransformBaseImpl* pImpl )
{
CACMWrapperImpl* This = pImpl->m_pUserData;
TRACE("(%p)\n",This);
if ( This != NULL )
return NOERROR;
This = (CACMWrapperImpl*)QUARTZ_AllocMem( sizeof(CACMWrapperImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
ZeroMemory( This, sizeof(CACMWrapperImpl) );
pImpl->m_pUserData = This;
/* construct */
This->has = (HACMSTREAM)NULL;
return E_NOTIMPL;
}
static HRESULT ACMWrapper_Cleanup( CTransformBaseImpl* pImpl )
{
CACMWrapperImpl* This = pImpl->m_pUserData;
TRACE("(%p)\n",This);
if ( This == NULL )
return NOERROR;
/* destruct */
ACMWrapper_Close( This );
QUARTZ_FreeMem( This );
pImpl->m_pUserData = NULL;
return S_OK;
}
static HRESULT ACMWrapper_CheckMediaType( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut )
{
CACMWrapperImpl* This = pImpl->m_pUserData;
FIXME("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
return E_NOTIMPL;
}
static HRESULT ACMWrapper_GetOutputTypes( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE** ppmtAcceptTypes, ULONG* pcAcceptTypes )
{
CACMWrapperImpl* This = pImpl->m_pUserData;
HRESULT hr;
FIXME("(%p)\n",This);
hr = ACMWrapper_CheckMediaType( pImpl, pmtIn, NULL );
if ( FAILED(hr) )
return hr;
return E_NOTIMPL;
}
static HRESULT ACMWrapper_GetAllocProp( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, ALLOCATOR_PROPERTIES* pProp, BOOL* pbTransInPlace, BOOL* pbTryToReuseSample )
{
CACMWrapperImpl* This = pImpl->m_pUserData;
HRESULT hr;
FIXME("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
hr = ACMWrapper_CheckMediaType( pImpl, pmtIn, pmtOut );
if ( FAILED(hr) )
return hr;
*pbTransInPlace = FALSE;
*pbTryToReuseSample = FALSE;
return E_NOTIMPL;
}
static HRESULT ACMWrapper_BeginTransform( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample )
{
CACMWrapperImpl* This = pImpl->m_pUserData;
FIXME("(%p,%p,%p,%d)\n",This,pmtIn,pmtOut,bReuseSample);
if ( This == NULL )
return E_UNEXPECTED;
return E_NOTIMPL;
}
static HRESULT ACMWrapper_ProcessReceive( CTransformBaseImpl* pImpl, IMediaSample* pSampIn )
{
CACMWrapperImpl* This = pImpl->m_pUserData;
BYTE* pDataIn = NULL;
LONG lDataInLen;
HRESULT hr;
FIXME("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
hr = IMediaSample_GetPointer( pSampIn, &pDataIn );
if ( FAILED(hr) )
return hr;
lDataInLen = IMediaSample_GetActualDataLength( pSampIn );
return E_NOTIMPL;
}
static HRESULT ACMWrapper_EndTransform( CTransformBaseImpl* pImpl )
{
CACMWrapperImpl* This = pImpl->m_pUserData;
TRACE("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
ACMWrapper_Close( This );
return S_OK;
}
static const TransformBaseHandlers transhandlers =
{
ACMWrapper_Init,
ACMWrapper_Cleanup,
ACMWrapper_CheckMediaType,
ACMWrapper_GetOutputTypes,
ACMWrapper_GetAllocProp,
ACMWrapper_BeginTransform,
ACMWrapper_ProcessReceive,
NULL,
ACMWrapper_EndTransform,
};
HRESULT QUARTZ_CreateACMWrapper(IUnknown* punkOuter,void** ppobj)
{
return QUARTZ_CreateTransformBase(
punkOuter,ppobj,
&CLSID_ACMWrapper,
ACMWrapper_FilterName,
NULL, NULL,
&transhandlers );
}
/*
* Implements AVI Parser(Splitter).
*
* FIXME - no seeking
*
* Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
* This library is free software; you can redistribute it and/or
......@@ -79,6 +81,7 @@ struct CAVIParseStream
DWORD cIndexCur;
REFERENCE_TIME rtCur;
REFERENCE_TIME rtInternal;
BOOL bDataDiscontinuity;
};
......@@ -288,6 +291,7 @@ static HRESULT CAVIParseImpl_InitParser( CParserImpl* pImpl, ULONG* pcStreams )
This->pStreamsBuf[nIndex].rtCur = 0;
This->pStreamsBuf[nIndex].rtInternal = 0;
TRACE("stream %lu - %lu entries\n",nIndex,This->pStreamsBuf[nIndex].cIndexEntries);
This->pStreamsBuf[nIndex].bDataDiscontinuity = TRUE;
}
QUARTZ_FreeMem(This->pIndexEntriesBuf);
This->pIndexEntriesBuf = pEntriesBuf;
......@@ -610,6 +614,11 @@ static HRESULT CAVIParseImpl_GetNextRequest( CParserImpl* pImpl, ULONG* pnStream
*prtStop = rtNext;
/* FIXME - is this frame keyframe?? */
*pdwSampleFlags = AM_SAMPLE_SPLICEPOINT;
if ( pStream->bDataDiscontinuity )
{
*pdwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
pStream->bDataDiscontinuity = FALSE;
}
switch ( pStream->strh.fccType )
{
......
......@@ -187,20 +187,21 @@ static HRESULT WINAPI
CBaseFilterImpl_fnGetState(IBaseFilter* iface,DWORD dw,FILTER_STATE* pState)
{
ICOM_THIS(CBaseFilterImpl,iface);
HRESULT hr = S_OK;
TRACE("(%p)->(%p)\n",This,pState);
if ( pState == NULL )
return E_POINTER;
/* FIXME - ignore 'intermediate state' now */
EnterCriticalSection( &This->csFilter );
TRACE("(%p) state = %d\n",This,This->fstate);
*pState = This->fstate;
if ( This->bIntermediateState )
hr = VFW_S_STATE_INTERMEDIATE;
LeaveCriticalSection( &This->csFilter );
return NOERROR;
return hr;
}
static HRESULT WINAPI
......@@ -455,6 +456,7 @@ HRESULT CBaseFilterImpl_InitIBaseFilter(
This->pClock = NULL;
This->rtStart = 0;
This->fstate = State_Stopped;
This->bIntermediateState = FALSE;
This->cbNameGraph = sizeof(WCHAR) * (lstrlenW(lpwszNameGraph)+1);
This->pwszNameGraph = (WCHAR*)QUARTZ_AllocMem( This->cbNameGraph );
......
......@@ -56,6 +56,7 @@ typedef struct CBaseFilterImpl
IReferenceClock* pClock;
REFERENCE_TIME rtStart;
FILTER_STATE fstate;
BOOL bIntermediateState; /* if set, fstate is ignored. */
} CBaseFilterImpl;
struct CBaseFilterHandlers
......
......@@ -104,6 +104,8 @@ static const QUARTZ_CLASSENTRY QUARTZ_ClassList[] =
{ &CLSID_VideoRenderer, &QUARTZ_CreateVideoRenderer },
{ &CLSID_quartzWaveParser, &QUARTZ_CreateWaveParser },
{ &CLSID_AviSplitter, &QUARTZ_CreateAVISplitter },
{ &CLSID_MPEG1Splitter, &QUARTZ_CreateMPEG1Splitter },
{ &CLSID_MMSPLITTER, &QUARTZ_CreateMPEG2Splitter },
{ &CLSID_AsyncReader, &QUARTZ_CreateAsyncReader },
{ &CLSID_URLReader, &QUARTZ_CreateURLReader },
{ &CLSID_AVIDec, &QUARTZ_CreateAVIDec },
......
/*
* Implements MPEG-1 / MPEG-2 Parser(Splitter).
*
* FIXME - no splitter implementation.
* FIXME - no packet support (implemented payload only)
* FIXME - no seeking
*
* Copyright (C) 2002 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmsystem.h"
#include "vfw.h"
#include "winerror.h"
#include "strmif.h"
#include "control.h"
#include "vfwmsgs.h"
#include "amvideo.h"
#include "mmreg.h"
#include "uuids.h"
#include "dvdmedia.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "parser.h"
#include "mtype.h"
static const WCHAR QUARTZ_MPEG1Parser_Name[] =
{ 'M','P','E','G','-','I',' ','S','p','l','i','t','t','e','r',0 };
static const WCHAR QUARTZ_MPEG2Parser_Name[] =
{ 'M','P','E','G','-','2',' ','S','p','l','i','t','t','e','r',0 };
static const WCHAR QUARTZ_MPGParserInPin_Name[] =
{ 'I','n',0 };
static const WCHAR QUARTZ_MPGParserOutPin_VideoPinName[] =
{ 'V','i','d','e','o',0 };
static const WCHAR QUARTZ_MPGParserOutPin_AudioPinName[] =
{ 'A','u','d','i','o',0 };
/* FIXME */
static const WCHAR QUARTZ_MPGParserOutPin_UnknownTypePinName[] =
{ 'O','u','t',0 };
static DWORD bitratesl1[16] =
{ 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448, 0};
static DWORD bitratesl2[16] =
{ 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384, 0};
static DWORD bitratesl3[16] =
{ 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320, 0};
/****************************************************************************
*
* CMPGParseImpl
*/
typedef struct CMPGParseImpl CMPGParseImpl;
typedef struct CMPGParsePayload CMPGParsePayload;
enum MPGPayloadType
{
MPGPayload_Video = 0xe0,
MPGPayload_Audio = 0xc0,
};
struct CMPGParseImpl
{
LONGLONG llPosNext;
BOOL bRawPayload;
DWORD dwPayloadBlockSizeMax;
DWORD cPayloads;
CMPGParsePayload* pPayloads;
};
struct CMPGParsePayload
{
enum MPGPayloadType payloadtype;
BOOL bDataDiscontinuity;
};
static HRESULT CMPGParseImpl_SyncReadPayload(
CParserImpl* pImpl, CMPGParseImpl* This,
enum MPGPayloadType payloadtype,
LONGLONG llPosStart, LONG lLength, BYTE* pbBuf )
{
if ( This == NULL || This->pPayloads == NULL )
return E_UNEXPECTED;
if ( This->bRawPayload )
{
if ( payloadtype != This->pPayloads[0].payloadtype )
return E_UNEXPECTED;
return IAsyncReader_SyncRead( pImpl->m_pReader, llPosStart, lLength, pbBuf );
}
else
{
FIXME( "not implemented\n" );
}
return E_NOTIMPL;
}
static HRESULT CMPGParseImpl_InitParser( CParserImpl* pImpl, ULONG* pcStreams )
{
CMPGParseImpl* This = NULL;
HRESULT hr;
BYTE hdrbuf[8];
TRACE("(%p,%p)\n",pImpl,pcStreams);
This = (CMPGParseImpl*)QUARTZ_AllocMem( sizeof(CMPGParseImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
pImpl->m_pUserData = This;
ZeroMemory( This, sizeof(CMPGParseImpl) );
hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 8, hdrbuf );
if ( FAILED(hr) )
return hr;
if ( hr != S_OK )
return E_FAIL;
if ( hdrbuf[0] == 0x00 && hdrbuf[1] == 0x00 &&
hdrbuf[2] == 0x01 && hdrbuf[3] == 0xba )
{
This->bRawPayload = FALSE;
This->dwPayloadBlockSizeMax = 0;
FIXME( "no mpeg/system support\n" );
return E_FAIL;
}
else
if ( hdrbuf[0] == 0x00 && hdrbuf[1] == 0x00 &&
hdrbuf[2] == 0x01 && hdrbuf[3] == 0xb3 )
{
TRACE( "mpeg/video payload\n" );
This->llPosNext = 0;
This->bRawPayload = TRUE;
This->dwPayloadBlockSizeMax = 0x4000;
This->cPayloads = 1;
This->pPayloads = (CMPGParsePayload*)QUARTZ_AllocMem( sizeof(CMPGParsePayload) );
if ( This->pPayloads == NULL )
return E_OUTOFMEMORY;
*pcStreams = 1;
This->pPayloads[0].payloadtype = MPGPayload_Video;
This->pPayloads[0].bDataDiscontinuity = TRUE;
}
else
if ( hdrbuf[0] == 0xff && (hdrbuf[1]&0xf0) == 0xf0 )
{
TRACE( "mpeg/audio payload\n" );
This->llPosNext = 0;
This->bRawPayload = TRUE;
This->dwPayloadBlockSizeMax = 0;
This->cPayloads = 1;
This->pPayloads = (CMPGParsePayload*)QUARTZ_AllocMem( sizeof(CMPGParsePayload) );
if ( This->pPayloads == NULL )
return E_OUTOFMEMORY;
*pcStreams = 1;
This->pPayloads[0].payloadtype = MPGPayload_Audio;
This->pPayloads[0].bDataDiscontinuity = TRUE;
}
else
{
return E_FAIL;
}
return S_OK;
}
static HRESULT CMPGParseImpl_UninitParser( CParserImpl* pImpl )
{
CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
ULONG nIndex;
TRACE("(%p)\n",This);
if ( This == NULL )
return NOERROR;
/* destruct */
if ( This->pPayloads != NULL )
{
for ( nIndex = 0; nIndex < This->cPayloads; nIndex++ )
{
/* release this stream */
}
QUARTZ_FreeMem( This->pPayloads );
This->pPayloads = NULL;
}
QUARTZ_FreeMem( This );
pImpl->m_pUserData = NULL;
return NOERROR;
}
static LPCWSTR CMPGParseImpl_GetOutPinName( CParserImpl* pImpl, ULONG nStreamIndex )
{
CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
TRACE("(%p,%lu)\n",This,nStreamIndex);
if ( This == NULL || nStreamIndex >= This->cPayloads )
return NULL;
switch ( This->pPayloads[nStreamIndex].payloadtype )
{
case MPGPayload_Video:
return QUARTZ_MPGParserOutPin_VideoPinName;
case MPGPayload_Audio:
return QUARTZ_MPGParserOutPin_AudioPinName;
default:
FIXME("mpeg - unknown stream type %02x\n",This->pPayloads[nStreamIndex].payloadtype);
}
/* FIXME */
return QUARTZ_MPGParserOutPin_UnknownTypePinName;
}
static HRESULT CMPGParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamIndex, AM_MEDIA_TYPE* pmt )
{
CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
HRESULT hr;
BYTE hdrbuf[140+10];
UINT seqhdrlen;
MPEG1VIDEOINFO* pmpg1vi;
MPEG2VIDEOINFO* pmpg2vi;
MPEG1WAVEFORMAT* pmpg1wav;
enum MPGPayloadType payloadtype;
DWORD dwPayloadBlockSize;
TRACE("(%p,%lu,%p)\n",This,nStreamIndex,pmt);
if ( This == NULL )
return E_UNEXPECTED;
if ( nStreamIndex >= This->cPayloads )
return E_INVALIDARG;
ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
payloadtype = This->pPayloads[nStreamIndex].payloadtype;
switch ( payloadtype )
{
case MPGPayload_Video:
hr = CMPGParseImpl_SyncReadPayload(
pImpl, This, payloadtype, 0, 140+10, hdrbuf );
if ( FAILED(hr) )
return hr;
if ( hr != S_OK )
return E_FAIL;
memcpy( &pmt->majortype, &MEDIATYPE_Video, sizeof(GUID) );
seqhdrlen = 12;
if ( hdrbuf[seqhdrlen-1] & 0x2 )
seqhdrlen += 64;
if ( hdrbuf[seqhdrlen-1] & 0x1 )
seqhdrlen += 64;
if ( hdrbuf[seqhdrlen ] == 0x00 && hdrbuf[seqhdrlen+1] == 0x00 &&
hdrbuf[seqhdrlen+2] == 0x01 && hdrbuf[seqhdrlen+3] == 0xb5 )
{
/* video MPEG-2 */
FIXME("video MPEG-2\n");
if ( (hdrbuf[seqhdrlen+4]&0xf0) != 0x1 )
return E_FAIL;
memcpy( &pmt->subtype, &MEDIASUBTYPE_MPEG2_VIDEO, sizeof(GUID) );
memcpy( &pmt->formattype, &FORMAT_MPEG2_VIDEO, sizeof(GUID) );
pmt->bFixedSizeSamples = 0;
pmt->bTemporalCompression = 1;
pmt->lSampleSize = 0;
pmt->cbFormat = sizeof(MPEG2VIDEOINFO);
pmt->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof(MPEG2VIDEOINFO) );
if ( pmt->pbFormat == NULL )
return E_OUTOFMEMORY;
ZeroMemory( pmt->pbFormat, sizeof(MPEG2VIDEOINFO) );
pmpg2vi = (MPEG2VIDEOINFO*)pmt->pbFormat;
pmpg2vi->hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pmpg2vi->hdr.bmiHeader.biWidth = ((UINT)hdrbuf[4] << 4) | ((UINT)hdrbuf[5] >> 4); /* FIXME! */
pmpg2vi->hdr.bmiHeader.biHeight = (((UINT)hdrbuf[5] & 0xf) << 8) | ((UINT)hdrbuf[6]); /* FIXME! */
pmpg2vi->hdr.dwInterlaceFlags = AMINTERLACE_FieldPatBothRegular; /* FIXME? */
pmpg2vi->hdr.dwCopyProtectFlags = AMCOPYPROTECT_RestrictDuplication; /* FIXME? */
pmpg2vi->hdr.dwPictAspectRatioX = 1; /* FIXME? */
pmpg2vi->hdr.dwPictAspectRatioY = 1; /* FIXME? */
pmpg2vi->dwStartTimeCode = 0;
pmpg2vi->cbSequenceHeader = seqhdrlen + 10;
switch ( hdrbuf[seqhdrlen+4] & 0xf )
{
case 5: pmpg2vi->dwProfile = AM_MPEG2Profile_Simple; break;
case 4: pmpg2vi->dwProfile = AM_MPEG2Profile_Main; break;
case 3: pmpg2vi->dwProfile = AM_MPEG2Profile_SNRScalable; break;
case 2: pmpg2vi->dwProfile = AM_MPEG2Profile_SpatiallyScalable; break;
case 1: pmpg2vi->dwProfile = AM_MPEG2Profile_High; break;
default: return E_FAIL;
}
switch ( hdrbuf[seqhdrlen+5] >> 4 )
{
case 10: pmpg2vi->dwLevel = AM_MPEG2Level_Low; break;
case 8: pmpg2vi->dwLevel = AM_MPEG2Level_Main; break;
case 6: pmpg2vi->dwLevel = AM_MPEG2Level_High1440; break;
case 4: pmpg2vi->dwLevel = AM_MPEG2Level_High; break;
default: return E_FAIL;
}
pmpg2vi->dwFlags = 0; /* FIXME? */
memcpy( pmpg2vi->dwSequenceHeader, hdrbuf, seqhdrlen + 10 );
return S_OK;
}
else
{
/* MPEG-1 */
memcpy( &pmt->subtype, &MEDIASUBTYPE_MPEG1Payload, sizeof(GUID) );
memcpy( &pmt->formattype, &FORMAT_MPEGVideo, sizeof(GUID) );
pmt->bFixedSizeSamples = 0;
pmt->bTemporalCompression = 1;
pmt->lSampleSize = 0;
pmt->cbFormat = sizeof(MPEG1VIDEOINFO);
pmt->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof(MPEG1VIDEOINFO) );
if ( pmt->pbFormat == NULL )
return E_OUTOFMEMORY;
ZeroMemory( pmt->pbFormat, sizeof(MPEG1VIDEOINFO) );
pmpg1vi = (MPEG1VIDEOINFO*)pmt->pbFormat;
pmpg1vi->hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pmpg1vi->hdr.bmiHeader.biWidth = ((UINT)hdrbuf[4] << 4) | ((UINT)hdrbuf[5] >> 4);
pmpg1vi->hdr.bmiHeader.biHeight = (((UINT)hdrbuf[5] & 0xf) << 8) | ((UINT)hdrbuf[6]);
pmpg1vi->hdr.bmiHeader.biPlanes = 1;
pmpg1vi->dwStartTimeCode = 0;
pmpg1vi->cbSequenceHeader = seqhdrlen;
memcpy( pmpg1vi->bSequenceHeader, hdrbuf, seqhdrlen );
}
return S_OK;
case MPGPayload_Audio:
hr = CMPGParseImpl_SyncReadPayload(
pImpl, This, payloadtype, 0, 4, hdrbuf );
if ( FAILED(hr) )
return hr;
if ( hr != S_OK )
return E_FAIL;
memcpy( &pmt->majortype, &MEDIATYPE_Audio, sizeof(GUID) );
memcpy( &pmt->formattype, &FORMAT_WaveFormatEx, sizeof(GUID) );
if ( !( hdrbuf[1] & 0x8 ) )
{
/* FIXME!!! */
FIXME("audio not MPEG-1\n");
return E_FAIL;
}
else
{
/* MPEG-1 */
memcpy( &pmt->subtype, &MEDIASUBTYPE_MPEG1AudioPayload, sizeof(GUID) );
pmt->bFixedSizeSamples = 0;
pmt->bTemporalCompression = 1;
pmt->lSampleSize = 0;
pmt->cbFormat = sizeof(MPEG1WAVEFORMAT);
pmt->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof(MPEG1WAVEFORMAT) );
if ( pmt->pbFormat == NULL )
return E_OUTOFMEMORY;
ZeroMemory( pmt->pbFormat, sizeof(MPEG1WAVEFORMAT) );
pmpg1wav = (MPEG1WAVEFORMAT*)pmt->pbFormat;
switch ( hdrbuf[1] & 0x6 )
{
case 0x6: pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER1;
case 0x4: pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER2;
case 0x2: pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER3;
default: return E_FAIL;
}
switch ( pmpg1wav->fwHeadLayer )
{
case ACM_MPEG_LAYER1:
pmpg1wav->dwHeadBitrate = bitratesl1[hdrbuf[2]>>4]*1000;
break;
case ACM_MPEG_LAYER2:
pmpg1wav->dwHeadBitrate = bitratesl2[hdrbuf[2]>>4]*1000;
break;
case ACM_MPEG_LAYER3:
pmpg1wav->dwHeadBitrate = bitratesl3[hdrbuf[2]>>4]*1000;
break;
}
if ( pmpg1wav->dwHeadBitrate == 0 )
return E_FAIL;
switch ( hdrbuf[3] & 0xc0 )
{
case 0x00: pmpg1wav->fwHeadMode = ACM_MPEG_STEREO;
case 0x40: pmpg1wav->fwHeadMode = ACM_MPEG_JOINTSTEREO;
case 0x80: pmpg1wav->fwHeadMode = ACM_MPEG_DUALCHANNEL;
case 0xc0: pmpg1wav->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
}
pmpg1wav->fwHeadModeExt = (hdrbuf[3] & 0x30) >> 4; /* FIXME?? */
pmpg1wav->wHeadEmphasis = (hdrbuf[3] & 0x03); /* FIXME?? */
pmpg1wav->fwHeadFlags = ACM_MPEG_ID_MPEG1;
if ( hdrbuf[1] & 0x1 )
pmpg1wav->fwHeadFlags |= ACM_MPEG_PROTECTIONBIT;
if ( hdrbuf[2] & 0x1 )
pmpg1wav->fwHeadFlags |= ACM_MPEG_PRIVATEBIT;
if ( hdrbuf[3] & 0x8 )
pmpg1wav->fwHeadFlags |= ACM_MPEG_COPYRIGHT;
if ( hdrbuf[3] & 0x4 )
pmpg1wav->fwHeadFlags |= ACM_MPEG_ORIGINALHOME;
pmpg1wav->dwPTSLow = 0;
pmpg1wav->dwPTSHigh = 0;
pmpg1wav->wfx.wFormatTag = WAVE_FORMAT_MPEG;
pmpg1wav->wfx.nChannels = (pmpg1wav->fwHeadMode != ACM_MPEG_SINGLECHANNEL) ? 2 : 1;
switch ( hdrbuf[2] & 0x0c )
{
case 0x00: pmpg1wav->wfx.nSamplesPerSec = 44100;
case 0x01: pmpg1wav->wfx.nSamplesPerSec = 48000;
case 0x02: pmpg1wav->wfx.nSamplesPerSec = 32000;
default: return E_FAIL;
}
pmpg1wav->wfx.nAvgBytesPerSec = pmpg1wav->dwHeadBitrate >> 3;
switch ( pmpg1wav->fwHeadLayer )
{
case ACM_MPEG_LAYER1:
pmpg1wav->wfx.nBlockAlign = (384>>3) * pmpg1wav->dwHeadBitrate / pmpg1wav->wfx.nSamplesPerSec;
break;
case ACM_MPEG_LAYER2:
pmpg1wav->wfx.nBlockAlign = (1152>>3) * pmpg1wav->dwHeadBitrate / pmpg1wav->wfx.nSamplesPerSec;
break;
case ACM_MPEG_LAYER3:
pmpg1wav->wfx.nBlockAlign = 1;
break;
}
pmpg1wav->wfx.wBitsPerSample = 0;
pmpg1wav->wfx.cbSize = sizeof(MPEG1WAVEFORMAT) - sizeof(WAVEFORMATEX);
if ( pmpg1wav->fwHeadLayer != ACM_MPEG_LAYER3 )
{
pmt->bFixedSizeSamples = 1;
pmt->lSampleSize = pmpg1wav->wfx.nBlockAlign;
}
dwPayloadBlockSize = (pmpg1wav->wfx.nAvgBytesPerSec + pmpg1wav->wfx.nBlockAlign - 1) / pmpg1wav->wfx.nBlockAlign;
if ( dwPayloadBlockSize > This->dwPayloadBlockSizeMax )
This->dwPayloadBlockSizeMax = dwPayloadBlockSize;
}
return S_OK;
default:
FIXME("mpeg - unknown stream type %02x\n",This->pPayloads[nStreamIndex].payloadtype);
break;
}
FIXME("stub\n");
return E_NOTIMPL;
}
static HRESULT CMPGParseImpl_CheckStreamType( CParserImpl* pImpl, ULONG nStreamIndex, const AM_MEDIA_TYPE* pmt )
{
CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
HRESULT hr;
AM_MEDIA_TYPE mt;
MPEG1VIDEOINFO* pmpg1vi;
MPEG1VIDEOINFO* pmpg1viCheck;
MPEG2VIDEOINFO* pmpg2vi;
MPEG2VIDEOINFO* pmpg2viCheck;
WAVEFORMATEX* pwfx;
WAVEFORMATEX* pwfxCheck;
enum MPGPayloadType payloadtype;
TRACE("(%p,%lu,%p)\n",This,nStreamIndex,pmt);
if ( This == NULL )
return E_UNEXPECTED;
if ( nStreamIndex >= This->cPayloads )
return E_INVALIDARG;
hr = CMPGParseImpl_GetStreamType( pImpl, nStreamIndex, &mt );
if ( FAILED(hr) )
return hr;
if ( !IsEqualGUID( &pmt->majortype, &mt.majortype ) ||
!IsEqualGUID( &pmt->subtype, &mt.subtype ) ||
!IsEqualGUID( &pmt->formattype, &mt.formattype ) )
{
hr = E_FAIL;
goto end;
}
TRACE("check format\n");
hr = S_OK;
payloadtype = This->pPayloads[nStreamIndex].payloadtype;
switch ( payloadtype )
{
case MPGPayload_Video:
if ( IsEqualGUID( &mt.formattype, &FORMAT_MPEGVideo ) )
{
/* MPEG-1 Video */
if ( pmt->cbFormat != mt.cbFormat ||
pmt->pbFormat == NULL )
{
hr = E_FAIL;
goto end;
}
pmpg1vi = (MPEG1VIDEOINFO*)mt.pbFormat;
pmpg1viCheck = (MPEG1VIDEOINFO*)pmt->pbFormat;
if ( memcmp( pmpg1vi, pmpg1viCheck, sizeof(MPEG1VIDEOINFO) ) != 0 )
{
hr = E_FAIL;
goto end;
}
}
else
if ( IsEqualGUID( &mt.formattype, &FORMAT_MPEG2_VIDEO ) )
{
/* MPEG-2 Video */
if ( pmt->cbFormat != mt.cbFormat ||
pmt->pbFormat == NULL )
{
hr = E_FAIL;
goto end;
}
pmpg2vi = (MPEG2VIDEOINFO*)mt.pbFormat;
pmpg2viCheck = (MPEG2VIDEOINFO*)pmt->pbFormat;
if ( memcmp( pmpg2vi, pmpg2viCheck, sizeof(MPEG2VIDEOINFO) ) != 0 )
{
hr = E_FAIL;
goto end;
}
}
else
{
hr = E_FAIL;
goto end;
}
break;
case MPGPayload_Audio:
if ( IsEqualGUID( &mt.formattype, &FORMAT_WaveFormatEx ) )
{
if ( mt.cbFormat != pmt->cbFormat ||
pmt->pbFormat == NULL )
{
hr = E_FAIL;
goto end;
}
pwfx = (WAVEFORMATEX*)mt.pbFormat;
pwfxCheck = (WAVEFORMATEX*)pmt->pbFormat;
if ( memcmp( pwfx, pwfxCheck, sizeof(WAVEFORMATEX) ) != 0 )
{
hr = E_FAIL;
goto end;
}
}
else
{
hr = E_FAIL;
goto end;
}
break;
default:
FIXME( "unsupported payload type\n" );
hr = E_FAIL;
goto end;
}
hr = S_OK;
end:
QUARTZ_MediaType_Free( &mt );
TRACE("%08lx\n",hr);
return hr;
}
static HRESULT CMPGParseImpl_GetAllocProp( CParserImpl* pImpl, ALLOCATOR_PROPERTIES* pReqProp )
{
CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
TRACE("(%p,%p)\n",This,pReqProp);
if ( This == NULL )
return E_UNEXPECTED;
ZeroMemory( pReqProp, sizeof(ALLOCATOR_PROPERTIES) );
pReqProp->cBuffers = This->cPayloads;
pReqProp->cbBuffer = This->dwPayloadBlockSizeMax;
return S_OK;
}
static HRESULT CMPGParseImpl_GetNextRequest( CParserImpl* pImpl, ULONG* pnStreamIndex, LONGLONG* pllStart, LONG* plLength, REFERENCE_TIME* prtStart, REFERENCE_TIME* prtStop, DWORD* pdwSampleFlags )
{
CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
if ( This == NULL )
return E_UNEXPECTED;
*pdwSampleFlags = AM_SAMPLE_SPLICEPOINT;
TRACE("(%p)\n",This);
if ( This->bRawPayload )
{
if ( This->dwPayloadBlockSizeMax == 0 ||
This->cPayloads != 1 || This->pPayloads == NULL )
return E_UNEXPECTED;
*pnStreamIndex = 0;
*pllStart = This->llPosNext;
*plLength = This->dwPayloadBlockSizeMax;
*prtStart = 0;
*prtStop = 0;
if ( This->pPayloads[0].bDataDiscontinuity )
{
*pdwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
This->pPayloads[0].bDataDiscontinuity = FALSE;
}
}
else
{
FIXME("stub\n");
return E_NOTIMPL;
}
return S_OK;
}
static HRESULT CMPGParseImpl_ProcessSample( CParserImpl* pImpl, ULONG nStreamIndex, LONGLONG llStart, LONG lLength, IMediaSample* pSample )
{
CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
HRESULT hr;
TRACE("(%p,%lu,%ld,%ld,%p)\n",This,nStreamIndex,(long)llStart,lLength,pSample);
if ( This == NULL )
return E_UNEXPECTED;
if ( This->bRawPayload )
{
hr = IMediaSample_SetTime(pSample,NULL,NULL);
if ( FAILED(hr) )
return hr;
}
return NOERROR;
}
static const struct ParserHandlers CMPGParseImpl_Handlers =
{
CMPGParseImpl_InitParser,
CMPGParseImpl_UninitParser,
CMPGParseImpl_GetOutPinName,
CMPGParseImpl_GetStreamType,
CMPGParseImpl_CheckStreamType,
CMPGParseImpl_GetAllocProp,
CMPGParseImpl_GetNextRequest,
CMPGParseImpl_ProcessSample,
/* for IQualityControl */
NULL, /* pQualityNotify */
/* for seeking */
NULL, /* pGetSeekingCaps */
NULL, /* pIsTimeFormatSupported */
NULL, /* pGetCurPos */
NULL, /* pSetCurPos */
NULL, /* pGetDuration */
NULL, /* pGetStopPos */
NULL, /* pSetStopPos */
NULL, /* pGetPreroll */
};
HRESULT QUARTZ_CreateMPEG1Splitter(IUnknown* punkOuter,void** ppobj)
{
return QUARTZ_CreateParser(
punkOuter,ppobj,
&CLSID_MPEG1Splitter,
QUARTZ_MPEG1Parser_Name,
QUARTZ_MPGParserInPin_Name,
&CMPGParseImpl_Handlers );
}
HRESULT QUARTZ_CreateMPEG2Splitter(IUnknown* punkOuter,void** ppobj)
{
return QUARTZ_CreateParser(
punkOuter,ppobj,
&CLSID_MMSPLITTER,
QUARTZ_MPEG2Parser_Name,
QUARTZ_MPGParserInPin_Name,
&CMPGParseImpl_Handlers );
}
......@@ -172,6 +172,28 @@ static HRESULT CParserImplThread_SendEndOfStream( CParserImpl* This )
return hrRet;
}
static
void CParserImplThread_MemDecommit( CParserImpl* This )
{
ULONG nIndex;
IMemAllocator* pAlloc;
TRACE("(%p)\n",This);
if ( This->m_pAllocator != NULL )
IMemAllocator_Decommit( This->m_pAllocator );
if ( This->m_ppOutPins != NULL && This->m_cOutStreams > 0 )
{
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
pAlloc = This->m_ppOutPins[nIndex]->m_pOutPinAllocator;
if ( pAlloc != NULL )
IMemAllocator_Decommit( pAlloc );
}
}
}
static HRESULT CParserImplThread_SendFlush( CParserImpl* This )
{
ULONG nIndex;
......@@ -210,6 +232,19 @@ static void CParserImplThread_ErrorAbort( CParserImpl* This, HRESULT hr )
CParserImplThread_SendEndOfStream(This);
}
static
void CParserImplThread_ResetAllStreams( CParserImpl* This )
{
ULONG nIndex;
if ( This->m_pHandler->pSetCurPos != NULL )
{
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
This->m_pHandler->pSetCurPos(This,
&This->m_guidTimeFormat,nIndex,(LONGLONG)0);
}
}
static
HRESULT CParserImplThread_ProcessNextSample( CParserImpl* This )
{
......@@ -233,6 +268,11 @@ HRESULT CParserImplThread_ProcessNextSample( CParserImpl* This )
CParserImplThread_ClearAllRequests(This);
CParserImplThread_SendFlush(This);
CParserImplThread_SendEndOfStream(This);
This->m_bSendEOS = FALSE;
CParserImplThread_ResetAllStreams(This);
CParserImplThread_MemDecommit(This);
TRACE("(%p) exit thread\n",This);
return S_FALSE;
case QUARTZ_MSG_SEEK:
......@@ -606,28 +646,6 @@ HRESULT CParserImpl_MemCommit( CParserImpl* This )
return NOERROR;
}
static
void CParserImpl_MemDecommit( CParserImpl* This )
{
ULONG nIndex;
IMemAllocator* pAlloc;
TRACE("(%p)\n",This);
if ( This->m_pAllocator != NULL )
IMemAllocator_Decommit( This->m_pAllocator );
if ( This->m_ppOutPins != NULL && This->m_cOutStreams > 0 )
{
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
pAlloc = This->m_ppOutPins[nIndex]->m_pOutPinAllocator;
if ( pAlloc != NULL )
IMemAllocator_Decommit( pAlloc );
}
}
}
static
HRESULT CParserImpl_GetPreferredTimeFormat( CParserImpl* This, GUID* pguidFormat )
{
......@@ -705,20 +723,10 @@ static HRESULT CParserImpl_OnInactive( CBaseFilterImpl* pImpl )
static HRESULT CParserImpl_OnStop( CBaseFilterImpl* pImpl )
{
CParserImpl_THIS(pImpl,basefilter);
DWORD n;
FIXME( "(%p)\n", This );
CParserImpl_EndThread(This);
CParserImpl_MemDecommit(This);
This->m_bSendEOS = FALSE;
/* reset streams. */
if ( This->m_pHandler->pSetCurPos != NULL )
{
for ( n = 0; n < This->m_cOutStreams; n++ )
This->m_pHandler->pSetCurPos(This,&This->m_guidTimeFormat,n,(LONGLONG)0);
}
return NOERROR;
}
......
......@@ -180,6 +180,8 @@ HRESULT QUARTZ_CreateParserOutPin(
HRESULT QUARTZ_CreateWaveParser(IUnknown* punkOuter,void** ppobj);
HRESULT QUARTZ_CreateAVISplitter(IUnknown* punkOuter,void** ppobj);
HRESULT QUARTZ_CreateMPEG1Splitter(IUnknown* punkOuter,void** ppobj);
HRESULT QUARTZ_CreateMPEG2Splitter(IUnknown* punkOuter,void** ppobj);
HRESULT RIFF_GetNext(
......
......@@ -5,6 +5,7 @@ init QUARTZ_DllMain
import oleaut32.dll
import ole32.dll
import msvfw32.dll
import msacm32.dll
import winmm.dll
import user32.dll
import gdi32.dll
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment