From 769a211a5ceaa3a0d2f3ce1a47d2a387f25a83ef Mon Sep 17 00:00:00 2001
From: Wang Bo <silencewang@msn.com>
Date: Sat, 31 Jan 2009 16:43:36 +0800
Subject: [PATCH] 1: sicne modules/demux/real.c has changed, the realvideo.c
    must changed to decode the correct data.
 2: give a simple hint to use realvide .

---
 doc/realvideo-howto.txt   |   18 +++++
 modules/codec/realvideo.c |  155 +++++++++++++++++++++++++++++---------------
 2 files changed, 120 insertions(+), 53 deletions(-)
 create mode 100644 doc/realvideo-howto.txt

diff --git a/doc/realvideo-howto.txt b/doc/realvideo-howto.txt
new file mode 100644
index 0000000..ff28e5e
--- /dev/null
+++ b/doc/realvideo-howto.txt
@@ -0,0 +1,18 @@
+RealVideo howto
+
+if you want to play RealNetworks' .rm/.rmvb video, 
+you need configure the vlc with --enable-real, and
+--enable-realrtsp for real's rtsp protocol.
+
+After config and make vlc, you need download the
+RealNetworks' codecs, general you can use codec
+from Real Player 9 or 10, the newer codec has not
+tested.  Or you can install Real's player or Helix SDK. 
+
+Now the realvideo has tested on linux ( intel, 32bit)
+and windows ( intel, 32bit ), if you have tested it on
+other platform, please let me know.
+
+-- 
+WangBo <silencewang __at__ msn.com>
+
diff --git a/modules/codec/realvideo.c b/modules/codec/realvideo.c
index 6e5c512..7e22619 100644
--- a/modules/codec/realvideo.c
+++ b/modules/codec/realvideo.c
@@ -89,9 +89,9 @@ struct rv_init_t
     short h;
     short unk3;
     int unk2;
-    unsigned int * subformat;
+    int subformat;
     int unk5;
-    unsigned int * format;
+    int format;
 } rv_init_t;
 
 struct decoder_sys_t
@@ -241,19 +241,81 @@ static int InitVideo(decoder_t *p_dec)
     init_data.h = p_dec->fmt_in.video.i_height ;
     init_data.unk3 = 0;
     init_data.unk2 = 0;
-    init_data.subformat = (unsigned int*)p_vide[0];
+    init_data.subformat = ntohl( p_vide[0] );
     init_data.unk5 = 1;
-    init_data.format = (unsigned int*)p_vide[1];
+    init_data.format = ntohl( p_vide[1]);
 
     /* first try to load linux dlls, if failed and we're supporting win32 dlls,
        then try to load the windows ones */
-    bool b_so_opened = false;
+
+    p_sys->rv_handle = NULL;
 
 #ifdef WIN32
