Ticket #1095: eit708-v2.patch
File eit708-v2.patch, 76.6 KB (added by , 20 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.h
14 14 #include "recordingprofile.h" 15 15 #include "videooutbase.h" 16 16 #include "tv_play.h" 17 #include "ccdecoder.h" 18 #include "cc708decoder.h" 19 #include "cc708window.h" 17 20 18 21 extern "C" { 19 22 #include "filter.h" 23 struct PacketBuf; 20 24 } 21 25 using namespace std; 22 26 … … 56 60 }; 57 61 #define TCTYPESMAX 4 58 62 59 class NuppelVideoPlayer 63 class NuppelVideoPlayer : public CCReader, public CC708Reader 60 64 { 61 65 public: 62 66 NuppelVideoPlayer(QString inUseID = "Unknown", … … 112 116 void Zoom(int direction); 113 117 void ClearBookmark(void); 114 118 119 void SetOSDFontName(const QString osdfonts[22], const QString &prefix); 120 void SetOSDThemeName(const QString themename); 121 115 122 // Toggle Sets 116 123 void ToggleLetterbox(int letterboxMode = -1); 117 124 … … 222 229 void AddAudioData(char *buffer, int len, long long timecode); 223 230 void AddAudioData(short int *lbuffer, short int *rbuffer, int samples, 224 231 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); 226 234 void AddSubtitle(const AVSubtitle& subtitle); 227 235 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 228 276 // Audio Track Selection 229 277 void incCurrentAudioTrack(void); 230 278 void decCurrentAudioTrack(void); … … 474 522 long long osdSubtitlesExpireAt; 475 523 MythDeque<AVSubtitle> nonDisplayedSubtitles; 476 524 525 CC708Service CC708services[64]; 526 QString osdfontname; 527 QString osdccfontname; 528 QString osd708fontnames[20]; 529 QString osdprefix; 530 QString osdtheme; 531 477 532 // OSD stuff 478 533 OSD *osd; 479 534 OSDSet *timedisplay; -
libs/libmythtv/cc708window.cpp
1 // -*- Mode: c++ -*- 2 // Copyright (c) 2003-2005, Daniel Kristjansson 3 4 #include <algorithm> 5 using 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 54 CC708Window::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 75 CC708Window::~CC708Window() 76 { 77 if (text) 78 delete [] text; 79 } 80 81 void CC708Window::Clear(void) 82 { 83 } 84 85 void CC708Window::SetWindowStyle(uint style) 86 { 87 } 88 89 void CC708Window::AddChar(QChar ch) 90 { 91 GetCCChar().attr = pen.attr; 92 GetCCChar().character = ch; 93 IncrPenLocation(); 94 } 95 96 enum 97 { 98 LEFT_TO_RIGHT = 0, 99 RIGHT_TO_LEFT = 1, 100 TOP_TO_BOTTOM = 2, 101 BOTTOM_TO_TOP = 3, 102 }; 103 104 void 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 131 void CC708Window::SetPenLocation(uint row, uint column) 132 { 133 pen.row = row; 134 pen.column = column; 135 136 LimitPenLocation(); 137 } 138 139 void 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 150 void CC708Pen::SetPenStyle(uint style) 151 { 152 } 153 154 CC708Character::CC708Character(const CC708Window &win) 155 { 156 attr = win.pen.attr; 157 character = ' '; 158 } 159 -
libs/libmythtv/nuppeldecoder.cpp
1148 1148 if (getrawframes) 1149 1149 StoreRawData(strm); 1150 1150 1151 GetNVP()->AddTextData( (char *)strm, frameheader.packetlength,1151 GetNVP()->AddTextData(strm, frameheader.packetlength, 1152 1152 frameheader.timecode, frameheader.comptype); 1153 1153 } 1154 1154 } … … 1166 1166 .arg(newKey).arg(skipFrames) 1167 1167 .arg((doFlush) ? "do" : "don't") 1168 1168 .arg((discardFrames) ? "do" : "don't")); 1169 1169 1170 1170 DecoderBase::SeekReset(newKey, skipFrames, doFlush, discardFrames); 1171 1171 1172 1172 if (mpa_codec && doFlush) -
libs/libmythtv/NuppelVideoPlayer.cpp
901 901 videoOutput->DrawSlice(frame, x, y, w, h); 902 902 } 903 903 904 void NuppelVideoPlayer::AddTextData( char *buffer, int len,904 void NuppelVideoPlayer::AddTextData(unsigned char *buffer, int len, 905 905 long long timecode, char type) 906 906 { 907 907 WrapTimecode(timecode, TC_CC); … … 929 929 } 930 930 } 931 931 932 void 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 939 void 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 994 void 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 1006 void 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 1018 void 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 1030 void 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 1042 void 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 1057 void 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 1084 void 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 1103 void 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 1121 void 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 1128 void 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 1134 void NuppelVideoPlayer::DelayCancel(uint service_num) 1135 { 1136 VERBOSE(VB_IMPORTANT, LOC + QString("DelayCancel(%1)").arg(service_num)); 1137 } 1138 1139 void 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 1146 void 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 1156 void 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 1166 void NuppelVideoPlayer::SetOSDThemeName(const QString themename) 1167 { 1168 osdtheme = QDeepCopy<QString>(themename); 1169 } 1170 1171 932 1172 void NuppelVideoPlayer::CheckPrebuffering(void) 933 1173 { 934 1174 if (kVideoOutput_IVTV == forceVideoOutput) … … 2237 2477 { 2238 2478 osd->DisableFade(); 2239 2479 } 2480 osd->SetCC708Service(&CC708services[1]); 2240 2481 } 2241 2482 2242 2483 playing = true; … … 4919 5160 usleep(100000); 4920 5161 ClearAfterSeek(); 4921 5162 } 4922 -
libs/libmythtv/osd.h
46 46 class QKeyEvent; 47 47 class OSDGenericTree; 48 48 class ccText; 49 class CC708Service; 49 50 50 51 class OSD : public QObject 51 52 { … … 68 69 const QString &callsign, const QString &iconpath, 69 70 int length); 70 71 void SetChannumText(const QString &text, int length); 72 73 // CC-608 and DVB text captions (not DVB/DVD subtitles). 71 74 void AddCCText(const QString &text, int x, int y, int color, 72 75 bool teletextmode = false); 73 76 void ClearAllCCText(); 74 77 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, 76 80 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 77 85 void SetSettingsText(const QString &text, int length); 78 86 79 87 void NewDialogBox(const QString &name, const QString &message, … … 140 148 QRect GetSubtitleBounds(); 141 149 142 150 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 144 157 TTFFont *LoadFont(QString name, int size); 145 158 QString FindTheme(QString name); 146 159 … … 201 214 202 215 OSDListTreeType *runningTreeMenu; 203 216 QString treeMenuContainer; 217 218 // EIA-708 captions 219 QString fontname; 220 QString ccfontname; 221 QString cc708fontnames[20]; 222 QString fontSizeType; 204 223 }; 205 224 206 225 #endif -
libs/libmythtv/avformatdecoder.cpp
18 18 #include "mythdbcon.h" 19 19 #include "iso639.h" 20 20 #include "pespacket.h" 21 #include "cc708decoder.h" 21 22 22 23 #ifdef USING_XVMC 23 24 #include "videoout_xv.h" … … 54 55 void render_slice_xvmc(struct AVCodecContext *s, const AVFrame *src, 55 56 int offset[4], int y, int type, int height); 56 57 void decode_cc_dvd(struct AVCodecContext *c, const uint8_t *buf, int buf_size); 57 void decode_cc_atsc(struct AVCodecContext *c, 58 void decode_cc_atsc(struct AVCodecContext *c,const uint8_t *buf, int buf_size); 58 59 59 60 static void align_dimensions(AVCodecContext *avctx, uint &width, uint &height) 60 61 { … … 261 262 lastccptsu(0), 262 263 using_null_videoout(use_null_videoout), 263 264 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)), 266 268 // Audio 267 269 audioSamples(new short int[AVCODEC_MAX_AUDIO_FRAME_SIZE]), 268 270 allow_ac3_passthru(false), allow_dts_passthru(false), … … 1383 1385 nd->lastccptsu = utc; 1384 1386 } 1385 1387 1386 void decode_cc_atsc(struct AVCodecContext *s, const uint8_t *buf, int buf_size)1388 void decode_cc_atsc(struct AVCodecContext *s, const uint8_t *buf, int sz) 1387 1389 { 1388 AvFormatDecoder *nd = (AvFormatDecoder *)(s->opaque); 1390 if (sz < 2) 1391 return; 1392 1393 AvFormatDecoder *nd = (AvFormatDecoder *)(s->opaque); 1389 1394 unsigned long long utc = nd->lastccptsu; 1395 uint buf_size = sz; 1390 1396 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 1398 1404 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 1401 1411 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; 1407 1415 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) 1413 1417 { 1414 cc_code = *current++; 1415 curbytes++; 1416 1417 if (buf_size - curbytes < 2) 1418 if (buf_size < index + 3) 1418 1419 break; 1419 1420 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; 1423 1426 curcount++; 1424 1427 1428 bool cc_valid = cc_code & 0x04; 1429 uint cc_type = cc_code & 0x03; 1430 1425 1431 // check cc_valid 1426 if (! (cc_code & 0x04))1432 if (!cc_valid) 1427 1433 continue; 1428 1434 1429 cc_code &= 0x03; 1430 if (cc_code <= 0x1) 1435 if (cc_type <= 0x1) 1431 1436 { 1432 1437 // EIA-608 field-1/2 1433 1438 int data = (data2 << 8) | data1; 1434 1439 unsigned int tc; 1435 1440 1436 if ((cc_state & cc_ code) == cc_code)1441 if ((cc_state & cc_type) == cc_type) 1437 1442 { 1438 1443 // another field of same type -- assume 1439 1444 // it's for the next frame 1440 1445 utc += 33367; 1441 1446 cc_state = 0; 1442 1447 } 1443 cc_state |= cc_ code;1448 cc_state |= cc_type; 1444 1449 tc = utc / 1000; 1445 1450 1446 1451 // For some reason, one frame can be out of order. … … 1448 1453 // frame so we can send the correct sequence to the 1449 1454 // decoder. 1450 1455 1451 if (nd->save_cctc[cc_ code])1456 if (nd->save_cctc[cc_type]) 1452 1457 { 1453 if (nd->save_cctc[cc_ code] < tc)1458 if (nd->save_cctc[cc_type] < tc) 1454 1459 { 1455 1460 // 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; 1460 1465 } 1461 else if ((nd->save_cctc[cc_ code] - tc) > 1000)1466 else if ((nd->save_cctc[cc_type] - tc) > 1000) 1462 1467 { 1463 1468 // saved code is too far in the future; probably bad 1464 1469 // - discard it 1465 nd->save_cctc[cc_ code] = 0;1470 nd->save_cctc[cc_type] = 0; 1466 1471 } 1467 1472 else 1468 1473 { 1469 1474 // send new code to decoder 1470 nd->ccd->FormatCCField(tc, cc_ code, data);1475 nd->ccd->FormatCCField(tc, cc_type, data); 1471 1476 } 1472 1477 } 1473 if (!nd->save_cctc[cc_ code])1478 if (!nd->save_cctc[cc_type]) 1474 1479 { 1475 1480 // no saved code 1476 1481 // - 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; 1479 1484 } 1480 1485 } 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); 1486 1488 } 1487 1489 nd->lastccptsu = utc; 1488 1490 } … … 2515 2517 continue; 2516 2518 } 2517 2519 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 2518 2528 VideoFrame *picframe = (VideoFrame *)(mpa_pic.opaque); 2519 2529 2520 2530 if (!directrendering) … … 2819 2829 return enc_len; 2820 2830 } 2821 2831 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 2828 2832 static int DTS_SAMPLEFREQS[16] = 2829 2833 { 2830 2834 0, 8000, 16000, 32000, 64000, 128000, 11025, 22050, -
libs/libmythtv/osdtypes.cpp
1 1 #include <qimage.h> 2 2 #include <qmap.h> 3 3 #include <qregexp.h> 4 #include < math.h>4 #include <cmath> 5 5 6 6 #include <iostream> 7 7 using namespace std; … … 1897 1897 } 1898 1898 } 1899 1899 } 1900 1901 OSDType708CC::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 1919 void 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 /* 1967 void 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 /* 2028 void 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 2053 void 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 /* 2082 void 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 /* 2099 void 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 /* 2106 void OSDType708CC::Delay(int tenths_of_seconds) 2107 { 2108 VERBOSE(VB_IMPORTANT, QString("Delay(%1)").arg(0.1*tenths_of_seconds)); 2109 } 2110 2111 void OSDType708CC::DelayCancel() 2112 { 2113 VERBOSE(VB_IMPORTANT, "DelayCancel()"); 2114 } 2115 */ 2116 /* 2117 void 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 /* 2136 void OSDType708CC::AddCCText(QString str) 2137 { 2138 VERBOSE(VB_IMPORTANT, QString("AddCCText(%1)").arg(str)); 2139 } 2140 */ -
libs/libmythtv/libmythtv.pro
91 91 HEADERS += recordingtypes.h jobqueue.h 92 92 HEADERS += filtermanager.h recordingprofile.h 93 93 HEADERS += remoteencoder.h videosource.h 94 HEADERS += ccdecoder.h 94 HEADERS += ccdecoder.h cc708decoder.h 95 HEADERS += cc708window.h 95 96 HEADERS += sr_dialog.h sr_root.h 96 97 HEADERS += sr_items.h scheduledrecording.h 97 98 HEADERS += signalmonitorvalue.h viewschdiff.h … … 108 109 SOURCES += recordingtypes.cpp jobqueue.cpp 109 110 SOURCES += filtermanager.cpp recordingprofile.cpp 110 111 SOURCES += remoteencoder.cpp videosource.cpp 111 SOURCES += ccdecoder.cpp 112 SOURCES += ccdecoder.cpp cc708decoder.cpp 113 SOURCES += cc708window.cpp 112 114 SOURCES += sr_dialog.cpp sr_root.cpp 113 115 SOURCES += sr_items.cpp scheduledrecording.cpp 114 116 SOURCES += signalmonitorvalue.cpp -
libs/libmythtv/osdtypes.h
8 8 #include <vector> 9 9 #include <qobject.h> 10 10 #include <qregexp.h> 11 #include <qcolor.h> 12 #include <qfont.h> 13 #include "cc708window.h" 11 14 12 15 using namespace std; 13 16 … … 467 470 468 471 int xoffset, yoffset, displaywidth, displayheight; 469 472 }; 473 /* 474 class 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 }; 470 487 488 class 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 */ 520 class 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 471 540 #endif -
libs/libmythtv/avformatdecoder.h
15 15 #include "../libavformat/avformat.h" 16 16 } 17 17 18 class CC708Decoder; 18 19 class ProgramInfo; 19 20 class MythSqlDatabase; 20 21 … … 76 77 /// The AvFormatDecoder is used to decode non-NuppleVideo files. 77 78 /// It's used a a decoder of last resort after trying the NuppelDecoder 78 79 /// and IvtvDecoder (if "USING_IVTV" is defined). 79 class AvFormatDecoder : public DecoderBase , public CCReader80 class AvFormatDecoder : public DecoderBase 80 81 { 81 82 friend void HandleStreamChange(void*); 82 83 public: … … 232 233 233 234 // Caption/Subtitle/Teletext decoders 234 235 CCDecoder *ccd; 236 CC708Decoder *ccd708; 235 237 236 238 // Audio 237 239 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 10 class 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 28 class CC708Pen 29 { 30 public: 31 void SetPenStyle(uint style); 32 public: 33 CC708CharacterAttribute attr; 34 35 int row; 36 int column; 37 }; 38 39 class CC708Window; 40 class CC708Character 41 { 42 public: 43 CC708Character(const CC708Window &win); 44 CC708CharacterAttribute attr; 45 QChar character; 46 }; 47 48 class 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 101 class 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 16 typedef enum 17 { 18 NTSC_CC_f1 = 0, 19 NTSC_CC_f2 = 1, 20 DTVCC_PACKET_DATA = 2, 21 DTVCC_PACKET_START = 3, 22 }; 23 24 const 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 32 static void parse_cc_packet(CC708Reader *cb_cbs, CaptionPacket *pkt); 33 34 CC708Reader::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 49 CC708Reader::~CC708Reader() 50 { 51 } 52 53 void 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 80 typedef 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 92 typedef 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 100 extern ushort CCtableG0[0x60]; 101 extern ushort CCtableG1[0x60]; 102 extern ushort CCtableG2[0x60]; 103 extern ushort CCtableG3[0x60]; 104 105 static void append_character(CC708Reader *cc, uint service_num, short ch); 106 static void parse_cc_service_stream(CC708Reader *cc, uint service_num); 107 static int handle_cc_c0_ext1_p16(CC708Reader *cc, uint service_num, int i); 108 static int handle_cc_c1(CC708Reader *cc, uint service_num, int i); 109 static int handle_cc_c2(CC708Reader *cc, uint service_num, int i); 110 static int handle_cc_c3(CC708Reader *cc, uint service_num, int i); 111 112 #define SEND_STR \ 113 do { \ 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 123 static 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 213 static 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 279 static 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 422 static 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 449 static 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 478 static 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 501 static 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 566 static 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 593 ushort 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 613 ushort 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 634 ushort 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 683 ushort 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
28 28 29 29 #include "osdlistbtntype.h" 30 30 31 static char *cc708_default_font_names[20]; 32 static bool cc708_defaults_initialized = false; 33 static QMutex cc708_init_lock; 34 static void initialize_osd_fonts(void); 35 31 36 static float sq(float a) { return a*a; } 32 37 38 #define LOC QString("OSD: ") 39 #define LOC_ERR QString("OSD, Error: ") 40 33 41 OSD::OSD(const QRect &osd_bounds, int frameRate, 34 42 const QRect &vis_bounds, float visibleAspect, float fontScaling) 35 43 : QObject(), … … 48 56 changed(false), runningTreeMenu(NULL), 49 57 treeMenuContainer("") 50 58 { 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 51 65 needPillarBox = visibleAspect > 1.51f; 52 66 wscale = visibleAspect / 1.3333f; 53 67 // adjust for wscale font size scaling … … 57 71 { 58 72 VERBOSE(VB_IMPORTANT, "Couldn't find OSD theme: " 59 73 <<gContext->GetSetting("OSDTheme")); 60 SetDefaults();74 InitDefaults(); 61 75 return; 62 76 } 63 77 … … 67 81 VERBOSE(VB_IMPORTANT, "Couldn't load OSD theme: " 68 82 <<gContext->GetSetting("OSDTheme")<<" at "<<themepath); 69 83 } 70 SetDefaults();84 InitDefaults(); 71 85 72 // Reinit since LoadThemes and SetDefaults() appear to mess things up.86 // Reinit since LoadThemes and InitDefaults() appear to mess things up. 73 87 Reinit(osd_bounds, frameRate, vis_bounds, visibleAspect, fontScaling); 74 88 } 75 89 … … 113 127 } 114 128 } 115 129 116 void OSD::SetDefaults(void)130 bool OSD::InitDefaults(void) 117 131 { 132 bool ok = true; 133 ok &= InitCC608(); 134 ok &= InitCC708(); 135 ok &= InitMenu(); 136 ok &= InitDVBSub(); 137 return ok; 138 } 139 140 bool OSD::InitCC608(void) 141 { 142 // EIA-608 captions 118 143 TTFFont *ccfont = GetFont("cc_font"); 119 144 if (!ccfont) 120 145 { … … 128 153 } 129 154 130 155 if (!ccfont) 131 return ;156 return false; 132 157 133 158 OSDSet *container = GetSet("cc_page"); 134 159 if (!container) … … 157 182 sub_dispw, sub_disph); 158 183 container->AddType(ccpage); 159 184 } 185 return true; 186 } 160 187 161 container = GetSet("menu"); 188 bool 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 241 bool OSD::InitMenu(void) 242 { 243 // Menu 244 OSDSet *container = GetSet("menu"); 162 245 if (!container) 163 246 { 164 247 QString name = "menu"; … … 208 291 209 292 container->AddType(lb); 210 293 } 294 return true; 295 } 211 296 297 bool OSD::InitDVBSub(void) 298 { 212 299 // Create container for subtitles 213 container = GetSet("subtitles");300 OSDSet *container = GetSet("subtitles"); 214 301 if (!container) 215 302 { 216 303 QString name = "subtitles"; … … 220 307 container->SetPriority(30); 221 308 AddSet(container, name); 222 309 } 310 return true; 223 311 } 224 312 225 313 void OSD::Reinit(const QRect &totalBounds, int frameRate, … … 1664 1752 osdlock.unlock(); 1665 1753 } 1666 1754 1755 void 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 1783 void 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 1667 1801 void OSD::SetSettingsText(const QString &text, int length) 1668 1802 { 1669 1803 HideAllExcept("settings"); … … 2413 2547 { 2414 2548 return QRect(xoffset, yoffset, displaywidth, displayheight); 2415 2549 } 2550 2551 static 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 */ 15 typedef struct CaptionPacket 16 { 17 unsigned char data[128+16]; 18 int size; 19 } CaptionPacket; 20 #endif 21 22 class 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 82 class 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
2989 2989 } 2990 2990 } else if (len >= 3 && 2991 2991 p[0] == 'C' && p[1] == 'C') { 2992 /* parse DVD Closed Caption data */ 2992 2993 p += 2; 2993 2994 len -= 2; 2994 2995 avctx->decode_cc_dvd(avctx, p, len); 2995 2996 } 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 } 3001 3008 } 3002 3009 } 3003 3010