Ticket #8299: 8299-v1.patch

File 8299-v1.patch, 15.0 KB (added by danielk, 11 years ago)
  • libs/libmythtv/avformatdecoder.cpp

     
    15321532}
    15331533#endif // USING_XVMC
    15341534
    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 
    15441535// CC Parity checking
    15451536// taken from xine-lib libspucc
    15461537
     
    15891580
    15901581void AvFormatDecoder::ScanATSCCaptionStreams(int av_index)
    15911582{
    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();
    15941586
    15951587    // Figure out languages of ATSC captions
    15961588    if (!ic->cur_pmt_sect)
    15971589    {
    1598         default_captions(tracks, av_index);
     1590        VERBOSE(VB_IMPORTANT, LOC_WARN +
     1591                "ScanATSCCaptionStreams() called with no PMT");
    15991592        return;
    16001593    }
    16011594
     
    16141607    }
    16151608
    16161609    if (!pmt.IsVideo(i, "dvb"))
    1617     {
    1618         default_captions(tracks, av_index);
    16191610        return;
    1620     }
    16211611
    16221612    const desc_list_t desc_list = MPEGDescriptor::ParseOnlyInclude(
    16231613        pmt.StreamInfo(i), pmt.StreamInfoLength(i),
    16241614        DescriptorID::caption_service);
    16251615
    1626     map<int,uint> lang_cc_cnt[2];
    16271616    for (uint j = 0; j < desc_list.size(); j++)
    16281617    {
    16291618        const CaptionServiceDescriptor csd(desc_list[j]);
     
    16311620        {
    16321621            int lang = csd.CanonicalLanguageKey(k);
    16331622            int type = csd.Type(k) ? 1 : 0;
    1634             int lang_indx = lang_cc_cnt[type][lang];
    1635             lang_cc_cnt[type][lang]++;
    16361623            if (type)
    16371624            {
    1638                 StreamInfo si(av_index, lang, lang_indx,
     1625                StreamInfo si(av_index, lang, 0/*lang_idx*/,
    16391626                              csd.CaptionServiceNumber(k),
    16401627                              csd.EasyReader(k),
    16411628                              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);
    16501633            }
    16511634            else
    16521635            {
    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);
    16601641            }
    16611642        }
    16621643    }
     1644}
    16631645
    1664     default_captions(tracks, av_index);
     1646void 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    }
    16651709}
    16661710
    16671711void AvFormatDecoder::ScanTeletextCaptions(int av_index)
     
    20102054                               selectedVideoIndex == (int) i);
    20112055
    20122056                ScanATSCCaptionStreams(i);
     2057                UpdateATSCCaptionTracks();
    20132058
    20142059                VERBOSE(VB_PLAYBACK, LOC +
    20152060                        QString("Using %1 for video decoding")
     
    26822727    // reserved                8 1.0   0xff
    26832728    // em_data                 8 2.0
    26842729
     2730    bool had_608 = false, had_708 = false;
    26852731    for (uint cur = 0; cur < cc_count; cur++)
    26862732    {
    26872733        uint cc_code  = buf[2+(cur*3)];
     
    26972743        if (cc_type <= 0x1) // EIA-608 field-1/2
    26982744        {
    26992745            if (cc608_good_parity(cc608_parity_table, data))
     2746            {
     2747                had_608 = true;
    27002748                ccd608->FormatCCField(lastccptsu / 1000, cc_type, data);
     2749            }
    27012750        }
    2702         else // EIA-708 CC data
     2751        else
     2752        {
     2753            had_708 = true;
    27032754            ccd708->decode_cc_data(cc_type, data1, data2);
     2755        }
    27042756    }
     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();
    27052814}
    27062815
    27072816void AvFormatDecoder::HandleGopStart(
  • libs/libmythtv/cc708decoder.cpp

     
    1010#define LOC QString("CC708: ")
    1111#define LOC_ERR QString("CC708, Error: ")
    1212
     13#define DEBUG_CAPTIONS         0
    1314#define DEBUG_CC_SERVICE       0
    1415#define DEBUG_CC_SERVICE_2     0
    1516#define DEBUG_CC_RAWPACKET     0
     17#define DEBUG_CC_VALIDPACKET   0
    1618#define DEBUG_CC_SERVICE_BLOCK 0
    1719
    1820typedef enum
     
    3133    "DTVCC Channel Packet Start"
    3234};
    3335
    34 static void parse_cc_packet(CC708Reader *cb_cbs, CaptionPacket *pkt);
     36static void parse_cc_packet(CC708Reader *cb_cbs, CaptionPacket *pkt,
     37                            time_t last_seen[64]);
    3538
    3639CC708Reader::CC708Reader()
    3740{
     
    6568        //        .arg(data1,0,16).arg(data2,0,16));
    6669
    6770        if (partialPacket.size && reader)
    68             parse_cc_packet(reader, &partialPacket);
     71            parse_cc_packet(reader, &partialPacket, last_seen);
    6972
    7073        partialPacket.data[0] = data1;
    7174        partialPacket.data[1] = data2;
     
    8285    }
    8386}
    8487
    85 #define DEBUG_CAPTIONS 0
     88void CC708Decoder::services(uint seconds, bool seen[64]) const
     89{
     90    time_t now = time(NULL);
     91    time_t then = now - seconds;
    8692
     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
    8798typedef enum
    8899{
    89100    NUL  = 0x00,
     
    212223        if (old_i == i)
    213224        {
    214225#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]);
    218229            fprintf(stderr, "\n");
    219230#endif
    220231            if (blk_size - i > 10)
     
    561572    parse_cc_service_stream(cc, service_num);
    562573}
    563574
    564 static void parse_cc_packet(CC708Reader* cb_cbs, CaptionPacket* pkt)
     575static void parse_cc_packet(CC708Reader* cb_cbs, CaptionPacket* pkt,
     576                            time_t last_seen[64])
    565577{
    566578    const unsigned char* pkt_buf = pkt->data;
    567579    const int pkt_size = pkt->size;
     
    573585
    574586    if (len < 0)
    575587        return;
     588
    576589#if DEBUG_CC_RAWPACKET
     590    if (1)
     591#elif DEBUG_CAPTIONS
     592    if (len > pkt_size)
    577593#else
    578     if (len > pkt_size)
     594    if (0)
    579595#endif
    580596    {
    581597        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);
    583601        for (j = 0; j < pkt_size; j++)
    584602            fprintf(stderr, "0x%x ", pkt_buf[j]);
    585603        fprintf(stderr, "\n");
     
    621639#endif
    622640            append_cc(cb_cbs, service_number,
    623641                      &pkt_buf[block_data_offset], block_size);
     642
     643            last_seen[service_number] = time(NULL);
    624644        }
    625645        off+=block_size+1;
    626646    }
  • libs/libmythtv/cc708decoder.h

     
    55#define CC708DECODER_H_
    66
    77#include <stdint.h>
     8#include <time.h>
    89
    910#include "format.h"
    1011#include "compat.h"
     
    8283{
    8384  public:
    8485    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    }
    8690   ~CC708Decoder() {}
    8791
    8892    void decode_cc_data(uint cc_type, uint data1, uint data2);
    8993
     94    /// \return Services seen in last few seconds as specified.
     95    void services(uint seconds, bool[64]) const;
     96
    9097  private:
    9198    CaptionPacket  partialPacket;
    9299    CC708Reader   *reader;
     100    time_t         last_seen[64];
    93101};
    94102
    95103#endif // CC708DECODER_H_
  • libs/libmythtv/cc608decoder.cpp

     
    9696    FormatCCField(tc, 1, code2);
    9797}
    9898
     99void 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
    99107static const int rowdata[] =
    100108{
    101109    11, -1, 1, 2, 3, 4, 12, 13,
     
    665673    }
    666674
    667675    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);
    668687
    669688    resumetext[mode] = 0;
    670689    if (clr && !len)
  • libs/libmythtv/cc608decoder.h

     
    33#ifndef CCDECODER_H_
    44#define CCDECODER_H_
    55
     6#include <time.h>
    67#include <stdint.h>
    78
    89#include <vector>
     
    5960    QString GetProgramType(bool future) const;
    6061    QString GetXDS(const QString &key) const;
    6162
     63    /// \return Services seen in last few seconds as specified.
     64    void GetServices(uint seconds, bool[4]) const;
     65
    6266  private:
    6367    QChar CharCC(int code) const { return stdchar[code]; }
    6468    void ResetCC(int mode);
     
    7983
    8084    bool ignore_time_code;
    8185
     86    time_t last_seen[4];
     87
    8288    // per-field
    8389    int badvbi[2];
    8490    int lasttc[2];
  • libs/libmythtv/avformatdecoder.h

     
    158158    virtual int AutoSelectTrack(uint type);
    159159
    160160    void ScanATSCCaptionStreams(int av_stream_index);
     161    void UpdateATSCCaptionTracks(void);
    161162    void ScanTeletextCaptions(int av_stream_index);
    162163    void ScanDSMCCStreams(void);
    163164    int AutoSelectAudioTrack(void);
     
    260261    CC708Decoder     *ccd708;
    261262    TeletextDecoder  *ttd;
    262263    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;
    263270
    264271    // MHEG
    265272    InteractiveTV    *itv;                ///< MHEG/MHP decoder