-    g_decode_path="plugins\\drv43260.dll";
+    static const char psz_paths[MAX_PATH*3] = "";
+    if ( strlen(psz_paths[0]) == 0 )
+    {
+        HKEY h_key;
+        DWORD i_type, i_data = MAX_PATH + 1;
+        char * p_data;
+        char * p_end = psz_paths;
+
+        if ( RegOpenKeyEx( HKEY_CLASSES_ROOT, 
+                           _T("Software\\RealNetworks\\Preferences\\DT_Codecs"),
+                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )
+        {
+            if ( RegQueryValueEx( h_key, _T(""), 0, &i_type,
+                                 (LPBYTE) p_data, &i_data ) == ERROR_SUCCESS 
+                 && i_type == REG_SZ )
+            {
+                int i_len = strlen( p_data );
+                if ( i_len && p_data[i_len-1] == '\\' )
+                    p_data[i_len - 1] = '\0';
+                memcpy( p_end, p_data, strlen( p_data) + 1 );
+                p_end += strlen( p_data ) + 1;
+            }
+            RegCloseKey( h_key );
+        }
+
+        if ( RegOpenKeyEx( HKEY_CLASSES_ROOT, 
+                           _T("Helix\\HelixSDK\\10.0\\Preferences\\DT_Codecs"),
+                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )
+        {
+            if ( RegQueryValueEx( h_key, _T(""), 0, &i_type,
+                                 (LPBYTE) p_data, &i_data ) == ERROR_SUCCESS
+                 && i_type == REG_SZ )
+            {
+                int i_len = strlen( p_data );
+                if ( i_len && p_data[i_len-1] == '\\' )
+                    p_data[i_len - 1] = '\0';
+                memcpy( p_end, p_data, strlen( p_data) + 1 );
+                p_end += strlen( p_data ) + 1;
+            }
+            RegCloseKey( h_key );
+        }
+
+        memcpy( p_end, ".\0codecs\0plugins\0\0\0", 20 );
+    }
 
-    if( (p_sys->rv_handle = load_syms(p_dec, g_decode_path)) )
-        b_so_opened = true;
+    for( size_t i = 0; psz_paths[i]; i += strlen( psz_paths + i ) + 1 )
+    {
+        if( asprintf( &g_decode_path, "%s/drv4.dll", psz_paths + i ) != -1 )
+        {
+            p_sys->rv_handle = load_syms(p_dec, g_decode_path);
+            free( g_decode_path );
+        }
+        if( p_sys->rv_handle )
+            break;
+
+        if( asprintf( &g_decode_path, "%s/drv43260.dll", psz_paths + i ) != -1 )
+        {
+            p_sys->rv_handle = load_syms(p_dec, g_decode_path);
+            free( g_decode_path );
+        }
+        if( p_sys->rv_handle )
+            break;
+
+        msg_Dbg( p_dec, "Cannot load real decoder library: %s", g_decode_path);
+    }
 #else
     static const char psz_paths[] =
     {
@@ -272,6 +334,8 @@ static int InitVideo(decoder_t *p_dec)
         "/usr/lib64/RealPlayer10/codecs\0"
         "/usr/lib64/RealPlayer10GOLD/codecs\0"
         "/usr/local/lib/codecs\0"
+        ".\0"
+        "codecs\0"
         "\0"
     };
 
@@ -283,10 +347,7 @@ static int InitVideo(decoder_t *p_dec)
             free( g_decode_path );
         }
         if( p_sys->rv_handle )
-        {
-            b_so_opened = true;
             break;
-        }
 
         if( asprintf( &g_decode_path, "%s/drv3.so.6.0", psz_paths + i ) != -1 )
         {
@@ -294,16 +355,13 @@ static int InitVideo(decoder_t *p_dec)
             free( g_decode_path );
         }
         if( p_sys->rv_handle )
-        {
-            b_so_opened = true;
             break;
-        }
 
         msg_Dbg( p_dec, "Cannot load real decoder library: %s", g_decode_path);
     }
 #endif
 
