[MPlayer-dev-eng] [PATCH] Support CineForm DirectShow codec

Steinar H. Gunderson sgunderson at bigfoot.com
Sun Jan 10 15:45:58 CET 2010


On Fri, Jan 08, 2010 at 12:23:20AM +0100, Steinar H. Gunderson wrote:
> Here is a patch to support CineForm, a relatively popular HD intermediate
> codec, in MPlayer. It's a bit raw (segfaults on exit, for one), but at least
> it's a usable starting point.

I found out there were corruption problems with the previous patch, so I
debugged a bit further. Here's an updated version, with the following
changes:

 - fflush(stdout) was taking 25% CPU (!) since it was called on every single
   lock/unlock call even when no debugging output was present. (Also, fflush
   is a serializing function, so it probably killed a lot of parallellity.)
   I moved that fflush call so it wouldn't be called if debugging was off.
 - The critical section implementation was totally borked -- it contained
   races to try to implement recursive mutexes on top of regular (fast)
   mutexes. I replaced it with just using recursive mutexes. Also, there is
   a global linked list of all critical sections in the system, but the list
   head (a global variable) was not protected by a mutex -- another race.
   NOTE: I do not know if all systems mplayer supports support recursive
   mutexes. It may be POSIX, or it may be some Linux extension.
 - When deleting a mutex, it needs to be unlocked first. Anything else is
   undefined behavior. Fixed one instance of that.
 - Events have a “reset” member that specify if they flag is automatically
   set back on read/wait. However, this was populated by bManualReset, so the
   flag was inverted and once an event was set, it would forever be counted
   as so. Fixed by inverting the flag.
 - SysAllocStringLen() (added by myself in the previous patch) assumed the
   parameter was using regular char* -- it's not, it's using OLECHAR*, ie.
   16-bit. Fixed. 

Still broken #1: WaitForMultipleObjects() for bWaitAll=false only ever
considers the first object. I fear this is reducing parallellity in CineForm,
and for other codecs it may lead to deadlocks, but for me it doesn't really
matter since x264 is the bottleneck in the pipeline anyway.

Still broken #2: Receive() on a codec's input pin is allowed to be
asynchronous, but the current DirectShow filter code assumes it's synchronous
and that it can read out the data as soon as Receive() returns. This doesn't
affect CineForm, but it may affect other codecs.
   
This fixes all issues I've seen with the codec save for speed -- in
particular, it now exits properly, and it no longer has Valgrind hits
(passes memcheck/helgrind/tsan, AFAICS).

I haven't done detailed tests of other codecs, but at least wmv8 via dshow
works fine.

/* Steinar */

diff -Nur orig/mplayer-export-2010-01-02/etc/codecs.conf mplayer-export-2010-01-02/etc/codecs.conf
--- orig/mplayer-export-2010-01-02/etc/codecs.conf	2010-01-01 00:45:07.000000000 +0100
+++ mplayer-export-2010-01-02/etc/codecs.conf	2010-01-06 21:06:17.000000000 +0100
@@ -1911,6 +1911,15 @@
   dll "aslcodec_vfw.dll"
   out BGR24 flip
 
+videocodec cineformhd
+  info "CineForm HD"
+  status working
+  fourcc CFHD
+  driver dshow
+  dll "CFDecode2.ax"
+  guid 0xAD83011E, 0x01d1, 0x4623, 0x91, 0xfd, 0x6b, 0x75, 0xf1, 0x83, 0xc5, 0xa9
+  out UYVY
+
 videocodec LEADMW20
   info "Lead CMW wavelet 2.0"
   status working
diff -Nur orig/mplayer-export-2010-01-02/loader/dshow/DS_Filter.c mplayer-export-2010-01-02/loader/dshow/DS_Filter.c
--- orig/mplayer-export-2010-01-02/loader/dshow/DS_Filter.c	2009-05-13 04:58:57.000000000 +0200
+++ mplayer-export-2010-01-02/loader/dshow/DS_Filter.c	2010-01-10 15:11:05.000000000 +0100
@@ -7,6 +7,7 @@
 #include "DS_Filter.h"
 #include "drv.h"
 #include "com.h"
