Ticket #8299: 8299-v1.patch
File 8299-v1.patch, 15.0 KB (added by , 14 years ago) |
---|
-
libs/libmythtv/avformatdecoder.cpp
1532 1532 } 1533 1533 #endif // USING_XVMC 1534 1534 1535 void default_captions(sinfo_vec_t *tracks, int av_index)1536 {1537 if (tracks[kTrackTypeCC608].empty())1538 {1539 tracks[kTrackTypeCC608].push_back(StreamInfo(av_index, 0, 0, 1));1540 tracks[kTrackTypeCC608].push_back(StreamInfo(av_index, 0, 2, 3));1541 }1542 }1543 1544 1535 // CC Parity checking 1545 1536 // taken from xine-lib libspucc 1546 1537 … … 1589 1580 1590 1581 void AvFormatDecoder::ScanATSCCaptionStreams(int av_index) 1591 1582 { 1592 tracks[kTrackTypeCC608].clear(); 1593 tracks[kTrackTypeCC708].clear(); 1583 memset(ccX08_in_pmt, 0, sizeof(ccX08_in_pmt)); 1584 pmt_tracks.clear(); 1585 pmt_track_types.clear(); 1594 1586 1595 1587 // Figure out languages of ATSC captions 1596 1588 if (!ic->cur_pmt_sect) 1597 1589 { 1598 default_captions(tracks, av_index); 1590 VERBOSE(VB_IMPORTANT, LOC_WARN + 1591 "ScanATSCCaptionStreams() called with no PMT"); 1599 1592 return; 1600 1593 } 1601 1594 … … 1614 1607 } 1615 1608 1616 1609 if (!pmt.IsVideo(i, "dvb")) 1617 {1618 default_captions(tracks, av_index);1619 1610 return; 1620 }1621 1611 1622 1612 const desc_list_t desc_list = MPEGDescriptor::ParseOnlyInclude( 1623 1613 pmt.StreamInfo(i), pmt.StreamInfoLength(i), 1624 1614 DescriptorID::caption_service); 1625 1615 1626 map<int,uint> lang_cc_cnt[2];1627 1616 for (uint j = 0; j < desc_list.size(); j++) 1628 1617 { 1629 1618 const CaptionServiceDescriptor csd(desc_list[j]); … … 1631 1620 { 1632 1621 int lang = csd.CanonicalLanguageKey(k); 1633 1622 int type = csd.Type(k) ? 1 : 0; 1634 int lang_indx = lang_cc_cnt[type][lang];1635 lang_cc_cnt[type][lang]++;1636 1623 if (type) 1637 1624 { 1638 StreamInfo si(av_index, lang, lang_indx,1625 StreamInfo si(av_index, lang, 0/*lang_idx*/, 1639 1626 csd.CaptionServiceNumber(k), 1640 1627 csd.EasyReader(k), 1641 1628 csd.WideAspectRatio(k)); 1642 1643 tracks[kTrackTypeCC708].push_back(si); 1644 1645 VERBOSE(VB_PLAYBACK, LOC + QString( 1646 "EIA-708 caption service #%1 " 1647 "is in the %2 language.") 1648 .arg(csd.CaptionServiceNumber(k)) 1649 .arg(iso639_key_toName(lang))); 1629 uint key = csd.CaptionServiceNumber(k) + 4; 1630 ccX08_in_pmt[key] = true; 1631 pmt_tracks.push_back(si); 1632 pmt_track_types.push_back(kTrackTypeCC708); 1650 1633 } 1651 1634 else 1652 1635 { 1653 int line21 = csd.Line21Field(k) ? 2 : 1; 1654 StreamInfo si(av_index, lang, lang_indx, line21); 1655 tracks[kTrackTypeCC608].push_back(si); 1656 1657 VERBOSE(VB_PLAYBACK, LOC + QString( 1658 "EIA-608 caption %1 is in the %2 language.") 1659 .arg(line21).arg(iso639_key_toName(lang))); 1636 int line21 = csd.Line21Field(k) ? 3 : 1; 1637 StreamInfo si(av_index, lang, 0/*lang_idx*/, line21); 1638 ccX08_in_pmt[line21-1] = true; 1639 pmt_tracks.push_back(si); 1640 pmt_track_types.push_back(kTrackTypeCC608); 1660 1641 } 1661 1642 } 1662 1643 } 1644 } 1663 1645 1664 default_captions(tracks, av_index); 1646 void AvFormatDecoder::UpdateATSCCaptionTracks(void) 1647 { 1648 tracks[kTrackTypeCC608].clear(); 1649 tracks[kTrackTypeCC708].clear(); 1650 memset(ccX08_in_tracks, 0, sizeof(ccX08_in_tracks)); 1651 1652 uint pidx = 0, sidx = 0; 1653 map<int,uint> lang_cc_cnt[2]; 1654 while (true) 1655 { 1656 bool pofr = pidx >= (uint)pmt_tracks.size(); 1657 bool sofr = sidx >= (uint)stream_tracks.size(); 1658 if (pofr && sofr) 1659 break; 1660 1661 // choose lowest available next.. 1662 // stream_id's of 608 and 708 streams alias, but this 1663 // is ok as we just want each list to be ordered. 1664 StreamInfo const *si = NULL; 1665 int type = 0; // 0 if 608, 1 if 708 1666 bool isp = true; // if true use pmt_tracks next, else stream_tracks 1667 1668 if (pofr && !sofr) 1669 isp = false; 1670 else if (!pofr && sofr) 1671 isp = true; 1672 else if (stream_tracks[sidx] < pmt_tracks[pidx]) 1673 isp = false; 1674 1675 if (isp) 1676 { 1677 si = &pmt_tracks[pidx]; 1678 type = kTrackTypeCC708 == pmt_track_types[pidx] ? 1 : 0; 1679 pidx++; 1680 } 1681 else 1682 { 1683 si = &stream_tracks[sidx]; 1684 type = kTrackTypeCC708 == stream_track_types[sidx] ? 1 : 0; 1685 sidx++; 1686 } 1687 1688 StreamInfo nsi(*si); 1689 int lang_indx = lang_cc_cnt[type][nsi.language]; 1690 lang_cc_cnt[type][nsi.language]++; 1691 nsi.language_index = lang_indx; 1692 tracks[(type) ? kTrackTypeCC708 : kTrackTypeCC608].push_back(nsi); 1693 int key = (int)nsi.stream_id + ((type) ? 4 : -1); 1694 if (key < 0) 1695 { 1696 VERBOSE(VB_IMPORTANT, LOC + 1697 "Programmer Error in_tracks key too small"); 1698 } 1699 else 1700 { 1701 ccX08_in_tracks[key] = true; 1702 } 1703 VERBOSE(VB_PLAYBACK, LOC + QString( 1704 "%1 caption service #%2 is in the %3 language.") 1705 .arg((type) ? "EIA-708" : "EIA-608") 1706 .arg(nsi.stream_id) 1707 .arg(iso639_key_toName(nsi.language))); 1708 } 1665 1709 } 1666 1710 1667 1711 void AvFormatDecoder::ScanTeletextCaptions(int av_index) … … 2010 2054 selectedVideoIndex == (int) i); 2011 2055 2012 2056 ScanATSCCaptionStreams(i); 2057 UpdateATSCCaptionTracks(); 2013 2058 2014 2059 VERBOSE(VB_PLAYBACK, LOC + 2015 2060 QString("Using %1 for video decoding") … … 2682 2727 // reserved 8 1.0 0xff 2683 2728 // em_data 8 2.0 2684 2729 2730 bool had_608 = false, had_708 = false; 2685 2731 for (uint cur = 0; cur < cc_count; cur++) 2686 2732 { 2687 2733 uint cc_code = buf[2+(cur*3)]; … … 2697 2743 if (cc_type <= 0x1) // EIA-608 field-1/2 2698 2744 { 2699 2745 if (cc608_good_parity(cc608_parity_table, data)) 2746 { 2747 had_608 = true; 2700 2748 ccd608->FormatCCField(lastccptsu / 1000, cc_type, data); 2749 } 2701 2750 } 2702 else // EIA-708 CC data 2751 else 2752 { 2753 had_708 = true; 2703 2754 ccd708->decode_cc_data(cc_type, data1, data2); 2755 } 2704 2756 } 2757 2758 bool need_change_608 = false; 2759 bool seen_608[4]; 2760 if (had_608) 2761 { 2762 ccd608->GetServices(15/*seconds*/, seen_608); 2763 for (uint i = 0; i < 4; i++) 2764 { 2765 need_change_608 |= (seen_608[i] && !ccX08_in_tracks[i]) || 2766 (!seen_608[i] && ccX08_in_tracks[i] && !ccX08_in_pmt[i]); 2767 } 2768 } 2769 2770 bool need_change_708 = false; 2771 bool seen_708[64]; 2772 if (had_708 || need_change_608) 2773 { 2774 ccd708->services(15/*seconds*/, seen_708); 2775 for (uint i = 1; i < 64 && !need_change_608 && !need_change_708; i++) 2776 { 2777 need_change_708 |= (seen_708[i] && !ccX08_in_tracks[i+4]) || 2778 (!seen_708[i] && ccX08_in_tracks[i+4] && !ccX08_in_pmt[i+4]); 2779 } 2780 if (need_change_708 && !had_608) 2781 ccd608->GetServices(15/*seconds*/, seen_608); 2782 } 2783 2784 if (!need_change_608 && !need_change_708) 2785 return; 2786 2787 ScanATSCCaptionStreams(selectedVideoIndex); 2788 2789 stream_tracks.clear(); 2790 stream_track_types.clear(); 2791 int av_index = selectedVideoIndex; 2792 int lang = iso639_str3_to_key("und"); 2793 for (uint i = 0; i < 4; i++) 2794 { 2795 if (seen_608[i]) 2796 { 2797 StreamInfo si(av_index, lang, 0/*lang_idx*/, 2798 i+1, false/*easy*/, false/*wide*/); 2799 stream_tracks.push_back(si); 2800 stream_track_types.push_back(kTrackTypeCC608); 2801 } 2802 } 2803 for (uint i = 1; i < 64; i++) 2804 { 2805 if (seen_708[i] && !ccX08_in_pmt[i+4]) 2806 { 2807 StreamInfo si(av_index, lang, 0/*lang_idx*/, 2808 i, false/*easy*/, true/*wide*/); 2809 stream_tracks.push_back(si); 2810 stream_track_types.push_back(kTrackTypeCC708); 2811 } 2812 } 2813 UpdateATSCCaptionTracks(); 2705 2814 } 2706 2815 2707 2816 void AvFormatDecoder::HandleGopStart( -
libs/libmythtv/cc708decoder.cpp
10 10 #define LOC QString("CC708: ") 11 11 #define LOC_ERR QString("CC708, Error: ") 12 12 13 #define DEBUG_CAPTIONS 0 13 14 #define DEBUG_CC_SERVICE 0 14 15 #define DEBUG_CC_SERVICE_2 0 15 16 #define DEBUG_CC_RAWPACKET 0 17 #define DEBUG_CC_VALIDPACKET 0 16 18 #define DEBUG_CC_SERVICE_BLOCK 0 17 19 18 20 typedef enum … … 31 33 "DTVCC Channel Packet Start" 32 34 }; 33 35 34 static void parse_cc_packet(CC708Reader *cb_cbs, CaptionPacket *pkt); 36 static void parse_cc_packet(CC708Reader *cb_cbs, CaptionPacket *pkt, 37 time_t last_seen[64]); 35 38 36 39 CC708Reader::CC708Reader() 37 40 { … … 65 68 // .arg(data1,0,16).arg(data2,0,16)); 66 69 67 70 if (partialPacket.size && reader) 68 parse_cc_packet(reader, &partialPacket );71 parse_cc_packet(reader, &partialPacket, last_seen); 69 72 70 73 partialPacket.data[0] = data1; 71 74 partialPacket.data[1] = data2; … … 82 85 } 83 86 } 84 87 85 #define DEBUG_CAPTIONS 0 88 void CC708Decoder::services(uint seconds, bool seen[64]) const 89 { 90 time_t now = time(NULL); 91 time_t then = now - seconds; 86 92 93 seen[0] = false; // service zero is not allowed in CEA-708-D 94 for (uint i = 1; i < 64; i++) 95 seen[i] = (last_seen[i] >= then); 96 } 97 87 98 typedef enum 88 99 { 89 100 NUL = 0x00, … … 212 223 if (old_i == i) 213 224 { 214 225 #if DEBUG_CC_SERVICE 215 fprintf(stderr, "old_i == i == % 1\n", i);216 for (int i=0; i < blk_size; i++)217 fprintf(stderr, "0x%x ", cc->buf[service_num][ i]);226 fprintf(stderr, "old_i == i == %i\n", i); 227 for (int j = 0; j < blk_size; j++) 228 fprintf(stderr, "0x%x ", cc->buf[service_num][j]); 218 229 fprintf(stderr, "\n"); 219 230 #endif 220 231 if (blk_size - i > 10) … … 561 572 parse_cc_service_stream(cc, service_num); 562 573 } 563 574 564 static void parse_cc_packet(CC708Reader* cb_cbs, CaptionPacket* pkt) 575 static void parse_cc_packet(CC708Reader* cb_cbs, CaptionPacket* pkt, 576 time_t last_seen[64]) 565 577 { 566 578 const unsigned char* pkt_buf = pkt->data; 567 579 const int pkt_size = pkt->size; … … 573 585 574 586 if (len < 0) 575 587 return; 588 576 589 #if DEBUG_CC_RAWPACKET 590 if (1) 591 #elif DEBUG_CAPTIONS 592 if (len > pkt_size) 577 593 #else 578 if ( len > pkt_size)594 if (0) 579 595 #endif 580 596 { 581 597 int j; 582 fprintf(stderr, "CC length(%2i) seq_num(%i) ", len, seq_num); 598 int srv = (pkt_buf[off]>>5) & 0x7; 599 fprintf(stderr, "CC708 len %2i srv0 %i seq %i ", 600 len, srv, seq_num); 583 601 for (j = 0; j < pkt_size; j++) 584 602 fprintf(stderr, "0x%x ", pkt_buf[j]); 585 603 fprintf(stderr, "\n"); … … 621 639 #endif 622 640 append_cc(cb_cbs, service_number, 623 641 &pkt_buf[block_data_offset], block_size); 642 643 last_seen[service_number] = time(NULL); 624 644 } 625 645 off+=block_size+1; 626 646 } -
libs/libmythtv/cc708decoder.h
5 5 #define CC708DECODER_H_ 6 6 7 7 #include <stdint.h> 8 #include <time.h> 8 9 9 10 #include "format.h" 10 11 #include "compat.h" … … 82 83 { 83 84 public: 84 85 CC708Decoder(CC708Reader *ccr) : reader(ccr) 85 { bzero(&partialPacket, sizeof(CaptionPacket)); } 86 { 87 memset(&partialPacket, 0, sizeof(CaptionPacket)); 88 memset(last_seen, 0, sizeof(last_seen)); 89 } 86 90 ~CC708Decoder() {} 87 91 88 92 void decode_cc_data(uint cc_type, uint data1, uint data2); 89 93 94 /// \return Services seen in last few seconds as specified. 95 void services(uint seconds, bool[64]) const; 96 90 97 private: 91 98 CaptionPacket partialPacket; 92 99 CC708Reader *reader; 100 time_t last_seen[64]; 93 101 }; 94 102 95 103 #endif // CC708DECODER_H_ -
libs/libmythtv/cc608decoder.cpp
96 96 FormatCCField(tc, 1, code2); 97 97 } 98 98 99 void CC608Decoder::GetServices(uint seconds, bool seen[4]) const 100 { 101 time_t now = time(NULL); 102 time_t then = now - seconds; 103 for (uint i = 0; i < 4; i++) 104 seen[i] = (last_seen[i] >= then); 105 } 106 99 107 static const int rowdata[] = 100 108 { 101 109 11, -1, 1, 2, 3, 4, 12, 13, … … 665 673 } 666 674 667 675 reader->AddTextData(rbuf, len, timecode[mode], 'C'); 676 int ccmode = rbuf[3] & CC_MODE_MASK; 677 int stream = -1; 678 switch (ccmode) 679 { 680 case CC_CC1: stream = 0; break; 681 case CC_CC2: stream = 1; break; 682 case CC_CC3: stream = 2; break; 683 case CC_CC4: stream = 3; break; 684 } 685 if (stream >= 0) 686 last_seen[stream] = time(NULL); 668 687 669 688 resumetext[mode] = 0; 670 689 if (clr && !len) -
libs/libmythtv/cc608decoder.h
3 3 #ifndef CCDECODER_H_ 4 4 #define CCDECODER_H_ 5 5 6 #include <time.h> 6 7 #include <stdint.h> 7 8 8 9 #include <vector> … … 59 60 QString GetProgramType(bool future) const; 60 61 QString GetXDS(const QString &key) const; 61 62 63 /// \return Services seen in last few seconds as specified. 64 void GetServices(uint seconds, bool[4]) const; 65 62 66 private: 63 67 QChar CharCC(int code) const { return stdchar[code]; } 64 68 void ResetCC(int mode); … … 79 83 80 84 bool ignore_time_code; 81 85 86 time_t last_seen[4]; 87 82 88 // per-field 83 89 int badvbi[2]; 84 90 int lasttc[2]; -
libs/libmythtv/avformatdecoder.h
158 158 virtual int AutoSelectTrack(uint type); 159 159 160 160 void ScanATSCCaptionStreams(int av_stream_index); 161 void UpdateATSCCaptionTracks(void); 161 162 void ScanTeletextCaptions(int av_stream_index); 162 163 void ScanDSMCCStreams(void); 163 164 int AutoSelectAudioTrack(void); … … 260 261 CC708Decoder *ccd708; 261 262 TeletextDecoder *ttd; 262 263 int cc608_parity_table[256]; 264 bool ccX08_in_pmt[64+4]; 265 bool ccX08_in_tracks[64+4]; 266 QList<StreamInfo> pmt_tracks; 267 QList<TrackType> pmt_track_types; 268 QList<StreamInfo> stream_tracks; 269 QList<TrackType> stream_track_types; 263 270 264 271 // MHEG 265 272 InteractiveTV *itv; ///< MHEG/MHP decoder