-    if(!b_so_opened )
+    if( p_sys->rv_handle == NULL )
     {
         msg_Err( p_dec, "Cannot any real decoder library" );
         free( p_sys );
@@ -321,24 +379,27 @@ static int InitVideo(decoder_t *p_dec)
         result=(*rvyuv_init)(&init_data, &p_sys->handle);
     if (result)
     {
-        msg_Err( p_dec, "Cannot Init real decoder library: %s",  g_decode_path);
+        msg_Err( p_dec, "Cannot Init real decoder, error code: %X", result );
         free( p_sys );
         return VLC_EGENERIC;
     }
 
+    msg_Dbg( p_dec, "codec id: 0x%8X subid: 0x%8X\n", ntohl(p_vide[1]), ntohl(p_vide[0]) );
+
     /* setup rv30 codec (codec sub-type and image dimensions): */
     /*if ( p_dec->fmt_in.i_codec == VLC_FOURCC('R','V','3','0') )*/
-    if (p_vide[1]>=0x20200002)
+    if ( ntohl( p_vide[1])>=0x20200002)
     {
-        int i, cmsg_cnt;
+        int cmsg_cnt;
+        unsigned char * p_extrahdr  = (unsigned char *) p_vide ;
         uint32_t cmsg24[16]={p_dec->fmt_in.video.i_width,p_dec->fmt_in.video.i_height};
-        cmsg_data_t cmsg_data={0x24,1+(p_vide[1]&7), &cmsg24[0]};
-        cmsg_cnt = (p_vide[1]&7)*2;
+        cmsg_data_t cmsg_data={0x24,1+(p_extrahdr[1]&7), &cmsg24[0]};
+        cmsg_cnt = (p_extrahdr[1]&7)*2;
         if (i_vide - 8 < cmsg_cnt) {
                     cmsg_cnt = i_vide - 8;
         }
-        for (i = 0; i < cmsg_cnt; i++)
-            cmsg24[2+i] = p_vide[8+i]*4;
+        for (int i = 0; i < cmsg_cnt; i++)
+            cmsg24[2+i] = p_extrahdr[8+i]*4;
         #ifdef WIN32
         if (dll_type == 1)
             (*wrvyuv_custom_message)(&cmsg_data,p_sys->handle);
@@ -349,7 +410,7 @@ static int InitVideo(decoder_t *p_dec)
     /*
     es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_FOURCC( 'Y','V','1','2' ));
     es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_FOURCC( 'Y','U','Y','2' ));
-     */
+    */
     es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_FOURCC( 'I', '4', '2', '0'));
      
     p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
@@ -467,25 +528,20 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
     if ( p_pic )
     {
         unsigned int transform_out[5];
-        dp_hdr_t dp_hdr;
         transform_in_t transform_in;
-        uint32_t pkg_len = ((uint32_t*)p_block->p_buffer)[0];
-        unsigned char* dp_data=((unsigned char*)p_block->p_buffer)+8;
-        uint32_t* extra=(uint32_t*)(((char*)p_block->p_buffer)+8+pkg_len);
-        uint32_t img_size;
 
-
-        dp_hdr.len = pkg_len;
-        dp_hdr.chunktab = 8 + pkg_len;
-        dp_hdr.chunks = ((uint32_t*)p_block->p_buffer)[1]-1;
-        dp_hdr.timestamp = i_pts;
+        uint8_t  i_chunks = p_block->p_buffer[0];
+        uint32_t pkg_len =  p_block->i_buffer - 2*4*(i_chunks + 1) - 1;
+        unsigned char* dp_data=p_block->p_buffer + 2*4*(i_chunks+1) + 1;
+        uint32_t* extra=(uint32_t*)(p_block->p_buffer + 1);
+        uint32_t img_size;
 
         memset(&transform_in, 0, sizeof(transform_in_t));
 
-        transform_in.len = dp_hdr.len;
+        transform_in.len = pkg_len;
         transform_in.extra = extra;
-        transform_in.chunks = dp_hdr.chunks;
-        transform_in.timestamp = dp_hdr.timestamp;
+        transform_in.chunks = i_chunks;
+        transform_in.timestamp = i_pts; 
 
         memset (p_sys->plane, 0, p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height *3/2 );
 
@@ -496,17 +552,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
         #endif
             result=(*rvyuv_transform)(dp_data, p_sys->plane, &transform_in, transform_out, p_sys->handle);
 
-        /* msg_Warn(p_dec, "Real Size %d X %d", transform_out[3],
-                 transform_out[4]); */
-        /* some bug rm file will print the messages :
-                [00000551] realvideo decoder warning: Real Size 320 X 240
-                [00000551] realvideo decoder warning: Real Size 480 X 272
-                [00000551] realvideo decoder warning: Real Size 320 X 240
-                [00000551] realvideo decoder warning: Real Size 320 X 240
-                ...
-            so it needs fixing!
-        */
-        if ( p_sys->inited == 0 )
+        if ( result == 0 && p_sys->inited == 0 )
         {
             /* fix and get the correct image size! */
             if ( p_dec->fmt_in.video.i_width != transform_out[3]
@@ -540,16 +586,19 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
             p_sys->inited = 1;
         }
 
-        img_size = p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height;
-        memcpy( p_pic->p[0].p_pixels, p_sys->plane,  img_size);
-        memcpy( p_pic->p[1].p_pixels, p_sys->plane + img_size, img_size/4);
-        memcpy( p_pic->p[2].p_pixels, p_sys->plane + img_size * 5/4, img_size/4);
-        p_pic->date = i_pts ;
+        if ( result == 0 )
+        {
+                img_size = p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height;
+                memcpy( p_pic->p[0].p_pixels, p_sys->plane,  img_size);
+                memcpy( p_pic->p[1].p_pixels, p_sys->plane + img_size, img_size/4);
+                memcpy( p_pic->p[2].p_pixels, p_sys->plane + img_size * 5/4, img_size/4);
+                p_pic->date = i_pts ;
 
         /*  real video frame is small( frame and frame's time-shift is short), 
             so it will become late picture easier (when render-time changed)and
             droped by video-output.*/
-        p_pic->b_force = 1;
+                p_pic->b_force = 1;
+        }
     }
 
     vlc_mutex_unlock( &rm_mutex );
-- 
1.5.5.1