+#include "graph.h"
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -125,6 +126,7 @@
 //    char eb[250];
     const char* em = NULL;
     MemAllocator* tempAll;
+    FilterGraph* graph;
     ALLOCATOR_PROPERTIES props,props1;
     DS_Filter* This = malloc(sizeof(DS_Filter));
     if (!This)
@@ -143,6 +145,7 @@
 	to CoCreateInstance(...,&IID_IMemoryAllocator,...) from binary codec.
     */
     tempAll=MemAllocatorCreate();
+    graph=FilterGraphCreate();
     This->m_pFilter = NULL;
     This->m_pInputPin = NULL;
     This->m_pOutputPin = NULL;
@@ -199,6 +202,9 @@
 	    em = "object does not provide IBaseFilter interface";
             break;
 	}
+
+	result = This->m_pFilter->vt->JoinFilterGraph(This->m_pFilter, (IFilterGraph*)graph, (short *)"F\0i\0l\0t\0e\0r\0");
+
 	// enumerate pins
 	result = This->m_pFilter->vt->EnumPins(This->m_pFilter, &enum_pins);
 	if (result || !enum_pins)
diff -Nur orig/mplayer-export-2010-01-02/loader/dshow/graph.c mplayer-export-2010-01-02/loader/dshow/graph.c
--- orig/mplayer-export-2010-01-02/loader/dshow/graph.c	1970-01-01 01:00:00.000000000 +0100
+++ mplayer-export-2010-01-02/loader/dshow/graph.c	2010-01-06 21:10:04.000000000 +0100
@@ -0,0 +1,77 @@
+/*
+ * Modified for use with MPlayer, detailed changelog at
+ * http://svn.mplayerhq.hu/mplayer/trunk/
+ */
+
+#include "config.h"
+#include "graph.h"
+#include "com.h"
+#include "wine/winerror.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static int GraphKeeper = 0;
+
+static long FilterGraph_CreateGraph(GUID* clsid, const GUID* iid, void** ppv)
+{
+    IFilterGraph* p;
+    int result;
+    if (!ppv)
+	return -1;
+    *ppv = 0;
+    if (memcmp(clsid, &CLSID_FilterGraph, sizeof(GUID)))
+	return -1;
+
+    p = (IFilterGraph*) FilterGraphCreate();
+    result = p->vt->QueryInterface((IUnknown*)p, iid, ppv);
+    p->vt->Release((IUnknown*)p);
+
+    return result;
+}
+
+static void FilterGraph_Destroy(FilterGraph* This)
+{
+    Debug printf("FilterGraph_Destroy(%p) called  (%d, %d)\n", This, This->refcount, GraphKeeper);
+#ifdef WIN32_LOADER
+    if (--GraphKeeper == 0)
+	UnregisterComClass(&CLSID_FilterGraph, FilterGraph_CreateGraph);
+#endif
+    free(This->vt);
+    free(This);
+}
+
+IMPLEMENT_IUNKNOWN(FilterGraph)
+
+FilterGraph* FilterGraphCreate()
+{
+    FilterGraph* This = (FilterGraph*) malloc(sizeof(FilterGraph));
+
+    if (!This)
+        return NULL;
+
+    Debug printf("FilterGraphCreate() called -> %p\n", This);
+
+    This->refcount = 1;
+
+    This->vt = (IFilterGraph_vt*) malloc(sizeof(IFilterGraph_vt));
+
+    if (!This->vt)
+    {
+        free(This);
+	return NULL;
+    }
+
+    This->vt->QueryInterface = FilterGraph_QueryInterface;
+    This->vt->AddRef = FilterGraph_AddRef;
+    This->vt->Release = FilterGraph_Release;
+
+    This->interfaces[0]=IID_IUnknown;
+    This->interfaces[1]=IID_IFilterGraph;
+
+#ifdef WIN32_LOADER
+    if (GraphKeeper++ == 0)
+	RegisterComClass(&CLSID_FilterGraph, FilterGraph_CreateGraph);
+#endif
+
+    return This;
+}
diff -Nur orig/mplayer-export-2010-01-02/loader/dshow/graph.h mplayer-export-2010-01-02/loader/dshow/graph.h
--- orig/mplayer-export-2010-01-02/loader/dshow/graph.h	1970-01-01 01:00:00.000000000 +0100
+++ mplayer-export-2010-01-02/loader/dshow/graph.h	2010-01-06 01:11:50.000000000 +0100
@@ -0,0 +1,20 @@
+#ifndef MPLAYER_GRAPH_H
+#define MPLAYER_GRAPH_H
+
+#include "interfaces.h"
+#include "cmediasample.h"
+
+typedef struct FilterGraph FilterGraph;
+
+struct FilterGraph
+{
+    IFilterGraph_vt* vt;
+    DECLARE_IUNKNOWN();
+    GUID interfaces[2];
+
+    // TODO: Add real methods here
+};
+
+FilterGraph* FilterGraphCreate(void);
+
+#endif /* MPLAYER_GRAPH_H */
diff -Nur orig/mplayer-export-2010-01-02/loader/dshow/guids.c mplayer-export-2010-01-02/loader/dshow/guids.c
--- orig/mplayer-export-2010-01-02/loader/dshow/guids.c	2002-11-26 22:00:20.000000000 +0100
+++ mplayer-export-2010-01-02/loader/dshow/guids.c	2010-01-06 01:15:33.000000000 +0100
@@ -13,6 +13,8 @@
     {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
 const GUID IID_IEnumMediaTypes={0x89c31040, 0x846b, 0x11ce,
     {0x97, 0xd3, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
+const GUID IID_IFilterGraph={0x56a8689f, 0x0ad4, 0x11ce,
+    {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
 const GUID IID_IMemInputPin={0x56a8689d, 0x0ad4, 0x11ce,
     {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
 const GUID IID_IMemAllocator={0x56a8689c, 0x0ad4, 0x11ce,
@@ -64,6 +66,8 @@
     {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
 const GUID MEDIASUBTYPE_IF09={0x39304649, 0x0000, 0x0010,
     {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
+const GUID CLSID_FilterGraph={0xe436ebb3, 0x524f, 0x11ce,
+    {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
 const GUID CLSID_MemoryAllocator={0x1e651cc0, 0xb199, 0x11d0,
     {0x82, 0x12, 0x00, 0xc0, 0x4f, 0xc3, 0x2c, 0x45}};
 const GUID IID_DivxHidden={0x598eba01, 0xb49a, 0x11d2,
diff -Nur orig/mplayer-export-2010-01-02/loader/dshow/guids.h mplayer-export-2010-01-02/loader/dshow/guids.h
--- orig/mplayer-export-2010-01-02/loader/dshow/guids.h	2008-02-23 15:50:55.000000000 +0100
+++ mplayer-export-2010-01-02/loader/dshow/guids.h	2010-01-06 20:40:34.000000000 +0100
@@ -46,6 +46,7 @@
 extern const GUID IID_IBaseFilter;
 extern const GUID IID_IEnumPins;
 extern const GUID IID_IEnumMediaTypes;
+extern const GUID IID_IFilterGraph;
 extern const GUID IID_IMemInputPin;
 extern const GUID IID_IMemAllocator;
 extern const GUID IID_IMediaSample;
@@ -54,6 +55,7 @@
 extern const GUID CLSID_DivxDecompressorCF;
 extern const GUID IID_IDivxFilterInterface;
 extern const GUID CLSID_IV50_Decoder;
+extern const GUID CLSID_FilterGraph;
 extern const GUID CLSID_MemoryAllocator;
 extern const GUID MEDIATYPE_Video;
 extern const GUID GUID_NULL;
diff -Nur orig/mplayer-export-2010-01-02/loader/dshow/interfaces.h mplayer-export-2010-01-02/loader/dshow/interfaces.h
--- orig/mplayer-export-2010-01-02/loader/dshow/interfaces.h	2008-02-23 15:50:55.000000000 +0100
+++ mplayer-export-2010-01-02/loader/dshow/interfaces.h	2010-01-06 01:07:14.000000000 +0100
@@ -13,7 +13,15 @@
 /*    Sh*t. MSVC++ and g++ use different methods of storing vtables.    */
 
 typedef struct IReferenceClock IReferenceClock;
+
 typedef struct IFilterGraph IFilterGraph;
+typedef struct IFilterGraph_vt
+{
+    INHERIT_IUNKNOWN();
+
+    // TODO: Implement
+} IFilterGraph_vt;
+struct IFilterGraph { IFilterGraph_vt* vt; };
 
 typedef struct IBaseFilter IBaseFilter;
 
diff -Nur orig/mplayer-export-2010-01-02/loader/registry.c mplayer-export-2010-01-02/loader/registry.c
--- orig/mplayer-export-2010-01-02/loader/registry.c	2009-05-04 19:35:26.000000000 +0200
+++ mplayer-export-2010-01-02/loader/registry.c	2010-01-06 21:09:22.000000000 +0100
@@ -385,7 +385,7 @@
     if(handle==head)
 	head=head->prev;
     free(handle);
-    return 1;
+    return 0;
 }
 
 long __stdcall RegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
@@ -396,6 +396,18 @@
     if(!regs)
 	init_registry();
 
+    // Hacks for CineForm.
+    if (value) {
+      if (strcmp(value, "Resolution") == 0) {
+        *data = 0x3e8;
+        return 0;
+      }
+      if (strcmp(value, "PixelFormats") == 0) {
+        *data = 0xffff;
+        return 0;
+      }
+    }
+
     c=build_keyname(key, value);
     if (!c)
 	return 1;
diff -Nur orig/mplayer-export-2010-01-02/loader/win32.c mplayer-export-2010-01-02/loader/win32.c
--- orig/mplayer-export-2010-01-02/loader/win32.c	2009-10-10 11:27:22.000000000 +0200
+++ mplayer-export-2010-01-02/loader/win32.c	2010-01-10 14:00:54.000000000 +0100
@@ -208,8 +208,8 @@
 	vprintf(fmt, va);
 //	mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
 	va_end(va);
+        fflush(stdout);
     }
-  fflush(stdout);
 }
 
 
@@ -344,9 +344,7 @@
 /* -- critical sections -- */
 struct CRITSECT
 {
-    pthread_t id;
     pthread_mutex_t mutex;
-    int locked;
     long deadbeef;
 };
 
@@ -436,9 +434,8 @@
 
     alccnt--;
 
-    if (last_alloc)
-	pthread_mutex_unlock(&memmut);
-    else
+    pthread_mutex_unlock(&memmut);
+    if (!last_alloc)
 	pthread_mutex_destroy(&memmut);
 
     //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld    (%d)\n", header, header->size, alccnt);
@@ -562,6 +559,7 @@
 #define	MODULE_HANDLE_msvcrt	((HMODULE)0x126)
 #define	MODULE_HANDLE_ole32	((HMODULE)0x127)
 #define	MODULE_HANDLE_winmm	((HMODULE)0x128)
+#define	MODULE_HANDLE_psapi	((HMODULE)0x129)
 
 static HMODULE WINAPI expGetModuleHandleA(const char* name)
 {
@@ -639,9 +637,11 @@
 };
 typedef struct mutex_list_t mutex_list;
 static mutex_list* mlist=NULL;
+static pthread_mutex_t mlist_lock = PTHREAD_MUTEX_INITIALIZER;
 
 void destroy_event(void* event)
 {
+    pthread_mutex_lock(&mlist_lock);
     mutex_list* pp=mlist;
     //    printf("garbage collector: destroy_event(%x)\n", event);
     while(pp)
@@ -663,10 +663,12 @@
 	     }
 	     printf("0\n");
 	     */
+            pthread_mutex_unlock(&mlist_lock);
 	    return;
 	}
 	pp=pp->prev;
     }
+    pthread_mutex_unlock(&mlist_lock);
 }
 
 static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
@@ -674,6 +676,7 @@
 {
     pthread_mutex_t *pm;
     pthread_cond_t  *pc;
+    void *ret;
     /*
      mutex_list* pp;
      pp=mlist;
@@ -684,6 +687,7 @@
      }
      printf("0\n");
      */
+    pthread_mutex_lock(&mlist_lock);
     if(mlist!=NULL)
     {
 	mutex_list* pp=mlist;
@@ -694,6 +698,7 @@
 	    {
 		dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
 			  pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
+                pthread_mutex_unlock(&mlist_lock);
 		return pp->pm;
 	    }
 	}while((pp=pp->prev) != NULL);
@@ -718,7 +723,7 @@
     mlist->pm=pm;
     mlist->pc=pc;
     mlist->state=bInitialState;
-    mlist->reset=bManualReset;
+    mlist->reset=!bManualReset;
     if(name)
 	strncpy(mlist->name, name, 127);
     else
@@ -735,7 +740,9 @@
     else
 	dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
 		  pSecAttr, bManualReset, bInitialState, mlist);
-    return mlist;
+    ret = mlist;
+    pthread_mutex_unlock(&mlist_lock);
+    return ret;
 }
 
 static void* WINAPI expSetEvent(void* event)
@@ -767,7 +774,9 @@
     mutex_list *ml = (mutex_list *)object;
     // FIXME FIXME FIXME - this value is sometime unititialize !!!
     int ret = WAIT_FAILED;
+    pthread_mutex_lock(&mlist_lock);
     mutex_list* pp=mlist;
+    pthread_mutex_unlock(&mlist_lock);
     if(object == (void*)0xcfcf9898)
     {
 	/**
@@ -1133,6 +1142,10 @@
     return result;
 }
 
+static WIN_BOOL WINAPI expIsDebuggerPresent(void)
+{
+    return 0;
+}
 
 static long WINAPI expGetVersion(void)
 {
@@ -1308,8 +1321,10 @@
 	    printf("InitializeCriticalSection(%p) - out of memory\n", c);
 	    return;
 	}
-	pthread_mutex_init(&cs->mutex, NULL);
-	cs->locked = 0;
+        pthread_mutexattr_t mutex_attr;
+	pthread_mutexattr_init(&mutex_attr);
+	pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP);
+	pthread_mutex_init(&cs->mutex, &mutex_attr);
 	critsecs_list[i].cs_win = c;
 	critsecs_list[i].cs_unix = cs;
 	dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
@@ -1319,8 +1334,10 @@
     {
 	struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
 					   0, AREATYPE_CRITSECT);
-	pthread_mutex_init(&cs->mutex, NULL);
-	cs->locked=0;
+        pthread_mutexattr_t mutex_attr;
+	pthread_mutexattr_init(&mutex_attr);
+	pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP);
+	pthread_mutex_init(&cs->mutex, &mutex_attr);
         cs->deadbeef = 0xdeadbeef;
 	*(void**)c = cs;
     }
@@ -1347,12 +1364,7 @@
 #endif
 	dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
     }
-    if(cs->locked)
-	if(cs->id==pthread_self())
-	    return;
     pthread_mutex_lock(&(cs->mutex));
-    cs->locked=1;
-    cs->id=pthread_self();
     return;
 }
 static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
@@ -1369,13 +1381,7 @@
 	dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
 	return;
     }
-    if (cs->locked)
-    {
-	cs->locked=0;
-	pthread_mutex_unlock(&(cs->mutex));
-    }
-    else
-	dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
+    pthread_mutex_unlock(&(cs->mutex));
     return;
 }
 
@@ -1397,12 +1403,6 @@
 	return;
     }
 
-    if (cs->locked)
-    {
-	dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!\n", c);
-	pthread_mutex_unlock(&(cs->mutex));
-    }
-
 #ifndef GARBAGE
     pthread_mutex_destroy(&(cs->mutex));
     // released by GarbageCollector in my_relase otherwise
@@ -1735,6 +1735,7 @@
 {
     pthread_mutex_t *pm;
     pthread_cond_t  *pc;
+    HANDLE ret;
     /*
     mutex_list* pp;
      printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "<null>"));
@@ -1746,6 +1747,7 @@
      }
      printf("0\n");
      */
+    pthread_mutex_lock(&mlist_lock);
     if(mlist!=NULL)
     {
 	mutex_list* pp=mlist;
@@ -1756,7 +1758,9 @@
 	    {
 		dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
 			  v1, init_count, max_count, name, name, mlist);
-		return (HANDLE)mlist;
+		ret = (HANDLE)mlist;
+                pthread_mutex_unlock(&mlist_lock);
+                return ret;
 	    }
 	}while((pp=pp->prev) != NULL);
     }
@@ -1795,7 +1799,9 @@
     else
 	dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n",
 		  v1, init_count, max_count, mlist);
-    return (HANDLE)mlist;
+    ret = (HANDLE)mlist;
+    pthread_mutex_unlock(&mlist_lock);
+    return ret;
 }
 
 static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
@@ -2269,6 +2275,21 @@
     return result;
 }
 
+static int WINAPI expGetModuleBaseNameA(int process, int module, char* s, int len)
+{
+    int result = 0;
+   
+    if (len >= 12) {
+	strcpy(s, "aviplay.dll");
+	result = 11;
+    }
+
+    dbgprintf("GetModuleBaseNameA(0x%x, 0x%x, 0x%x, %d) => %d\n",
+        process, module, s, len, result);
+
+    return result;
+}
+
 static int WINAPI expSetUnhandledExceptionFilter(void* filter)
 {
     dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
@@ -2329,6 +2350,8 @@
 	return MODULE_HANDLE_ole32;
     if (strcasecmp(name, "winmm.dll") == 0 || strcasecmp(name, "winmm") == 0)
 	return MODULE_HANDLE_winmm;
+    if (strcasecmp(name, "psapi.dll") == 0 || strcasecmp(name, "psapi") == 0)
+	return MODULE_HANDLE_psapi;
 
     result=LoadLibraryA(name);
     dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
@@ -2371,6 +2394,8 @@
 	result=LookupExternalByName("ole32.dll", name); break;
     case MODULE_HANDLE_winmm:
 	result=LookupExternalByName("winmm.dll", name); break;
+    case MODULE_HANDLE_psapi:
+	result=LookupExternalByName("psapi.dll", name); break;
     default:
 	result=GetProcAddress(mod, name);
     }
@@ -3518,7 +3543,7 @@
 	free(tmp);
 	return result;
     }
-    if (strstr(cs1, "vp3") || strstr(cs1, ".fpf"))
+    if (strstr(cs1, "vp3") || strstr(cs1, ".fpf") || strstr(cs1, ".col"))
     {
 	int r;
 	int flg = 0;
@@ -4543,6 +4568,12 @@
     return TRUE;
 }
 
+static void WINAPI expTerminateProcess( DWORD process, DWORD status )
+{
+    printf("EXIT - process %ld code %ld\n", process, status);
+    exit(status);
+}
+
 static void WINAPI expExitProcess( DWORD status )
 {
     printf("EXIT - code %ld\n",status);
@@ -4592,6 +4623,28 @@
 //    dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
     return ntohl(netlong);
 }
+
+static char* WINAPI expSysAllocStringLen(char *pch, unsigned cch)
+{
+    char *str;
+    dbgprintf("SysAllocStringLen('%s', %d)\n", pch, cch);
+    str = (char *)malloc(cch * 2 + sizeof(unsigned) + 2);
+    if (pch != NULL) {
+        memcpy(str + sizeof(unsigned), pch, cch * 2);
+    }
+    *(str + sizeof(unsigned) + cch * 2) = 0;
+    *(str + sizeof(unsigned) + cch * 2 + 1) = 0;
+    memcpy(str, &cch, sizeof(cch));
+    return str + sizeof(unsigned);
+}
+
+static void WINAPI expSysFreeString(char *str)
+{
+    if (str) {
+        free(str - sizeof(unsigned));
+    }
+}
+
 static void WINAPI expVariantInit(void* p)
 {
     printf("InitCommonControls called!\n");
@@ -4846,6 +4899,20 @@
     return p;
 }
 
+static DWORD WINAPI expGetThreadLocale(void)
+{
+    return 0;
+}
+
+static DWORD WINAPI expGetLocaleInfoA(DWORD locale, DWORD lctype, char* lpLCData, int cchData)
+{
+    if (lctype == 0x1004) {  // LOCALE_IDEFAULTANSICODEPAGE
+       strcpy(lpLCData, "437");
+       return 0;
+    }
+    return 1;
+}
+
 struct exports
 {
     char name[64];
@@ -4997,6 +5064,7 @@
     FF(GetFullPathNameA,-1)
     FF(SetErrorMode, -1)
     FF(IsProcessorFeaturePresent, -1)
+    FF(IsDebuggerPresent, -1)
     FF(GetProcessAffinityMask, -1)
     FF(InterlockedExchange, -1)
     FF(InterlockedCompareExchange, -1)
@@ -5017,12 +5085,15 @@
     FF(GlobalMemoryStatus,-1)
     FF(GetThreadPriority,-1)
     FF(SetThreadPriority,-1)
+    FF(TerminateProcess,-1)
     FF(ExitProcess,-1)
     {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
     FF(SetThreadIdealProcessor,-1)
     FF(SetProcessAffinityMask, -1)
     FF(EncodePointer, -1)
     FF(DecodePointer, -1)
+    FF(GetThreadLocale, -1)
+    FF(GetLocaleInfoA, -1)
     UNDEFF(FlsAlloc, -1)
     UNDEFF(FlsGetValue, -1)
     UNDEFF(FlsSetValue, -1)
@@ -5106,6 +5177,9 @@
     FF(waveOutGetNumDevs, -1)
 #endif
 };
+struct exports exp_psapi[]={
+    FF(GetModuleBaseNameA, -1)
+};
 struct exports exp_user32[]={
     FF(LoadIconA,-1)
     FF(LoadStringA, -1)
@@ -5220,6 +5294,8 @@
     FF(MoInitMediaType, -1)
 };
 struct exports exp_oleaut32[]={
+    FF(SysAllocStringLen, 4)
+    FF(SysFreeString, 6)
     FF(VariantInit, 8)
 #ifdef QTX
     FF(SysStringByteLen, 149)
@@ -5302,6 +5378,7 @@
     LL(kernel32)
     LL(msvcrt)
     LL(winmm)
+    LL(psapi)
     LL(user32)
     LL(advapi32)
     LL(gdi32)
diff -Nur orig/mplayer-export-2010-01-02/Makefile mplayer-export-2010-01-02/Makefile
--- orig/mplayer-export-2010-01-02/Makefile	2009-12-31 19:25:35.000000000 +0100
+++ mplayer-export-2010-01-02/Makefile	2010-01-09 01:57:43.000000000 +0100
@@ -312,6 +312,7 @@
                                         loader/dshow/DS_VideoDecoder.c \
                                         loader/dshow/allocator.c \
                                         loader/dshow/cmediasample.c \
+                                        loader/dshow/graph.c \
                                         loader/dshow/guids.c \
                                         loader/dshow/inputpin.c \
                                         loader/dshow/mediatype.c \

-- 
Homepage: http://www.sesse.net/



More information about the MPlayer-dev-eng mailing list