typo fixes
[mplayer/greg.git] / libmpcodecs / vd_realvid.c
blob4a0702bb855828908bfa3943ff84b767f7da3c29
1 #include <stdio.h>
2 #include <stdlib.h>
4 #include "config.h"
5 #ifdef USE_REALCODECS
7 #ifdef HAVE_LIBDL
8 #include <dlfcn.h>
9 #endif
11 #include "mp_msg.h"
12 #include "help_mp.h"
14 #include "vd_internal.h"
15 #include "wine/windef.h"
17 static vd_info_t info = {
18 "RealVideo decoder",
19 "realvid",
20 "Alex Beregszaszi",
21 "Florian Schneider, Arpad Gereoffy, Alex Beregszaszi, Donnie Smith",
22 "binary real video codecs"
25 LIBVD_EXTERN(realvid)
29 * Structures for data packets. These used to be tables of unsigned ints, but
30 * that does not work on 64 bit platforms (e.g. Alpha). The entries that are
31 * pointers get truncated. Pointers on 64 bit platforms are 8 byte longs.
32 * So we have to use structures so the compiler will assign the proper space
33 * for the pointer.
35 typedef struct cmsg_data_s {
36 uint32_t data1;
37 uint32_t data2;
38 uint32_t* dimensions;
39 } cmsg_data_t;
41 typedef struct transform_in_s {
42 uint32_t len;
43 uint32_t unknown1;
44 uint32_t chunks;
45 uint32_t* extra;
46 uint32_t unknown2;
47 uint32_t timestamp;
48 } transform_in_t;
50 static unsigned long (*rvyuv_custom_message)(cmsg_data_t* ,void*);
51 static unsigned long (*rvyuv_free)(void*);
52 static unsigned long (*rvyuv_hive_message)(unsigned long,unsigned long);
53 static unsigned long (*rvyuv_init)(void*, void*); // initdata,context
54 static unsigned long (*rvyuv_transform)(char*, char*,transform_in_t*,unsigned int*,void*);
55 #ifdef USE_WIN32DLL
56 static unsigned long WINAPI (*wrvyuv_custom_message)(cmsg_data_t* ,void*);
57 static unsigned long WINAPI (*wrvyuv_free)(void*);
58 static unsigned long WINAPI (*wrvyuv_hive_message)(unsigned long,unsigned long);
59 static unsigned long WINAPI (*wrvyuv_init)(void*, void*); // initdata,context
60 static unsigned long WINAPI (*wrvyuv_transform)(char*, char*,transform_in_t*,unsigned int*,void*);
61 #endif
63 static void *rv_handle=NULL;
64 static int inited=0;
65 #ifdef USE_WIN32DLL
66 static int dll_type = 0; /* 0 = unix dlopen, 1 = win32 dll */
67 #endif
69 void *__builtin_vec_new(unsigned long size) {
70 return malloc(size);
73 void __builtin_vec_delete(void *mem) {
74 free(mem);
77 void __pure_virtual(void) {
78 printf("FATAL: __pure_virtual() called!\n");
79 // exit(1);
82 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
83 void ___brk_addr(void) {exit(0);}
84 char **__environ={NULL};
85 #undef stderr
86 FILE *stderr=NULL;
87 #endif
89 // to set/get/query special features/parameters
90 static int control(sh_video_t *sh,int cmd,void* arg,...){
91 // switch(cmd){
92 // case VDCTRL_QUERY_MAX_PP_LEVEL:
93 // return 9;
94 // case VDCTRL_SET_PP_LEVEL:
95 // vfw_set_postproc(sh,10*(*((int*)arg)));
96 // return CONTROL_OK;
97 // }
98 return CONTROL_UNKNOWN;
101 /* exits program when failure */
102 #ifdef HAVE_LIBDL
103 static int load_syms_linux(char *path) {
104 void *handle;
106 mp_msg(MSGT_DECVIDEO,MSGL_V, "opening shared obj '%s'\n", path);
107 handle = dlopen (path, RTLD_LAZY);
108 if (!handle) {
109 mp_msg(MSGT_DECVIDEO,MSGL_WARN,"Error: %s\n",dlerror());
110 return 0;
113 rvyuv_custom_message = dlsym(handle, "RV20toYUV420CustomMessage");
114 rvyuv_free = dlsym(handle, "RV20toYUV420Free");
115 rvyuv_hive_message = dlsym(handle, "RV20toYUV420HiveMessage");
116 rvyuv_init = dlsym(handle, "RV20toYUV420Init");
117 rvyuv_transform = dlsym(handle, "RV20toYUV420Transform");
119 if(rvyuv_custom_message &&
120 rvyuv_free &&
121 rvyuv_hive_message &&
122 rvyuv_init &&
123 rvyuv_transform)
125 rv_handle = handle;
126 return 1;
129 rvyuv_custom_message = dlsym(handle, "RV40toYUV420CustomMessage");
130 rvyuv_free = dlsym(handle, "RV40toYUV420Free");
131 rvyuv_hive_message = dlsym(handle, "RV40toYUV420HiveMessage");
132 rvyuv_init = dlsym(handle, "RV40toYUV420Init");
133 rvyuv_transform = dlsym(handle, "RV40toYUV420Transform");
135 if(rvyuv_custom_message &&
136 rvyuv_free &&
137 rvyuv_hive_message &&
138 rvyuv_init &&
139 rvyuv_transform)
141 rv_handle = handle;
142 return 1;
145 mp_msg(MSGT_DECVIDEO,MSGL_WARN,"Error resolving symbols! (version incompatibility?)\n");
146 dlclose(handle);
147 return 0;
149 #endif
151 #ifdef USE_WIN32DLL
153 #ifdef WIN32_LOADER
154 #include "loader/ldt_keeper.h"
155 #endif
156 void* WINAPI LoadLibraryA(char* name);
157 void* WINAPI GetProcAddress(void* handle,char* func);
158 int WINAPI FreeLibrary(void *handle);
160 static int load_syms_windows(char *path) {
161 void *handle;
163 mp_msg(MSGT_DECVIDEO,MSGL_V, "opening win32 dll '%s'\n", path);
164 #ifdef WIN32_LOADER
165 Setup_LDT_Keeper();
166 #endif
167 handle = LoadLibraryA(path);
168 mp_msg(MSGT_DECVIDEO,MSGL_V,"win32 real codec handle=%p \n",handle);
169 if (!handle) {
170 mp_msg(MSGT_DECVIDEO,MSGL_WARN,"Error loading dll\n");
171 return 0;
174 wrvyuv_custom_message = GetProcAddress(handle, "RV20toYUV420CustomMessage");
175 wrvyuv_free = GetProcAddress(handle, "RV20toYUV420Free");
176 wrvyuv_hive_message = GetProcAddress(handle, "RV20toYUV420HiveMessage");
177 wrvyuv_init = GetProcAddress(handle, "RV20toYUV420Init");
178 wrvyuv_transform = GetProcAddress(handle, "RV20toYUV420Transform");
180 if(wrvyuv_custom_message &&
181 wrvyuv_free &&
182 wrvyuv_hive_message &&
183 wrvyuv_init &&
184 wrvyuv_transform)
186 dll_type = 1;
187 rv_handle = handle;
188 return 1;
190 mp_msg(MSGT_DECVIDEO,MSGL_WARN,"Error resolving symbols! (version incompatibility?)\n");
191 FreeLibrary(handle);
192 return 0; // error
194 #endif
196 /* we need exact positions */
197 struct rv_init_t {
198 short unk1;
199 short w;
200 short h;
201 short unk3;
202 int unk2;
203 int subformat;
204 int unk5;
205 int format;
206 } rv_init_t;
208 // init driver
209 static int init(sh_video_t *sh){
210 //unsigned int out_fmt;
211 char *path;
212 int result;
213 // we export codec id and sub-id from demuxer in bitmapinfohdr:
214 unsigned int* extrahdr=(unsigned int*)(sh->bih+1);
215 struct rv_init_t init_data={
216 11, sh->disp_w, sh->disp_h,0,0,extrahdr[0],
217 1,extrahdr[1]}; // rv30
219 mp_msg(MSGT_DECVIDEO,MSGL_V,"realvideo codec id: 0x%08X sub-id: 0x%08X\n",extrahdr[1],extrahdr[0]);
221 path = malloc(strlen(REALCODEC_PATH)+strlen(sh->codec->dll)+2);
222 if (!path) return 0;
223 sprintf(path, REALCODEC_PATH "/%s", sh->codec->dll);
225 /* first try to load linux dlls, if failed and we're supporting win32 dlls,
226 then try to load the windows ones */
227 #ifdef HAVE_LIBDL
228 if(strstr(sh->codec->dll,".dll") || !load_syms_linux(path))
229 #endif
230 #ifdef USE_WIN32DLL
231 if (!load_syms_windows(sh->codec->dll))
232 #endif
234 mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_MissingDLLcodec,sh->codec->dll);
235 mp_msg(MSGT_DECVIDEO,MSGL_HINT,"Read the RealVideo section of the DOCS!\n");
236 free(path);
237 return 0;
239 free(path);
240 // only I420 supported
241 // if((sh->format!=0x30335652) && !mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_I420)) return 0;
242 // init codec:
243 sh->context=NULL;
244 #ifdef USE_WIN32DLL
245 if (dll_type == 1)
246 result=(*wrvyuv_init)(&init_data, &sh->context);
247 else
248 #endif
249 result=(*rvyuv_init)(&init_data, &sh->context);
250 if (result){
251 mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Couldn't open RealVideo codec, error code: 0x%X \n",result);
252 return 0;
254 // setup rv30 codec (codec sub-type and image dimensions):
255 if((sh->format<=0x30335652) && (extrahdr[1]>=0x20200002)){
256 // We could read nonsense data while filling this, but input is big enough so no sig11
257 uint32_t cmsg24[8]={sh->disp_w,sh->disp_h,((unsigned char *)extrahdr)[8]*4,((unsigned char *)extrahdr)[9]*4,
258 ((unsigned char *)extrahdr)[10]*4,((unsigned char *)extrahdr)[11]*4,
259 ((unsigned char *)extrahdr)[12]*4,((unsigned char *)extrahdr)[13]*4};
260 cmsg_data_t cmsg_data={0x24,1+((extrahdr[0]>>16)&7), &cmsg24[0]};
262 #ifdef USE_WIN32DLL
263 if (dll_type == 1)
264 (*wrvyuv_custom_message)(&cmsg_data,sh->context);
265 else
266 #endif
267 (*rvyuv_custom_message)(&cmsg_data,sh->context);
269 mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: RealVideo codec init OK!\n");
270 return 1;
273 // uninit driver
274 static void uninit(sh_video_t *sh){
275 #ifdef USE_WIN32DLL
276 if (dll_type == 1)
278 if (wrvyuv_free) wrvyuv_free(sh->context);
279 } else
280 #endif
281 if(rvyuv_free) rvyuv_free(sh->context);
283 #ifdef USE_WIN32DLL
284 if (dll_type == 1)
286 if (rv_handle) FreeLibrary(rv_handle);
287 } else
288 #endif
289 #ifdef HAVE_LIBDL
290 if(rv_handle) dlclose(rv_handle);
291 #endif
292 rv_handle=NULL;
293 inited = 0;
296 // copypaste from demux_real.c - it should match to get it working!
297 typedef struct dp_hdr_s {
298 uint32_t chunks; // number of chunks
299 uint32_t timestamp; // timestamp from packet header
300 uint32_t len; // length of actual data
301 uint32_t chunktab; // offset to chunk offset array
302 } dp_hdr_t;
304 // decode a frame
305 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
306 mp_image_t* mpi;
307 unsigned long result;
308 dp_hdr_t* dp_hdr=(dp_hdr_t*)data;
309 unsigned char* dp_data=((unsigned char*)data)+sizeof(dp_hdr_t);
310 uint32_t* extra=(uint32_t*)(((char*)data)+dp_hdr->chunktab);
311 unsigned char* buffer;
313 unsigned int transform_out[5];
314 transform_in_t transform_in={
315 dp_hdr->len, // length of the packet (sub-packets appended)
316 0, // unknown, seems to be unused
317 dp_hdr->chunks, // number of sub-packets - 1
318 extra, // table of sub-packet offsets
319 0, // unknown, seems to be unused
320 dp_hdr->timestamp,// timestamp (the integer value from the stream)
323 if(len<=0 || flags&2) return NULL; // skipped frame || hardframedrop
325 if(inited){ // rv30 width/height not yet known
326 mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, 0 /*MP_IMGFLAG_ACCEPT_STRIDE*/,
327 sh->disp_w, sh->disp_h);
328 if(!mpi) return NULL;
329 buffer=mpi->planes[0];
330 } else {
331 buffer=malloc(sh->disp_w*sh->disp_h*3/2);
332 if (!buffer) return 0;
335 #ifdef USE_WIN32DLL
336 if (dll_type == 1)
337 result=(*wrvyuv_transform)(dp_data, buffer, &transform_in,
338 transform_out, sh->context);
339 else
340 #endif
341 result=(*rvyuv_transform)(dp_data, buffer, &transform_in,
342 transform_out, sh->context);
344 if(!inited){ // rv30 width/height now known
345 sh->aspect=(float)sh->disp_w/(float)sh->disp_h;
346 sh->disp_w=transform_out[3];
347 sh->disp_h=transform_out[4];
348 if (!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_I420)) return 0;
349 mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, 0 /*MP_IMGFLAG_ACCEPT_STRIDE*/,
350 sh->disp_w, sh->disp_h);
351 if(!mpi) return NULL;
352 memcpy(mpi->planes[0],buffer,sh->disp_w*sh->disp_h*3/2);
353 free(buffer);
354 inited=1;
357 return (result?NULL:mpi);
360 #endif