Mercurial > mplayer.hg
view loader/dshow/outputpin.c @ 18118:f9a939c204ad
Adds "cheap" subtitle switching for non-DVD playouts (for ex. OGG or MKV).
Patch by Stanislav Maslovski <stanislav POIS maslovski AH gmail POIS com>
Original thread:
Date: Apr 12, 2006 1:50 PM
Subject: [MPlayer-dev-eng] [PATCH] GUI: add cheap subtitle switching for non-DVD
author | gpoirier |
---|---|
date | Sun, 16 Apr 2006 16:58:36 +0000 |
parents | f5537cc95b02 |
children | 0783dd397f74 |
line wrap: on
line source
/* * Modified for use with MPlayer, detailed CVS changelog at * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/ * $Id$ */ #include "wine/winerror.h" #include "wine/windef.h" #include "outputpin.h" #include <stdio.h> #include <string.h> #include <stdlib.h> /* An object beyond interface IEnumMediaTypes. Returned by COutputPin through call IPin::EnumMediaTypes(). */ static inline int output_unimplemented(const char* s, void* p) { Debug printf("%s(%p) called (UNIMPLEMENTED)", s, p); return E_NOTIMPL; } typedef struct CEnumMediaTypes { IEnumMediaTypes_vt* vt; DECLARE_IUNKNOWN(); AM_MEDIA_TYPE type; GUID interfaces[2]; } CEnumMediaTypes; struct _COutputMemPin { IMemInputPin_vt* vt; DECLARE_IUNKNOWN(); char** frame_pointer; long* frame_size_pointer; MemAllocator* pAllocator; COutputPin* parent; }; static HRESULT STDCALL CEnumMediaTypes_Next(IEnumMediaTypes * This, /* [in] */ ULONG cMediaTypes, /* [size_is][out] */ AM_MEDIA_TYPE **ppMediaTypes, /* [out] */ ULONG *pcFetched) { AM_MEDIA_TYPE* type = &((CEnumMediaTypes*)This)->type; Debug printf("CEnumMediaTypes::Next(%p) called\n", This); if (!ppMediaTypes) return E_INVALIDARG; if (!pcFetched && (cMediaTypes!=1)) return E_INVALIDARG; if (cMediaTypes <= 0) return 0; if (pcFetched) *pcFetched=1; ppMediaTypes[0] = (AM_MEDIA_TYPE *)malloc(sizeof(AM_MEDIA_TYPE)); // copy structures - C can handle this... **ppMediaTypes = *type; if (ppMediaTypes[0]->pbFormat) { ppMediaTypes[0]->pbFormat=(char *)malloc(ppMediaTypes[0]->cbFormat); memcpy(ppMediaTypes[0]->pbFormat, type->pbFormat, ppMediaTypes[0]->cbFormat); } if (cMediaTypes == 1) return 0; return 1; } /* I expect that these methods are unused. */ static HRESULT STDCALL CEnumMediaTypes_Skip(IEnumMediaTypes * This, /* [in] */ ULONG cMediaTypes) { return output_unimplemented("CEnumMediaTypes::Skip", This); } static HRESULT STDCALL CEnumMediaTypes_Reset(IEnumMediaTypes * This) { Debug printf("CEnumMediaTypes::Reset(%p) called\n", This); return 0; } static HRESULT STDCALL CEnumMediaTypes_Clone(IEnumMediaTypes * This, /* [out] */ IEnumMediaTypes **ppEnum) { Debug printf("CEnumMediaTypes::Clone(%p) called\n", This); return E_NOTIMPL; } static void CEnumMediaTypes_Destroy(CEnumMediaTypes* This) { free(This->vt); free(This); } // IPin->IUnknown methods IMPLEMENT_IUNKNOWN(CEnumMediaTypes) static CEnumMediaTypes* CEnumMediaTypesCreate(const AM_MEDIA_TYPE* amt) { CEnumMediaTypes *This = (CEnumMediaTypes*) malloc(sizeof(CEnumMediaTypes)) ; if (!This) return NULL; This->vt = (IEnumMediaTypes_vt*) malloc(sizeof(IEnumMediaTypes_vt)); if (!This->vt) { free(This); return NULL; } This->refcount = 1; This->type = *amt; This->vt->QueryInterface = CEnumMediaTypes_QueryInterface; This->vt->AddRef = CEnumMediaTypes_AddRef; This->vt->Release = CEnumMediaTypes_Release; This->vt->Next = CEnumMediaTypes_Next; This->vt->Skip = CEnumMediaTypes_Skip; This->vt->Reset = CEnumMediaTypes_Reset; This->vt->Clone = CEnumMediaTypes_Clone; This->interfaces[0] = IID_IUnknown; This->interfaces[1] = IID_IEnumMediaTypes; return This; } /************* * COutputPin *************/ static HRESULT STDCALL COutputPin_QueryInterface(IUnknown* This, const GUID* iid, void** ppv) { COutputPin* p = (COutputPin*) This; Debug printf("COutputPin_QueryInterface(%p) called\n", This); if (!ppv) return E_INVALIDARG; if (memcmp(iid, &IID_IUnknown, 16) == 0) { *ppv = p; p->vt->AddRef(This); return 0; } if (memcmp(iid, &IID_IMemInputPin, 16) == 0) { *ppv = p->mempin; p->mempin->vt->AddRef((IUnknown*)*ppv); return 0; } Debug printf("Unknown interface : %08x-%04x-%04x-%02x%02x-" "%02x%02x%02x%02x%02x%02x\n", iid->f1, iid->f2, iid->f3, (unsigned char)iid->f4[1], (unsigned char)iid->f4[0], (unsigned char)iid->f4[2], (unsigned char)iid->f4[3], (unsigned char)iid->f4[4], (unsigned char)iid->f4[5], (unsigned char)iid->f4[6], (unsigned char)iid->f4[7]); return E_NOINTERFACE; } // IPin methods static HRESULT STDCALL COutputPin_Connect(IPin * This, /* [in] */ IPin *pReceivePin, /* [in] */ /* const */ AM_MEDIA_TYPE *pmt) { Debug printf("COutputPin_Connect() called\n"); /* *pmt=((COutputPin*)This)->type; if(pmt->cbFormat>0) { pmt->pbFormat=malloc(pmt->cbFormat); memcpy(pmt->pbFormat, ((COutputPin*)This)->type.pbFormat, pmt->cbFormat); } */ //return E_NOTIMPL; return 0;// XXXXXXXXXXXXX CHECKME XXXXXXXXXXXXXXX // if I put return 0; here, it crashes } static HRESULT STDCALL COutputPin_ReceiveConnection(IPin * This, /* [in] */ IPin *pConnector, /* [in] */ const AM_MEDIA_TYPE *pmt) { Debug printf("COutputPin_ReceiveConnection(%p) called\n", This); ((COutputPin*)This)->remote = pConnector; return 0; } static HRESULT STDCALL COutputPin_Disconnect(IPin * This) { Debug printf("COutputPin_Disconnect(%p) called\n", This); return 1; } static HRESULT STDCALL COutputPin_ConnectedTo(IPin * This, /* [out] */ IPin **pPin) { Debug printf("COutputPin_ConnectedTo(%p) called\n", This); if (!pPin) return E_INVALIDARG; *pPin = ((COutputPin*)This)->remote; return 0; } static HRESULT STDCALL COutputPin_ConnectionMediaType(IPin * This, /* [out] */ AM_MEDIA_TYPE *pmt) { Debug printf("CInputPin::ConnectionMediaType() called\n"); if (!pmt) return E_INVALIDARG; *pmt = ((COutputPin*)This)->type; if (pmt->cbFormat>0) { pmt->pbFormat=(char *)malloc(pmt->cbFormat); memcpy(pmt->pbFormat, ((COutputPin*)This)->type.pbFormat, pmt->cbFormat); } return 0; } static HRESULT STDCALL COutputPin_QueryPinInfo(IPin * This, /* [out] */ PIN_INFO *pInfo) { return output_unimplemented("COutputPin_QueryPinInfo", This); } static HRESULT STDCALL COutputPin_QueryDirection(IPin * This, /* [out] */ PIN_DIRECTION *pPinDir) { Debug printf("COutputPin_QueryDirection(%p) called\n", This); if (!pPinDir) return E_INVALIDARG; *pPinDir = PINDIR_INPUT; return 0; } static HRESULT STDCALL COutputPin_QueryId(IPin * This, /* [out] */ LPWSTR *Id) { return output_unimplemented("COutputPin_QueryId", This); } static HRESULT STDCALL COutputPin_QueryAccept(IPin * This, /* [in] */ const AM_MEDIA_TYPE *pmt) { return output_unimplemented("COutputPin_QueryAccept", This); } static HRESULT STDCALL COutputPin_EnumMediaTypes(IPin * This, /* [out] */ IEnumMediaTypes **ppEnum) { Debug printf("COutputPin_EnumMediaTypes() called\n"); if (!ppEnum) return E_INVALIDARG; *ppEnum = (IEnumMediaTypes*) CEnumMediaTypesCreate(&((COutputPin*)This)->type); return 0; } static HRESULT STDCALL COutputPin_QueryInternalConnections(IPin * This, /* [out] */ IPin **apPin, /* [out][in] */ ULONG *nPin) { return output_unimplemented("COutputPin_QueryInternalConnections", This); } static HRESULT STDCALL COutputPin_EndOfStream(IPin * This) { return output_unimplemented("COutputPin_EndOfStream", This); } static HRESULT STDCALL COutputPin_BeginFlush(IPin * This) { return output_unimplemented("COutputPin_BeginFlush", This); } static HRESULT STDCALL COutputPin_EndFlush(IPin * This) { return output_unimplemented("COutputPin_EndFlush", This); } static HRESULT STDCALL COutputPin_NewSegment(IPin * This, /* [in] */ REFERENCE_TIME tStart, /* [in] */ REFERENCE_TIME tStop, /* [in] */ double dRate) { Debug printf("COutputPin_NewSegment(%Ld,%Ld,%f) called\n", tStart, tStop, dRate); return 0; } // IMemInputPin->IUnknown methods static HRESULT STDCALL COutputPin_M_QueryInterface(IUnknown* This, const GUID* iid, void** ppv) { COutputPin* p = (COutputPin*)This; Debug printf("COutputPin_M_QueryInterface(%p) called\n", This); if (!ppv) return E_INVALIDARG; if(!memcmp(iid, &IID_IUnknown, 16)) { *ppv = p; p->vt->AddRef(This); return 0; } /*if(!memcmp(iid, &IID_IPin, 16)) { COutputPin* ptr=(COutputPin*)(This-1); *ppv=(void*)ptr; AddRef((IUnknown*)ptr); return 0; }*/ if(!memcmp(iid, &IID_IMemInputPin, 16)) { *ppv = p->mempin; p->mempin->vt->AddRef(This); return 0; } Debug printf("Unknown interface : %08x-%04x-%04x-%02x%02x-" \ "%02x%02x%02x%02x%02x%02x\n", iid->f1, iid->f2, iid->f3, (unsigned char)iid->f4[1], (unsigned char)iid->f4[0], (unsigned char)iid->f4[2], (unsigned char)iid->f4[3], (unsigned char)iid->f4[4], (unsigned char)iid->f4[5], (unsigned char)iid->f4[6], (unsigned char)iid->f4[7]); return E_NOINTERFACE; } // IMemInputPin methods static HRESULT STDCALL COutputPin_GetAllocator(IMemInputPin* This, /* [out] */ IMemAllocator** ppAllocator) { Debug printf("COutputPin_GetAllocator(%p, %p) called\n", This->vt, ppAllocator); *ppAllocator = (IMemAllocator*) MemAllocatorCreate(); return 0; } static HRESULT STDCALL COutputPin_NotifyAllocator(IMemInputPin* This, /* [in] */ IMemAllocator* pAllocator, /* [in] */ int bReadOnly) { Debug printf("COutputPin_NotifyAllocator(%p, %p) called\n", This, pAllocator); ((COutputMemPin*)This)->pAllocator = (MemAllocator*) pAllocator; return 0; } static HRESULT STDCALL COutputPin_GetAllocatorRequirements(IMemInputPin* This, /* [out] */ ALLOCATOR_PROPERTIES* pProps) { return output_unimplemented("COutputPin_GetAllocatorRequirements", This); } static HRESULT STDCALL COutputPin_Receive(IMemInputPin* This, /* [in] */ IMediaSample* pSample) { COutputMemPin* mp = (COutputMemPin*)This; char* pointer; int len; Debug printf("COutputPin_Receive(%p) called\n", This); if (!pSample) return E_INVALIDARG; if (pSample->vt->GetPointer(pSample, (BYTE**) &pointer)) return -1; len = pSample->vt->GetActualDataLength(pSample); if (len == 0) len = pSample->vt->GetSize(pSample);//for iv50 //if(me.frame_pointer)memcpy(me.frame_pointer, pointer, len); if (mp->frame_pointer) *(mp->frame_pointer) = pointer; if (mp->frame_size_pointer) *(mp->frame_size_pointer) = len; /* FILE* file=fopen("./uncompr.bmp", "wb"); char head[14]={0x42, 0x4D, 0x36, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00}; *(int*)(&head[2])=len+0x36; fwrite(head, 14, 1, file); fwrite(&((VIDEOINFOHEADER*)me.type.pbFormat)->bmiHeader, sizeof(BITMAPINFOHEADER), 1, file); fwrite(pointer, len, 1, file); fclose(file); */ // pSample->vt->Release((IUnknown*)pSample); return 0; } static HRESULT STDCALL COutputPin_ReceiveMultiple(IMemInputPin * This, /* [size_is][in] */ IMediaSample **pSamples, /* [in] */ long nSamples, /* [out] */ long *nSamplesProcessed) { return output_unimplemented("COutputPin_ReceiveMultiple", This); } static HRESULT STDCALL COutputPin_ReceiveCanBlock(IMemInputPin * This) { return output_unimplemented("COutputPin_ReceiveCanBlock", This); } static void COutputPin_SetFramePointer(COutputPin* This, char** z) { This->mempin->frame_pointer = z; } static void COutputPin_SetPointer2(COutputPin* This, char* p) { if (This->mempin->pAllocator) // fixme This->mempin->pAllocator->SetPointer(This->mempin->pAllocator, p); } static void COutputPin_SetFrameSizePointer(COutputPin* This, long* z) { This->mempin->frame_size_pointer = z; } static void COutputPin_SetNewFormat(COutputPin* This, const AM_MEDIA_TYPE* amt) { This->type = *amt; } static void COutputPin_Destroy(COutputPin* This) { if (This->mempin->vt) free(This->mempin->vt); if (This->mempin) free(This->mempin); if (This->vt) free(This->vt); free(This); } static HRESULT STDCALL COutputPin_AddRef(IUnknown* This) { Debug printf("COutputPin_AddRef(%p) called (%d)\n", This, ((COutputPin*)This)->refcount); ((COutputPin*)This)->refcount++; return 0; } static HRESULT STDCALL COutputPin_Release(IUnknown* This) { Debug printf("COutputPin_Release(%p) called (%d)\n", This, ((COutputPin*)This)->refcount); if (--((COutputPin*)This)->refcount <= 0) COutputPin_Destroy((COutputPin*)This); return 0; } static HRESULT STDCALL COutputPin_M_AddRef(IUnknown* This) { COutputMemPin* p = (COutputMemPin*) This; Debug printf("COutputPin_MAddRef(%p) called (%p, %d)\n", p, p->parent, p->parent->refcount); p->parent->refcount++; return 0; } static HRESULT STDCALL COutputPin_M_Release(IUnknown* This) { COutputMemPin* p = (COutputMemPin*) This; Debug printf("COutputPin_MRelease(%p) called (%p, %d)\n", p, p->parent, p->parent->refcount); if (--p->parent->refcount <= 0) COutputPin_Destroy(p->parent); return 0; } COutputPin* COutputPinCreate(const AM_MEDIA_TYPE* amt) { COutputPin* This = (COutputPin*) malloc(sizeof(COutputPin)); IMemInputPin_vt* ivt; if (!This) return NULL; This->vt = (IPin_vt*) malloc(sizeof(IPin_vt)); This->mempin = (COutputMemPin*) malloc(sizeof(COutputMemPin)); ivt = (IMemInputPin_vt*) malloc(sizeof(IMemInputPin_vt)); if (!This->vt || !This->mempin || !ivt) { COutputPin_Destroy(This); return NULL; } This->mempin->vt = ivt; This->refcount = 1; This->remote = 0; This->type = *amt; This->vt->QueryInterface = COutputPin_QueryInterface; This->vt->AddRef = COutputPin_AddRef; This->vt->Release = COutputPin_Release; This->vt->Connect = COutputPin_Connect; This->vt->ReceiveConnection = COutputPin_ReceiveConnection; This->vt->Disconnect = COutputPin_Disconnect; This->vt->ConnectedTo = COutputPin_ConnectedTo; This->vt->ConnectionMediaType = COutputPin_ConnectionMediaType; This->vt->QueryPinInfo = COutputPin_QueryPinInfo; This->vt->QueryDirection = COutputPin_QueryDirection; This->vt->QueryId = COutputPin_QueryId; This->vt->QueryAccept = COutputPin_QueryAccept; This->vt->EnumMediaTypes = COutputPin_EnumMediaTypes; This->vt->QueryInternalConnections = COutputPin_QueryInternalConnections; This->vt->EndOfStream = COutputPin_EndOfStream; This->vt->BeginFlush = COutputPin_BeginFlush; This->vt->EndFlush = COutputPin_EndFlush; This->vt->NewSegment = COutputPin_NewSegment; This->mempin->vt->QueryInterface = COutputPin_M_QueryInterface; This->mempin->vt->AddRef = COutputPin_M_AddRef; This->mempin->vt->Release = COutputPin_M_Release; This->mempin->vt->GetAllocator = COutputPin_GetAllocator; This->mempin->vt->NotifyAllocator = COutputPin_NotifyAllocator; This->mempin->vt->GetAllocatorRequirements = COutputPin_GetAllocatorRequirements; This->mempin->vt->Receive = COutputPin_Receive; This->mempin->vt->ReceiveMultiple = COutputPin_ReceiveMultiple; This->mempin->vt->ReceiveCanBlock = COutputPin_ReceiveCanBlock; This->mempin->frame_size_pointer = 0; This->mempin->frame_pointer = 0; This->mempin->pAllocator = 0; This->mempin->refcount = 1; This->mempin->parent = This; This->SetPointer2 = COutputPin_SetPointer2; This->SetFramePointer = COutputPin_SetFramePointer; This->SetFrameSizePointer = COutputPin_SetFrameSizePointer; This->SetNewFormat = COutputPin_SetNewFormat; return This; }