Ticket #1095: eia708-v3.patch
File eia708-v3.patch, 87.7 KB (added by , 20 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.h
15 15 #include "videooutbase.h" 16 16 #include "tv_play.h" 17 17 #include "yuv2rgb.h" 18 #include "ccdecoder.h" 19 #include "cc708decoder.h" 20 #include "cc708window.h" 18 21 19 22 extern "C" { 20 23 #include "filter.h" … … 57 60 }; 58 61 #define TCTYPESMAX 4 59 62 60 class NuppelVideoPlayer 63 class NuppelVideoPlayer : public CCReader, public CC708Reader 61 64 { 62 65 public: 63 66 NuppelVideoPlayer(QString inUseID = "Unknown", … … 112 115 void Zoom(int direction); 113 116 void ClearBookmark(void); 114 117 118 void SetOSDFontName(const QString osdfonts[22], const QString &prefix); 119 void SetOSDThemeName(const QString themename); 120 115 121 // Toggle Sets 116 122 void ToggleLetterbox(int letterboxMode = -1); 117 123 … … 227 233 void AddAudioData(char *buffer, int len, long long timecode); 228 234 void AddAudioData(short int *lbuffer, short int *rbuffer, int samples, 229 235 long long timecode); 230 void AddTextData(char *buffer, int len, long long timecode, char type); 236 void AddTextData(unsigned char *buffer, int len, 237 long long timecode, char type); 231 238 void AddSubtitle(const AVSubtitle& subtitle); 232 239 240 // ATSC EIA-708 Captions 241 CC708Window &GetCCWin(uint service_num, uint window_id) 242 { return CC708services[service_num].windows[window_id]; } 243 CC708Window &GetCCWin(uint svc_num) 244 { return GetCCWin(svc_num, CC708services[svc_num].current_window); } 245 246 void SetCurrentWindow(uint service_num, int window_id); 247 void DefineWindow(uint service_num, int window_id, 248 int priority, int visible, 249 int anchor_point, int relative_pos, 250 int anchor_vertical, int anchor_horizontal, 251 int row_count, int column_count, 252 int row_lock, int column_lock, 253 int pen_style, int window_style); 254 void DeleteWindows( uint service_num, int window_map); 255 void DisplayWindows(uint service_num, int window_map); 256 void HideWindows( uint service_num, int window_map); 257 void ClearWindows( uint service_num, int window_map); 258 void ToggleWindows( uint service_num, int window_map); 259 void SetWindowAttributes(uint service_num, 260 int fill_color, int fill_opacity, 261 int border_color, int border_type, 262 int scroll_dir, int print_dir, 263 int effect_dir, 264 int display_effect, int effect_speed, 265 int justify, int word_wrap); 266 void SetPenAttributes(uint service_num, int pen_size, 267 int offset, int text_tag, int font_tag, 268 int edge_type, int underline, int italics); 269 void SetPenColor(uint service_num, 270 int fg_color, int fg_opacity, 271 int bg_color, int bg_opacity, 272 int edge_color); 273 void SetPenLocation(uint service_num, int row, int column); 274 275 void Delay(uint service_num, int tenths_of_seconds); 276 void DelayCancel(uint service_num); 277 void Reset(uint service_num); 278 void TextWrite(uint service_num, short* unicode_string, short len); 279 233 280 // Audio Track Selection 234 281 void incCurrentAudioTrack(void); 235 282 void decCurrentAudioTrack(void); … … 479 526 long long osdSubtitlesExpireAt; 480 527 MythDeque<AVSubtitle> nonDisplayedSubtitles; 481 528 529 CC708Service CC708services[64]; 530 QString osdfontname; 531 QString osdccfontname; 532 QString osd708fontnames[20]; 533 QString osdprefix; 534 QString osdtheme; 535 482 536 // OSD stuff 483 537 OSD *osd; 484 538 OSDSet *timedisplay; -
libs/libmythtv/cc708window.cpp
1 // -*- Mode: c++ -*- 2 // Copyright (c) 2003-2005, Daniel Kristjansson 3 4 #include <cassert> 5 #include <algorithm> 6 using namespace std; 7 8 #include "cc708window.h" 9 #include "mythcontext.h" 10 11 /************************************************************************ 12 13 FCC Addons to EIA-708. 14 15 * Decoders must support the standard, large, and small caption sizes 16 and must allow the caption provider to choose a size and allow the 17 viewer to choose an alternative size. 18 19 * Decoders must support the eight fonts listed in EIA-708. Caption 20 providers may specify 1 of these 8 font styles to be used to write 21 caption text. Decoders must include the ability for consumers to 22 choose among the eight fonts. The decoder must display the font 23 chosen by the caption provider unless the viewer chooses a different 24 font. 25 26 * Decoders must implement the same 8 character background colors 27 as those that Section 9 requires be implemented for character 28 foreground (white, black, red, green, blue, yellow, magenta and cyan). 29 30 * Decoders must implement options for altering the appearance of 31 caption character edges. 32 33 * Decoders must display the color chosen by the caption provider, 34 and must allow viewers to override the foreground and/or background 35 color chosen by the caption provider and select alternate colors. 36 37 * Decoders must be capable of decoding and processing data for the 38 six standard services, but information from only one service need 39 be displayed at a given time. 40 41 * Decoders must include an option that permits a viewer to choose a 42 setting that will display captions as intended by the caption 43 provider (a default). Decoders must also include an option that 44 allows a viewer's chosen settings to remain until the viewer 45 chooses to alter these settings, including during periods when 46 the television is turned off. 47 48 * Cable providers and other multichannel video programming 49 distributors must transmit captions in a format that will be 50 understandable to this decoder circuitry in digital cable 51 television sets when transmitting programming to digital 52 television devices. 53 54 ******************************************************************************/ 55 56 const uint k708JustifyLeft = 0; 57 const uint k708JustifyRight = 1; 58 const uint k708JustifyCenter = 2; 59 const uint k708JustifyFull = 3; 60 61 const uint k708EffectSnap = 0; 62 const uint k708EffectFade = 1; 63 const uint k708EffectWipe = 2; 64 65 const uint k708BorderNone = 0; 66 const uint k708BorderRaised = 1; 67 const uint k708BorderDepressed = 2; 68 const uint k708BorderUniform = 3; 69 const uint k708BorderShadowLeft = 4; 70 const uint k708BorderShadowRight = 5; 71 72 const uint k708DirLeftToRight = 0; 73 const uint k708DirRightToLeft = 1; 74 const uint k708DirTopToBottom = 2; 75 const uint k708DirBottomToTop = 3; 76 77 const uint k708AttrSizeSmall = 0; 78 const uint k708AttrSizeStandard = 1; 79 const uint k708AttrSizeLarge = 2; 80 81 const uint k708AttrOffsetSubscript = 0; 82 const uint k708AttrOffsetNormal = 1; 83 const uint k708AttrOffsetSuperscript = 2; 84 85 const uint k708AttrFontDefault = 1; 86 const uint k708AttrFontMonospacedSerif = 1; 87 const uint k708AttrFontProportionalSerif = 2; 88 const uint k708AttrFontMonospacedSansSerif = 3; 89 const uint k708AttrFontProportionalSansSerif = 4; 90 const uint k708AttrFontCasual = 5; 91 const uint k708AttrFontCursive = 6; 92 const uint k708AttrFontSmallCaps = 7; 93 94 const uint k708AttrColorBlack = 0; 95 const uint k708AttrColorWhite = 63; 96 97 const uint k708AttrOpacitySolid = 0; 98 const uint k708AttrOpacityFlash = 1; 99 const uint k708AttrOpacityTranslucent = 2; 100 const uint k708AttrOpacityTransparent = 3; 101 102 CC708Window::CC708Window() 103 : priority(0), visible(0), 104 anchor_point(0), 105 anchor_vertical(0), anchor_horizontal(0), 106 row_count(0), column_count(0), 107 row_lock(0), column_lock(0), 108 pen_style(0), window_style(0), 109 110 fill_color(0), fill_opacity(0), 111 border_color(0), border_type(0), 112 scroll_dir(0), print_dir(0), 113 effect_dir(0), display_effect(0), 114 effect_speed(0), 115 justify(0), word_wrap(0), 116 117 true_row_count(0), true_column_count(0), 118 text(NULL), exists(false), 119 lock(true) 120 { 121 } 122 123 CC708Window::~CC708Window() 124 { 125 if (text) 126 delete [] text; 127 } 128 129 void CC708Window::Clear(void) 130 { 131 // TODO 132 } 133 134 CC708Character &CC708Window::GetCCChar(void) const 135 { 136 QMutexLocker locker(&lock); 137 assert(exists); 138 assert(text); 139 assert(pen.row < true_row_count); 140 assert(pen.column < true_column_count); 141 return text[pen.row * true_column_count + pen.column]; 142 } 143 144 vector<CC708String*> CC708Window::GetStrings(void) const 145 { 146 vector<CC708String*> list; 147 148 CC708String *cur = NULL; 149 150 for (uint j = 0; j < true_row_count; j++) 151 { 152 for (uint i = 0; i < true_column_count; i++) 153 { 154 CC708Character &chr = text[j * true_column_count + i]; 155 if (!cur) 156 { 157 cur = new CC708String; 158 cur->x = i; 159 cur->y = j; 160 cur->str = QString("%1").arg(chr.character); 161 cur->attr = chr.attr; 162 } 163 else if (cur->attr == chr.attr) 164 { 165 cur->str = QString("%1%2").arg(cur->str).arg(chr.character); 166 } 167 else// if (cur->attr != chr.attr) 168 { 169 list.push_back(cur); 170 cur = NULL; 171 i--; 172 } 173 } 174 if (cur) 175 { 176 list.push_back(cur); 177 cur = NULL; 178 } 179 } 180 return list; 181 } 182 183 void CC708Window::SetWindowStyle(uint style) 184 { 185 const uint style2justify[] = 186 { 187 k708JustifyLeft, k708JustifyLeft, k708JustifyLeft, k708JustifyCenter, 188 k708JustifyLeft, k708JustifyLeft, k708JustifyCenter, k708JustifyLeft, 189 }; 190 191 if ((style < 1) || (style > 7)) 192 return; 193 194 fill_color = k708AttrColorBlack; 195 fill_opacity = ((2 == style) || (5 == style)) ? 196 k708AttrOpacityTransparent : k708AttrOpacitySolid; 197 border_color = k708AttrColorBlack; 198 border_type = k708BorderNone; 199 scroll_dir = (style < 7) ? k708DirBottomToTop : k708DirRightToLeft; 200 print_dir = (style < 7) ? k708DirLeftToRight : k708DirTopToBottom; 201 effect_dir = scroll_dir; 202 display_effect = k708EffectSnap; 203 effect_speed = 0; 204 justify = style2justify[style]; 205 word_wrap = (style > 3) && (style < 7) ? 1 : 0; 206 } 207 208 void CC708Window::AddChar(QChar ch) 209 { 210 if (exists) 211 { 212 GetCCChar().attr = pen.attr; 213 GetCCChar().character = ch; 214 int c = pen.column; 215 int r = pen.row; 216 IncrPenLocation(); 217 218 VERBOSE(VB_IMPORTANT, QString("AddChar(%1) at (%2,%3) -> (%4,%5)") 219 .arg(ch).arg(c).arg(r).arg(pen.column).arg(pen.row)); 220 } 221 } 222 223 void CC708Window::IncrPenLocation(void) 224 { 225 VERBOSE(VB_IMPORTANT, QString("dir %1: col %2, row %3") 226 .arg(print_dir).arg(pen.column).arg(pen.row)); 227 // TODO: Scroll direction and up/down printing, 228 // and word wrap not handled yet... 229 int new_column = pen.column, new_row = pen.row; 230 231 new_column += (print_dir == k708DirLeftToRight) ? +1 : 0; 232 new_column += (print_dir == k708DirRightToLeft) ? -1 : 0; 233 new_row += (print_dir == k708DirTopToBottom) ? +1 : 0; 234 new_row += (print_dir == k708DirBottomToTop) ? -1 : 0; 235 236 if (1) 237 { 238 // basic wrapping for l->r, r->l languages 239 if (new_column > (int)true_column_count - 1) 240 { 241 new_column = 0; 242 new_row += 1; 243 } 244 else if (new_column < 0) 245 { 246 new_column = (int)true_column_count - 1; 247 new_row -= 1; 248 } 249 } 250 pen.column = max(new_column, 0); 251 pen.row = max(new_row, 0); 252 253 LimitPenLocation(); 254 } 255 256 void CC708Window::SetPenLocation(uint row, uint column) 257 { 258 pen.row = row; 259 pen.column = column; 260 261 LimitPenLocation(); 262 } 263 264 void CC708Window::LimitPenLocation(void) 265 { 266 // basic limiting 267 uint max_col = max((int)true_column_count - 1, 0); 268 uint max_row = max((int)true_row_count - 1, 0); 269 pen.column = min(pen.column, max_col); 270 pen.row = min(pen.row, max_row); 271 } 272 273 /***************************************************************************/ 274 275 void CC708Pen::SetPenStyle(uint style) 276 { 277 static const uint style2font[] = { 1, 1, 2, 3, 4, 5, 4, 5 }; 278 279 if ((style < 1) || (style > 7)) 280 return; 281 282 attr.pen_size = k708AttrSizeStandard; 283 attr.offset = k708AttrOffsetNormal; 284 attr.font_tag = style2font[style]; 285 attr.italics = 0; 286 attr.underline = 0; 287 attr.edge_type = 0; 288 attr.fg_color = k708AttrColorWhite; 289 attr.fg_opacity = k708AttrOpacitySolid; 290 attr.bg_color = k708AttrColorBlack; 291 attr.bg_opacity = (style<6) ? 292 k708AttrOpacitySolid : k708AttrOpacityTransparent; 293 attr.edge_color = k708AttrColorBlack; 294 } 295 296 CC708Character::CC708Character(const CC708Window &win) 297 { 298 attr = win.pen.attr; 299 character = ' '; 300 } 301 302 bool CC708CharacterAttribute::operator==( 303 const CC708CharacterAttribute &other) const 304 { 305 return ((pen_size == other.pen_size) && 306 (offset == other.offset) && 307 (text_tag == other.text_tag) && 308 (font_tag == other.font_tag) && 309 (edge_type == other.edge_type) && 310 (underline == other.underline) && 311 (italics == other.italics) && 312 (fg_color == other.fg_color) && 313 (fg_opacity == other.fg_opacity) && 314 (bg_color == other.bg_color) && 315 (bg_opacity == other.bg_opacity) && 316 (edge_color == other.edge_color)); 317 } -
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
912 912 videoOutput->DrawSlice(frame, x, y, w, h); 913 913 } 914 914 915 void NuppelVideoPlayer::AddTextData( char *buffer, int len,915 void NuppelVideoPlayer::AddTextData(unsigned char *buffer, int len, 916 916 long long timecode, char type) 917 917 { 918 918 WrapTimecode(timecode, TC_CC); … … 940 940 } 941 941 } 942 942 943 void NuppelVideoPlayer::SetCurrentWindow(uint service_num, int window_id) 944 { 945 VERBOSE(VB_IMPORTANT, LOC + QString("SetCurrentWindow(%1, %2)") 946 .arg(service_num).arg(window_id)); 947 CC708services[service_num].current_window = window_id; 948 } 949 950 void NuppelVideoPlayer::DefineWindow( 951 uint service_num, int window_id, 952 int priority, int visible, 953 int anchor_point, int relative_pos, 954 int anchor_vertical, int anchor_horizontal, 955 int row_count, int column_count, 956 int row_lock, int column_lock, 957 int pen_style, int window_style) 958 { 959 VERBOSE(VB_IMPORTANT, LOC + 960 QString("DefineWindow(%1, %2)") 961 .arg(service_num).arg(window_id) + 962 QString("\n\t\t\t prio %1, vis %2, ap %3, rp %4, av %5, ah %6") 963 .arg(priority).arg(visible).arg(anchor_point).arg(relative_pos) 964 .arg(anchor_vertical).arg(anchor_horizontal) + 965 QString("\n\t\t\t row_cnt %1, row_lck %2, " 966 "col_cnt %3, col_lck %4 ") 967 .arg(row_count).arg(row_lock) 968 .arg(column_count).arg(column_lock) + 969 QString("\n\t\t\t pen style %1, win style %2") 970 .arg(pen_style).arg(window_style)); 971 972 CC708services[service_num].current_window = window_id; 973 CC708Window &win = GetCCWin(service_num, window_id); 974 975 QMutexLocker locker(&win.lock); 976 977 win.priority = priority; 978 win.visible = visible; 979 win.anchor_point = anchor_point; 980 win.relative_pos = relative_pos; 981 win.anchor_vertical = anchor_vertical; 982 win.anchor_horizontal = anchor_horizontal; 983 win.row_count = row_count; 984 win.column_count = column_count; 985 win.row_lock = row_lock; 986 win.column_lock = column_lock; 987 988 if ((!pen_style && !win.exists) || pen_style) 989 win.pen.SetPenStyle(pen_style ? pen_style : 1); 990 991 if ((!window_style && !win.exists) || window_style) 992 win.SetWindowStyle(window_style ? window_style : 1); 993 994 // these could be bigger if row/column lock is false, resp. 995 win.true_row_count = row_count; 996 win.true_column_count = column_count; 997 998 if (win.text) 999 delete [] win.text; 1000 uint num = win.true_row_count * win.true_column_count; 1001 win.text = new CC708Character[num](win); 1002 1003 win.exists = true; 1004 } 1005 1006 void NuppelVideoPlayer::DeleteWindows(uint service_num, int window_map) 1007 { 1008 VERBOSE(VB_IMPORTANT, LOC + QString("DeleteWindows(%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).exists = false; 1015 } 1016 } 1017 1018 void NuppelVideoPlayer::DisplayWindows(uint service_num, int window_map) 1019 { 1020 VERBOSE(VB_IMPORTANT, LOC + QString("DisplayWindows(%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 = true; 1027 } 1028 } 1029 1030 void NuppelVideoPlayer::HideWindows(uint service_num, int window_map) 1031 { 1032 VERBOSE(VB_IMPORTANT, LOC + QString("HideWindows(%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).visible = false; 1039 } 1040 } 1041 1042 void NuppelVideoPlayer::ClearWindows(uint service_num, int window_map) 1043 { 1044 VERBOSE(VB_IMPORTANT, LOC + QString("ClearWindows(%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 GetCCWin(service_num, i).Clear(); 1051 } 1052 } 1053 1054 void NuppelVideoPlayer::ToggleWindows(uint service_num, int window_map) 1055 { 1056 VERBOSE(VB_IMPORTANT, LOC + QString("ToggleWindows(%1, 0x%2)") 1057 .arg(service_num).arg(window_map,0,16)); 1058 1059 for (uint i=0; i<8; i++) 1060 { 1061 if (i & window_map) 1062 { 1063 GetCCWin(service_num, i).visible = 1064 !GetCCWin(service_num, i).visible; 1065 } 1066 } 1067 } 1068 1069 void NuppelVideoPlayer::SetWindowAttributes( 1070 uint service_num, 1071 int fill_color, int fill_opacity, 1072 int border_color, int border_type, 1073 int scroll_dir, int print_dir, 1074 int effect_dir, 1075 int display_effect, int effect_speed, 1076 int justify, int word_wrap) 1077 { 1078 VERBOSE(VB_IMPORTANT, LOC + QString("SetWindowAttributes(%1...)") 1079 .arg(service_num)); 1080 1081 CC708Window &win = GetCCWin(service_num); 1082 1083 win.fill_color = fill_color; 1084 win.fill_opacity = fill_opacity; 1085 win.border_color = border_color; 1086 win.border_type = border_type; 1087 win.scroll_dir = scroll_dir; 1088 win.print_dir = print_dir; 1089 win.effect_dir = effect_dir; 1090 win.display_effect = display_effect; 1091 win.effect_speed = effect_speed; 1092 win.justify = justify; 1093 win.word_wrap = word_wrap; 1094 } 1095 1096 void NuppelVideoPlayer::SetPenAttributes( 1097 uint service_num, int pen_size, 1098 int offset, int text_tag, int font_tag, 1099 int edge_type, int underline, int italics) 1100 { 1101 VERBOSE(VB_IMPORTANT, LOC + QString("SetPenAttributes(%1...)") 1102 .arg(service_num)); 1103 1104 CC708CharacterAttribute &attr = GetCCWin(service_num).pen.attr; 1105 1106 attr.pen_size = pen_size; 1107 attr.offset = offset; 1108 attr.text_tag = text_tag; 1109 attr.font_tag = font_tag; 1110 attr.edge_type = edge_type; 1111 attr.underline = underline; 1112 attr.italics = italics; 1113 } 1114 1115 void NuppelVideoPlayer::SetPenColor( 1116 uint service_num, 1117 int fg_color, int fg_opacity, 1118 int bg_color, int bg_opacity, 1119 int edge_color) 1120 { 1121 VERBOSE(VB_IMPORTANT, LOC + QString("SetPenColor(%1...)") 1122 .arg(service_num)); 1123 1124 CC708CharacterAttribute &attr = GetCCWin(service_num).pen.attr; 1125 1126 attr.fg_color = fg_color; 1127 attr.fg_opacity = fg_opacity; 1128 attr.bg_color = bg_color; 1129 attr.bg_opacity = bg_opacity; 1130 attr.edge_color = edge_color; 1131 } 1132 1133 void NuppelVideoPlayer::SetPenLocation(uint service_num, int row, int column) 1134 { 1135 VERBOSE(VB_IMPORTANT, LOC + QString("SetPenLocation(%1, (%2x%3))") 1136 .arg(service_num).arg(row).arg(column)); 1137 GetCCWin(service_num).SetPenLocation(row, column); 1138 } 1139 1140 void NuppelVideoPlayer::Delay(uint service_num, int tenths_of_seconds) 1141 { 1142 VERBOSE(VB_IMPORTANT, LOC + QString("Delay(%1, %2 seconds)") 1143 .arg(service_num).arg(tenths_of_seconds * 0.1f)); 1144 } 1145 1146 void NuppelVideoPlayer::DelayCancel(uint service_num) 1147 { 1148 VERBOSE(VB_IMPORTANT, LOC + QString("DelayCancel(%1)").arg(service_num)); 1149 } 1150 1151 void NuppelVideoPlayer::Reset(uint service_num) 1152 { 1153 VERBOSE(VB_IMPORTANT, LOC + QString("Reset(%1)").arg(service_num)); 1154 DeleteWindows(service_num, 0x7); 1155 DelayCancel(service_num); 1156 } 1157 1158 void NuppelVideoPlayer::TextWrite(uint service_num, 1159 short* unicode_string, short len) 1160 { 1161 for (uint i = 0; i < (uint)len; i++) 1162 GetCCWin(service_num).AddChar(QChar(unicode_string[i])); 1163 1164 if (GetOSD()) 1165 GetOSD()->CC708Updated(); 1166 } 1167 1168 void NuppelVideoPlayer::SetOSDFontName(const QString osdfonts[22], 1169 const QString &prefix) 1170 { 1171 osdfontname = QDeepCopy<QString>(osdfonts[0]); 1172 osdccfontname = QDeepCopy<QString>(osdfonts[1]); 1173 for (int i = 2; i < 22; i++) 1174 osd708fontnames[i - 2] = QDeepCopy<QString>(osdfonts[i]); 1175 osdprefix = QDeepCopy<QString>(prefix); 1176 } 1177 1178 void NuppelVideoPlayer::SetOSDThemeName(const QString themename) 1179 { 1180 osdtheme = QDeepCopy<QString>(themename); 1181 } 1182 1183 943 1184 void NuppelVideoPlayer::CheckPrebuffering(void) 944 1185 { 945 1186 if (kVideoOutput_IVTV == forceVideoOutput) … … 2375 2616 { 2376 2617 osd->DisableFade(); 2377 2618 } 2619 osd->SetCC708Service(&CC708services[1]); 2378 2620 } 2379 2621 2380 2622 playing = true; … … 5057 5299 usleep(100000); 5058 5300 ClearAfterSeek(); 5059 5301 } 5060 -
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 } … … 2521 2523 continue; 2522 2524 } 2523 2525 2526 #if 0 2527 if (mpa_pic.captions.size) { 2528 av_log(NULL, AV_LOG_ERROR, "picture # (%i, %i)\n", 2529 mpa_pic.coded_picture_number, 2530 mpa_pic.display_picture_number); 2531 m_parent->ParseATSCCaptions(&mpa_pic.captions); 2532 } 2533 #endif 2524 2534 VideoFrame *picframe = (VideoFrame *)(mpa_pic.opaque); 2525 2535 2526 2536 if (!directrendering) … … 2825 2835 return enc_len; 2826 2836 } 2827 2837 2828 void AvFormatDecoder::AddTextData(unsigned char *buf, int len,2829 long long timecode, char type)2830 {2831 m_parent->AddTextData((char*)buf, len, timecode, type);2832 }2833 2834 2838 static int DTS_SAMPLEFREQS[16] = 2835 2839 { 2836 2840 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; … … 216 216 { 217 217 item->Reinit(xoff, yoff, displaywidth, displayheight); 218 218 } 219 else if (OSDType708CC *item = dynamic_cast<OSDType708CC*>(type)) 220 { 221 item->Reinit(xoff, yoff, displaywidth, displayheight); 222 } 219 223 else if (OSDListTreeType *item = dynamic_cast<OSDListTreeType*>(type)) 220 224 { 221 225 item->Reinit(wchange, hchange, wmult, hmult); … … 1897 1901 } 1898 1902 } 1899 1903 } 1904 1905 void OSDType708CC::Reinit(int x, int y, int dispw, int disph) 1906 { 1907 xoffset = x; 1908 yoffset = y; 1909 displaywidth = dispw; 1910 displayheight = disph; 1911 } 1912 1913 OSDType708CC::OSDType708CC(const QString &name, TTFFont *fonts[60], 1914 int xoff, int yoff, int dispw, int disph) : 1915 OSDType(name) 1916 { 1917 xoffset = xoff; 1918 yoffset = yoff; 1919 displaywidth = dispw; 1920 displayheight = disph; 1921 1922 int c[4] = {0, 85, 170, 255}; 1923 1924 for (int i = 0; i < 64; i++) 1925 colors[i].setRgb(c[(i>>4)&3], c[(i>>2)&3], c[i&3]); 1926 1927 for (int i = 0; i < 60; i++) 1928 { 1929 m_fonts[i] = fonts[i]; 1930 } 1931 } 1932 1933 QRect OSDType708CC::CalcBounds(const OSDSurface *surface, 1934 const CC708Window &win, 1935 const vector<CC708String*> &list) 1936 { 1937 uint max_width = 0, total_height = 0, i = 0; 1938 for (uint row = 0; (row < win.true_row_count) && (i < list.size()); row++) 1939 { 1940 uint tot_width = 0, max_height = 0; 1941 for (; list[i] && (list[i]->y <= row) && (i < list.size()); i++) 1942 { 1943 int text_length; 1944 if (list[i]->y < row) 1945 continue; 1946 if (list[i]->str.stripWhiteSpace().isEmpty()) 1947 continue; 1948 1949 TTFFont *font = m_fonts[0]; 1950 font->CalcWidth(list[i]->str, &text_length); 1951 1952 VERBOSE(VB_IMPORTANT, "Row#"<<i<<" w/x("<<list[i]->x<<"): WxH " 1953 <<text_length<<"x" 1954 <<max_height<<" '"<<list[i]->str<<"'"); 1955 tot_width += max(text_length, 0); 1956 max_height = max(max_height, (uint)font->Size() * 3 / 2); 1957 } 1958 max_width = max(max_width, tot_width); 1959 total_height += max_height; 1960 } 1961 if (!max_width && !total_height) 1962 return QRect(0,0,0,0); 1963 1964 // add some padding.. 1965 max_width += 4; 1966 total_height += 4; 1967 1968 // 16:9 1969 float xrange = 210.0f; 1970 float yrange = 75.0f; 1971 // 4:3 1972 //float xrange = 160.0f; 1973 //float yrange = 75.0f; 1974 1975 // relative position 1976 xrange = (win.relative_pos) ? 100.0f : xrange; 1977 yrange = (win.relative_pos) ? 100.0f : yrange; 1978 1979 float xmult = (surface->width - 4) / xrange; 1980 float ymult = (surface->height - 4) / yrange; 1981 1982 uint anchor_x = (uint) xmult * win.anchor_horizontal + 2; 1983 uint anchor_y = (uint) ymult * win.anchor_vertical + 2; 1984 1985 VERBOSE(VB_IMPORTANT, "Anchor loc: "<<anchor_x<<"x"<<anchor_y); 1986 VERBOSE(VB_IMPORTANT, "Window size: (" 1987 <<max_width<<", "<<total_height<<")"); 1988 1989 // Make sure bounds are within window by adjusting anchor point 1990 int x_adj = (int)(anchor_x + max_width) - (surface->width - 4); 1991 if (x_adj > 0) 1992 anchor_x = max(0, (int)anchor_x - x_adj); 1993 1994 int y_adj = (int)(anchor_y + total_height) - (surface->height - 4); 1995 if (y_adj > 0) 1996 anchor_y = max(0, (int)anchor_y - y_adj); 1997 1998 // If it is still out of bounds, shrink the surface 1999 if (anchor_x + max_width > (uint)surface->width) 2000 max_width = surface->width - anchor_x; 2001 2002 if (anchor_y + total_height > (uint)surface->height) 2003 total_height = surface->height - anchor_y; 2004 2005 return QRect(anchor_x, anchor_y, max_width, total_height); 2006 } 2007 2008 void OSDType708CC::Draw(OSDSurface *surface, 2009 const QPoint &ul, /* upper left corner */ 2010 const CC708Window &win, 2011 const vector<CC708String*> &list) 2012 { 2013 int maxx = surface->width; 2014 int maxy = surface->height; 2015 uint max_width = 0, total_height = 0, i = 0; 2016 for (uint row = 0; (row < win.true_row_count) && (i < list.size()); row++) 2017 { 2018 uint tot_width = 0, max_height = 0; 2019 for (; list[i] && (list[i]->y == row) && (i < list.size()); i++) 2020 { 2021 int text_length; 2022 2023 if (list[i]->str.isEmpty()) 2024 continue; 2025 2026 TTFFont *font = m_fonts[0]; 2027 2028 font->CalcWidth(list[i]->str, &text_length); 2029 font->setColor(Qt::white, kTTF_Normal); 2030 font->DrawString(surface, 2031 ul.x() + tot_width, ul.y() + total_height + 2, 2032 list[i]->str, maxx, maxy, 255); 2033 2034 tot_width += max(text_length, 0); 2035 max_height = max(max_height, (uint)font->Size() * 3 / 2); 2036 } 2037 max_width = max(max_width, tot_width); 2038 total_height += max_height; 2039 } 2040 } 2041 2042 void OSDType708CC::Draw(OSDSurface *surface, int /*fade*/, int /*maxfade*/, 2043 int /*xoff*/, int /*yoff*/) 2044 { 2045 if (!cc708data || surface->width < 4 || surface->height < 4) 2046 return; 2047 2048 for (uint i = 0; i < 8; i++) 2049 { 2050 const CC708Window &win = cc708data->windows[i]; 2051 if (!win.exists) 2052 continue; 2053 2054 QMutexLocker locker(&win.lock); 2055 2056 VERBOSE(VB_IMPORTANT, "Window #"<<i); 2057 vector<CC708String*> list = win.GetStrings(); 2058 QRect bounds = CalcBounds(surface, win, list); 2059 QPoint ul(0,0); 2060 if (bounds.width()) 2061 { 2062 QRect rect(0,0, bounds.width(), bounds.height()); 2063 OSDTypeBox box(QString("cc708_background%1").arg(i), rect); 2064 box.SetRect(rect); 2065 box.Draw(surface, 0/*fade*/, 0/*maxfade*/, 2066 bounds.left()/*xoff*/, bounds.bottom()/*yoff*/); 2067 Draw(surface, bounds.topLeft(), win, list); 2068 } 2069 VERBOSE(VB_IMPORTANT, ""); 2070 2071 for (uint i = 0; i < list.size(); i++) 2072 delete list[i]; 2073 } 2074 } 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 #if 0 2099 void OSDType708CC::DefineWindow( 2100 int window_id, int priority, int visible, 2101 int anchor_id, int anchor_vertical, int anchor_horizontal, 2102 int row_count, int col_count, int row_lock, int col_lock, 2103 int pen_style, int window_style) 2104 { 2105 QString str("DefineWindow(%1, %2, %3, %4, %5, %6"); 2106 str.arg(window_id).arg(priority).arg(visible) 2107 .arg(anchor_id).arg(anchor_vertical).arg(anchor_horizontal); 2108 str.append(QString("%1, %2, %3, %4, %5, %6)") 2109 .arg(row_count).arg(col_count).arg(row_lock).arg(col_lock) 2110 .arg(pen_style).arg(window_style)); 2111 2112 m_current_window = window_id; 2113 2114 Window708 win = m_windows[m_current_window]; 2115 win.anchorPoint = 2116 QPoint(anchor_horizontal, anchor_vertical); 2117 win.priority = priority; 2118 win.visible = visible; 2119 win.anchor_id = anchor_id; 2120 win.row_count = row_count; 2121 win.col_count = col_count; 2122 win.row_lock = row_lock; 2123 win.col_lock = col_lock; 2124 2125 if (pen_style>0) 2126 { 2127 win.curPen.font.setStyleHint( 2128 (pen_style<4) ? QFont::Serif : QFont::SansSerif); 2129 win.curPen.font.setFixedPitch((pen_style&1)); 2130 win.curPen.textTag = 0; // dialog text 2131 win.curPen.font.setPointSize(24); // standard font size 2132 win.curPen.offset = 1; // normal 2133 win.curPen.font.setItalic(false); 2134 win.curPen.font.setUnderline(false); 2135 win.curPen.edgeType = 0; // none 2136 win.curPen.foregroundColor = Qt::white; 2137 win.curPen.edgeColor = Qt::black; 2138 win.curPen.backgroundColor = Qt::black; 2139 win.curPen.foregroundOpacity = 3; // solid 2140 win.curPen.backgroundOpacity = (pen_style>5) ? 0:3; // transparent:solid 2141 } 2142 2143 if (window_style>0) 2144 { 2145 win.justify = (3==window_style || 6==window_style) ? 2:0; // center:left 2146 win.printDir = (7==window_style) ? 2 : 0; // Top-to-Bottom:Left-to-Right 2147 win.scrollDir = (7==window_style) ? 1 : 3; // Right-to-Left:Bottom-to-Top 2148 win.wordWrap = (4<=window_style && window_style<=6) ? true : false; 2149 win.displayEffect = 0; // Snap 2150 win.effectDir = 0; 2151 win.effectSpeed = 0; 2152 win.fillColor = Qt::black; 2153 win.fillOpacity = (2==window_style || 5==window_style) ? 0:3; // transparent:solid 2154 win.borderType = 0; // none 2155 } 2156 VERBOSE(VB_IMPORTANT, str); 2157 } 2158 #endif 2159 /* 2160 void OSDType708CC::SetWindowAttributes(int fill_color, int fill_opacity, 2161 int border_color, int border_type, 2162 int scroll_dir, int print_dir, 2163 int effect_dir, 2164 int display_effect, int effect_speed, 2165 int justify, int word_wrap) 2166 { 2167 VERBOSE(VB_IMPORTANT, "SetWindowAttributes()"); 2168 if (m_current_window>=0) 2169 { 2170 Window708 &win = m_windows[m_current_window]; 2171 win.fillColor = colors[fill_color&0x3f]; 2172 win.borderColor = colors[border_color&0x3f]; 2173 win.fillOpacity = fill_opacity; 2174 win.borderType = border_type; 2175 win.scrollDir = scroll_dir; 2176 win.printDir = print_dir; 2177 win.effectDir = effect_dir; 2178 win.displayEffect = display_effect; 2179 win.effectSpeed = effect_speed; 2180 win.justify = justify; 2181 win.wordWrap = word_wrap; 2182 } 2183 } 2184 2185 void OSDType708CC::SetPenAttributes(int pen_size, 2186 int offset, int text_tag, int font_tag, 2187 int edge_type, int underline, int italics) 2188 { 2189 int pointSize[4] = { 18, 24, 30, 24 }; 2190 VERBOSE(VB_IMPORTANT, "SetPenAttributes()"); 2191 if (m_current_window>=0) 2192 { 2193 QFont::StyleHint stylemap[8] = 2194 { 2195 QFont::AnyStyle, QFont::Serif, QFont::Serif, 2196 QFont::SansSerif, QFont::SansSerif, QFont::Decorative, 2197 QFont::Decorative, QFont::Decorative 2198 }; 2199 bool mono[8] = { true, true, false, true, false, false, false, false }; 2200 Pen708 &pen = m_windows[m_current_window].curPen; 2201 pen.font.setStyleHint(stylemap[font_tag]); 2202 pen.font.setFixedPitch(mono[font_tag]); 2203 2204 pen.font.setPointSize(pointSize[pen_size]); 2205 pen.font.setUnderline(underline); 2206 pen.font.setItalic(italics); 2207 pen.offset = offset; 2208 pen.textTag = text_tag; 2209 pen.edgeType = edge_type; 2210 } 2211 } 2212 */ 2213 /* 2214 void OSDType708CC::SetPenColor(int fg_color, int fg_opacity, 2215 int bg_color, int bg_opacity, 2216 int edge_color) 2217 { 2218 VERBOSE(VB_IMPORTANT, QString("SetPenColor()")); 2219 if (m_current_window>=0) 2220 { 2221 Pen708 &pen = m_windows[m_current_window].curPen; 2222 pen.foregroundColor = colors[fg_color&0x3f]; 2223 pen.backgroundColor = colors[bg_color&0x3f]; 2224 pen.edgeColor = colors[edge_color&0x3f]; 2225 pen.foregroundOpacity = fg_opacity; 2226 pen.backgroundOpacity = bg_opacity; 2227 } 2228 } 2229 */ 2230 /* 2231 void OSDType708CC::SetPenLocation(int row, int column) 2232 { 2233 VERBOSE(VB_IMPORTANT, QString("SetPenLocation(%1, %2)").arg(row).arg(column)); 2234 m_windows[m_current_window].cursorPoint = QPoint(column, row); 2235 } 2236 */ 2237 /* 2238 void OSDType708CC::Delay(int tenths_of_seconds) 2239 { 2240 VERBOSE(VB_IMPORTANT, QString("Delay(%1)").arg(0.1*tenths_of_seconds)); 2241 } 2242 2243 void OSDType708CC::DelayCancel() 2244 { 2245 VERBOSE(VB_IMPORTANT, "DelayCancel()"); 2246 } 2247 */ 2248 /* 2249 void OSDType708CC::Reset() 2250 { 2251 VERBOSE(VB_IMPORTANT, "Reset()"); 2252 for (int i=0; i<8; i++) 2253 { 2254 Pen708 &pen = m_windows[i].curPen; 2255 pen.offset = 1; 2256 pen.textTag = 0; 2257 pen.edgeType = 0; 2258 pen.font.setStyleHint(QFont::Serif); 2259 pen.font.setFixedPitch(false); 2260 pen.font.setItalic(false); 2261 pen.font.setBold(false); 2262 pen.font.setUnderline(false); 2263 pen.font.setPointSize(24); 2264 } 2265 } 2266 */ 2267 /* 2268 void OSDType708CC::AddCCText(QString str) 2269 { 2270 VERBOSE(VB_IMPORTANT, QString("AddCCText(%1)").arg(str)); 2271 } 2272 */ -
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 Reinit(int xoff, int yoff, int dispw, int disph); 528 529 void SetCCService(const CC708Service *service) 530 { cc708data = service; } 531 532 void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff); 533 534 private: 535 QRect CalcBounds(const OSDSurface*, const CC708Window&, 536 const vector<CC708String*>&); 537 void Draw(OSDSurface*, const QPoint&, 538 const CC708Window&, const vector<CC708String*>&); 539 540 const CC708Service *cc708data; 541 542 TTFFont *m_fonts[60]; 543 QColor colors[64]; 544 545 int xoffset, yoffset, displaywidth, displayheight; 546 }; 547 471 548 #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 <vector> 8 using namespace std; 9 10 #include <qstring.h> 11 #include <qmutex.h> 12 13 class CC708CharacterAttribute 14 { 15 public: 16 uint pen_size; 17 uint offset; 18 uint text_tag; 19 uint font_tag; 20 uint edge_type; 21 uint underline; 22 uint italics; 23 24 uint fg_color; 25 uint fg_opacity; 26 uint bg_color; 27 uint bg_opacity; 28 uint edge_color; 29 bool operator==(const CC708CharacterAttribute &other) const; 30 bool operator!=(const CC708CharacterAttribute &other) const 31 { return !(*this == other); } 32 }; 33 34 class CC708Pen 35 { 36 public: 37 void SetPenStyle(uint style); 38 public: 39 CC708CharacterAttribute attr; 40 41 uint row; 42 uint column; 43 }; 44 45 class CC708Window; 46 class CC708Character 47 { 48 public: 49 CC708Character(const CC708Window &win); 50 CC708CharacterAttribute attr; 51 QChar character; 52 }; 53 54 class CC708String 55 { 56 public: 57 uint x; 58 uint y; 59 QString str; 60 CC708CharacterAttribute attr; 61 }; 62 63 class CC708Window 64 { 65 public: 66 CC708Window(); 67 ~CC708Window(); 68 69 void Clear(void); 70 void SetWindowStyle(uint); 71 72 void AddChar(QChar); 73 void IncrPenLocation(void); 74 void SetPenLocation(uint, uint); 75 void LimitPenLocation(void); 76 77 CC708Character &GetCCChar(void) const; 78 vector<CC708String*> GetStrings(void) const; 79 80 public: 81 uint priority; 82 uint visible; 83 uint anchor_point; 84 uint relative_pos; 85 uint anchor_vertical; 86 uint anchor_horizontal; 87 uint row_count; 88 uint column_count; 89 uint row_lock; 90 uint column_lock; 91 uint pen_style; 92 uint window_style; 93 94 uint fill_color; 95 uint fill_opacity; 96 uint border_color; 97 uint border_type; 98 uint scroll_dir; 99 uint print_dir; 100 uint effect_dir; 101 uint display_effect; 102 uint effect_speed; 103 uint justify; 104 uint word_wrap; 105 106 uint true_row_count; 107 uint true_column_count; 108 CC708Character *text; 109 CC708Pen pen; 110 111 /// set to false when DeleteWindow is called on the window. 112 bool exists; 113 114 mutable QMutex lock; 115 }; 116 117 class CC708Service 118 { 119 public: 120 CC708Service() { current_window = 0; } 121 122 public: 123 uint current_window; 124 CC708Window windows[8]; 125 }; 126 127 #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 for (uint i=0; i<64; i++) 52 { 53 free(buf[i]); 54 free(temp_str[i]); 55 } 56 } 57 58 void CC708Decoder::decode_cc_data(uint cc_type, uint data1, uint data2) 59 { 60 if (DTVCC_PACKET_START == cc_type) 61 { 62 //VERBOSE(VB_IMPORTANT, LOC + QString("CC ST data(0x%1 0x%2)") 63 // .arg(data1,0,16).arg(data2,0,16)); 64 65 if (partialPacket.size && reader) 66 parse_cc_packet(reader, &partialPacket); 67 68 partialPacket.data[0] = data1; 69 partialPacket.data[1] = data2; 70 partialPacket.size = 2; 71 } 72 else if (DTVCC_PACKET_DATA == cc_type) 73 { 74 //VERBOSE(VB_IMPORTANT, LOC + QString("CC Ex data(0x%1 0x%2)") 75 // .arg(data1,0,16).arg(data2,0,16)); 76 77 partialPacket.data[partialPacket.size + 0] = data1; 78 partialPacket.data[partialPacket.size + 1] = data2; 79 partialPacket.size += 2; 80 } 81 } 82 83 #define DEBUG_CAPTIONS 0 84 85 typedef enum 86 { 87 NUL = 0x00, 88 EXT1 = 0x01, 89 ETX = 0x03, 90 BS = 0x08, 91 FF = 0x0C, 92 CR = 0x0D, 93 HCR = 0x0E, 94 P16 = 0x18, 95 } C0; 96 97 typedef enum 98 { 99 CW0=0x80, CW1, CW2, CW3, CW4, CW5, CW6, CW7, 100 CLW, DSW, HDW, TGW, DLW, DLY, DLC, RST, 101 SPA=0x90, SPC, SPL, SWA=0x97, 102 DF0, DF1, DF2, DF3, DF4, DF5, DF6, DF7, 103 } C1; 104 105 extern ushort CCtableG0[0x60]; 106 extern ushort CCtableG1[0x60]; 107 extern ushort CCtableG2[0x60]; 108 extern ushort CCtableG3[0x60]; 109 110 static void append_character(CC708Reader *cc, uint service_num, short ch); 111 static void parse_cc_service_stream(CC708Reader *cc, uint service_num); 112 static int handle_cc_c0_ext1_p16(CC708Reader *cc, uint service_num, int i); 113 static int handle_cc_c1(CC708Reader *cc, uint service_num, int i); 114 static int handle_cc_c2(CC708Reader *cc, uint service_num, int i); 115 static int handle_cc_c3(CC708Reader *cc, uint service_num, int i); 116 117 #define SEND_STR \ 118 do { \ 119 if (cc->temp_str_size[service_num]) \ 120 { \ 121 cc->TextWrite(service_num, \ 122 cc->temp_str[service_num], \ 123 cc->temp_str_size[service_num]); \ 124 cc->temp_str_size[service_num] = 0; \ 125 } \ 126 } while (0) 127 128 static void parse_cc_service_stream(CC708Reader* cc, uint service_num) 129 { 130 const int blk_size = cc->buf_size[service_num]; 131 int blk_start = 0, i = 0; 132 133 for (i = 0; i < blk_size; i++) 134 { 135 if (RST == cc->buf[service_num][i]) 136 { 137 fprintf(stderr, "Reset i(%i)\n", i); 138 cc->Reset(service_num); 139 blk_start = i+1; 140 cc->delayed[service_num] = 0; 141 break; 142 } 143 else if (DLC == cc->buf[service_num][i]) 144 { 145 fprintf(stderr, "DelayCancel i(%i)\n", i); 146 cc->DelayCancel(service_num); 147 cc->delayed[service_num] = 0; 148 break; 149 } 150 } 151 if (cc->buf_size[service_num] >= 126) 152 cc->delayed[service_num] = 0; 153 154 /* 155 av_log(NULL, AV_LOG_ERROR, 156 "cc_ss delayed(%i) blk_start(%i) blk_size(%i)\n", 157 cc->delayed, blk_start, blk_size); 158 */ 159 160 for (int i = (cc->delayed[service_num]) ? blk_size : blk_start; 161 i < blk_size; ) 162 { 163 const int old_i = i; 164 const int code = cc->buf[service_num][i]; 165 //fprintf(stderr, "cc(0x%x,i%i) ", code, i); 166 if (0x0 == code) 167 { 168 i++; 169 } 170 else if (code <= 0x1f) 171 { 172 // C0 code -- ASCII commands + ext1: C2,C3,G2,G3 + p16: 16 chars 173 i = handle_cc_c0_ext1_p16(cc, service_num, i); 174 } 175 else if (code <= 0x7f) 176 { 177 // G0 code -- mostly ASCII printables 178 short character = CCtableG0[code-0x20]; 179 append_character(cc, service_num, character); 180 i++; 181 } 182 else if (code <= 0x9f) 183 { 184 // C1 code -- caption control codes 185 i = handle_cc_c1(cc, service_num, i); 186 } 187 else if (code <= 0xff) 188 { 189 // G1 code -- ISO 8859-1 Latin 1 characters 190 short character = CCtableG1[code-0xA0]; 191 append_character(cc, service_num, character); 192 i++; 193 } 194 if ((old_i == i) || cc->delayed[service_num]) 195 break; 196 } 197 198 assert(((int)cc->buf_size[service_num] - i) >= 0); 199 if ((cc->buf_size[service_num] - i)>0) 200 { 201 memmove(cc->buf[service_num], cc->buf[service_num] + i, 202 cc->buf_size[service_num] - i); 203 cc->buf_size[service_num] -= i; 204 } 205 else 206 { 207 if (0!=(cc->buf_size[service_num] - i)) 208 { 209 fprintf(stderr, "parse_cc_service_stream buffer error " 210 "i(%i) buf_size(%i)\n", i, cc->buf_size[service_num]); 211 for (i=0; (uint)i < cc->buf_size[service_num]; i++) 212 fprintf(stderr, "0x%x ", cc->buf[service_num][i]); 213 fprintf(stderr, "\n"); 214 } 215 cc->buf_size[service_num] = 0; 216 } 217 } 218 219 static int handle_cc_c0_ext1_p16(CC708Reader* cc, uint service_num, int i) 220 { 221 // C0 code -- subset of ASCII misc. control codes 222 const int code = cc->buf[service_num][i]; 223 if (code<=0xf) 224 { 225 // single byte code 226 if (ETX==code) 227 SEND_STR; 228 else if (BS==code) 229 append_character(cc, service_num, 0x08); 230 else if (FF==code) 231 append_character(cc, service_num, 0x0c); 232 else if (CR==code) 233 append_character(cc, service_num, 0x0d); 234 else if (HCR==code) 235 append_character(cc, service_num, 0x0d); 236 i++; 237 } 238 else if (code<=0x17) 239 { 240 // double byte code 241 const int blk_size = cc->buf_size[service_num]; 242 if (EXT1==code && ((i+1)<blk_size)) 243 { 244 const int code2 = cc->buf[service_num][i+1]; 245 if (code2<=0x1f) 246 { 247 // C2 code -- nothing in EIA-708-A 248 i = handle_cc_c2(cc, service_num, i+1); 249 } 250 else if (code2<=0x7f) 251 { 252 // G2 code -- fractions, drawing, symbols 253 append_character(cc, service_num, CCtableG2[code2-0x20]); 254 i+=2; 255 } 256 else if (code2<=0x9f) 257 { 258 // C3 code -- nothing in EIA-708-A 259 i = handle_cc_c3(cc, service_num, i); 260 } 261 else if (code2<=0xff) 262 { 263 // G3 code -- one symbol in EIA-708-A "[cc]" 264 append_character(cc, service_num, CCtableG3[code2-0xA0]); 265 i+=2; 266 } 267 } 268 else if ((i+1)<blk_size) 269 i+=2; 270 } 271 else if (code<=0x1f) 272 { 273 // triple byte code 274 const int blk_size = cc->buf_size[service_num]; 275 if (P16==code && ((i+2)<blk_size)) 276 { 277 // reserved for large alphabets, but not yet defined 278 } 279 if ((i+2)<blk_size) 280 i+=3; 281 } 282 return i; 283 } 284 285 static int handle_cc_c1(CC708Reader* cc, uint service_num, int i) 286 { 287 const int blk_size = cc->buf_size[service_num]; 288 const int code = cc->buf[service_num][i]; 289 290 //fprintf(stderr, "handle_cc_c1(0x%x, %i, %i)\n", code, i, blk_size); 291 const unsigned char* blk_buf = cc->buf[service_num]; 292 if (code<=CW7) 293 { // no paramaters 294 SEND_STR; 295 cc->SetCurrentWindow(service_num, code-0x80); 296 i+=1; 297 } 298 else if (DLC == cc->buf[service_num][i]) 299 { 300 fprintf(stderr, "DelayCancel i(%i)\n", i); 301 cc->DelayCancel(service_num); 302 cc->delayed[service_num] = 0; 303 i+=1; 304 } 305 else if (code>=CLW && code<=DLY && ((i+1)<blk_size)) 306 { // 1 byte of paramaters 307 int param1 = blk_buf[i+1]; 308 SEND_STR; 309 if (CLW==code) 310 cc->ClearWindows(service_num, param1); 311 else if (DSW==code) 312 cc->DisplayWindows(service_num, param1); 313 else if (HDW==code) 314 cc->HideWindows(service_num, param1); 315 else if (TGW==code) 316 cc->ToggleWindows(service_num, param1); 317 else if (DLW==code) 318 cc->DeleteWindows(service_num, param1); 319 else if (DLY==code) 320 { 321 fprintf(stderr, "Delay()"); 322 cc->Delay(service_num, param1); 323 cc->delayed[service_num] = 1; 324 } 325 i+=2; 326 } 327 else if (SPA==code && ((i+2)<blk_size)) 328 { 329 int pen_size = (blk_buf[i+1] ) & 0x3; 330 int offset = (blk_buf[i+1]>>2) & 0x3; 331 int text_tag = (blk_buf[i+1]>>4) & 0xf; 332 int font_tag = (blk_buf[i+2] ) & 0x7; 333 int edge_type = (blk_buf[i+2]>>3) & 0x7; 334 int underline = (blk_buf[i+2]>>4) & 0x1; 335 int italic = (blk_buf[i+2]>>5) & 0x1; 336 SEND_STR; 337 //fprintf(stderr, "set_pen_attr(0x%08x)(0x%08x, 0x%02x, 0x%02x)\n", 338 // cc->SetPenAttributes, cc, blk_buf[i+1], blk_buf[i+2]); 339 cc->SetPenAttributes(service_num, pen_size, offset, text_tag, 340 font_tag, edge_type, underline, italic); 341 i+=3; 342 } 343 else if (SPC==code && ((i+3)<blk_size)) 344 { 345 int fg_color = (blk_buf[i+1] ) & 0x3f; 346 int fg_opacity = (blk_buf[i+1]>>6) & 0x03; 347 int bg_color = (blk_buf[i+2] ) & 0x3f; 348 int bg_opacity = (blk_buf[i+2]>>6) & 0x03; 349 int edge_color = (blk_buf[i+3]>>6) & 0x3f; 350 SEND_STR; 351 //fprintf(stderr, "set_pen_color(0x%08x)(0x%08x, 0x%02x, 0x%02x, 0x%02x)\n", 352 // cc->SetPenColor, cc, blk_buf[i+1], blk_buf[i+2], blk_buf[i+3]); 353 cc->SetPenColor(service_num, fg_color, fg_opacity, 354 bg_color, bg_opacity, edge_color); 355 i+=4; 356 } 357 else if (SPL==code && ((i+2)<blk_size)) 358 { 359 int row = blk_buf[i+1] & 0x0f; 360 int col = blk_buf[i+2] & 0x3f; 361 SEND_STR; 362 //fprintf(stderr, "set_pen_loc(0x%08x)(0x%08x, 0x%02x, 0x%02x)\n", 363 // cc->SetPenLocation, cc, blk_buf[i+1], blk_buf[i+2]); 364 cc->SetPenLocation(service_num, row, col); 365 i+=3; 366 } 367 else if (SWA==code && ((i+4)<blk_size)) 368 { 369 int fill_color = (blk_buf[i+1] ) & 0x3f; 370 int fill_opacity = (blk_buf[i+1]>>6) & 0x03; 371 int border_color = (blk_buf[i+2] ) & 0x3f; 372 int border_type01 = (blk_buf[i+2]>>6) & 0x03; 373 int justify = (blk_buf[i+3] ) & 0x03; 374 int scroll_dir = (blk_buf[i+3]>>2) & 0x03; 375 int print_dir = (blk_buf[i+3]>>4) & 0x03; 376 int word_wrap = (blk_buf[i+3]>>6) & 0x01; 377 int border_type = (blk_buf[i+3]>>5) | border_type01; 378 int display_eff = (blk_buf[i+4] ) & 0x03; 379 int effect_dir = (blk_buf[i+4]>>2) & 0x03; 380 int effect_speed = (blk_buf[i+4]>>4) & 0x0f; 381 SEND_STR; 382 //fprintf(stderr, "set_win_attr(0x%08x)(0x%08x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n", 383 // cc->SetWindowAttributes, cc, blk_buf[i+1], blk_buf[i+2], blk_buf[i+3], blk_buf[i+4]); 384 cc->SetWindowAttributes( 385 service_num, fill_color, fill_opacity, border_color, border_type, 386 scroll_dir, print_dir, effect_dir, 387 display_eff, effect_speed, justify, word_wrap); 388 i+=5; 389 } 390 else if ((code>=DF0) && (code<=DF7) && ((i+6)<blk_size)) 391 { 392 //fprintf(stderr, "define_window(%i)\n", code-0x98); 393 // param1 394 int priority = ( blk_buf[i+1] ) & 0x7; 395 int col_lock = (blk_buf[i+1]>>3) & 0x1; 396 int row_lock = (blk_buf[i+1]>>4) & 0x1; 397 int visible = (blk_buf[i+1]>>5) & 0x1; 398 // param2 399 int anchor_vertical = blk_buf[i+2] & 0x7f; 400 int relative_pos = (blk_buf[i+2]>>7); 401 // param3 402 int anchor_horizontal = blk_buf[i+3]; 403 // param4 404 int row_count = blk_buf[i+4] & 0xf; 405 int anchor_point = blk_buf[i+4]>>4; 406 // param5 407 int col_count = blk_buf[i+5] & 0x3f; 408 // param6 409 int pen_style = blk_buf[i+6] & 0x7; 410 int win_style = (blk_buf[i+6]>>3) & 0x7; 411 SEND_STR; 412 cc->DefineWindow(service_num, code-0x98, priority, visible, 413 anchor_point, relative_pos, 414 anchor_vertical, anchor_horizontal, 415 row_count, col_count, row_lock, col_lock, 416 pen_style, win_style); 417 i+=7; 418 } 419 else 420 { 421 fprintf(stderr, "handle_cc_c1: (NOT HANDLED) " 422 "code(0x%02x) i(%i) blk_size(%i)\n", code, i, blk_size); 423 } 424 //fprintf(stderr, "handle_cc_c1, returning %i\n", i); 425 return i; 426 } 427 428 static int handle_cc_c2(CC708Reader* cc, uint service_num, int i) 429 { 430 const int blk_size = cc->buf_size[service_num]; 431 const int code = cc->buf[service_num][i+1]; 432 fprintf(stderr, "handle_cc_C2(0x%x)\n", code); 433 if ((code<=0x7) && ((i+1)<blk_size)){ 434 i+=2; 435 SEND_STR; 436 } 437 else if ((code<=0xf) && ((i+2)<blk_size)) 438 { 439 i+=3; 440 SEND_STR; 441 } 442 else if ((code<=0x17) && ((i+3)<blk_size)) 443 { 444 i+=4; 445 SEND_STR; 446 } 447 else if ((code<=0x1f) && ((i+4)<blk_size)) 448 { 449 i+=5; 450 SEND_STR; 451 } 452 return i; 453 } 454 455 static int handle_cc_c3(CC708Reader* cc, uint service_num, int i) 456 { 457 const unsigned char* blk_buf = cc->buf[service_num]; 458 const int blk_size = cc->buf_size[service_num]; 459 const int code = cc->buf[service_num][i+1]; 460 461 fprintf(stderr, "handle_cc_C3(0x%x)\n", code); 462 if ((code<=0x87) && ((i+5)<blk_size)) 463 { 464 i+=6; 465 SEND_STR; 466 } 467 else if ((code<=0x8f) && ((i+6)<blk_size)) 468 { 469 i+=7; 470 SEND_STR; 471 } 472 else if ((i+2)<blk_size) 473 { // varible length commands 474 int length = blk_buf[i+2]&0x3f; 475 if ((i+length)<blk_size) 476 { 477 i+=1+length; 478 SEND_STR; 479 } 480 } 481 return i; 482 } 483 484 static void append_cc(CC708Reader* cc, uint service_num, 485 const unsigned char* blk_buf, int block_size) 486 { 487 assert(cc); 488 assert(block_size + cc->buf_size[service_num] < 489 cc->buf_alloc[service_num]); 490 491 memcpy(cc->buf[service_num] + cc->buf_size[service_num], 492 blk_buf, block_size); 493 494 cc->buf_size[service_num] += block_size; 495 #if DEBUG_CC_SERVICE_2 496 { 497 uint i; 498 fprintf(stderr, "append_cc: "); 499 for (i = 0; i < cc->buf_size[service_num]; i++) 500 fprintf(stderr, "0x%x ", cc->buf[service_num][i]); 501 fprintf(stderr, "\n"); 502 } 503 #endif 504 parse_cc_service_stream(cc, service_num); 505 } 506 507 static void parse_cc_packet(CC708Reader* cb_cbs, CaptionPacket* pkt) 508 { 509 const unsigned char* pkt_buf = pkt->data; 510 const int pkt_size = pkt->size; 511 int off = 1; 512 int service_number = 0; 513 int block_data_offset = 0; 514 int len = ((((int)pkt_buf[0])&0x3f)*2-1)&0xff; 515 int seq_num = (((int)pkt_buf[0])>>6)&0x3; 516 517 #if DEBUG_CC_RAWPACKET 518 { 519 int j; 520 fprintf(stderr, "CC length(%2i) seq_num(%i) ", len, seq_num); 521 for (j=1; j<pkt_size; j++) 522 fprintf(stderr, "0x%x ", pkt_buf[j]); 523 fprintf(stderr, "\n"); 524 } 525 #else 526 (void) seq_num; 527 #endif 528 529 assert(pkt_size<127); 530 assert(len<128); 531 532 while (pkt_buf[off] && off<pkt_size) 533 { // service_block 534 int block_size = pkt_buf[off] & 0x1f; 535 service_number = (pkt_buf[off]>>5) & 0x7; 536 block_data_offset = (0x7==service_number && block_size!=0) ? off+2 : off+1; 537 #if DEBUG_CC_SERVICE_BLOCK 538 fprintf(stderr, "service_block size(%i) num(%i) off(%i) ", 539 block_size, service_number, block_data_offset); 540 #endif 541 if (off+2 == block_data_offset) 542 { 543 int extended_service_number = pkt_buf[off+2] & 0x3f; 544 #if DEBUG_CC_SERVICE_BLOCK 545 fprintf(stderr, "ext_svc_num(%i) ", extended_service_number); 546 #endif 547 service_number = extended_service_number; 548 } 549 if (service_number) 550 { 551 #if DEBUG_CC_SERVICE 552 int i; 553 if (!(2==block_size && 554 0==pkt_buf[block_data_offset] && 555 0==pkt_buf[block_data_offset+1])) 556 { 557 fprintf(stderr, "service %i: ", service_number); 558 for (i=0; i<block_size; i++) 559 fprintf(stderr, "0x%x ", pkt_buf[block_data_offset+i]); 560 fprintf(stderr, "\n"); 561 } 562 #endif 563 append_cc(cb_cbs, service_number, 564 &pkt_buf[block_data_offset], block_size); 565 } 566 off+=block_size+1; 567 } 568 if (off<pkt_size) // must end in null service block, if packet is not full. 569 assert(pkt_buf[off]==0); 570 } 571 572 static void append_character(CC708Reader *cc, uint service_num, short ch) 573 { 574 if (cc->temp_str_size[service_num]+2 > cc->temp_str_alloc[service_num]) 575 { 576 int new_alloc = (cc->temp_str_alloc[service_num]) ? 577 cc->temp_str_alloc[service_num] * 2 : 64; 578 579 cc->temp_str[service_num] = (short*) 580 realloc(cc->temp_str[service_num], new_alloc * sizeof(short)); 581 582 assert(cc->temp_str[service_num]); 583 cc->temp_str_alloc[service_num] = new_alloc; // shorts allocated 584 } 585 586 if (cc->temp_str[service_num]) 587 { 588 int i = cc->temp_str_size[service_num]; 589 cc->temp_str[service_num][i] = ch; 590 cc->temp_str_size[service_num]++; 591 } 592 else 593 { 594 cc->temp_str_size[service_num] = 0; 595 cc->temp_str_alloc[service_num]=0; 596 } 597 } 598 599 ushort CCtableG0[0x60] = 600 { 601 // 0 1 2 3 4 5 6 7 602 // 8 9 a b c d e f 603 ' ', '!','\"', '#', '$', '%', '&', '\'', /* 0x20-0x27 */ 604 '(', ')', '*', '+', ',', '-', '.', '/', /* 0x28-0x2f */ 605 '0', '1', '2', '3', '4', '5', '6', '7', /* 0x30-0x37 */ 606 '8', '9', ':', ';', '<', '=', '>', '?', /* 0x38-0x3f */ 607 608 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 0x40-0x47 */ 609 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 0x48-0x4f */ 610 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 0x50-0x57 */ 611 'X', 'Y', 'Z', '[', '\\',']', '^', '_', /* 0x58-0x5f */ 612 613 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 0x60-0x67 */ 614 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 0x68-0x6f */ 615 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 0x70-0x77 */ 616 'x', 'y', 'z', '{', '|', '}', '~', 0x1d16, // music note /* 0x78-0x7f */ 617 }; 618 619 ushort CCtableG1[0x60] = 620 { 621 // 0 1 2 3 4 5 6 7 622 // 8 9 a b c d e f 623 0xA0, // unicode non-breaking space 624 '¡', '¢', '£', '€', '¥', 'Š', '§', /* 0xa0-0xa7 */ 625 'š', '©', 'ª', '«', '¬', '', '®', '¯', /* 0xa8-0xaf */ 626 '°', '±', '²', '³', 'Ž', 'µ', '¶', '·', /* 0xb0-0xb7 */ 627 'ž', '¹', 'º', '»', 'Œ', 'œ', 'Ÿ', '¿', /* 0xbf-0xbf */ 628 629 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', /* 0xc0-0xc7 */ 630 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', /* 0xcf-0xcf */ 631 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', /* 0xd0-0xd7 */ 632 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', /* 0xdf-0xdf */ 633 634 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', /* 0xe0-0xe7 */ 635 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', /* 0xef-0xef */ 636 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', /* 0xf0-0xf7 */ 637 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ', /* 0xff-0xff */ 638 }; 639 640 ushort CCtableG2[0x60] = 641 { 642 ' ', /* transparent space */ 643 0xA0, /* non-breaking transparent space */ 644 0, 0, /* 0x20-0x23 */ 645 0, 0x2026,/* elipsis */ 646 0, 0, /* 0x24-0x27 */ 647 0, 0, 648 0x160,/*S under \/*/0, /* 0x28-0x2b */ 649 0x152, /* CE */ 0, 650 0, 0, /* 0x2c-0x2f */ 651 0x2DA, /*super dot*/0x2018,/* open ' */ 652 0x2019,/*close ' */ 0x201c,/* open " */ /* 0x30-0x33 */ 653 0x201d,/*close " */ '*', /* dot */ 654 0, 0, /* 0x34-0x37 */ 655 0, '#', /* super TM */ 656 0x161,/*s under \/*/0, /* 0x38-0x3b */ 657 0x153, /* ce */ '#', /* super SM */ 658 0, 0x178,/*Y w/umlout*/ /* 0x3c-0x3f */ 659 660 // 0 1 2 3 661 // 4 5 6 7 662 // 8 9 a b 663 // c d e f 664 0, 0, 0, 0, 665 0, 0, 0, 0, /* 0x40-0x47 */ 666 0, 0, 0, 0, 667 0, 0, 0, 0, /* 0x48-0x4f */ 668 669 0, 0, 0, 0, 670 0, 0, 0, 0, /* 0x50-0x57 */ 671 0, 0, 0, 0, 672 0, 0, 0, 0, /* 0x58-0x5f */ 673 674 0, 0, 0, 0, 675 0, 0, 0, 0, /* 0x60-0x67 */ 676 0, 0, 0, 0, 677 0, 0, 0, 0, /* 0x68-0x6f */ 678 679 0, 0, 680 0, 0, /* 0x70-0x73 */ 681 0, 0, 682 0x215b, /* 1/8 */ 0x215c, /* 3/8 */ /* 0x74-0x77 */ 683 0x215d, /* 5/8 */ 0x215e, /* 7/8 */ 684 0x2502, /*line | */ 0x2510, /*line ~| */ /* 0x78-0x7b */ 685 0x2514, /*line |_*/ 0x2500, /*line -*/ 686 0x2518, /*line _|*/ 0x250c, /*line |~ */ /* 0x7c-0x7f */ 687 }; 688 689 ushort CCtableG3[0x60] = 690 { 691 // 0 1 2 3 4 5 6 7 8 9 a b c d e f 692 '#', /* [CC] closed captioning logo */ 693 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */ 694 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */ 695 696 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0-0xcf */ 697 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0-0xdf */ 698 699 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0-0xff */ 700 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0-0xff */ 701 }; -
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 } 222 ccfonts[i] = ccfont; 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 relative_pos, 33 int anchor_vertical, 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