Index: libmpcodecs/dec_video.c
===================================================================
--- libmpcodecs/dec_video.c	(revision 32647)
+++ libmpcodecs/dec_video.c	(working copy)
@@ -41,6 +41,7 @@
 #include "vd.h"
 #include "vf.h"
 #include "sub/eosd.h"
+#include "sub/sub_cc.h"
 
 #include "dec_video.h"
 
@@ -401,7 +402,7 @@
 	*full_frame = got_picture;
 
     delay = get_current_video_decoder_lag(sh_video);
-    if (correct_pts && pts != MP_NOPTS_VALUE
+    if (pts != MP_NOPTS_VALUE
         && (got_picture || sh_video->num_buffered_pts < delay)) {
         if (sh_video->num_buffered_pts ==
             sizeof(sh_video->buffered_pts) / sizeof(double))
@@ -411,9 +412,16 @@
             for (i = 0; i < sh_video->num_buffered_pts; i++)
                 if (sh_video->buffered_pts[i] < pts)
                     break;
-            for (j = sh_video->num_buffered_pts; j > i; j--)
+            for (j = sh_video->num_buffered_pts; j > i; j--) {
                 sh_video->buffered_pts[j] = sh_video->buffered_pts[j - 1];
+                sh_video->buffered_userdata[j] = sh_video->buffered_userdata[j - 1];
+                sh_video->buffered_userdata_len[j] = sh_video->buffered_userdata_len[j - 1];
+            }
             sh_video->buffered_pts[i] = pts;
+            sh_video->buffered_userdata[i] = sh_video->userdata;
+            sh_video->buffered_userdata_len[i] = sh_video->userdata_len;
+            sh_video->userdata = NULL;
+            sh_video->userdata_len = 0;
             sh_video->num_buffered_pts++;
         }
     }
@@ -441,13 +449,20 @@
     else if (field_dominance == 1)
         mpi->fields &= ~MP_IMGFIELD_TOP_FIRST;
 
-    if (correct_pts) {
         if (sh_video->num_buffered_pts) {
             sh_video->num_buffered_pts--;
+            if (correct_pts)
             sh_video->pts = sh_video->buffered_pts[sh_video->num_buffered_pts];
+            if (sh_video->buffered_userdata_len[sh_video->num_buffered_pts] > 2)
+                subcc_process_eia708(sh_video->buffered_userdata[sh_video->num_buffered_pts] + 2,
+                                     sh_video->buffered_userdata_len[sh_video->num_buffered_pts] - 2);
+            free(sh_video->buffered_userdata[sh_video->num_buffered_pts]);
+            sh_video->buffered_userdata[sh_video->num_buffered_pts] = NULL;
+            sh_video->buffered_userdata_len[sh_video->num_buffered_pts] = 0;
         } else {
             mp_msg(MSGT_CPLAYER, MSGL_ERR,
                    "No pts value from demuxer to use for frame!\n");
+            if (correct_pts)
             sh_video->pts = MP_NOPTS_VALUE;
         }
         if (delay >= 0) {
@@ -463,10 +478,13 @@
 #else
                 ;
 #endif
-            else
-                sh_video->num_buffered_pts = delay;
+            else while (sh_video->num_buffered_pts > delay) {
+                sh_video->num_buffered_pts--;
+                free(sh_video->buffered_userdata[sh_video->num_buffered_pts]);
+                sh_video->buffered_userdata[sh_video->num_buffered_pts] = NULL;
+                sh_video->buffered_userdata_len[sh_video->num_buffered_pts] = 0;
+            }
         }
-    }
     return mpi;
 }
 
Index: sub/sub_cc.c
===================================================================
--- sub/sub_cc.c	(revision 32653)
+++ sub/sub_cc.c	(working copy)
@@ -33,6 +33,7 @@
 #include <string.h>
 
 #include "config.h"
+#include "mp_msg.h"
 #include "sub_cc.h"
 
 #include "subreader.h"
@@ -40,7 +41,9 @@
 #include "libvo/video_out.h"
 #include "sub.h"
 
+#include "libavutil/avutil.h"
 
+
 #define CC_MAX_LINE_LENGTH 64
 
 static char chartbl[128];
@@ -345,3 +348,33 @@
 
 	subcc_decode(inputdata, len);
 }
