commit 99db3bd9a9d0aabd23c058414a725aa3e1653024
Author: Gregorio Gervasio, Jr <ggervasio@yahoo.com>
Date:   Thu Dec 2 19:39:19 2010 -0800

    Fix CC for digital streams with duplicate codes.  Fix handling of multiple CC backspace codes.

diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index 484af06..e8254c7 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.cpp
+++ b/mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -295,7 +295,7 @@ AvFormatDecoder::AvFormatDecoder(MythPlayer *parent,
     params.prealloced_context = 1;
     audioSamples = (short int *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE *
                                            sizeof(int32_t));
-    ccd608->SetIgnoreTimecode(true);
+    ccd608->SetDigitalTimecode(true);
 
     bool debug = VERBOSE_LEVEL_CHECK(VB_LIBAV);
     av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR);
@@ -2406,6 +2406,7 @@ void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len)
         return;
 
     bool had_608 = false, had_708 = false;
+    int cc_type_found[2] = { 0, 0 };
     for (uint cur = 0; cur < cc_count; cur++)
     {
         uint cc_code  = buf[2+(cur*3)];
@@ -2423,7 +2424,10 @@ void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len)
             if (cc608_good_parity(cc608_parity_table, data))
             {
                 had_608 = true;
-                ccd608->FormatCCField(lastccptsu / 1000, cc_type, data);
+                ccd608->FormatCCField(lastccptsu / 1000 + cc_type_found[cc_type], cc_type, data);
+                cc_type_found[cc_type]++;  // need unique timestamps to help decoder
+                                           // distinguish multiple codes in the same packet
+                                           // from repeated codes in separate packets
             }
         }
         else
diff --git a/mythtv/libs/libmythtv/cc608decoder.cpp b/mythtv/libs/libmythtv/cc608decoder.cpp
index 9e21e1f..d689298 100644
--- a/mythtv/libs/libmythtv/cc608decoder.cpp
+++ b/mythtv/libs/libmythtv/cc608decoder.cpp
@@ -18,7 +18,7 @@ using namespace std;
 static void init_xds_program_type(QString xds_program_type[96]);
 
 CC608Decoder::CC608Decoder(CC608Input *ccr)
-    : reader(ccr),                  ignore_time_code(false),
+    : reader(ccr),                  digital_time_code(false),
       rbuf(new unsigned char[sizeof(ccsubtitle)+255]),
       vps_l(0),
       wss_flags(0),                 wss_valid(false),
@@ -176,7 +176,12 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
     }
 
     if (FalseDup(tc, field, data))
-        goto skip;
+    {
+        if (digital_time_code)
+            return;
+        else
+           goto skip;
+    }
 
     XDSDecode(field, b1, b2);
 
@@ -416,7 +421,7 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
                             style[mode] = CC_STYLE_ROLLUP;
                             break;
                         case 0x2C:      //erase displayed memory
-                            if (ignore_time_code ||
+                            if (digital_time_code ||
                                 (tc - lastclr[mode]) > 5000 ||
                                 lastclr[mode] == 0)
                                 // don't overflow the frontend with
@@ -451,7 +456,7 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
                                     // flush
                                     BufferCC(mode, len, 0);
                             }
-                            else if (ignore_time_code ||
+                            else if (digital_time_code ||
                                      (tc - lastclr[mode]) > 5000 ||
                                      lastclr[mode] == 0)
                                 // clear and flush
@@ -505,7 +510,7 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
     for (mode = field*4; mode < (field*4 + 4); mode++)
     {
         len = ccbuf[mode].length();
-        if ((ignore_time_code || ((tc - timecode[mode]) > 100)) &&
+        if ((digital_time_code || ((tc - timecode[mode]) > 100)) &&
              (style[mode] != CC_STYLE_POPUP) && len)
         {
             // flush unfinished line if waiting too long
@@ -533,12 +538,26 @@ int CC608Decoder::FalseDup(int tc, int field, int data)
     b1 = data & 0x7f;
     b2 = (data >> 8) & 0x7f;
 
-    if (ignore_time_code)
+    if (digital_time_code)
     {
-        // just suppress duplicate control codes
+        // some digital streams have duplicate codes
+        // with the same time code;
+        // suppress those
         if ((data == lastcode[field]) &&
+            (tc == lasttc[field]))
+        {
+            return 1;
+        }
+
+        // most digital streams with encoded VBI
+        // have duplicate control codes;
+        // suppress every other repeated control code
+        else if ((data == lastcode[field]) &&
             ((b1 & 0x70) == 0x10))
+        {
+            lastcode[field] = -1;
             return 1;
+        }
         else
             return 0;
     }
diff --git a/mythtv/libs/libmythtv/cc608decoder.h b/mythtv/libs/libmythtv/cc608decoder.h
index 1463144..16ba609 100644
--- a/mythtv/libs/libmythtv/cc608decoder.h
+++ b/mythtv/libs/libmythtv/cc608decoder.h
@@ -51,7 +51,7 @@ class CC608Decoder
     void DecodeVPS(const unsigned char *buf);
     void DecodeWSS(const unsigned char *buf);
 
-    void SetIgnoreTimecode(bool val) { ignore_time_code = val; }
+    void SetDigitalTimecode(bool val) { digital_time_code = val; }
 
     uint    GetRatingSystems(bool future) const;
     uint    GetRating(uint i, bool future) const;
@@ -81,7 +81,7 @@ class CC608Decoder
 
     CC608Input *reader;
 
-    bool ignore_time_code;
+    bool digital_time_code;
 
     time_t last_seen[4];
 
