Ticket #9772: cc608_colors_v3.patch

File cc608_colors_v3.patch, 14.4 KB (added by Jim Stichnoth <stichnot@…>, 9 years ago)

Add support for preamble address codes.

  • mythtv/libs/libmythtv/cc608decoder.cpp

    diff --git a/mythtv/libs/libmythtv/cc608decoder.cpp b/mythtv/libs/libmythtv/cc608decoder.cpp
    index 9e21e1f..9649c87 100644
    a b CC608Decoder::CC608Decoder(CC608Input *ccr) 
    4343    memset(lastrow,    0, sizeof(lastrow));
    4444    memset(newrow,     0, sizeof(newrow));
    4545    memset(newcol,     0, sizeof(newcol));
     46    memset(newattr,    0, sizeof(newattr));
    4647    memset(timecode,   0, sizeof(timecode));
    4748    memset(row,        0, sizeof(row));
    4849    memset(col,        0, sizeof(col));
    void CC608Decoder::FormatCCField(int tc, int field, int data) 
    254255                newrow[mode] = lastrow[mode] + 1;
    255256
    256257            if (b2 & 0x10)        //row contains indent flag
     258            {
    257259                newcol[mode] = (b2 & 0x0E) << 1;
     260                // Encode as 0x7020 or 0x7021 depending on the
     261                // underline flag.
     262                newattr[mode] = (b2 & 0x1) + 0x20;
     263                VERBOSE(VB_VBI,
     264                        QString("cc608 preamble indent, b2=%1")
     265                        .arg(b2, 2, 16));
     266            }
    258267            else
     268            {
    259269                newcol[mode] = 0;
     270                newattr[mode] = (b2 & 0xf) + 0x10;
     271                // Encode as 0x7010 through 0x702f for the 16 possible
     272                // values of b2.
     273                VERBOSE(VB_VBI,
     274                        QString("cc608 preamble color change, b2=%1")
     275                        .arg(b2, 2, 16));
     276            }
    260277
    261             // row, indent settings are not final
     278            // row, indent, attribute settings are not final
    262279            // until text code arrives
    263280        }
    264281        else
    void CC608Decoder::FormatCCField(int tc, int field, int data) 
    278295                    switch (b2 & 0x70)
    279296                    {
    280297                        case 0x20:      //midrow attribute change
    281                             // TODO: we _do_ want colors, is that an attribute?
    282                             ccbuf[mode] += ' ';
     298                            VERBOSE(VB_VBI,
     299                                    QString("cc608 mid-row color change, b2=%1")
     300                                    .arg(b2, 2, 16));
     301                            // Encode as 0x7000 through 0x700f for the
     302                            // 16 possible values of b2.
     303                            ccbuf[mode] += QChar(0x7000 + (b2 & 0xf));
    283304                            len = ccbuf[mode].length();
    284305                            col[mode]++;
    285306                            break;
    void CC608Decoder::FormatCCField(int tc, int field, int data) 
    412433                            {
    413434                                newrow[mode] = 1;
    414435                                newcol[mode] = 0;
     436                                newattr[mode] = 0;
    415437                            }
    416438                            style[mode] = CC_STYLE_ROLLUP;
    417439                            break;
    void CC608Decoder::FormatCCField(int tc, int field, int data) 
    474496                            // TXT starts at row 1
    475497                            newrow[mode] = 1;
    476498                            newcol[mode] = 0;
     499                            newattr[mode] = 0;
    477500                            style[mode] = CC_STYLE_ROLLUP;
    478501                            break;
    479502
    void CC608Decoder::BufferCC(int mode, int len, int clr) 
    651674        int i = 0;
    652675        while (i < dispbuf.length()) {
    653676            QChar cp = dispbuf.at(i);
    654             switch (cp.unicode())
     677            int cpu = cp.unicode();
     678            switch (cpu)
    655679            {
    656680                case 0x2120 :  vbuf += "(SM)"; break;
    657681                case 0x2122 :  vbuf += "(TM)"; break;
    void CC608Decoder::BufferCC(int mode, int len, int clr) 
    665689                case 0x2588 :  vbuf += "[]"; break;
    666690                case 0x266A :  vbuf += "o/~"; break;
    667691                case '\b'   :  vbuf += "\\b"; break;
    668                 default     :  vbuf += QString(cp.toLatin1());
     692                default     :
     693                    if (cpu >= 0x7000 && cpu < 0x7000 + 0x30)
     694                        vbuf += QString("[%1]").arg(cpu - 0x7000, 2, 16);
     695                    else vbuf += QString(cp.toLatin1());
    669696            }
    670697            i++;
    671698        }
    int CC608Decoder::NewRowCC(int mode, int len) 
    771798    lastrow[mode] = newrow[mode];
    772799    newrow[mode] = 0;
    773800
    774     for (int x = 0; x < newcol[mode]; x++)
     801    int limit = (newattr[mode] ? newcol[mode] - 1 : newcol[mode]);
     802    for (int x = 0; x < limit; x++)
    775803    {
    776804        ccbuf[mode] += ' ';
    777805        len++;
    778806        col[mode]++;
    779807    }
     808    if (newattr[mode])
     809    {
     810        ccbuf[mode] += QChar(newattr[mode] + 0x7000);
     811        len++;
     812        col[mode]++;
     813    }
    780814    newcol[mode] = 0;
     815    newattr[mode] = 0;
    781816
    782817    return len;
    783818}
  • mythtv/libs/libmythtv/cc608decoder.h

    diff --git a/mythtv/libs/libmythtv/cc608decoder.h b/mythtv/libs/libmythtv/cc608decoder.h
    index 1463144..b87bbf5 100644
    a b class CC608Decoder 
    9898    int lastrow[8];
    9999    int newrow[8];
    100100    int newcol[8];
     101    int newattr[8]; // color+italic+underline
    101102    int timecode[8];
    102103    int row[8];
    103104    int col[8];
  • mythtv/libs/libmythtv/cc608reader.cpp

    diff --git a/mythtv/libs/libmythtv/cc608reader.cpp b/mythtv/libs/libmythtv/cc608reader.cpp
    index f430c65..f5cc1c5 100644
    a b CC608Buffer* CC608Reader::GetOutputText(bool &changed) 
    7474                    inpos += sizeof(st);
    7575
    7676                    CC608Text *cc = new CC608Text(QString((const char*) inpos),
    77                                         st.row, st.col, st.fg, true);
     77                                        st.row, st.col, true);
    7878                    m_outputBuffers.lock.lock();
    7979                    m_outputBuffers.buffers.push_back(cc);
    8080                    m_outputBuffers.lock.unlock();
    void CC608Reader::Update(unsigned char *inpos) 
    188188                else
    189189                    m_outputText = QString::fromUtf8((const char *)inpos, -1);
    190190                tmpcc = new CC608Text(m_outputText, m_outputCol, m_outputRow,
    191                                       0, false);
     191                                      false);
    192192                ccbuf->push_back(tmpcc);
    193193#if 0
    194194                if (ccbuf->size() > 4)
  • mythtv/libs/libmythtv/cc608reader.h

    diff --git a/mythtv/libs/libmythtv/cc608reader.h b/mythtv/libs/libmythtv/cc608reader.h
    index 5e020db..96a4507 100644
    a b  
    1414class CC608Text
    1515{
    1616  public:
    17     CC608Text(QString T, int X, int Y, int C, int TT)
    18       : text(T), x(X), y(Y), color(C), teletextmode(TT) {}
     17    CC608Text(QString T, int X, int Y, int TT)
     18      : text(T), x(X), y(Y), teletextmode(TT) {}
    1919    QString text;
    2020    int x;
    2121    int y;
    22     int color;
    2322    bool teletextmode;
    2423};
    2524
  • mythtv/libs/libmythtv/subtitlescreen.cpp

    diff --git a/mythtv/libs/libmythtv/subtitlescreen.cpp b/mythtv/libs/libmythtv/subtitlescreen.cpp
    index 7c949f8..05804dc 100644
    a b void SubtitleScreen::DisplayTextSubtitles(void) 
    339339            changed = true;
    340340            int height = (m_safeArea.height() * m_textFontZoom) / 1800;
    341341            gTextSubFont->GetFace()->setPixelSize(height);
     342            gTextSubFont->GetFace()->setItalic(false);
     343            gTextSubFont->GetFace()->setUnderline(false);
    342344            gTextSubFont->SetColor(Qt::white);
    343345        }
    344346    }
    void SubtitleScreen::DisplayRawTextSubtitles(void) 
    424426        {
    425427            int height = (m_safeArea.height() * m_textFontZoom) / 1800;
    426428            gTextSubFont->GetFace()->setPixelSize(height);
     429            gTextSubFont->GetFace()->setItalic(false);
     430            gTextSubFont->GetFace()->setUnderline(false);
    427431            gTextSubFont->SetColor(Qt::white);
    428432        }
    429433    }
    void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos) 
    576580    AddScaledImage(fg_image, button);
    577581}
    578582
     583// Extract everything from the text buffer up until the next format
     584// control character.  Return that substring, and remove it from the
     585// input string.  Bogus control characters are left unchanged.  If the
     586// buffer starts with a valid control character, the output parameters
     587// are corresondingly updated (and the control character is stripped).
     588static QString GetNextCC608Chunk(QString &text, bool teletextmode,
     589                                 int &color, bool &isItalic, bool &isUnderline,
     590                                 bool &showedNonControl)
     591{
     592    QString result;
     593    QString orig(text);
     594
     595    if (teletextmode)
     596    {
     597        result = text;
     598        text = QString::null;
     599        showedNonControl = true;
     600        return result;
     601    }
     602
     603    // Handle an initial control sequence.
     604    if (text.length() >= 1 && text[0] >= 0x7000)
     605    {
     606        int op = text[0].unicode() - 0x7000;
     607        isUnderline = (op & 0x1);
     608        switch (op & ~1)
     609        {
     610        case 0x0e:
     611            // color unchanged
     612            isItalic = true;
     613            break;
     614        case 0x1e:
     615            color = op >> 1;
     616            isItalic = true;
     617            break;
     618        case 0x20:
     619            // color unchanged
     620            // italics unchanged
     621            break;
     622        default:
     623            color = (op & 0xf) >> 1;
     624            isItalic = false;
     625            break;
     626        }
     627        text = text.mid(1);
     628    }
     629
     630    // Copy the string into the result, up to the next control
     631    // character.
     632    int nextControl = text.indexOf(QRegExp("[\\x7000-\\x7fff]"));
     633    if (nextControl < 0)
     634    {
     635        result = text;
     636        text = QString::null;
     637        showedNonControl = true;
     638    }
     639    else
     640    {
     641        result = text.left(nextControl);
     642        // Print the space character before handling the next control
     643        // character, otherwise the space character will be lost due
     644        // to the text.trimmed() operation in the MythUIText
     645        // constructor, combined with the left-justification of
     646        // captions.
     647        if (text[nextControl] < (0x7000 + 0x10))
     648            result += " ";
     649        text = text.mid(nextControl);
     650        if (nextControl > 0)
     651            showedNonControl = true;
     652    }
     653
     654    return result;
     655}
     656
    579657void SubtitleScreen::DisplayCC608Subtitles(void)
    580658{
    581659    static const QColor clr[8] =
    582660    {
    583         Qt::white,   Qt::red,     Qt::green, Qt::yellow,
    584         Qt::blue,    Qt::magenta, Qt::cyan, Qt::white,
     661        Qt::white,   Qt::green,   Qt::blue,    Qt::cyan,
     662        Qt::red,     Qt::yellow,  Qt::magenta, Qt::white,
    585663    };
    586664
    587665    if (!InitialiseFont(m_fontStretch) || !m_608reader)
    void SubtitleScreen::DisplayCC608Subtitles(void) 
    621699    int xscale = teletextmode ? 40 : 36;
    622700    int yscale = teletextmode ? 25 : 17;
    623701    gTextSubFont->GetFace()->setPixelSize(m_safeArea.height() / (yscale * 1.2));
    624     QFontMetrics font(*(gTextSubFont->GetFace()));
    625702    QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern);
    626     int height = font.height() * (1 + PAD_HEIGHT);
    627     int pad_width = font.maxWidth() * PAD_WIDTH;
    628703
    629704    for (; i != textlist->buffers.end(); i++)
    630705    {
    631706        CC608Text *cc = (*i);
     707        int color = 0;
     708        bool isItalic = false, isUnderline = false;
     709        bool first = true;
     710        bool showedNonControl = false;
     711        int x = 0, width = 0;
     712        QString text(cc->text);
    632713
    633         if (cc && (cc->text != QString::null))
     714        for (int chunk = 0; text != QString::null; first = false, chunk++)
    634715        {
    635             int width  = font.width(cc->text) + pad_width;
    636             int x = teletextmode ? cc->y : (cc->x + 3);
     716            QString captionText =
     717                GetNextCC608Chunk(text, cc->teletextmode,
     718                                  color, isItalic, isUnderline,
     719                                  showedNonControl);
     720            gTextSubFont->GetFace()->setItalic(isItalic);
     721            gTextSubFont->GetFace()->setUnderline(isUnderline);
     722            gTextSubFont->SetColor(clr[min(max(0, color), 7)]);
     723            QFontMetrics font(*(gTextSubFont->GetFace()));
     724            // XXX- could there be different heights across the same line?
     725            int height = font.height() * (1 + PAD_HEIGHT);
     726            if (first)
     727            {
     728                x = teletextmode ? cc->y : (cc->x + 3);
     729                x = (int)(((float)x / (float)xscale) * (float)m_safeArea.width());
     730            }
     731            else
     732            {
     733                x += width; // bump x by the previous width
     734            }
     735            int pad_width = font.maxWidth() * PAD_WIDTH;
     736            width = font.width(captionText) + pad_width;
    637737            int y = teletextmode ? cc->x : cc->y;
    638             x = (int)(((float)x / (float)xscale) * (float)m_safeArea.width());
    639738            y = (int)(((float)y / (float)yscale) * (float)m_safeArea.height());
     739            // Sometimes a line of caption text begins with a mid-row
     740            // format control like italics or a color change.  The
     741            // spec says the mid-row control also includes a space
     742            // character.  But this looks clumsy when using a
     743            // background, so we suppress it after the placement is
     744            // calculated.
     745            if (!showedNonControl)
     746                continue;
    640747            QRect rect(x, y, width, height);
    641748
    642749            if (!teletextmode && m_useBackground)
    void SubtitleScreen::DisplayCC608Subtitles(void) 
    648755                shape->SetArea(MythRect(bgrect));
    649756            }
    650757
    651             gTextSubFont->SetColor(clr[min(max(0, cc->color), 7)]);
    652758            MythUIText *text = new MythUIText(
    653                    cc->text, *gTextSubFont, rect, rect, (MythUIType*)this,
    654                    QString("cc608txt%1%2%3").arg(cc->x).arg(cc->y).arg(width));
     759                   captionText, *gTextSubFont, rect, rect, (MythUIType*)this,
     760                   QString("cc608txt%1%2%3%4").arg(cc->x).arg(cc->y).arg(width).arg(chunk));
    655761            if (text)
    656762                text->SetJustification(Qt::AlignLeft);
    657763            m_refreshArea = true;
    658             VERBOSE(VB_VBI, QString("x %1 y %2 String: '%3'")
    659                                 .arg(cc->x).arg(cc->y).arg(cc->text));
     764            VERBOSE(VB_VBI, QString("x %1 y %2 uline=%4 ital=%5 color=%6 coord=%7,%8 String: '%3'")
     765                                .arg(cc->x).arg(cc->y).arg(captionText)
     766                    .arg(isUnderline).arg(isItalic).arg(color).arg(x).arg(y));
    660767        }
    661768    }
    662769    textlist->lock.unlock();