commit 99db3bd9a9d0aabd23c058414a725aa3e1653024
Author: Gregorio Gervasio, Jr <ggervasio@yahoo.com>
Date: Thu Dec 2 19:39:19 2010 -0800
Fix CC for digital streams with duplicate codes. Fix handling of multiple CC backspace codes.
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index 484af06..e8254c7 100644
a
|
b
|
AvFormatDecoder::AvFormatDecoder(MythPlayer *parent, |
295 | 295 | params.prealloced_context = 1; |
296 | 296 | audioSamples = (short int *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE * |
297 | 297 | sizeof(int32_t)); |
298 | | ccd608->SetIgnoreTimecode(true); |
| 298 | ccd608->SetDigitalTimecode(true); |
299 | 299 | |
300 | 300 | bool debug = VERBOSE_LEVEL_CHECK(VB_LIBAV); |
301 | 301 | av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR); |
… |
… |
void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len) |
2406 | 2406 | return; |
2407 | 2407 | |
2408 | 2408 | bool had_608 = false, had_708 = false; |
| 2409 | int cc_type_found[2] = { 0, 0 }; |
2409 | 2410 | for (uint cur = 0; cur < cc_count; cur++) |
2410 | 2411 | { |
2411 | 2412 | uint cc_code = buf[2+(cur*3)]; |
… |
… |
void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len) |
2423 | 2424 | if (cc608_good_parity(cc608_parity_table, data)) |
2424 | 2425 | { |
2425 | 2426 | had_608 = true; |
2426 | | ccd608->FormatCCField(lastccptsu / 1000, cc_type, data); |
| 2427 | ccd608->FormatCCField(lastccptsu / 1000 + cc_type_found[cc_type], cc_type, data); |
| 2428 | cc_type_found[cc_type]++; // need unique timestamps to help decoder |
| 2429 | // distinguish multiple codes in the same packet |
| 2430 | // from repeated codes in separate packets |
2427 | 2431 | } |
2428 | 2432 | } |
2429 | 2433 | else |
diff --git a/mythtv/libs/libmythtv/cc608decoder.cpp b/mythtv/libs/libmythtv/cc608decoder.cpp
index 9e21e1f..d689298 100644
a
|
b
|
using namespace std; |
18 | 18 | static void init_xds_program_type(QString xds_program_type[96]); |
19 | 19 | |
20 | 20 | CC608Decoder::CC608Decoder(CC608Input *ccr) |
21 | | : reader(ccr), ignore_time_code(false), |
| 21 | : reader(ccr), digital_time_code(false), |
22 | 22 | rbuf(new unsigned char[sizeof(ccsubtitle)+255]), |
23 | 23 | vps_l(0), |
24 | 24 | wss_flags(0), wss_valid(false), |
… |
… |
void CC608Decoder::FormatCCField(int tc, int field, int data) |
176 | 176 | } |
177 | 177 | |
178 | 178 | if (FalseDup(tc, field, data)) |
179 | | goto skip; |
| 179 | { |
| 180 | if (digital_time_code) |
| 181 | return; |
| 182 | else |
| 183 | goto skip; |
| 184 | } |
180 | 185 | |
181 | 186 | XDSDecode(field, b1, b2); |
182 | 187 | |
… |
… |
void CC608Decoder::FormatCCField(int tc, int field, int data) |
416 | 421 | style[mode] = CC_STYLE_ROLLUP; |
417 | 422 | break; |
418 | 423 | case 0x2C: //erase displayed memory |
419 | | if (ignore_time_code || |
| 424 | if (digital_time_code || |
420 | 425 | (tc - lastclr[mode]) > 5000 || |
421 | 426 | lastclr[mode] == 0) |
422 | 427 | // don't overflow the frontend with |
… |
… |
void CC608Decoder::FormatCCField(int tc, int field, int data) |
451 | 456 | // flush |
452 | 457 | BufferCC(mode, len, 0); |
453 | 458 | } |
454 | | else if (ignore_time_code || |
| 459 | else if (digital_time_code || |
455 | 460 | (tc - lastclr[mode]) > 5000 || |
456 | 461 | lastclr[mode] == 0) |
457 | 462 | // clear and flush |
… |
… |
void CC608Decoder::FormatCCField(int tc, int field, int data) |
505 | 510 | for (mode = field*4; mode < (field*4 + 4); mode++) |
506 | 511 | { |
507 | 512 | len = ccbuf[mode].length(); |
508 | | if ((ignore_time_code || ((tc - timecode[mode]) > 100)) && |
| 513 | if ((digital_time_code || ((tc - timecode[mode]) > 100)) && |
509 | 514 | (style[mode] != CC_STYLE_POPUP) && len) |
510 | 515 | { |
511 | 516 | // flush unfinished line if waiting too long |
… |
… |
int CC608Decoder::FalseDup(int tc, int field, int data) |
533 | 538 | b1 = data & 0x7f; |
534 | 539 | b2 = (data >> 8) & 0x7f; |
535 | 540 | |
536 | | if (ignore_time_code) |
| 541 | if (digital_time_code) |
537 | 542 | { |
538 | | // just suppress duplicate control codes |
| 543 | // some digital streams have duplicate codes |
| 544 | // with the same time code; |
| 545 | // suppress those |
539 | 546 | if ((data == lastcode[field]) && |
| 547 | (tc == lasttc[field])) |
| 548 | { |
| 549 | return 1; |
| 550 | } |
| 551 | |
| 552 | // most digital streams with encoded VBI |
| 553 | // have duplicate control codes; |
| 554 | // suppress every other repeated control code |
| 555 | else if ((data == lastcode[field]) && |
540 | 556 | ((b1 & 0x70) == 0x10)) |
| 557 | { |
| 558 | lastcode[field] = -1; |
541 | 559 | return 1; |
| 560 | } |
542 | 561 | else |
543 | 562 | return 0; |
544 | 563 | } |
diff --git a/mythtv/libs/libmythtv/cc608decoder.h b/mythtv/libs/libmythtv/cc608decoder.h
index 1463144..16ba609 100644
a
|
b
|
class CC608Decoder |
51 | 51 | void DecodeVPS(const unsigned char *buf); |
52 | 52 | void DecodeWSS(const unsigned char *buf); |
53 | 53 | |
54 | | void SetIgnoreTimecode(bool val) { ignore_time_code = val; } |
| 54 | void SetDigitalTimecode(bool val) { digital_time_code = val; } |
55 | 55 | |
56 | 56 | uint GetRatingSystems(bool future) const; |
57 | 57 | uint GetRating(uint i, bool future) const; |
… |
… |
class CC608Decoder |
81 | 81 | |
82 | 82 | CC608Input *reader; |
83 | 83 | |
84 | | bool ignore_time_code; |
| 84 | bool digital_time_code; |
85 | 85 | |
86 | 86 | time_t last_seen[4]; |
87 | 87 | |