+
+void subcc_process_eia708(const uint8_t *data, int len)
+{
+    int cc_count;
+    if (!subcc_enabled)
+        return;
+    if (!initialized)
+        subcc_init();
+    if (len <= 5)
+        return;
+    if (data[0] != '9' || data[1] != '4' || data[2] != 3) {
+        mp_msg(MSGT_OSD, MSGL_ERR, "Unknown ATSC CC type "
+                                   "0x%"PRIx8" 0x%"PRIx8" 0x%"PRIx8"\n",
+                                   data[0], data[1], data[2]);
+        return;
+    }
+    // process_cc_data_flag
+    if (!(data[3] & 0x40))
+        return;
+    cc_count = data[3] & 0x1f;
+    data += 5;
+    len  -= 5;
+    cc_count = FFMIN(cc_count, len / 3);
+    while (cc_count--) {
+        // EAI-608 data
+        if ((data[0] & 0xfe) == 0xfc && (data[0] & 1) == selected_channel() >> 1)
+            cc_decode_EIA608(data[1] | (data[2] << 8));
+        data += 3;
+    }
+}
Index: sub/sub_cc.h
===================================================================
--- sub/sub_cc.h	(revision 32653)
+++ sub/sub_cc.h	(working copy)
@@ -25,5 +25,6 @@
 
 void subcc_init(void);
 void subcc_process_data(const uint8_t *inputdata, unsigned int len);
+void subcc_process_eia708(const uint8_t *data, int len);
 
 #endif /* MPLAYER_SUB_CC_H */
Index: mplayer.c
===================================================================
--- mplayer.c	(revision 32648)
+++ mplayer.c	(working copy)
@@ -2395,6 +2395,7 @@
 	int full_frame;
 
     do {
+double pts = mpctx->d_video->pts;
 	current_module = "video_read_frame";
 	frame_time = sh_video->next_frame_time;
 	in_size = video_read_frame(sh_video, &sh_video->next_frame_time,
@@ -2424,7 +2425,7 @@
 	if (in_size > 0 && !decoded_frame)
 #endif
 	decoded_frame = decode_video(sh_video, start, in_size, drop_frame,
-				     sh_video->pts, &full_frame);
+				     pts, &full_frame);
 
     if (full_frame) {
 	sh_video->timer += frame_time;
Index: libmpdemux/video.c
===================================================================
--- libmpdemux/video.c	(revision 32655)
+++ libmpdemux/video.c	(working copy)
@@ -408,13 +408,26 @@
 return 1;
 }
 
-static void process_userdata(const unsigned char* buf,int len){
+static void process_userdata(sh_video_t *sh, const unsigned char* buf,int len){
     int i;
     /* 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");
       subcc_process_data(buf+2,len-2);
     }
+    if (len > 2 && buf[0] == 'G' && buf[1] == 'A') {
+      free(sh->userdata);
+      sh->userdata = NULL;
+      sh->userdata_len = 0;
+
+      sh->userdata = malloc(len);
+      if (sh->userdata) {
+          memcpy(sh->userdata, buf, len);
+          sh->userdata_len = len;
+//      subcc_process_eia708(buf + 2, len - 2);
+      }
+    }
+
     if( len > 2 && buf[ 0 ] == 'T' && buf[ 1 ] == 'Y' )
     {
        ty_processuserdata( buf + 2, len - 2 );
@@ -468,7 +481,7 @@
           switch(i){
             case 0x1B3: mp_header_process_sequence_header (&picture, &videobuffer[start]);break;
             case 0x1B5: mp_header_process_extension (&picture, &videobuffer[start]);break;
-            case 0x1B2: process_userdata (&videobuffer[start], videobuf_len-start);break;
+            case 0x1B2: process_userdata (sh_video, &videobuffer[start], videobuf_len-start);break;
             case 0x100: picture_coding_type=(videobuffer[start+1] >> 3) & 7;break;
           }
         }
Index: libmpdemux/stheader.h
===================================================================
--- libmpdemux/stheader.h	(revision 32647)
+++ libmpdemux/stheader.h	(working copy)
@@ -99,6 +99,11 @@
   double last_pts;
   double buffered_pts[20];
   int num_buffered_pts;
+  // per-frame userdata, reordered along with pts
+  uint8_t *userdata;
+  int userdata_len;
+  uint8_t *buffered_userdata[20];
+  int buffered_userdata_len[20];
   // output format: (set by demuxer)
   float fps;              // frames per second (set only if constant fps)
   float frametime;        // 1/fps
Index: libmpdemux/demuxer.c
===================================================================
--- libmpdemux/demuxer.c	(revision 32647)
+++ libmpdemux/demuxer.c	(working copy)
@@ -388,6 +388,15 @@
 {
     mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_video at %p\n", sh);
     free(sh->bih);
+    while (sh->num_buffered_pts) {
+        sh->num_buffered_pts--;
+        free(sh->buffered_userdata[sh->num_buffered_pts]);
+        sh->buffered_userdata[sh->num_buffered_pts] = NULL;
+        sh->buffered_userdata_len[sh->num_buffered_pts] = 0;
+    }
+    free(sh->userdata);
+    sh->userdata = NULL;
+    sh->userdata_len = 0;
 #ifdef CONFIG_FFMPEG
     clear_parser((sh_common_t *)sh);
 #endif
