From Wen-King Su, wen-king@myri.com

These are sample mpegs from a ReplayTV DVR.  They are uploaded for
Sascha Sommer and Diego Biurrun.  These mpeg files contain Closed
Caption information in user_data records that are store in locations
and formats different from that in the DVD, and therefore are not
recognized by the stock process_userdata function in libmpdemux/video.c.

replay_mpeg.4kn
replay_mpeg.5kn   These are samples from 4000 and 5000 serie ReplayTV.
		  They contain the normal closed caption stream --
		  the same kind of stream found in movie DVDs.
		  To make them work, I modified process_userdata in
		  libmpdemux/video.c to recognize their unique
		  user_data records, and to pass the stream on to the
		  stock CC decoder module through a new function in
		  sub_cc.c.

replay_mpeg.5ks	  This is a recording from a program with scrolling
		  closed caption.  The same mods above will pass the
		  stream to the stock CC decoder module, but the
		  module does not correctly handle a scrolling
		  closed caption stream.  For one thing, it never
		  call "display_buffer" for such a stream.
		  Secondly, as it accumulate undisplayed lines,
		  it overflows a fixed sized line array with no
		  bound check.  Causing the mplayer to die.
		  My patch below made further changes to sub_cc.c
		  to allow it handle scrolling captions.

==================================================

diff -ruN MPlayer-1.0pre5.orig/libmpdemux/video.c MPlayer-1.0pre5/libmpdemux/video.c
--- MPlayer-1.0pre5.orig/libmpdemux/video.c	Sun Apr 11 12:03:12 2004
+++ MPlayer-1.0pre5/libmpdemux/video.c	Wed Oct 20 16:01:45 2004
@@ -287,18 +287,37 @@
 }
 
 void ty_processuserdata( unsigned char* buf, int len );
+void replay_subcc_process_data(unsigned char b1, unsigned char b2);
 
 static void process_userdata(unsigned char* buf,int len){
     int i;
+    static int normal_cc = 0;
     /* if the user data starts with "CC", assume it is a CC info packet */
     if(len>2 && buf[0]=='C' && buf[1]=='C'){
 //    	mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"video.c: process_userdata() detected Closed Captions!\n");
 	if(subcc_enabled) subcc_process_data(buf+2,len-2);
+	normal_cc = 1;
     }
     if( len > 2 && buf[ 0 ] == 'T' && buf[ 1 ] == 'Y' )
     {
        ty_processuserdata( buf + 2, len - 2 );
        return;
+    }
+    if(!normal_cc && subcc_enabled)
+    {
+       if(len == 10 && buf[0] == 0x99 && buf[1] == 0x02 &&
+                       buf[4] == 0xAA && buf[5] == 0x02)
+       {
+           replay_subcc_process_data(buf[2],buf[3]);  /* RTV5K series */
+           return;
+       }
+
+       if(len ==  8 && buf[0] == 0xBB && buf[1] == 0x02 &&
+                       buf[4] == 0xCC && buf[5] == 0x02)
+       {
+           replay_subcc_process_data(buf[6],buf[7]);  /* RTV4K series */
+           return;
+       }
     }
     if(verbose<2) return;
     printf( "user_data: len=%3d  %02X %02X %02X %02X '",
diff -ruN MPlayer-1.0pre5.orig/sub_cc.c MPlayer-1.0pre5/sub_cc.c
--- MPlayer-1.0pre5.orig/sub_cc.c	Wed Nov  6 15:54:21 2002
+++ MPlayer-1.0pre5/sub_cc.c	Wed Oct 20 17:01:18 2004
@@ -66,6 +66,20 @@
 	for(i=0;i<SUB_MAX_TEXT;i++) if(buf->text[i]) {free(buf->text[i]);buf->text[i]=NULL;}
 }
 
+static void scroll_buffer()
+{
+    int i;
+
+    if(bb->lines > 3)
+    {
+	free(bb->text[0]);
+
+	for(i = 0; i < (bb->lines - 1); i++) bb->text[i] = bb->text[i+1];
+
+	bb->text[bb->lines-1] = 0;
+	bb->lines = bb->lines-1;
+    }
+}
 
 void subcc_init()
 {
@@ -93,7 +107,12 @@
 	if(c=='\n')
 	{
 		if(cursor_pos>0)
-			bb->lines++;cursor_pos=0;
+		{
+		    bb->lines++;
+		    bb->text[bb->lines - 1]=malloc(CC_MAX_LINE_LENGTH);
+		    memset(bb->text[bb->lines - 1],0,CC_MAX_LINE_LENGTH);
+		}
+		cursor_pos=0;
 	}
 	else 
 	{
@@ -164,7 +183,11 @@
 					{
 						case 0x2C: display_buffer(NULL); //EDM
 							   clear_buffer(fb); break;
+						case 0x26: display_buffer(bb);
+							   break;
 						case 0x2d: append_char('\n');	//carriage return
+							   scroll_buffer();
+							   display_buffer(bb);
 							   break;
 						case 0x2e: clear_buffer(bb);	//ENM
 							   break;
@@ -291,3 +314,9 @@
 	subcc_decode();
 }
 
+
+void replay_subcc_process_data(unsigned char b1, unsigned char b2)
+{
+	if(!inited) subcc_init();
+	cc_decode_EIA608(b1 | (b2 << 8));
+}