14 #include "vd_internal.h"
15 #include "wine/windef.h"
17 static vd_info_t info
= {
21 "Florian Schneider, Arpad Gereoffy, Alex Beregszaszi, Donnie Smith",
22 "binary real video codecs"
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
35 typedef struct cmsg_data_s
{
41 typedef struct transform_in_s
{
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*);
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*);
63 static void *rv_handle
=NULL
;
66 static int dll_type
= 0; /* 0 = unix dlopen, 1 = win32 dll */
69 void *__builtin_vec_new(unsigned long size
) {
73 void __builtin_vec_delete(void *mem
) {
77 void __pure_virtual(void) {
78 printf("FATAL: __pure_virtual() called!\n");
82 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
83 void ___brk_addr(void) {exit(0);}
84 char **__environ
={NULL
};
89 // to set/get/query special features/parameters
90 static int control(sh_video_t
*sh
,int cmd
,void* arg
,...){
92 // case VDCTRL_QUERY_MAX_PP_LEVEL:
94 // case VDCTRL_SET_PP_LEVEL:
95 // vfw_set_postproc(sh,10*(*((int*)arg)));
98 return CONTROL_UNKNOWN
;
101 /* exits program when failure */
103 static int load_syms_linux(char *path
) {
106 mp_msg(MSGT_DECVIDEO
,MSGL_V
, "opening shared obj '%s'\n", path
);
107 handle
= dlopen (path
, RTLD_LAZY
);
109 mp_msg(MSGT_DECVIDEO
,MSGL_WARN
,"Error: %s\n",dlerror());
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
&&
121 rvyuv_hive_message
&&
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
&&
137 rvyuv_hive_message
&&
145 mp_msg(MSGT_DECVIDEO
,MSGL_WARN
,"Error resolving symbols! (version incompatibility?)\n");
154 #include "loader/ldt_keeper.h"
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
) {
163 mp_msg(MSGT_DECVIDEO
,MSGL_V
, "opening win32 dll '%s'\n", path
);
167 handle
= LoadLibraryA(path
);
168 mp_msg(MSGT_DECVIDEO
,MSGL_V
,"win32 real codec handle=%p \n",handle
);
170 mp_msg(MSGT_DECVIDEO
,MSGL_WARN
,"Error loading dll\n");
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
&&
182 wrvyuv_hive_message
&&
190 mp_msg(MSGT_DECVIDEO
,MSGL_WARN
,"Error resolving symbols! (version incompatibility?)\n");
196 /* we need exact positions */
209 static int init(sh_video_t
*sh
){
210 //unsigned int out_fmt;
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);
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 */
228 if(strstr(sh
->codec
->dll
,".dll") || !load_syms_linux(path
))
231 if (!load_syms_windows(sh
->codec
->dll
))
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");
240 // only I420 supported
241 // if((sh->format!=0x30335652) && !mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_I420)) return 0;
246 result
=(*wrvyuv_init
)(&init_data
, &sh
->context
);
249 result
=(*rvyuv_init
)(&init_data
, &sh
->context
);
251 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"Couldn't open RealVideo codec, error code: 0x%X \n",result
);
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]};
264 (*wrvyuv_custom_message
)(&cmsg_data
,sh
->context
);
267 (*rvyuv_custom_message
)(&cmsg_data
,sh
->context
);
269 mp_msg(MSGT_DECVIDEO
,MSGL_V
,"INFO: RealVideo codec init OK!\n");
274 static void uninit(sh_video_t
*sh
){
278 if (wrvyuv_free
) wrvyuv_free(sh
->context
);
281 if(rvyuv_free
) rvyuv_free(sh
->context
);
286 if (rv_handle
) FreeLibrary(rv_handle
);
290 if(rv_handle
) dlclose(rv_handle
);
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
305 static mp_image_t
* decode(sh_video_t
*sh
,void* data
,int len
,int flags
){
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];
331 buffer
=malloc(sh
->disp_w
*sh
->disp_h
*3/2);
332 if (!buffer
) return 0;
337 result
=(*wrvyuv_transform
)(dp_data
, buffer
, &transform_in
,
338 transform_out
, sh
->context
);
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);
357 return (result
?NULL
:mpi
);