Ticket #1095: eit708-v2.patch

File eit708-v2.patch, 76.6 KB (added by danielk, 20 years ago)

decoding portion of EIA-708 caption support

  • libs/libmythtv/NuppelVideoPlayer.h

     
    1414#include "recordingprofile.h"
    1515#include "videooutbase.h"
    1616#include "tv_play.h"
     17#include "ccdecoder.h"
     18#include "cc708decoder.h"
     19#include "cc708window.h"
    1720
    1821extern "C" {
    1922#include "filter.h"
     23struct PacketBuf;
    2024}
    2125using namespace std;
    2226
     
    5660};
    5761#define TCTYPESMAX 4
    5862
    59 class NuppelVideoPlayer
     63class NuppelVideoPlayer : public CCReader, public CC708Reader
    6064{
    6165 public:
    6266    NuppelVideoPlayer(QString inUseID = "Unknown",
     
    112116    void Zoom(int direction);
    113117    void ClearBookmark(void);
    114118
     119    void SetOSDFontName(const QString osdfonts[22], const QString &prefix);
     120    void SetOSDThemeName(const QString themename);
     121
    115122    // Toggle Sets
    116123    void ToggleLetterbox(int letterboxMode = -1);
    117124
     
    222229    void AddAudioData(char *buffer, int len, long long timecode);
    223230    void AddAudioData(short int *lbuffer, short int *rbuffer, int samples,
    224231                      long long timecode);
    225     void AddTextData(char *buffer, int len, long long timecode, char type);
     232    void AddTextData(unsigned char *buffer, int len,
     233                     long long timecode, char type);
    226234    void AddSubtitle(const AVSubtitle& subtitle);
    227235
     236    // ATSC EIA-708 Captions
     237    CC708Window &GetCCWin(uint service_num, uint window_id)
     238        { return CC708services[service_num].windows[window_id]; }
     239    CC708Window &GetCCWin(uint svc_num)
     240        { return GetCCWin(svc_num, CC708services[svc_num].current_window); }
     241
     242    void SetCurrentWindow(uint service_num, int window_id);
     243    void DefineWindow(uint service_num,     int window_id,
     244                      int priority,         int visible,
     245                      int anchor_point,     int anchor_vertical,
     246                      int anchor_horizontal,
     247                      int row_count,        int column_count,
     248                      int row_lock,         int column_lock,
     249                      int pen_style,        int window_style);
     250    void DeleteWindows( uint service_num,   int window_map);
     251    void DisplayWindows(uint service_num,   int window_map);
     252    void HideWindows(   uint service_num,   int window_map);
     253    void ClearWindows(  uint service_num,   int window_map);
     254    void ToggleWindows( uint service_num,   int window_map);
     255    void SetWindowAttributes(uint service_num,
     256                             int fill_color,     int fill_opacity,
     257                             int border_color,   int border_type,
     258                             int scroll_dir,     int print_dir,
     259                             int effect_dir,
     260                             int display_effect, int effect_speed,
     261                             int justify,        int word_wrap);
     262    void SetPenAttributes(uint service_num, int pen_size,
     263                          int offset,       int text_tag,  int font_tag,
     264                          int edge_type,    int underline, int italics);
     265    void SetPenColor(uint service_num,
     266                     int fg_color, int fg_opacity,
     267                     int bg_color, int bg_opacity,
     268                     int edge_color);
     269    void SetPenLocation(uint service_num, int row, int column);
     270
     271    void Delay(uint service_num, int tenths_of_seconds);
     272    void DelayCancel(uint service_num);
     273    void Reset(uint service_num);
     274    void TextWrite(uint service_num, short* unicode_string, short len);
     275
    228276    // Audio Track Selection
    229277    void incCurrentAudioTrack(void);
    230278    void decCurrentAudioTrack(void);
     
    474522    long long osdSubtitlesExpireAt;
    475523    MythDeque<AVSubtitle> nonDisplayedSubtitles;
    476524
     525    CC708Service CC708services[64];
     526    QString    osdfontname;
     527    QString    osdccfontname;
     528    QString    osd708fontnames[20];
     529    QString    osdprefix;
     530    QString    osdtheme;
     531
    477532    // OSD stuff
    478533    OSD      *osd;
    479534    OSDSet   *timedisplay;
  • libs/libmythtv/cc708window.cpp

     
     1// -*- Mode: c++ -*-
     2// Copyright (c) 2003-2005, Daniel Kristjansson
     3
     4#include <algorithm>
     5using namespace std;
     6
     7#include "cc708window.h"
     8
     9/************************************************************************
     10
     11    FCC Addons to EIA-708.
     12
     13    * Decoders must support the standard, large, and small caption sizes
     14      and must allow the caption provider to choose a size and allow the
     15      viewer to choose an alternative size.
     16
     17    * Decoders must support the eight fonts listed in EIA-708. Caption
     18      providers may specify 1 of these 8 font styles to be used to write
     19      caption text. Decoders must include the ability for consumers to
     20      choose among the eight fonts. The decoder must display the font
     21      chosen by the caption provider unless the viewer chooses a different
     22      font.
     23
     24    * Decoders must implement the same 8 character background colors
     25      as those that Section 9 requires be implemented for character
     26      foreground (white, black, red, green, blue, yellow, magenta and cyan).
     27
     28    * Decoders must implement options for altering the appearance of
     29      caption character edges.
     30
     31    * Decoders must display the color chosen by the caption provider,
     32      and must allow viewers to override the foreground and/or background
     33      color chosen by the caption provider and select alternate colors.
     34
     35    * Decoders must be capable of decoding and processing data for the
     36      six standard services, but information from only one service need
     37      be displayed at a given time.
     38
     39    * Decoders must include an option that permits a viewer to choose a
     40      setting that will display captions as intended by the caption
     41      provider (a default). Decoders must also include an option that
     42      allows a viewer's chosen settings to remain until the viewer
     43      chooses to alter these settings, including during periods when
     44      the television is turned off.
     45
     46    * Cable providers and other multichannel video programming
     47      distributors must transmit captions in a format that will be
     48      understandable to this decoder circuitry in digital cable
     49      television sets when transmitting programming to digital
     50      television devices.
     51
     52******************************************************************************/
     53
     54CC708Window::CC708Window()
     55    : priority(0),              visible(0),
     56      anchor_point(0),
     57      anchor_vertical(0),       anchor_horizontal(0),
     58      row_count(0),             column_count(0),
     59      row_lock(0),              column_lock(0),
     60      pen_style(0),             window_style(0),
     61
     62      fill_color(0),            fill_opacity(0),
     63      border_color(0),          border_type(0),
     64      scroll_dir(0),            print_dir(0),
     65      effect_dir(0),            display_effect(0),
     66      effect_speed(0),
     67      justify(0),               word_wrap(0),
     68
     69      true_row_count(0),        true_column_count(0),
     70      text(NULL),               exists(false),
     71      lock(true)
     72{
     73}
     74
     75CC708Window::~CC708Window()
     76{
     77    if (text)
     78        delete [] text;
     79}
     80
     81void CC708Window::Clear(void)
     82{
     83}
     84
     85void CC708Window::SetWindowStyle(uint style)
     86{
     87}
     88
     89void CC708Window::AddChar(QChar ch)
     90{
     91    GetCCChar().attr      = pen.attr;
     92    GetCCChar().character = ch;
     93    IncrPenLocation();
     94}
     95
     96enum
     97{
     98    LEFT_TO_RIGHT = 0,
     99    RIGHT_TO_LEFT = 1,
     100    TOP_TO_BOTTOM = 2,
     101    BOTTOM_TO_TOP = 3,
     102};
     103
     104void CC708Window::IncrPenLocation(void)
     105{
     106    // TODO: Scroll direction and up/down printing, and
     107    // word wrap not handled yet...
     108
     109    pen.column += (print_dir == LEFT_TO_RIGHT) ? +1 : 0;
     110    pen.column += (print_dir == RIGHT_TO_LEFT) ? -1 : 0;
     111    pen.row    += (print_dir == TOP_TO_BOTTOM) ? +1 : 0;
     112    pen.row    += (print_dir == BOTTOM_TO_TOP) ? -1 : 0;
     113
     114    if (1)
     115    {
     116        // basic wrapping for l->r, r->l languages
     117        if (pen.column > true_column_count - 1)
     118        {
     119            pen.column  = 0;
     120            pen.row    += 1;
     121        }
     122        else if (pen.column < 0)
     123        {
     124            pen.column  = true_column_count - 1;
     125            pen.row    -= 1;
     126        }
     127    }
     128    LimitPenLocation();
     129}
     130
     131void CC708Window::SetPenLocation(uint row, uint column)
     132{
     133    pen.row    = row;
     134    pen.column = column;
     135
     136    LimitPenLocation();
     137}
     138
     139void CC708Window::LimitPenLocation(void)
     140{
     141    // basic limiting
     142    pen.column = max(pen.column, true_column_count - 1);
     143    pen.column = min(pen.column, 0);
     144    pen.row    = max(pen.row,    true_row_count - 1);
     145    pen.row    = min(pen.row,    0);
     146}
     147
     148/***************************************************************************/
     149
     150void CC708Pen::SetPenStyle(uint style)
     151{
     152}
     153
     154CC708Character::CC708Character(const CC708Window &win)
     155{
     156    attr = win.pen.attr;
     157    character = ' ';
     158}
     159
  • libs/libmythtv/nuppeldecoder.cpp

     
    11481148            if (getrawframes)
    11491149                StoreRawData(strm);
    11501150
    1151             GetNVP()->AddTextData((char *)strm, frameheader.packetlength,
     1151            GetNVP()->AddTextData(strm, frameheader.packetlength,
    11521152                                  frameheader.timecode, frameheader.comptype);
    11531153        }
    11541154    }
     
    11661166            .arg(newKey).arg(skipFrames)
    11671167            .arg((doFlush) ? "do" : "don't")
    11681168            .arg((discardFrames) ? "do" : "don't"));
    1169    
     1169
    11701170    DecoderBase::SeekReset(newKey, skipFrames, doFlush, discardFrames);
    11711171
    11721172    if (mpa_codec && doFlush)
  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    901901    videoOutput->DrawSlice(frame, x, y, w, h);
    902902}
    903903
    904 void NuppelVideoPlayer::AddTextData(char *buffer, int len,
     904void NuppelVideoPlayer::AddTextData(unsigned char *buffer, int len,
    905905                                    long long timecode, char type)
    906906{
    907907    WrapTimecode(timecode, TC_CC);
     
    929929    }
    930930}
    931931
     932void NuppelVideoPlayer::SetCurrentWindow(uint service_num, int window_id)
     933{
     934    VERBOSE(VB_IMPORTANT, LOC + QString("SetCurrentWindow(%1, %2)")
     935            .arg(service_num).arg(window_id));
     936    CC708services[service_num].current_window = window_id;
     937}
     938
     939void NuppelVideoPlayer::DefineWindow(
     940    uint service_num,     int window_id,
     941    int priority,         int visible,
     942    int anchor_point,
     943    int anchor_vertical,  int anchor_horizontal,
     944    int row_count,        int column_count,
     945    int row_lock,         int column_lock,
     946    int pen_style,        int window_style)
     947{
     948    VERBOSE(VB_IMPORTANT, LOC +
     949            QString("DefineWindow(%1, %2)")
     950            .arg(service_num).arg(window_id) +
     951            QString("\n\t\t\t     prio %1, vis %2, ap %3, av %4, ah %5")
     952            .arg(priority).arg(visible).arg(anchor_point)
     953            .arg(anchor_vertical).arg(anchor_horizontal) +
     954            QString("\n\t\t\t     row_cnt %1, row_lck %2, "
     955                    "col_cnt %3, col_lck %4 ")
     956            .arg(row_count).arg(row_lock)
     957            .arg(column_count).arg(column_lock) +
     958            QString("\n\t\t\t     pen style %1, win style %2")
     959            .arg(pen_style).arg(window_style));
     960
     961    CC708services[service_num].current_window = window_id;
     962    CC708Window &win = GetCCWin(service_num, window_id);
     963
     964    QMutexLocker locker(&win.lock);
     965
     966    win.priority          = priority;
     967    win.visible           = visible;
     968    win.anchor_point      = anchor_point;
     969    win.anchor_vertical   = anchor_vertical;
     970    win.anchor_horizontal = anchor_horizontal;
     971    win.row_count         = row_count;
     972    win.column_count      = column_count;
     973    win.row_lock          = row_lock;
     974    win.column_lock       = column_lock;
     975
     976    if ((!pen_style && !win.exists) || pen_style)
     977        win.pen.SetPenStyle(pen_style ? pen_style : 1);
     978
     979    if ((!window_style && !win.exists) || window_style)
     980        win.SetWindowStyle(window_style ? window_style : 1);
     981
     982    // these could be bigger if row/column lock is false, resp.
     983    win.true_row_count        = row_count;
     984    win.true_column_count     = column_count;
     985
     986    if (win.text)
     987        delete [] win.text;
     988    uint num = win.true_row_count * win.true_column_count;
     989    win.text = new CC708Character[num](win);
     990
     991    win.exists            = true;
     992}
     993
     994void NuppelVideoPlayer::DeleteWindows( uint service_num,   int window_map)
     995{
     996    VERBOSE(VB_IMPORTANT, LOC + QString("DeleteWindows(%1, 0x%2)")
     997            .arg(service_num).arg(window_map,0,16));
     998
     999    for (uint i=0; i<8; i++)
     1000    {
     1001        if (i & window_map)
     1002            GetCCWin(service_num, i).exists = false;
     1003    }
     1004}
     1005
     1006void NuppelVideoPlayer::DisplayWindows(uint service_num,   int window_map)
     1007{
     1008    VERBOSE(VB_IMPORTANT, LOC + QString("DisplayWindows(%1, 0x%2)")
     1009            .arg(service_num).arg(window_map,0,16));
     1010
     1011    for (uint i=0; i<8; i++)
     1012    {
     1013        if (i & window_map)
     1014            GetCCWin(service_num, i).visible = true;
     1015    }
     1016}
     1017
     1018void NuppelVideoPlayer::HideWindows(   uint service_num,   int window_map)
     1019{
     1020    VERBOSE(VB_IMPORTANT, LOC + QString("HideWindows(%1, 0x%2)")
     1021            .arg(service_num).arg(window_map,0,16));
     1022
     1023    for (uint i=0; i<8; i++)
     1024    {
     1025        if (i & window_map)
     1026            GetCCWin(service_num, i).visible = false;
     1027    }
     1028}
     1029
     1030void NuppelVideoPlayer::ClearWindows(  uint service_num,   int window_map)
     1031{
     1032    VERBOSE(VB_IMPORTANT, LOC + QString("ClearWindows(%1, 0x%2)")
     1033            .arg(service_num).arg(window_map,0,16));
     1034
     1035    for (uint i=0; i<8; i++)
     1036    {
     1037        if (i & window_map)
     1038            GetCCWin(service_num, i).Clear();
     1039    }
     1040}
     1041
     1042void NuppelVideoPlayer::ToggleWindows( uint service_num,   int window_map)
     1043{
     1044    VERBOSE(VB_IMPORTANT, LOC + QString("ToggleWindows(%1, 0x%2)")
     1045            .arg(service_num).arg(window_map,0,16));
     1046
     1047    for (uint i=0; i<8; i++)
     1048    {
     1049        if (i & window_map)
     1050        {
     1051            GetCCWin(service_num, i).visible =
     1052                !GetCCWin(service_num, i).visible;
     1053        }
     1054    }
     1055}
     1056
     1057void NuppelVideoPlayer::SetWindowAttributes(
     1058    uint service_num,
     1059    int fill_color,     int fill_opacity,
     1060    int border_color,   int border_type,
     1061    int scroll_dir,     int print_dir,
     1062    int effect_dir,
     1063    int display_effect, int effect_speed,
     1064    int justify,        int word_wrap)
     1065{
     1066    VERBOSE(VB_IMPORTANT, LOC + QString("SetWindowAttributes(%1...)")
     1067            .arg(service_num));
     1068
     1069    CC708Window &win = GetCCWin(service_num);
     1070
     1071    win.fill_color     = fill_color;
     1072    win.fill_opacity   = fill_opacity;
     1073    win.border_color   = border_color;
     1074    win.border_type    = border_type;
     1075    win.scroll_dir     = scroll_dir;
     1076    win.print_dir      = print_dir;
     1077    win.effect_dir     = effect_dir;
     1078    win.display_effect = display_effect;
     1079    win.effect_speed   = effect_speed;
     1080    win.justify        = justify;
     1081    win.word_wrap      = word_wrap;
     1082}
     1083
     1084void NuppelVideoPlayer::SetPenAttributes(
     1085    uint service_num, int pen_size,
     1086    int offset,       int text_tag,  int font_tag,
     1087    int edge_type,    int underline, int italics)
     1088{
     1089    VERBOSE(VB_IMPORTANT, LOC + QString("SetPenAttributes(%1...)")
     1090            .arg(service_num));
     1091
     1092    CC708CharacterAttribute &attr = GetCCWin(service_num).pen.attr;
     1093
     1094    attr.pen_size  = pen_size;
     1095    attr.offset    = offset;
     1096    attr.text_tag  = text_tag;
     1097    attr.font_tag  = font_tag;
     1098    attr.edge_type = edge_type;
     1099    attr.underline = underline;
     1100    attr.italics   = italics;
     1101}
     1102
     1103void NuppelVideoPlayer::SetPenColor(
     1104    uint service_num,
     1105    int fg_color, int fg_opacity,
     1106    int bg_color, int bg_opacity,
     1107    int edge_color)
     1108{
     1109    VERBOSE(VB_IMPORTANT, LOC + QString("SetPenColor(%1...)")
     1110            .arg(service_num));
     1111
     1112    CC708CharacterAttribute &attr = GetCCWin(service_num).pen.attr;
     1113
     1114    attr.fg_color   = fg_color;
     1115    attr.fg_opacity = fg_opacity;
     1116    attr.bg_color   = bg_color;
     1117    attr.bg_opacity = bg_opacity;
     1118    attr.edge_color = edge_color;
     1119}
     1120
     1121void NuppelVideoPlayer::SetPenLocation(uint service_num, int row, int column)
     1122{
     1123    VERBOSE(VB_IMPORTANT, LOC + QString("SetPenLocation(%1, (%2x%3))")
     1124            .arg(service_num).arg(row).arg(column));
     1125    GetCCWin(service_num).SetPenLocation(row, column);
     1126}
     1127
     1128void NuppelVideoPlayer::Delay(uint service_num, int tenths_of_seconds)
     1129{
     1130    VERBOSE(VB_IMPORTANT, LOC + QString("Delay(%1, %2 seconds)")
     1131            .arg(service_num).arg(tenths_of_seconds * 0.1f));
     1132}
     1133
     1134void NuppelVideoPlayer::DelayCancel(uint service_num)
     1135{
     1136    VERBOSE(VB_IMPORTANT, LOC + QString("DelayCancel(%1)").arg(service_num));
     1137}
     1138
     1139void NuppelVideoPlayer::Reset(uint service_num)
     1140{
     1141    VERBOSE(VB_IMPORTANT, LOC + QString("Reset(%1)").arg(service_num));
     1142    DeleteWindows(service_num, 0x7);
     1143    DelayCancel(service_num);
     1144}
     1145
     1146void NuppelVideoPlayer::TextWrite(uint service_num,
     1147                                  short* unicode_string, short len)
     1148{
     1149    for (uint i = 0; i < (uint)len; i++)
     1150        GetCCWin(service_num).AddChar(QChar(unicode_string[i]));
     1151
     1152    if (GetOSD())
     1153        GetOSD()->CC708Updated();
     1154}
     1155
     1156void NuppelVideoPlayer::SetOSDFontName(const QString osdfonts[22],
     1157                                       const QString &prefix)
     1158{
     1159    osdfontname   = QDeepCopy<QString>(osdfonts[0]);
     1160    osdccfontname = QDeepCopy<QString>(osdfonts[1]);
     1161    for (int i = 2; i < 22; i++)
     1162        osd708fontnames[i - 2] = QDeepCopy<QString>(osdfonts[i]);
     1163    osdprefix = QDeepCopy<QString>(prefix);
     1164}
     1165
     1166void NuppelVideoPlayer::SetOSDThemeName(const QString themename)
     1167{
     1168    osdtheme = QDeepCopy<QString>(themename);
     1169}
     1170
     1171
    9321172void NuppelVideoPlayer::CheckPrebuffering(void)
    9331173{
    9341174    if (kVideoOutput_IVTV == forceVideoOutput)
     
    22372477        {           
    22382478            osd->DisableFade();
    22392479        }
     2480        osd->SetCC708Service(&CC708services[1]);
    22402481    }
    22412482
    22422483    playing = true;
     
    49195160    usleep(100000);
    49205161    ClearAfterSeek();
    49215162}
    4922 
  • libs/libmythtv/osd.h

     
    4646class QKeyEvent;
    4747class OSDGenericTree;
    4848class ccText;
     49class CC708Service;
    4950
    5051class OSD : public QObject
    5152{
     
    6869                     const QString &callsign, const QString &iconpath,
    6970                     int length);
    7071    void SetChannumText(const QString &text, int length);
     72
     73    // CC-608 and DVB text captions (not DVB/DVD subtitles).
    7174    void AddCCText(const QString &text, int x, int y, int color,
    7275                   bool teletextmode = false);
    7376    void ClearAllCCText();
    7477    void UpdateCCText(vector<ccText*> *ccbuf,
    75                       int replace = 0, int scroll = 0, bool scroll_prsv = false,
     78                      int replace = 0, int scroll = 0,
     79                      bool scroll_prsv = false,
    7680                      int scroll_yoff = 0, int scroll_ymax = 15);
     81    // CC-708 text captions (for ATSC)
     82    void SetCC708Service(const CC708Service *service);
     83    void CC708Updated(void);
     84
    7785    void SetSettingsText(const QString &text, int length);
    7886
    7987    void NewDialogBox(const QString &name, const QString &message,
     
    140148    QRect GetSubtitleBounds();
    141149
    142150 private:
    143     void SetDefaults();
     151    bool InitDefaults(void);
     152    bool InitCC608(void);
     153    bool InitCC708(void);
     154    bool InitDVBSub(void);
     155    bool InitMenu(void);
     156
    144157    TTFFont *LoadFont(QString name, int size);
    145158    QString FindTheme(QString name);
    146159
     
    201214
    202215    OSDListTreeType *runningTreeMenu;
    203216    QString treeMenuContainer;
     217
     218    // EIA-708 captions
     219    QString fontname;
     220    QString ccfontname;
     221    QString cc708fontnames[20];
     222    QString fontSizeType;
    204223};
    205224   
    206225#endif
  • libs/libmythtv/avformatdecoder.cpp

     
    1818#include "mythdbcon.h"
    1919#include "iso639.h"
    2020#include "pespacket.h"
     21#include "cc708decoder.h"
    2122
    2223#ifdef USING_XVMC
    2324#include "videoout_xv.h"
     
    5455void render_slice_xvmc(struct AVCodecContext *s, const AVFrame *src,
    5556                       int offset[4], int y, int type, int height);
    5657void decode_cc_dvd(struct AVCodecContext *c, const uint8_t *buf, int buf_size);
    57 void decode_cc_atsc(struct AVCodecContext *c, const uint8_t *buf, int buf_size);
     58void decode_cc_atsc(struct AVCodecContext *c,const uint8_t *buf, int buf_size);
    5859
    5960static void align_dimensions(AVCodecContext *avctx, uint &width, uint &height)
    6061{
     
    261262      lastccptsu(0),
    262263      using_null_videoout(use_null_videoout),
    263264      video_codec_id(kCodec_NONE),
    264       maxkeyframedist(-1),
    265       ccd(new CCDecoder(this)),
     265      maxkeyframedist(-1),
     266      // Closed Caption decoders
     267      ccd(new CCDecoder(parent)),     ccd708(new CC708Decoder(parent)),
    266268      // Audio
    267269      audioSamples(new short int[AVCODEC_MAX_AUDIO_FRAME_SIZE]),
    268270      allow_ac3_passthru(false),    allow_dts_passthru(false),
     
    13831385    nd->lastccptsu = utc;
    13841386}
    13851387
    1386 void decode_cc_atsc(struct AVCodecContext *s, const uint8_t *buf, int buf_size)
     1388void decode_cc_atsc(struct AVCodecContext *s, const uint8_t *buf, int sz)
    13871389{
    1388     AvFormatDecoder *nd = (AvFormatDecoder *)(s->opaque);
     1390    if (sz < 2)
     1391        return;
     1392
     1393    AvFormatDecoder *nd    = (AvFormatDecoder *)(s->opaque);
    13891394    unsigned long long utc = nd->lastccptsu;
     1395    uint buf_size          = sz;
    13901396
    1391     const uint8_t *current = buf;
    1392     int curbytes = 0;
    1393     int curcount = 0;
    1394     uint8_t data1, data2;
    1395     uint8_t cc_count;
    1396     uint8_t cc_code;
    1397     int  cc_state;
     1397    // closed caption data
     1398    //cc_data() {
     1399    // reserved                1 0.0   1 
     1400    // process_cc_data_flag    1 0.1   bslbf
     1401    bool process_cc_data = buf[0] & 0x40;
     1402    if (!process_cc_data)
     1403        return; // early exit if process_cc_data_flag false
    13981404
    1399     if (buf_size < 2)
    1400         return;
     1405    // additional_data_flag    1 0.2   bslbf
     1406    //bool additional_data = buf[0] & 0x20;
     1407    // cc_count                5 0.3   uimsbf
     1408    uint cc_count = buf[0] & 0x1f;
     1409    // reserved                8 1.0   0xff
     1410    // em_data                 8 2.0
    14011411
    1402     // check process_cc_data_flag
    1403     if (!(*current & 0x40))
    1404         return;
    1405     cc_count = *current & 0x1f;
    1406     current++;  curbytes++;
     1412    uint index    = 2; // skip reserved & em_data
     1413    uint curcount = 0;
     1414    uint cc_state = 0;
    14071415
    1408     // skip em_data
    1409     current++;  curbytes++;
    1410 
    1411     cc_state = 0;
    1412     while (curbytes < buf_size && curcount < cc_count)
     1416    while (index < buf_size && curcount < cc_count)
    14131417    {
    1414         cc_code = *current++;
    1415         curbytes++;
    1416    
    1417         if (buf_size - curbytes < 2)
     1418        if (buf_size < index + 3)
    14181419            break;
    14191420   
    1420         data1 = *current++;
    1421         data2 = *current++;
    1422         curbytes += 2;
     1421        uint cc_code = buf[index];
     1422        uint data1   = buf[index+1];
     1423        uint data2   = buf[index+2];
     1424
     1425        index += 3;
    14231426        curcount++;
    14241427
     1428        bool cc_valid = cc_code & 0x04;
     1429        uint cc_type  = cc_code & 0x03;
     1430
    14251431        // check cc_valid
    1426         if (!(cc_code & 0x04))
     1432        if (!cc_valid)
    14271433            continue;
    14281434
    1429         cc_code &= 0x03;
    1430         if (cc_code <= 0x1)
     1435        if (cc_type <= 0x1)
    14311436        {
    14321437            // EIA-608 field-1/2
    14331438            int data = (data2 << 8) | data1;
    14341439            unsigned int tc;
    14351440
    1436             if ((cc_state & cc_code) == cc_code)
     1441            if ((cc_state & cc_type) == cc_type)
    14371442            {
    14381443                // another field of same type -- assume
    14391444                // it's for the next frame
    14401445                utc += 33367;
    14411446                cc_state = 0;
    14421447            }
    1443             cc_state |= cc_code;
     1448            cc_state |= cc_type;
    14441449            tc = utc / 1000;
    14451450
    14461451            // For some reason, one frame can be out of order.
     
    14481453            // frame so we can send the correct sequence to the
    14491454            // decoder.
    14501455
    1451             if (nd->save_cctc[cc_code])
     1456            if (nd->save_cctc[cc_type])
    14521457            {
    1453                 if (nd->save_cctc[cc_code] < tc)
     1458                if (nd->save_cctc[cc_type] < tc)
    14541459                {
    14551460                    // send saved code to decoder
    1456                     nd->ccd->FormatCCField(nd->save_cctc[cc_code],
    1457                                            cc_code,
    1458                                            nd->save_ccdata[cc_code]);
    1459                     nd->save_cctc[cc_code] = 0;
     1461                    nd->ccd->FormatCCField(nd->save_cctc[cc_type],
     1462                                           cc_type,
     1463                                           nd->save_ccdata[cc_type]);
     1464                    nd->save_cctc[cc_type] = 0;
    14601465                }
    1461                 else if ((nd->save_cctc[cc_code] - tc) > 1000)
     1466                else if ((nd->save_cctc[cc_type] - tc) > 1000)
    14621467                {
    14631468                    // saved code is too far in the future; probably bad
    14641469                    // - discard it
    1465                     nd->save_cctc[cc_code] = 0;
     1470                    nd->save_cctc[cc_type] = 0;
    14661471                }
    14671472                else
    14681473                {
    14691474                    // send new code to decoder
    1470                     nd->ccd->FormatCCField(tc, cc_code, data);
     1475                    nd->ccd->FormatCCField(tc, cc_type, data);
    14711476                }
    14721477            }
    1473             if (!nd->save_cctc[cc_code])
     1478            if (!nd->save_cctc[cc_type])
    14741479            {
    14751480                // no saved code
    14761481                // - save new code since it may be out of order
    1477                 nd->save_cctc[cc_code] = tc;
    1478                 nd->save_ccdata[cc_code] = data;
     1482                nd->save_cctc[cc_type] = tc;
     1483                nd->save_ccdata[cc_type] = data;
    14791484            }
    14801485        }
    1481         else
    1482         {
    1483             // TODO:  EIA-708 DTVCC packet data
    1484         }
    1485 
     1486        else // EIA-708 CC data
     1487            nd->ccd708->decode_cc_data(cc_type, data1, data2);
    14861488    }
    14871489    nd->lastccptsu = utc;
    14881490}
     
    25152517                        continue;
    25162518                    }
    25172519
     2520#if 0
     2521                    if (mpa_pic.captions.size) {
     2522                        av_log(NULL, AV_LOG_ERROR, "picture # (%i, %i)\n",
     2523                               mpa_pic.coded_picture_number,
     2524                               mpa_pic.display_picture_number);
     2525                        m_parent->ParseATSCCaptions(&mpa_pic.captions);
     2526                    }
     2527#endif
    25182528                    VideoFrame *picframe = (VideoFrame *)(mpa_pic.opaque);
    25192529
    25202530                    if (!directrendering)
     
    28192829    return enc_len;
    28202830}
    28212831
    2822 void AvFormatDecoder::AddTextData(unsigned char *buf, int len,
    2823                                   long long timecode, char type)
    2824 {
    2825     m_parent->AddTextData((char*)buf, len, timecode, type);
    2826 }
    2827  
    28282832static int DTS_SAMPLEFREQS[16] =
    28292833{
    28302834    0,      8000,   16000,  32000,  64000,  128000, 11025,  22050,
  • libs/libmythtv/osdtypes.cpp

     
    11#include <qimage.h>
    22#include <qmap.h>
    33#include <qregexp.h>
    4 #include <math.h>
     4#include <cmath>
    55
    66#include <iostream>
    77using namespace std;
     
    18971897        }
    18981898    }
    18991899}
     1900
     1901OSDType708CC::OSDType708CC(const QString &name, TTFFont *fonts[60],
     1902                           int xoff, int yoff, int dispw, int disph) :
     1903    OSDType(name)
     1904{
     1905    xoffset = xoff;
     1906    yoffset = yoff;
     1907    displaywidth  = dispw;
     1908    displayheight = disph;
     1909
     1910    int c[4] = {0, 85, 170, 255};
     1911
     1912    for (int i = 0; i < 64; i++)
     1913        colors[i].setRgb(c[(i>>4)&3], c[(i>>2)&3], c[i&3]);
     1914
     1915    for (int i = 0; i < 60; i++)
     1916        m_fonts[i] = fonts[i];
     1917}
     1918
     1919void OSDType708CC::Draw(OSDSurface *surface, int /*fade*/,
     1920                        int /*maxfade*/, int /*xoff*/, int /*yoff*/)
     1921{
     1922    int ccx = 0, ccy = 0;
     1923    //TODO
     1924    //VERBOSE(VB_IMPORTANT, "Draw()");
     1925    /*
     1926    int x = (ccx + 3) * displaywidth / 36 + xoffset;
     1927    int y = ccy * displayheight / 17 + yoffset;
     1928    int textlength = 0;
     1929    QString m_message("test");
     1930    TTFFont* font = m_fonts[0];
     1931    font->CalcWidth(m_message, &textlength);
     1932    int maxx = x + textlength;
     1933    int maxy = y + font->Size() * 3 / 2;
     1934    font->DrawString(surface, x, y + 2, m_message, maxx, maxy, 255);
     1935    */
     1936    QRect rect = QRect(0, 0, 100, 25);
     1937    OSDTypeBox *m_box = new OSDTypeBox("cc_background", rect);
     1938    m_box->SetRect(rect);
     1939
     1940    m_box->Draw(surface, 0, 0, displaywidth - 2, displayheight - 2);
     1941    delete m_box;
     1942}
     1943
     1944
     1945
     1946
     1947
     1948
     1949
     1950
     1951
     1952
     1953
     1954
     1955
     1956
     1957
     1958
     1959
     1960
     1961
     1962
     1963
     1964
     1965
     1966/*
     1967void OSDType708CC::DefineWindow(
     1968    int window_id,    int priority,        int visible,
     1969    int anchor_id,    int anchor_vertical, int anchor_horizontal,
     1970    int row_count,    int col_count,       int row_lock, int col_lock,
     1971    int pen_style,    int window_style)
     1972{
     1973    QString str("DefineWindow(%1, %2, %3,  %4, %5, %6");
     1974    str.arg(window_id).arg(priority).arg(visible)
     1975       .arg(anchor_id).arg(anchor_vertical).arg(anchor_horizontal);
     1976    str.append(QString("%1, %2, %3, %4, %5, %6)")
     1977               .arg(row_count).arg(col_count).arg(row_lock).arg(col_lock)
     1978               .arg(pen_style).arg(window_style));
     1979
     1980    m_current_window = window_id;
     1981
     1982    Window708 win = m_windows[m_current_window];
     1983    win.anchorPoint =
     1984    QPoint(anchor_horizontal, anchor_vertical);
     1985    win.priority  = priority;
     1986    win.visible   = visible;
     1987    win.anchor_id = anchor_id;
     1988    win.row_count = row_count;
     1989    win.col_count = col_count;
     1990    win.row_lock  = row_lock;
     1991    win.col_lock  = col_lock;
     1992
     1993    if (pen_style>0)
     1994    {
     1995        win.curPen.font.setStyleHint(
     1996            (pen_style<4) ? QFont::Serif : QFont::SansSerif);
     1997        win.curPen.font.setFixedPitch((pen_style&1));
     1998        win.curPen.textTag           = 0;    // dialog text
     1999        win.curPen.font.setPointSize(24);    // standard font size
     2000        win.curPen.offset            = 1;    // normal
     2001        win.curPen.font.setItalic(false);
     2002        win.curPen.font.setUnderline(false);
     2003        win.curPen.edgeType          = 0;    // none
     2004        win.curPen.foregroundColor   = Qt::white;
     2005        win.curPen.edgeColor         = Qt::black;
     2006        win.curPen.backgroundColor   = Qt::black;
     2007        win.curPen.foregroundOpacity = 3;    // solid
     2008        win.curPen.backgroundOpacity = (pen_style>5) ? 0:3; // transparent:solid
     2009    }
     2010
     2011    if (window_style>0)
     2012    {
     2013        win.justify   = (3==window_style || 6==window_style) ? 2:0; // center:left
     2014        win.printDir  = (7==window_style) ? 2 : 0; // Top-to-Bottom:Left-to-Right
     2015        win.scrollDir = (7==window_style) ? 1 : 3; // Right-to-Left:Bottom-to-Top
     2016        win.wordWrap  = (4<=window_style && window_style<=6) ? true : false;
     2017        win.displayEffect = 0; // Snap
     2018        win.effectDir     = 0;
     2019        win.effectSpeed   = 0;
     2020        win.fillColor     = Qt::black;
     2021        win.fillOpacity   = (2==window_style || 5==window_style) ? 0:3; // transparent:solid
     2022        win.borderType    = 0; // none
     2023    }
     2024    VERBOSE(VB_IMPORTANT, str);
     2025}
     2026*/
     2027/*
     2028void OSDType708CC::SetWindowAttributes(int fill_color,     int fill_opacity,
     2029                                       int border_color,   int border_type,
     2030                                       int scroll_dir,     int print_dir,
     2031                                       int effect_dir,
     2032                                       int display_effect, int effect_speed,
     2033                                       int justify,        int word_wrap)
     2034{
     2035    VERBOSE(VB_IMPORTANT, "SetWindowAttributes()");
     2036    if (m_current_window>=0)
     2037    {
     2038        Window708 &win = m_windows[m_current_window];
     2039        win.fillColor     = colors[fill_color&0x3f];
     2040        win.borderColor   = colors[border_color&0x3f];
     2041        win.fillOpacity   = fill_opacity;
     2042        win.borderType    = border_type;
     2043        win.scrollDir     = scroll_dir;
     2044        win.printDir      = print_dir;
     2045        win.effectDir     = effect_dir;
     2046        win.displayEffect = display_effect;
     2047        win.effectSpeed   = effect_speed;
     2048        win.justify       = justify;
     2049        win.wordWrap      = word_wrap;
     2050    }
     2051}
     2052
     2053void OSDType708CC::SetPenAttributes(int pen_size,
     2054                                    int offset,    int text_tag,  int font_tag,
     2055                                    int edge_type, int underline, int italics)
     2056{
     2057    int pointSize[4] = { 18, 24, 30, 24 };
     2058    VERBOSE(VB_IMPORTANT, "SetPenAttributes()");
     2059    if (m_current_window>=0)
     2060    {
     2061        QFont::StyleHint stylemap[8] =
     2062        {
     2063            QFont::AnyStyle,  QFont::Serif,     QFont::Serif,
     2064            QFont::SansSerif, QFont::SansSerif, QFont::Decorative,
     2065            QFont::Decorative, QFont::Decorative
     2066        };
     2067        bool mono[8] = { true, true, false, true, false, false, false, false };
     2068        Pen708 &pen = m_windows[m_current_window].curPen;
     2069        pen.font.setStyleHint(stylemap[font_tag]);
     2070        pen.font.setFixedPitch(mono[font_tag]);
     2071
     2072        pen.font.setPointSize(pointSize[pen_size]);
     2073        pen.font.setUnderline(underline);
     2074        pen.font.setItalic(italics);
     2075        pen.offset = offset;
     2076        pen.textTag = text_tag;
     2077        pen.edgeType = edge_type;
     2078    }
     2079}
     2080*/
     2081/*
     2082void OSDType708CC::SetPenColor(int fg_color,   int fg_opacity,
     2083                               int bg_color,   int bg_opacity,
     2084                               int edge_color)
     2085{
     2086    VERBOSE(VB_IMPORTANT, QString("SetPenColor()"));
     2087    if (m_current_window>=0)
     2088    {
     2089        Pen708 &pen = m_windows[m_current_window].curPen;
     2090        pen.foregroundColor   = colors[fg_color&0x3f];
     2091        pen.backgroundColor   = colors[bg_color&0x3f];
     2092        pen.edgeColor         = colors[edge_color&0x3f];
     2093        pen.foregroundOpacity = fg_opacity;
     2094        pen.backgroundOpacity = bg_opacity;
     2095    }
     2096}
     2097*/
     2098/*
     2099void OSDType708CC::SetPenLocation(int row, int column)
     2100{
     2101    VERBOSE(VB_IMPORTANT, QString("SetPenLocation(%1, %2)").arg(row).arg(column));
     2102    m_windows[m_current_window].cursorPoint = QPoint(column, row);
     2103}
     2104*/
     2105/*
     2106void OSDType708CC::Delay(int tenths_of_seconds)
     2107{
     2108    VERBOSE(VB_IMPORTANT, QString("Delay(%1)").arg(0.1*tenths_of_seconds));
     2109}
     2110
     2111void OSDType708CC::DelayCancel()
     2112{
     2113    VERBOSE(VB_IMPORTANT, "DelayCancel()");
     2114}
     2115*/
     2116/*
     2117void OSDType708CC::Reset()
     2118{
     2119    VERBOSE(VB_IMPORTANT, "Reset()");
     2120    for (int i=0; i<8; i++)
     2121    {
     2122        Pen708 &pen = m_windows[i].curPen;
     2123        pen.offset   = 1;
     2124        pen.textTag  = 0;
     2125        pen.edgeType = 0;
     2126        pen.font.setStyleHint(QFont::Serif);
     2127        pen.font.setFixedPitch(false);
     2128        pen.font.setItalic(false);
     2129        pen.font.setBold(false);
     2130        pen.font.setUnderline(false);
     2131        pen.font.setPointSize(24);
     2132    }
     2133}
     2134*/
     2135/*
     2136void OSDType708CC::AddCCText(QString str)
     2137{
     2138    VERBOSE(VB_IMPORTANT, QString("AddCCText(%1)").arg(str));
     2139}
     2140*/
  • libs/libmythtv/libmythtv.pro

     
    9191HEADERS += recordingtypes.h         jobqueue.h
    9292HEADERS += filtermanager.h          recordingprofile.h
    9393HEADERS += remoteencoder.h          videosource.h
    94 HEADERS += ccdecoder.h
     94HEADERS += ccdecoder.h              cc708decoder.h
     95HEADERS += cc708window.h
    9596HEADERS += sr_dialog.h              sr_root.h
    9697HEADERS += sr_items.h               scheduledrecording.h
    9798HEADERS += signalmonitorvalue.h     viewschdiff.h
     
    108109SOURCES += recordingtypes.cpp       jobqueue.cpp
    109110SOURCES += filtermanager.cpp        recordingprofile.cpp
    110111SOURCES += remoteencoder.cpp        videosource.cpp
    111 SOURCES += ccdecoder.cpp
     112SOURCES += ccdecoder.cpp            cc708decoder.cpp
     113SOURCES += cc708window.cpp
    112114SOURCES += sr_dialog.cpp            sr_root.cpp
    113115SOURCES += sr_items.cpp             scheduledrecording.cpp
    114116SOURCES += signalmonitorvalue.cpp
  • libs/libmythtv/osdtypes.h

     
    88#include <vector>
    99#include <qobject.h>
    1010#include <qregexp.h>
     11#include <qcolor.h>
     12#include <qfont.h>
     13#include "cc708window.h"
    1114
    1215using namespace std;
    1316
     
    467470
    468471    int xoffset, yoffset, displaywidth, displayheight;
    469472};
     473/*
     474class Pen708 {
     475    friend class OSDType708CC;
     476  private:
     477    QFont  font;
     478    QColor foregroundColor;
     479    QColor backgroundColor;
     480    QColor edgeColor;
     481    int offset;
     482    int textTag;
     483    int edgeType;
     484    int foregroundOpacity; // also used for edge opacity
     485    int backgroundOpacity;
     486};
    470487
     488class Window708 {
     489    friend class OSDType708CC;
     490  private:
     491    Window708() : anchorPoint(0,0), fillColor("black"), borderColor("white") {}
     492    ~Window708() {}
     493
     494    // Pen Attributes
     495    QPoint cursorPoint;
     496    QPoint anchorPoint;
     497    Pen708 curPen;
     498
     499    QColor fillColor;
     500    QColor borderColor;
     501    int fillOpacity;
     502    int borderType;
     503    int scrollDir;
     504    int printDir;
     505    int effectDir;
     506    int displayEffect;
     507    int effectSpeed;
     508    int justify;
     509    bool wordWrap;
     510
     511    int priority; // higher is better
     512    int visible;
     513    int anchor_id;
     514    int row_count;
     515    int col_count;
     516    bool row_lock;
     517    bool col_lock;
     518};
     519*/
     520class OSDType708CC : public OSDType
     521{
     522  public:
     523    OSDType708CC(const QString &name, TTFFont *fonts[60],
     524                 int xoff, int yoff, int dispw, int disph);
     525    virtual ~OSDType708CC() {}
     526
     527    void SetCCService(const CC708Service *service)
     528        { cc708data = service; }
     529
     530    void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
     531  private:
     532    const CC708Service *cc708data;
     533
     534    TTFFont *m_fonts[60];
     535    QColor   colors[64];
     536
     537    int xoffset, yoffset, displaywidth, displayheight;
     538};
     539
    471540#endif
  • libs/libmythtv/avformatdecoder.h

     
    1515#include "../libavformat/avformat.h"
    1616}
    1717
     18class CC708Decoder;
    1819class ProgramInfo;
    1920class MythSqlDatabase;
    2021
     
    7677/// The AvFormatDecoder is used to decode non-NuppleVideo files.
    7778/// It's used a a decoder of last resort after trying the NuppelDecoder
    7879/// and IvtvDecoder (if "USING_IVTV" is defined).
    79 class AvFormatDecoder : public DecoderBase, public CCReader
     80class AvFormatDecoder : public DecoderBase
    8081{
    8182    friend void HandleStreamChange(void*);
    8283  public:
     
    232233
    233234    // Caption/Subtitle/Teletext decoders
    234235    CCDecoder        *ccd;
     236    CC708Decoder     *ccd708;
    235237
    236238    // Audio
    237239    short int        *audioSamples;
  • libs/libmythtv/cc708window.h

     
     1// -*- Mode: c++ -*-
     2// Copyright (c) 2003-2005, Daniel Kristjansson
     3
     4#ifndef _CC708_WINDOW_
     5#define _CC708_WINDOW_
     6
     7#include <qstring.h>
     8#include <qmutex.h>
     9
     10class CC708CharacterAttribute
     11{
     12  public:
     13    int pen_size;
     14    int offset;
     15    int text_tag;
     16    int font_tag;
     17    int edge_type;
     18    int underline;
     19    int italics;
     20
     21    int fg_color;
     22    int fg_opacity;
     23    int bg_color;
     24    int bg_opacity;
     25    int edge_color;
     26};
     27
     28class CC708Pen
     29{
     30  public:
     31    void SetPenStyle(uint style);
     32  public:
     33    CC708CharacterAttribute attr;
     34
     35    int row;
     36    int column;
     37};
     38
     39class CC708Window;
     40class CC708Character
     41{
     42  public:
     43    CC708Character(const CC708Window &win);
     44    CC708CharacterAttribute attr;
     45    QChar character;
     46};
     47
     48class CC708Window
     49{
     50  public:
     51    CC708Window();
     52    ~CC708Window();
     53
     54    void Clear(void);
     55    void SetWindowStyle(uint);
     56
     57    void AddChar(QChar);
     58    void IncrPenLocation(void);
     59    void SetPenLocation(uint, uint);
     60    void LimitPenLocation(void);
     61
     62    CC708Character &GetCCChar(void)
     63        { return text[pen.row * true_column_count + pen.column]; }
     64
     65  public:
     66    int priority;
     67    int visible;
     68    int anchor_point;
     69    int anchor_vertical;
     70    int anchor_horizontal;
     71    int row_count;
     72    int column_count;
     73    int row_lock;
     74    int column_lock;
     75    int pen_style;
     76    int window_style;
     77
     78    int fill_color;
     79    int fill_opacity;
     80    int border_color;
     81    int border_type;
     82    int scroll_dir;
     83    int print_dir;
     84    int effect_dir;
     85    int display_effect;
     86    int effect_speed;
     87    int justify;
     88    int word_wrap;
     89
     90    int true_row_count;
     91    int true_column_count;
     92    CC708Character *text;
     93    CC708Pen        pen;
     94
     95    /// set to false when DeleteWindow is called on the window.
     96    bool            exists;
     97
     98    mutable QMutex  lock;
     99};
     100
     101class CC708Service
     102{
     103  public:
     104    int current_window;
     105    CC708Window windows[8];
     106};
     107
     108#endif // _CC708_WINDOW_
  • libs/libmythtv/cc708decoder.cpp

     
     1// -*- Mode: c++ -*-
     2// Copyright (c) 2003-2005, Daniel Kristjansson
     3
     4#include <cassert>
     5
     6#include "mythcontext.h"
     7#include "cc708decoder.h"
     8
     9#define LOC QString("CC708: ")
     10#define LOC_ERR QString("CC708, Error: ")
     11
     12#define DEBUG_CC_SERVICE_2     0
     13#define DEBUG_CC_RAWPACKET     0
     14#define DEBUG_CC_SERVICE_BLOCK 0
     15
     16typedef enum
     17{
     18    NTSC_CC_f1         = 0,
     19    NTSC_CC_f2         = 1,
     20    DTVCC_PACKET_DATA  = 2,
     21    DTVCC_PACKET_START = 3,
     22};
     23
     24const char* cc_types[4] =
     25{
     26    "NTSC line 21 field 1 closed captions"
     27    "NTSC line 21 field 2 closed captions"
     28    "DTVCC Channel Packet Data"
     29    "DTVCC Channel Packet Start"
     30};
     31
     32static void parse_cc_packet(CC708Reader *cb_cbs, CaptionPacket *pkt);
     33
     34CC708Reader::CC708Reader()
     35{
     36    for (uint i=0; i<64; i++)
     37    {
     38        buf_alloc[i] = 512;
     39        buf[i]       = (unsigned char*) malloc(buf_alloc[i]);
     40        buf_size[i]  = 0;
     41        delayed[i]   = 0;
     42
     43        temp_str_alloc[i] = 512;
     44        temp_str_size[i]  = 0;
     45        temp_str[i]       = (short*) malloc(temp_str_alloc[i] * sizeof(short));
     46    }
     47}
     48
     49CC708Reader::~CC708Reader()
     50{
     51}
     52
     53void CC708Decoder::decode_cc_data(uint cc_type, uint data1, uint data2)
     54{
     55    if (DTVCC_PACKET_START == cc_type)
     56    {
     57        //VERBOSE(VB_IMPORTANT, LOC + QString("CC ST data(0x%1 0x%2)")
     58        //        .arg(data1,0,16).arg(data2,0,16));
     59
     60        if (partialPacket.size && reader)
     61            parse_cc_packet(reader, &partialPacket);
     62
     63        partialPacket.data[0] = data1;
     64        partialPacket.data[1] = data2;
     65        partialPacket.size   = 2;
     66    }
     67    else if (DTVCC_PACKET_DATA == cc_type)
     68    {
     69        //VERBOSE(VB_IMPORTANT, LOC + QString("CC Ex data(0x%1 0x%2)")
     70        //        .arg(data1,0,16).arg(data2,0,16));
     71
     72        partialPacket.data[partialPacket.size + 0] = data1;
     73        partialPacket.data[partialPacket.size + 1] = data2;
     74        partialPacket.size += 2;
     75    }
     76}
     77
     78#define DEBUG_CAPTIONS 0
     79
     80typedef enum
     81{
     82    NUL  = 0x00,
     83    EXT1 = 0x01,
     84    ETX  = 0x03,
     85    BS   = 0x08,
     86    FF   = 0x0C,
     87    CR   = 0x0D,
     88    HCR  = 0x0E,
     89    P16  = 0x18,
     90} C0;
     91
     92typedef enum
     93{
     94    CW0=0x80, CW1, CW2, CW3, CW4, CW5, CW6, CW7,     
     95    CLW,      DSW, HDW, TGW, DLW, DLY, DLC, RST,
     96    SPA=0x90, SPC, SPL,                     SWA=0x97,
     97    DF0,      DF1, DF2, DF3, DF4, DF5, DF6, DF7,
     98} C1;
     99
     100extern ushort CCtableG0[0x60];
     101extern ushort CCtableG1[0x60];
     102extern ushort CCtableG2[0x60];
     103extern ushort CCtableG3[0x60];
     104
     105static void append_character(CC708Reader *cc, uint service_num, short ch);
     106static void parse_cc_service_stream(CC708Reader *cc, uint service_num);
     107static int handle_cc_c0_ext1_p16(CC708Reader *cc, uint service_num, int i);
     108static int handle_cc_c1(CC708Reader *cc, uint service_num, int i);
     109static int handle_cc_c2(CC708Reader *cc, uint service_num, int i);
     110static int handle_cc_c3(CC708Reader *cc, uint service_num, int i);
     111
     112#define SEND_STR \
     113do { \
     114    if (cc->temp_str_size[service_num]) \
     115    { \
     116        cc->TextWrite(service_num, \
     117                      cc->temp_str[service_num], \
     118                      cc->temp_str_size[service_num]); \
     119        cc->temp_str_size[service_num] = 0; \
     120    } \
     121} while (0)
     122
     123static void parse_cc_service_stream(CC708Reader* cc, uint service_num)
     124{
     125    const int blk_size = cc->buf_size[service_num];
     126    int blk_start = 0, i = 0;
     127
     128    for (i = 0; i < blk_size; i++)
     129    {
     130        if (RST == cc->buf[service_num][i])
     131        {       
     132            fprintf(stderr, "Reset i(%i)\n", i);
     133            cc->Reset(service_num);
     134            blk_start = i+1;
     135            cc->delayed[service_num] = 0;
     136            break;
     137        }
     138        else if (DLC == cc->buf[service_num][i])
     139        {
     140            fprintf(stderr, "DelayCancel i(%i)\n", i);
     141            cc->DelayCancel(service_num);
     142            cc->delayed[service_num] = 0;
     143            break;
     144        }
     145    }
     146    if (cc->buf_size[service_num] >= 126)
     147        cc->delayed[service_num] = 0;
     148   
     149/*
     150  av_log(NULL, AV_LOG_ERROR,
     151  "cc_ss delayed(%i) blk_start(%i) blk_size(%i)\n",
     152  cc->delayed, blk_start, blk_size);
     153*/
     154
     155    for (int i = (cc->delayed[service_num]) ? blk_size : blk_start;
     156         i < blk_size; )
     157    {
     158        const int old_i = i;
     159        const int code = cc->buf[service_num][i];
     160        //fprintf(stderr, "cc(0x%x,i%i) ", code, i);
     161        if (0x0 == code)
     162        {
     163            i++;
     164        }
     165        else if (code <= 0x1f)
     166        {
     167            // C0 code -- ASCII commands + ext1: C2,C3,G2,G3 + p16: 16 chars
     168            i = handle_cc_c0_ext1_p16(cc, service_num, i);
     169        }
     170        else if (code <= 0x7f)
     171        {
     172            // G0 code -- mostly ASCII printables
     173            short character = CCtableG0[code-0x20];
     174            append_character(cc, service_num, character);
     175            i++;
     176        }
     177        else if (code <= 0x9f)
     178        {
     179            // C1 code -- caption control codes
     180            i = handle_cc_c1(cc, service_num, i);
     181        }
     182        else if (code <= 0xff)
     183        {
     184            // G1 code -- ISO 8859-1 Latin 1 characters
     185            short character = CCtableG1[code-0xA0];
     186            append_character(cc, service_num, character);
     187            i++;
     188        }
     189        if ((old_i == i) || cc->delayed[service_num])
     190            break;
     191    }
     192
     193    assert(((int)cc->buf_size[service_num]-i)>=0);
     194    if ((cc->buf_size[service_num]-i)>0)
     195    {
     196        memmove(cc->buf[service_num], cc->buf[service_num]+i, cc->buf_size[service_num]-i);
     197        cc->buf_size[service_num] -= i;
     198    }
     199    else
     200    {
     201        if (0!=(cc->buf_size[service_num]-i))
     202        {
     203            fprintf(stderr, "parse_cc_service_stream buffer error "
     204                    "i(%i) buf_size(%i)\n", i, cc->buf_size[service_num]);
     205            for (i=0; (uint)i<cc->buf_size[service_num]; i++)
     206                fprintf(stderr, "0x%x ", cc->buf[service_num][i]);
     207            fprintf(stderr, "\n");
     208        }
     209        cc->buf_size[service_num] = 0;
     210    }
     211}
     212
     213static int handle_cc_c0_ext1_p16(CC708Reader* cc, uint service_num, int i)
     214{
     215    // C0 code -- subset of ASCII misc. control codes
     216    const int code = cc->buf[service_num][i];
     217    if (code<=0xf)
     218    {
     219        // single byte code
     220        if (ETX==code)
     221            SEND_STR;
     222        else if (BS==code)
     223            append_character(cc, service_num, 0x08);
     224        else if (FF==code)
     225            append_character(cc, service_num, 0x0c);
     226        else if (CR==code)
     227            append_character(cc, service_num, 0x0d);
     228        else if (HCR==code)
     229            append_character(cc, service_num, 0x0d);
     230        i++;
     231    }
     232    else if (code<=0x17)
     233    {
     234        // double byte code
     235        const int blk_size = cc->buf_size[service_num];
     236        if (EXT1==code && ((i+1)<blk_size))
     237        {
     238            const int code2 = cc->buf[service_num][i+1];
     239            if (code2<=0x1f)
     240            {
     241                // C2 code -- nothing in EIA-708-A
     242                i = handle_cc_c2(cc, service_num, i+1);
     243            }
     244            else if (code2<=0x7f)
     245            {
     246                // G2 code -- fractions, drawing, symbols
     247                append_character(cc, service_num, CCtableG2[code2-0x20]);
     248                i+=2;
     249            }
     250            else if (code2<=0x9f)
     251            {
     252                // C3 code -- nothing in EIA-708-A
     253                i = handle_cc_c3(cc, service_num, i);
     254            }
     255            else if (code2<=0xff)
     256            {
     257                // G3 code -- one symbol in EIA-708-A "[cc]"
     258                append_character(cc, service_num, CCtableG3[code2-0xA0]);
     259                i+=2;
     260            }
     261        }
     262        else if ((i+1)<blk_size)
     263            i+=2;
     264    }
     265    else if (code<=0x1f)
     266    {
     267        // triple byte code
     268        const int blk_size = cc->buf_size[service_num];
     269        if (P16==code && ((i+2)<blk_size))
     270        {
     271            // reserved for large alphabets, but not yet defined
     272        }
     273        if ((i+2)<blk_size)
     274            i+=3;
     275    }
     276    return i;
     277}
     278
     279static int handle_cc_c1(CC708Reader* cc, uint service_num, int i)
     280{
     281    const int blk_size = cc->buf_size[service_num];
     282    const int code = cc->buf[service_num][i];
     283
     284    //fprintf(stderr, "handle_cc_c1(0x%x, %i, %i)\n", code, i, blk_size);
     285    const unsigned char* blk_buf = cc->buf[service_num];
     286    if (code<=CW7)
     287    { // no paramaters
     288        SEND_STR;
     289        cc->SetCurrentWindow(service_num, code-0x80);
     290        i+=1;
     291    }
     292    else if (DLC == cc->buf[service_num][i])
     293    {
     294        fprintf(stderr, "DelayCancel i(%i)\n", i);
     295        cc->DelayCancel(service_num);
     296        cc->delayed[service_num] = 0;
     297        i+=1;
     298    }
     299    else if (code>=CLW && code<=DLY && ((i+1)<blk_size))
     300    { // 1 byte of paramaters
     301        int param1 = blk_buf[i+1];
     302        SEND_STR;
     303        if (CLW==code)
     304            cc->ClearWindows(service_num, param1);
     305        else if (DSW==code)
     306            cc->DisplayWindows(service_num, param1);
     307        else if (HDW==code)
     308            cc->HideWindows(service_num, param1);
     309        else if (TGW==code)
     310            cc->ToggleWindows(service_num, param1);
     311        else if (DLW==code)
     312            cc->DeleteWindows(service_num, param1);
     313        else if (DLY==code)
     314        {
     315            fprintf(stderr, "Delay()");
     316            cc->Delay(service_num, param1);
     317            cc->delayed[service_num] = 1;
     318        }
     319        i+=2;
     320    }
     321    else if (SPA==code && ((i+2)<blk_size))
     322    {
     323        int pen_size  = (blk_buf[i+1]   ) & 0x3;
     324        int offset    = (blk_buf[i+1]>>2) & 0x3;
     325        int text_tag  = (blk_buf[i+1]>>4) & 0xf;
     326        int font_tag  = (blk_buf[i+2]   ) & 0x7;
     327        int edge_type = (blk_buf[i+2]>>3) & 0x7;
     328        int underline = (blk_buf[i+2]>>4) & 0x1;
     329        int italic    = (blk_buf[i+2]>>5) & 0x1;
     330        SEND_STR;
     331        //fprintf(stderr, "set_pen_attr(0x%08x)(0x%08x, 0x%02x, 0x%02x)\n",
     332        //        cc->SetPenAttributes, cc, blk_buf[i+1], blk_buf[i+2]);
     333        cc->SetPenAttributes(service_num, pen_size, offset, text_tag,
     334                             font_tag, edge_type, underline, italic);
     335        i+=3;
     336    }
     337    else if (SPC==code && ((i+3)<blk_size))
     338    {
     339        int fg_color   = (blk_buf[i+1]   ) & 0x3f;
     340        int fg_opacity = (blk_buf[i+1]>>6) & 0x03;
     341        int bg_color   = (blk_buf[i+2]   ) & 0x3f;
     342        int bg_opacity = (blk_buf[i+2]>>6) & 0x03;
     343        int edge_color = (blk_buf[i+3]>>6) & 0x3f;
     344        SEND_STR;
     345        //fprintf(stderr, "set_pen_color(0x%08x)(0x%08x, 0x%02x, 0x%02x, 0x%02x)\n",
     346        //        cc->SetPenColor, cc, blk_buf[i+1], blk_buf[i+2], blk_buf[i+3]);
     347        cc->SetPenColor(service_num, fg_color, fg_opacity,
     348                        bg_color, bg_opacity, edge_color);
     349        i+=4;
     350    }
     351    else if (SPL==code && ((i+2)<blk_size))
     352    {
     353        int row = blk_buf[i+1] & 0x0f;
     354        int col = blk_buf[i+2] & 0x3f;
     355        SEND_STR;
     356        //fprintf(stderr, "set_pen_loc(0x%08x)(0x%08x, 0x%02x, 0x%02x)\n",
     357        //        cc->SetPenLocation, cc, blk_buf[i+1], blk_buf[i+2]);
     358        cc->SetPenLocation(service_num, row, col);
     359        i+=3;
     360    }
     361    else if (SWA==code && ((i+4)<blk_size))
     362    {
     363        int fill_color    = (blk_buf[i+1]   ) & 0x3f;
     364        int fill_opacity  = (blk_buf[i+1]>>6) & 0x03;
     365        int border_color  = (blk_buf[i+2]   ) & 0x3f;
     366        int border_type01 = (blk_buf[i+2]>>6) & 0x03;
     367        int justify       = (blk_buf[i+3]   ) & 0x03;
     368        int scroll_dir    = (blk_buf[i+3]>>2) & 0x03;
     369        int print_dir     = (blk_buf[i+3]>>4) & 0x03;
     370        int word_wrap     = (blk_buf[i+3]>>6) & 0x01;
     371        int border_type   = (blk_buf[i+3]>>5) | border_type01;
     372        int display_eff   = (blk_buf[i+4]   ) & 0x03;
     373        int effect_dir    = (blk_buf[i+4]>>2) & 0x03;
     374        int effect_speed  = (blk_buf[i+4]>>4) & 0x0f;
     375        SEND_STR;
     376        //fprintf(stderr, "set_win_attr(0x%08x)(0x%08x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",
     377        //        cc->SetWindowAttributes, cc, blk_buf[i+1], blk_buf[i+2], blk_buf[i+3], blk_buf[i+4]);
     378        cc->SetWindowAttributes(
     379            service_num, fill_color, fill_opacity, border_color, border_type,
     380            scroll_dir,     print_dir,    effect_dir,
     381            display_eff,    effect_speed, justify, word_wrap);
     382        i+=5;
     383    }
     384    else if ((code>=DF0) && (code<=DF7) && ((i+6)<blk_size))
     385    {
     386        //fprintf(stderr, "define_window(%i)\n", code-0x98);
     387        // param1
     388        int priority = ( blk_buf[i+1]  ) & 0x7;
     389        int col_lock = (blk_buf[i+1]>>3) & 0x1;
     390        int row_lock = (blk_buf[i+1]>>4) & 0x1;
     391        int visible  = (blk_buf[i+1]>>5) & 0x1;
     392        // param2
     393        int anchor_vertical = blk_buf[i+2] & 0x7f;
     394        int relative_pos = (blk_buf[i+2]>>7);
     395        (void) relative_pos;
     396        // param3
     397        int anchor_horizontal = blk_buf[i+3];
     398        // param4
     399        int row_count = blk_buf[i+4] & 0xf;
     400        int anchor_point = blk_buf[i+4]>>4;
     401        // param5
     402        int col_count = blk_buf[i+5] & 0x3f;
     403        // param6
     404        int pen_style = blk_buf[i+6] & 0x7;
     405        int win_style = (blk_buf[i+6]>>3) & 0x7;
     406        SEND_STR;
     407        cc->DefineWindow(service_num, code-0x98, priority, visible,
     408                         anchor_point, anchor_vertical, anchor_horizontal,
     409                         row_count, col_count, row_lock, col_lock,
     410                         pen_style, win_style);
     411        i+=7;
     412    }
     413    else
     414    {
     415        fprintf(stderr, "handle_cc_c1: (NOT HANDLED) "
     416                "code(0x%02x) i(%i) blk_size(%i)\n", code, i, blk_size);
     417    }
     418    //fprintf(stderr, "handle_cc_c1, returning %i\n", i);
     419    return i;
     420}
     421
     422static int handle_cc_c2(CC708Reader* cc, uint service_num, int i)
     423{
     424    const int blk_size = cc->buf_size[service_num];
     425    const int code = cc->buf[service_num][i+1];
     426    fprintf(stderr, "handle_cc_C2(0x%x)\n", code);
     427    if ((code<=0x7) && ((i+1)<blk_size)){
     428        i+=2;
     429        SEND_STR;
     430    }
     431    else if ((code<=0xf) && ((i+2)<blk_size))
     432    {
     433        i+=3;
     434        SEND_STR;
     435    }
     436    else if ((code<=0x17) && ((i+3)<blk_size))
     437    {
     438        i+=4;
     439        SEND_STR;
     440    }
     441    else if ((code<=0x1f) && ((i+4)<blk_size))
     442    {
     443        i+=5;
     444        SEND_STR;
     445    }
     446    return i;
     447}
     448
     449static int handle_cc_c3(CC708Reader* cc, uint service_num, int i)
     450{
     451    const unsigned char* blk_buf = cc->buf[service_num];
     452    const int blk_size = cc->buf_size[service_num];
     453    const int code = cc->buf[service_num][i+1];
     454
     455    fprintf(stderr, "handle_cc_C3(0x%x)\n", code);
     456    if ((code<=0x87) && ((i+5)<blk_size))
     457    {
     458        i+=6;
     459        SEND_STR;
     460    }
     461    else if ((code<=0x8f) && ((i+6)<blk_size))
     462    {
     463        i+=7;
     464        SEND_STR;
     465    }
     466    else if ((i+2)<blk_size)
     467    { // varible length commands
     468        int length = blk_buf[i+2]&0x3f;
     469        if ((i+length)<blk_size)
     470        {
     471            i+=1+length;
     472            SEND_STR;
     473        }
     474    }
     475    return i;
     476}
     477
     478static void append_cc(CC708Reader* cc, uint service_num,
     479                      const unsigned char* blk_buf, int block_size)
     480{
     481    assert(cc);
     482    assert(block_size + cc->buf_size[service_num] <
     483           cc->buf_alloc[service_num]);
     484
     485    memcpy(cc->buf[service_num] + cc->buf_size[service_num],
     486           blk_buf, block_size);
     487
     488    cc->buf_size[service_num] += block_size;
     489#if DEBUG_CC_SERVICE_2
     490    {
     491        uint i;
     492        fprintf(stderr, "append_cc: ");
     493        for (i = 0; i < cc->buf_size[service_num]; i++)
     494            fprintf(stderr, "0x%x ", cc->buf[service_num][i]);
     495        fprintf(stderr, "\n");
     496    }
     497#endif
     498    parse_cc_service_stream(cc, service_num);
     499}
     500
     501static void parse_cc_packet(CC708Reader* cb_cbs, CaptionPacket* pkt)
     502{
     503    const unsigned char* pkt_buf = pkt->data;
     504    const int pkt_size = pkt->size;
     505    int off = 1;
     506    int service_number = 0;
     507    int block_data_offset = 0;
     508    int len = ((((int)pkt_buf[0])&0x3f)*2-1)&0xff;
     509    int seq_num = (((int)pkt_buf[0])>>6)&0x3;
     510
     511#if DEBUG_CC_RAWPACKET
     512    {
     513        int j;
     514        fprintf(stderr, "CC length(%2i) seq_num(%i) ", len, seq_num);
     515        for (j=1; j<pkt_size; j++)
     516            fprintf(stderr, "0x%x ", pkt_buf[j]);
     517        fprintf(stderr, "\n");
     518    }
     519#else
     520    (void) seq_num;
     521#endif
     522
     523    assert(pkt_size<127);
     524    assert(len<128);
     525
     526    while (pkt_buf[off] && off<pkt_size)
     527    { // service_block
     528        int block_size = pkt_buf[off] & 0x1f;
     529        service_number = (pkt_buf[off]>>5) & 0x7;
     530        block_data_offset = (0x7==service_number && block_size!=0) ? off+2 : off+1;
     531#if DEBUG_CC_SERVICE_BLOCK
     532        fprintf(stderr, "service_block size(%i) num(%i) off(%i) ",
     533                block_size, service_number, block_data_offset);
     534#endif
     535        if (off+2 == block_data_offset)
     536        {
     537            int extended_service_number = pkt_buf[off+2] & 0x3f;
     538#if DEBUG_CC_SERVICE_BLOCK
     539            fprintf(stderr, "ext_svc_num(%i) ", extended_service_number);
     540#endif
     541            service_number =  extended_service_number;
     542        }
     543        if (service_number)
     544        {
     545#if DEBUG_CC_SERVICE
     546            int i;
     547            if (!(2==block_size &&
     548                  0==pkt_buf[block_data_offset] &&
     549                  0==pkt_buf[block_data_offset+1]))
     550            {
     551                fprintf(stderr, "service %i: ", service_number);
     552                for (i=0; i<block_size; i++)
     553                    fprintf(stderr, "0x%x ", pkt_buf[block_data_offset+i]);
     554                fprintf(stderr, "\n");
     555            }
     556#endif
     557            append_cc(cb_cbs, service_number,
     558                      &pkt_buf[block_data_offset], block_size);
     559        }
     560        off+=block_size+1;
     561    }
     562    if (off<pkt_size) // must end in null service block, if packet is not full.
     563        assert(pkt_buf[off]==0);
     564}
     565
     566static void append_character(CC708Reader *cc, uint service_num, short ch)
     567{
     568    if (cc->temp_str_size[service_num]+2 > cc->temp_str_alloc[service_num])
     569    {
     570        int new_alloc = (cc->temp_str_alloc[service_num]) ?
     571            cc->temp_str_alloc[service_num] * 2 : 64;
     572
     573        cc->temp_str[service_num] = (short*)
     574            realloc(cc->temp_str[service_num], new_alloc * sizeof(short));
     575
     576        assert(cc->temp_str[service_num]);
     577        cc->temp_str_alloc[service_num] = new_alloc; // shorts allocated
     578    }
     579
     580    if (cc->temp_str[service_num])
     581    {
     582        int i = cc->temp_str_size[service_num];
     583        cc->temp_str[service_num][i] = ch;
     584        cc->temp_str_size[service_num]++;
     585    }
     586    else
     587    {
     588        cc->temp_str_size[service_num] = 0;
     589        cc->temp_str_alloc[service_num]=0;
     590    }
     591}
     592
     593ushort CCtableG0[0x60] =
     594{
     595//   0    1    2    3       4    5    6    7
     596//   8    9    a    b       c    d    e    f 
     597    ' ', '!','\"', '#',    '$', '%', '&', '\'', /* 0x20-0x27 */
     598    '(', ')', '*', '+',    ',', '-', '.', '/',  /* 0x28-0x2f */
     599    '0', '1', '2', '3',    '4', '5', '6', '7',  /* 0x30-0x37 */
     600    '8', '9', ':', ';',    '<', '=', '>', '?',  /* 0x38-0x3f */
     601
     602    '@', 'A', 'B', 'C',    'D', 'E', 'F', 'G',  /* 0x40-0x47 */
     603    'H', 'I', 'J', 'K',    'L', 'M', 'N', 'O',  /* 0x48-0x4f */
     604    'P', 'Q', 'R', 'S',    'T', 'U', 'V', 'W',  /* 0x50-0x57 */
     605    'X', 'Y', 'Z', '[',    '\\',']', '^', '_',  /* 0x58-0x5f */
     606
     607    '`', 'a', 'b', 'c',    'd', 'e', 'f', 'g',  /* 0x60-0x67 */
     608    'h', 'i', 'j', 'k',    'l', 'm', 'n', 'o',  /* 0x68-0x6f */
     609    'p', 'q', 'r', 's',    't', 'u', 'v', 'w',  /* 0x70-0x77 */
     610    'x', 'y', 'z', '{',    '|', '}', '~',  0x1d16, // music note /* 0x78-0x7f */
     611};
     612
     613ushort CCtableG1[0x60] =
     614{
     615//   0    1    2    3       4    5    6    7
     616//   8    9    a    b       c    d    e    f 
     617    0xA0, // unicode non-breaking space
     618         '¡', '¢', '£',    '€', '¥', 'Š', '§', /* 0xa0-0xa7 */
     619    'š', '©', 'ª', '«',    '¬', '­', '®', '¯', /* 0xa8-0xaf */
     620    '°', '±', '²', '³',    'Ž', 'µ', '¶', '·', /* 0xb0-0xb7 */
     621    'ž', '¹', 'º', '»',    'Œ', 'œ', 'Ÿ', '¿', /* 0xbf-0xbf */
     622
     623    'À', 'Á', 'Â', 'Ã',    'Ä', 'Å', 'Æ', 'Ç', /* 0xc0-0xc7 */
     624    'È', 'É', 'Ê', 'Ë',    'Ì', 'Í', 'Î', 'Ï', /* 0xcf-0xcf */
     625    'Ð', 'Ñ', 'Ò', 'Ó',    'Ô', 'Õ', 'Ö', '×', /* 0xd0-0xd7 */
     626    'Ø', 'Ù', 'Ú', 'Û',    'Ü', 'Ý', 'Þ', 'ß', /* 0xdf-0xdf */
     627
     628    'à', 'á', 'â', 'ã',    'ä', 'å', 'æ', 'ç', /* 0xe0-0xe7 */
     629    'è', 'é', 'ê', 'ë',    'ì', 'í', 'î', 'ï', /* 0xef-0xef */
     630    'ð', 'ñ', 'ò', 'ó',    'ô', 'õ', 'ö', '÷', /* 0xf0-0xf7 */
     631    'ø', 'ù', 'ú', 'û',    'ü', 'ý', 'þ', 'ÿ', /* 0xff-0xff */
     632};
     633
     634ushort CCtableG2[0x60] =
     635{
     636    ' ', /* transparent space */
     637                        0xA0, /* non-breaking transparent space */
     638    0,                  0,                     /* 0x20-0x23 */
     639    0,                  0x2026,/* elipsis */
     640    0,                  0,                     /* 0x24-0x27 */
     641    0,                  0,
     642    0x160,/*S under \/*/0,                     /* 0x28-0x2b */
     643    0x152, /* CE */     0,
     644    0,                  0,                     /* 0x2c-0x2f */
     645    0x2DA, /*super dot*/0x2018,/* open ' */
     646    0x2019,/*close ' */ 0x201c,/* open " */    /* 0x30-0x33 */
     647    0x201d,/*close " */ '*',   /* dot */
     648    0,                  0,                     /* 0x34-0x37 */
     649    0,                  '#',   /* super TM */
     650    0x161,/*s under \/*/0,                     /* 0x38-0x3b */
     651    0x153, /* ce */     '#',   /* super SM */
     652    0,                  0x178,/*Y w/umlout*/   /* 0x3c-0x3f */
     653   
     654//  0         1         2         3
     655//  4         5         6         7
     656//  8         9         a         b
     657//  c         d         e         f 
     658    0,        0,        0,        0,
     659    0,        0,        0,        0, /* 0x40-0x47 */
     660    0,        0,        0,        0,
     661    0,        0,        0,        0, /* 0x48-0x4f */
     662
     663    0,        0,        0,        0,
     664    0,        0,        0,        0, /* 0x50-0x57 */
     665    0,        0,        0,        0,
     666    0,        0,        0,        0, /* 0x58-0x5f */
     667
     668    0,        0,        0,        0,
     669    0,        0,        0,        0, /* 0x60-0x67 */
     670    0,        0,        0,        0,
     671    0,        0,        0,        0, /* 0x68-0x6f */
     672
     673    0,                  0,
     674    0,                  0,           /* 0x70-0x73 */
     675    0,                  0,
     676    0x215b, /* 1/8 */   0x215c, /* 3/8 */    /* 0x74-0x77 */
     677    0x215d, /* 5/8 */   0x215e, /* 7/8 */
     678    0x2502, /*line | */ 0x2510, /*line ~| */ /* 0x78-0x7b */
     679    0x2514, /*line |_*/ 0x2500, /*line -*/
     680    0x2518, /*line _|*/ 0x250c, /*line |~ */ /* 0x7c-0x7f */
     681};
     682
     683ushort CCtableG3[0x60] =
     684{
     685//   0 1  2  3    4  5  6  7     8  9  a  b    c  d  e  f 
     686    '#', /* [CC] closed captioning logo */
     687       0, 0, 0,   0, 0, 0, 0,    0, 0, 0, 0,   0, 0, 0, 0, /* 0xa0-0xaf */
     688    0, 0, 0, 0,   0, 0, 0, 0,    0, 0, 0, 0,   0, 0, 0, 0, /* 0xb0-0xbf */
     689
     690    0, 0, 0, 0,   0, 0, 0, 0,    0, 0, 0, 0,   0, 0, 0, 0, /* 0xc0-0xcf */
     691    0, 0, 0, 0,   0, 0, 0, 0,    0, 0, 0, 0,   0, 0, 0, 0, /* 0xd0-0xdf */
     692
     693    0, 0, 0, 0,   0, 0, 0, 0,    0, 0, 0, 0,   0, 0, 0, 0, /* 0xe0-0xff */
     694    0, 0, 0, 0,   0, 0, 0, 0,    0, 0, 0, 0,   0, 0, 0, 0, /* 0xf0-0xff */
     695};
  • libs/libmythtv/osd.cpp

     
    2828
    2929#include "osdlistbtntype.h"
    3030
     31static char  *cc708_default_font_names[20];
     32static bool   cc708_defaults_initialized = false;
     33static QMutex cc708_init_lock;
     34static void initialize_osd_fonts(void);
     35
    3136static float sq(float a) { return a*a; }
    3237
     38#define LOC QString("OSD: ")
     39#define LOC_ERR QString("OSD, Error: ")
     40
    3341OSD::OSD(const QRect &osd_bounds, int   frameRate,
    3442         const QRect &vis_bounds, float visibleAspect, float fontScaling)
    3543    : QObject(),
     
    4856      changed(false),                     runningTreeMenu(NULL),
    4957      treeMenuContainer("")
    5058{
     59    if (!cc708_defaults_initialized)
     60        initialize_osd_fonts();
     61
     62    for (uint i = 0; i < 20; i++)
     63        cc708fontnames[i] = cc708_default_font_names[i];
     64
    5165    needPillarBox = visibleAspect > 1.51f;
    5266    wscale = visibleAspect / 1.3333f;
    5367    // adjust for wscale font size scaling
     
    5771    {
    5872        VERBOSE(VB_IMPORTANT, "Couldn't find OSD theme: "
    5973                <<gContext->GetSetting("OSDTheme"));
    60         SetDefaults();
     74        InitDefaults();
    6175        return;
    6276    }
    6377
     
    6781        VERBOSE(VB_IMPORTANT, "Couldn't load OSD theme: "
    6882                <<gContext->GetSetting("OSDTheme")<<" at "<<themepath);
    6983    }
    70     SetDefaults();
     84    InitDefaults();
    7185
    72     // Reinit since LoadThemes and SetDefaults() appear to mess things up.
     86    // Reinit since LoadThemes and InitDefaults() appear to mess things up.
    7387    Reinit(osd_bounds, frameRate, vis_bounds, visibleAspect, fontScaling);
    7488}
    7589
     
    113127    }
    114128}
    115129
    116 void OSD::SetDefaults(void)
     130bool OSD::InitDefaults(void)
    117131{
     132    bool ok = true;
     133    ok &= InitCC608();
     134    ok &= InitCC708();
     135    ok &= InitMenu();
     136    ok &= InitDVBSub();
     137    return ok;
     138}
     139
     140bool OSD::InitCC608(void)
     141{
     142    // EIA-608 captions
    118143    TTFFont *ccfont = GetFont("cc_font");
    119144    if (!ccfont)
    120145    {
     
    128153    }
    129154
    130155    if (!ccfont)
    131         return;
     156        return false;
    132157
    133158    OSDSet *container = GetSet("cc_page");
    134159    if (!container)
     
    157182                                          sub_dispw, sub_disph);
    158183        container->AddType(ccpage);
    159184    }
     185    return true;
     186}
    160187
    161     container = GetSet("menu");
     188bool OSD::InitCC708(void)
     189{
     190    VERBOSE(VB_IMPORTANT, LOC + "InitCC708() -- begin");
     191    // EIA-708 captions
     192    // Check if cc708 osd already exits, exit early if it does
     193    QString name("cc708_page");
     194    OSDSet *container = GetSet(name);
     195    if (container)
     196    {
     197        VERBOSE(VB_IMPORTANT, LOC + "InitCC708() -- end (already exits)");
     198        return true;
     199    }
     200
     201    // Create fonts...
     202    TTFFont* ccfonts[60];
     203    for (uint i = 0; i < 60; i++)
     204    {
     205        TTFFont *ccfont = GetFont("cc_font");
     206        //TTFFont *ccfont = GetFont(QString("cc708_font%1").arg(i));
     207        if (!ccfont)
     208        {
     209            QString name = QString("cc708_font%1").arg(i);
     210            int fontsizes[3] = { 480/36, 480/27, 480/20 };
     211            int fontsize = fontsizes[i%3];
     212            ccfont = LoadFont(gContext->GetSetting("OSDCCFont")
     213                              /*cc708fontnames[i/3]*/, fontsize);
     214            if (ccfont)
     215                fontMap[name] = ccfont;
     216            if (!ccfont)
     217            {
     218                VERBOSE(VB_IMPORTANT, LOC_ERR + "A CC708 font is missing");
     219                return false;
     220            }
     221            ccfonts[i] = ccfont;
     222        }
     223    }
     224
     225    // Create a container for one service
     226    container = new OSDSet(
     227        name, true, osdBounds.width(), osdBounds.height(),
     228        wmult, hmult, frameint);
     229    container->SetPriority(30);
     230
     231    AddSet(container, name);
     232    OSDType708CC *ccpage =
     233        new OSDType708CC(name, ccfonts, xoffset, yoffset,
     234                         displaywidth, displayheight);
     235    container->AddType(ccpage);
     236
     237    VERBOSE(VB_IMPORTANT, LOC + "InitCC708() -- end");
     238    return true;
     239}
     240
     241bool OSD::InitMenu(void)
     242{
     243    // Menu
     244    OSDSet *container = GetSet("menu");
    162245    if (!container)
    163246    {
    164247        QString name = "menu";
     
    208291
    209292        container->AddType(lb);
    210293    }
     294    return true;
     295}
    211296
     297bool OSD::InitDVBSub(void)
     298{
    212299    // Create container for subtitles
    213     container = GetSet("subtitles");
     300    OSDSet *container = GetSet("subtitles");
    214301    if (!container)
    215302    {
    216303        QString name = "subtitles";
     
    220307        container->SetPriority(30);
    221308        AddSet(container, name);
    222309    }
     310    return true;
    223311}
    224312
    225313void OSD::Reinit(const QRect &totalBounds,   int   frameRate,
     
    16641752    osdlock.unlock();
    16651753}
    16661754
     1755void OSD::SetCC708Service(const CC708Service *service)
     1756{
     1757    QMutexLocker locker(&osdlock);
     1758
     1759    VERBOSE(VB_IMPORTANT, "SetCC708Service() -- 1");
     1760
     1761    OSDSet *container = GetSet("cc708_page");
     1762    if (!container)
     1763    {
     1764        VERBOSE(VB_IMPORTANT, "SetCC708Service() -- can't find container");
     1765        return;
     1766    }
     1767
     1768    OSDType *type = container->GetType("cc708_page");
     1769    OSDType708CC *ccpage = (OSDType708CC*) type;
     1770    if (!ccpage)
     1771    {
     1772        VERBOSE(VB_IMPORTANT, "SetCC708Service() -- no OSDType708CC");
     1773        return;
     1774    }
     1775
     1776    VERBOSE(VB_IMPORTANT, "SetCC708Service() -- 2");
     1777    ccpage->SetCCService(service);
     1778    container->Display(1/*visible*/);
     1779    m_setsvisible = true;
     1780    changed = true;
     1781}
     1782
     1783void OSD::CC708Updated(void)
     1784{
     1785    QMutexLocker locker(&osdlock);
     1786
     1787    OSDSet *container = GetSet("cc708_page");
     1788    if (!container)
     1789        return;
     1790
     1791    OSDType *type = container->GetType("cc708_page");
     1792    OSDType708CC *ccpage = dynamic_cast<OSDType708CC*>(type);
     1793    if (ccpage)
     1794    {
     1795        container->Display(1/*visible*/);
     1796        m_setsvisible = true;
     1797        changed = true;
     1798    }
     1799}
     1800
    16671801void OSD::SetSettingsText(const QString &text, int length)
    16681802{
    16691803    HideAllExcept("settings");
     
    24132547{
    24142548    return QRect(xoffset, yoffset, displaywidth, displayheight);
    24152549}
     2550
     2551static void initialize_osd_fonts(void)
     2552{
     2553    QMutexLocker locker(&cc708_init_lock);
     2554    if (cc708_defaults_initialized)
     2555        return;
     2556    cc708_defaults_initialized = true;
     2557
     2558    cc708_default_font_names[0]  = strdup(gContext->GetSetting(
     2559        "OSDCC708MonoSerifFont"));
     2560    cc708_default_font_names[1]  = strdup(gContext->GetSetting(
     2561        "OSDCC708MonoSerifItalicFont"));
     2562    cc708_default_font_names[2]  = strdup(gContext->GetSetting(
     2563        "OSDCC708PropSerifFont"));
     2564    cc708_default_font_names[3]  = strdup(gContext->GetSetting(
     2565        "OSDCC708PropSerifItalicFont"));
     2566
     2567    cc708_default_font_names[4]  = strdup(gContext->GetSetting(
     2568        "OSDCC708MonoSansSerifFont"));
     2569    cc708_default_font_names[5]  = strdup(gContext->GetSetting(
     2570        "OSDCC708MonoSansSerifItalicFont"));
     2571    cc708_default_font_names[6]  = strdup(gContext->GetSetting(
     2572        "OSDCC708PropSansSerifFont"));
     2573    cc708_default_font_names[7]  = strdup(gContext->GetSetting(
     2574        "OSDCC708PropSansSerifItalicFont"));
     2575
     2576    cc708_default_font_names[8]  = strdup(gContext->GetSetting(
     2577        "OSDCC708MonoCasualFont"));
     2578    cc708_default_font_names[9]  = strdup(gContext->GetSetting(
     2579        "OSDCC708MonoCasualItalicFont"));
     2580    cc708_default_font_names[10] = strdup(gContext->GetSetting(
     2581        "OSDCC708PropCasualFont"));
     2582    cc708_default_font_names[11] = strdup(gContext->GetSetting(
     2583        "OSDCC708PropCasualItalicFont"));
     2584
     2585    cc708_default_font_names[12] = strdup(gContext->GetSetting(
     2586        "OSDCC708MonoCursiveFont"));
     2587    cc708_default_font_names[13] = strdup(gContext->GetSetting(
     2588        "OSDCC708MonoCursiveItalicFont"));
     2589    cc708_default_font_names[14] = strdup(gContext->GetSetting(
     2590        "OSDCC708PropCursiveFont"));
     2591    cc708_default_font_names[15] = strdup(gContext->GetSetting(
     2592        "OSDCC708PropCursiveItalicFont"));
     2593
     2594    cc708_default_font_names[16] = strdup(gContext->GetSetting(
     2595        "OSDCC708MonoCapitalsFont"));
     2596    cc708_default_font_names[17] = strdup(gContext->GetSetting(
     2597        "OSDCC708MonoCapitalsItalicFont"));
     2598    cc708_default_font_names[18] = strdup(gContext->GetSetting(
     2599        "OSDCC708PropCapitalsFont"));
     2600    cc708_default_font_names[19] = strdup(gContext->GetSetting(
     2601        "OSDCC708PropCapitalsItalicFont"));
     2602}
  • libs/libmythtv/cc708decoder.h

     
     1// -*- Mode: c++ -*-
     2// Copyright (c) 2003-2005, Daniel Kristjansson
     3
     4#ifndef CC708DECODER_H_
     5#define CC708DECODER_H_
     6
     7#include <stdint.h>
     8
     9#include <qstringlist.h>
     10
     11#include "format.h"
     12
     13#ifndef __CC_CALLBACKS_H__
     14/** EIA-708-A closed caption packet */
     15typedef struct CaptionPacket
     16{
     17    unsigned char data[128+16];
     18    int size;
     19} CaptionPacket;
     20#endif
     21
     22class CC708Reader
     23{
     24  public:
     25    CC708Reader();
     26    virtual ~CC708Reader();
     27
     28    // Window settings
     29    virtual void SetCurrentWindow(uint service_num, int window_id) = 0;
     30    virtual void DefineWindow(uint service_num,     int window_id,
     31                              int priority,         int visible,
     32                              int anchor_point,     int anchor_vertical,
     33                              int anchor_horizontal,
     34                              int row_count,        int column_count,
     35                              int row_lock,         int column_lock,
     36                              int pen_style,        int window_style) = 0;
     37    virtual void DeleteWindows( uint service_num,   int window_map) = 0;
     38    virtual void DisplayWindows(uint service_num,   int window_map) = 0;
     39    virtual void HideWindows(   uint service_num,   int window_map) = 0;
     40    virtual void ClearWindows(  uint service_num,   int window_map) = 0;
     41    virtual void ToggleWindows( uint service_num,   int window_map) = 0;
     42    virtual void SetWindowAttributes(uint service_num,
     43                                     int fill_color,     int fill_opacity,
     44                                     int border_color,   int border_type,
     45                                     int scroll_dir,     int print_dir,
     46                                     int effect_dir,
     47                                     int display_effect, int effect_speed,
     48                                     int justify,        int word_wrap) = 0;
     49
     50    // Pen settings
     51    virtual void SetPenAttributes(uint service_num,
     52                                  int pen_size,  int offset,
     53                                  int text_tag,  int font_tag,
     54                                  int edge_type,
     55                                  int underline, int italics) = 0;
     56    virtual void SetPenColor(uint service_num,
     57                             int fg_color, int fg_opacity,
     58                             int bg_color, int bg_opacity,
     59                             int edge_color) = 0;
     60    virtual void SetPenLocation(uint service_num, int row, int column) = 0;
     61
     62    // Display State
     63    virtual void Delay(uint service_num, int tenths_of_seconds) = 0;
     64    virtual void DelayCancel(uint service_num) = 0;
     65    virtual void Reset(uint service_num) = 0;
     66
     67    // Text
     68    virtual void TextWrite(uint service_num,
     69                           short* unicode_string, short len) = 0;
     70
     71    // Data
     72    unsigned char* buf[64];
     73    uint   buf_alloc[64];
     74    uint   buf_size[64];
     75    bool   delayed[64];
     76
     77    short* temp_str[64];
     78    int    temp_str_alloc[64];
     79    int    temp_str_size[64];
     80};
     81
     82class CC708Decoder
     83{
     84  public:
     85    CC708Decoder(CC708Reader *ccr) : reader(ccr)
     86        { bzero(&partialPacket, sizeof(CaptionPacket)); }
     87
     88    ~CC708Decoder();
     89
     90    void decode_cc_data(uint cc_type, uint data1, uint data2);
     91
     92  private:
     93    CaptionPacket  partialPacket;
     94    CC708Reader   *reader;
     95};
     96
     97#endif // CC708DECODER_H_
  • libs/libavcodec/mpeg12.c

     
    29892989        }
    29902990    } else if (len >= 3 &&
    29912991               p[0] == 'C' && p[1] == 'C') {
     2992        /* parse DVD Closed Caption data */
    29922993        p += 2;
    29932994        len -= 2;
    29942995        avctx->decode_cc_dvd(avctx, p, len);
    29952996    } else if (len >= 6 &&
    2996                p[0] == 0x47 && p[1] == 0x41 && p[2] == 0x39 && p[3] == 0x34 &&
    2997                p[4] == 0x03) {
    2998         p += 5;
    2999         len -= 5;
    3000         avctx->decode_cc_atsc(avctx, p, len);
     2997               p[0] == 'G' && p[1] == 'A' && p[2] == '9' && p[3] == '4') {
     2998        /* parse ATSC info (EIA-708 Closed Captions && letterbox info) */
     2999        int user_data_type_code = p[4];
     3000        if (user_data_type_code == 0x03) { // caption data
     3001            p += 5;
     3002            len -= 5;
     3003            avctx->decode_cc_atsc(avctx, p, len);
     3004        }
     3005        else if (user_data_type_code == 0x06) {
     3006            // bar data (letterboxing info)
     3007        }
    30013008    }
    30023009}
    30033010