Ticket #4273: mythtv-4273.patch

File mythtv-4273.patch, 13.5 KB (added by pholmes@…, 16 years ago)

Modification for mythtranscode (needs the srttypeteletext files)

  • programs/mythtranscode/mpeg2fix.cpp

     
    1515#include <getopt.h>
    1616#include <stdint.h>
    1717
     18#include "../libmythtv/mpeg/mpegtables.h"
     19#include "../libs/libmythtv/mpeg/dvbdescriptors.h"
     20#include "../libs/libmythtv/vbilut.h"
     21
    1822#ifndef O_LARGEFILE
    1923#define O_LARGEFILE 0
    2024#endif
     
    196200    return (delta);
    197201}
    198202
    199 MPEG2fixup::MPEG2fixup(const char *inf, const char *outf,
     203MPEG2fixup::MPEG2fixup(const char *inf, const char *outf, const char *subtitlef,
    200204                       QMap<long long, int> *deleteMap,
    201205                       const char *fmt, int norp, int fixPTS, int maxf,
    202206                       bool showprog, int otype, void (*update_func)(float),
     
    204208{
    205209    displayFrame = new QPtrListIterator<MPEG2frame> (vFrame);
    206210
     211    subtitle_id = -1;
     212    ttd = NULL;
     213    subtitlefile = subtitlef;
     214    if (subtitlefile.length() > 0)
     215    {
     216        ttd = new TeletextDecoder();
     217        ttd_viewer = new SRTTypeTeletext();
     218        ttd->SetViewer(ttd_viewer);
     219    }
     220   
    207221    infile = inf;
    208222    rx.outfile = outf;
    209223    rx.done = 0;
     
    307321            delete tmpFrame;
    308322        }
    309323    }
     324    max_frames += sFrame.count();
     325    while (sFrame.count())
     326    {
     327        tmpFrame = sFrame.first();
     328        sFrame.remove();
     329        delete tmpFrame;
     330    }
    310331    max_frames += framePool.count();
    311332    while (framePool.count())
    312333        delete framePool.dequeue();
     
    766787                            .arg(inputFC->streams[i]->codec->codec_id));
    767788                break;
    768789
     790            case CODEC_TYPE_DATA:
     791                if (subtitle_id == -1 &&                                                            // see if subtitle not yet found
     792                    ttd != NULL)                                                                    // and we want to decode the subtitles
     793                {
     794                    if (inputFC->cur_pmt_sect)
     795                    {
     796                        const PESPacket pes = PESPacket::ViewData(inputFC->cur_pmt_sect);
     797                        const PSIPTable psip(pes);
     798                        const ProgramMapTable pmt(psip);
     799   
     800                        for (uint i = 0; i < pmt.StreamCount() && subtitle_id == -1; i++)
     801                        {
     802                            if (pmt.StreamType(i) != 6)
     803                                continue;
     804
     805                            const desc_list_t desc_list = MPEGDescriptor::ParseOnlyInclude(
     806                                    pmt.StreamInfo(i), pmt.StreamInfoLength(i),
     807                                    DescriptorID::teletext);
     808
     809                            for (uint j = 0; j < desc_list.size() && subtitle_id == -1; j++)
     810                            {
     811                                const TeletextDescriptor td(desc_list[j]);
     812                                for (uint k = 0; k < td.StreamCount() && subtitle_id == -1; k++)
     813                                {
     814                                    int type = td.TeletextType(k);
     815                                    if (type != 2)
     816                                        continue;
     817
     818                                    subtitle_language = td.CanonicalLanguageKey(k);
     819                                    subtitle_magazine = td.TeletextMagazineNum(k)?:8;
     820                                    subtitle_pagenum  = td.TeletextPageNum(k);
     821                                    aubtitle_lang_idx = (subtitle_magazine << 8) | subtitle_pagenum;
     822
     823                                    VERBOSE(MPF_GENERAL, QString("Teletext caption #%1 is in the %2 language "
     824                                                                 "on page %3 %4.")
     825                                                            .arg(k).arg(iso639_key_toName(subtitle_language))
     826                                                            .arg(subtitle_magazine).arg(subtitle_pagenum));
     827                                    subtitle_id = i;
     828                                    ttd_viewer->SetPage((subtitle_magazine << 8) | subtitle_pagenum, -1);
     829                                    ttd_viewer->SetDisplaying(true);
     830                                }
     831                            }
     832                        }
     833                    }
     834                }
     835                break;
     836               
    769837            default:
    770838                VERBOSE(MPF_GENERAL, QString(
    771839                        "Skipping unsupported codec %1 on stream %2")
     
    11811249            }
    11821250
    11831251            if (pkt->stream_index == vid_id ||
     1252                pkt->stream_index == subtitle_id ||
    11841253                    aFrame.contains(pkt->stream_index))
    11851254                done = 1;
    11861255            else
     
    12321301                av_free_packet(pkt);
    12331302                return 0;
    12341303
     1304            case CODEC_TYPE_DATA:
     1305                if (inputFC->streams[pkt->stream_index]->codec->codec_id   == CODEC_ID_DVB_VBI)
     1306                {
     1307                    sFrame.append(tmpFrame);
     1308                }
     1309                else if (inputFC->streams[pkt->stream_index]->codec->codec_id == CODEC_ID_MPEG2VBI)
     1310                {
     1311                    //todo....
     1312                    framePool.enqueue(tmpFrame);
     1313                }
     1314                else
     1315                {
     1316                    framePool.enqueue(tmpFrame);
     1317                }
     1318                av_free_packet(pkt);
     1319                return 0;
     1320               
    12351321            default:
    12361322                framePool.enqueue(tmpFrame);
    12371323                av_free_packet(pkt);
     
    12831369        if (vFrame.isEmpty())
    12841370            continue;
    12851371
     1372        while (!sFrame.isEmpty())
     1373        {
     1374            framePool.enqueue(sFrame.first());
     1375            sFrame.removeFirst();
     1376        }
     1377       
    12861378        for (QMap<int, QPtrList<MPEG2frame> >::iterator it = aFrame.begin();
    12871379                it != aFrame.end(); it++)
    12881380        {
     
    17611853                       GetNbFields(curFrame)));
    17621854}
    17631855
     1856void MPEG2fixup::ProcessDVBDataPacket()
     1857{
     1858    const uint8_t *buf     = sFrame.first()->pkt.data;
     1859    const uint8_t *buf_end = sFrame.first()->pkt.data + sFrame.first()->pkt.size;
     1860
     1861    while (buf < buf_end)
     1862    {
     1863        if (*buf == 0x10)
     1864            buf++; // skip
     1865
     1866        if (*buf == 0x02)
     1867        {
     1868            buf += 3;
     1869            ttd->Decode(buf+1, VBI_DVB);
     1870        }
     1871        else if (*buf == 0x03)
     1872        {
     1873            buf += 3;
     1874            ttd->Decode(buf+1, VBI_DVB_SUBTITLE);
     1875        }
     1876        else if (*buf == 0xff)
     1877        {
     1878            buf += 3;
     1879        }
     1880        else
     1881        {
     1882            VERBOSE(VB_VBI, QString("VBI: Unknown descriptor: %1").arg(*buf));
     1883        }
     1884
     1885        buf += 43;
     1886    }
     1887}
     1888
    17641889int MPEG2fixup::Start()
    17651890{
    17661891    //NOTE: expectedvPTS/DTS are in units of SCR (300*PTS) to allow for better
     
    17741899    int ret;
    17751900    QMap<int, int> af_dlta_cnt, cutState;
    17761901    //  int i;
    1777 
    17781902    AVPacket pkt, lastRealvPkt;
    1779 
     1903    SRTOutputFile subtitleOutput(subtitlefile);
     1904   
    17801905    if (! InitAV(infile.ascii(), format, 0))
    17811906    {
    17821907        return (TRANSCODE_EXIT_UNKNOWN_ERROR);
     
    17851910    if (! FindStart())
    17861911        return (TRANSCODE_EXIT_UNKNOWN_ERROR);
    17871912
     1913    if (ttd != NULL)
     1914    {
     1915        if (subtitleOutput.Open() == false)
     1916        {
     1917             return (TRANSCODE_EXIT_UNKNOWN_ERROR);
     1918        }
     1919        ttd_viewer->Set_Output_Device(&subtitleOutput);
     1920    }
     1921
    17881922    av_init_packet(&pkt);
    17891923
    17901924    ptsIncrement = vFrame.first()->mpeg2_seq.frame_period / 300;
     
    21872321                StoreSecondary();
    21882322        }
    21892323
     2324        if (ttd != NULL)
     2325        {
     2326            subtitleOutput.Set_DTS(expectedDTS / 300);                                          // need to update the DTS value
     2327            subtitleOutput.Set_Enable(discard == 0);                                            // need to handle cut points
     2328            while (sFrame.count() > 1)
     2329            {   
     2330                ProcessDVBDataPacket();                                                         // process the frames
     2331                //here... to do. Need to get the data from the subtitle and save to a file.
     2332                //or do it in the above procedure?
     2333                framePool.enqueue(sFrame.first());
     2334                sFrame.remove();           
     2335            }
     2336        }
     2337       
    21902338        for (QMap<int, QPtrList<MPEG2frame> >::iterator it = aFrame.begin();
    21912339                it != aFrame.end(); it++)
    21922340        {
     
    21942342            AVCodecContext *CC = getCodecContext(it.key());
    21952343            bool backwardsPTS = false;
    21962344
     2345            VERBOSE(MPF_PROCESS, QString("AFrame.key %1").arg(it.key()));
     2346           
    21972347            while (af->count())
    21982348            {
    21992349                // What to do if the CC is corrupt?
  • programs/mythtranscode/mythtranscode.pro

     
    1010QMAKE_CLEAN += $(TARGET)
    1111
    1212# Input
    13 SOURCES += main.cpp transcode.cpp mpeg2fix.cpp helper.c
     13SOURCES += main.cpp transcode.cpp mpeg2fix.cpp helper.c srttypeteletext.cpp
    1414SOURCES += replex/element.c replex/mpg_common.c replex/multiplex.c \
    1515           replex/pes.c     replex/ringbuffer.c replex/ts.c
    16 HEADERS += mpeg2fix.h transcodedefs.h
     16HEADERS += mpeg2fix.h transcodedefs.h srttypeteletext.h
    1717HEADERS += replex/element.h replex/mpg_common.h replex/multiplex.h \
    1818           replex/pes.h     replex/ringbuffer.h replex/ts.h
    1919
  • programs/mythtranscode/main.cpp

     
    5757    cerr << "\t--video               : Specifies that this is not a mythtv recording\n";
    5858    cerr << "\t                        (must be used with --infile)\n";
    5959    cerr << "\t--showprogress        : Display status info to the stdout\n";
     60    cerr << "\t--subtitle       or -t: Subtitle output file\n";
    6061    cerr << "\t--verbose level  or -v: Use '-v help' for level info\n";
    6162    cerr << "\t--help           or -h: Prints this help statement.\n";
    6263}
    6364
    6465int main(int argc, char *argv[])
    6566{
    66     QString chanid, starttime, infile, outfile;
     67    QString chanid, starttime, infile, outfile, subtitlefile;
    6768    QString profilename = QString("autodetect");
    6869    QString fifodir = NULL;
    6970    int jobID = -1;
     
    161162                return TRANSCODE_EXIT_INVALID_CMDLINE;
    162163            }
    163164        }
     165        else if (!strcmp(a.argv()[argpos],"-t") ||
     166                 !strcmp(a.argv()[argpos],"--subtitle"))
     167        {
     168            if(a.argc() > argpos)
     169            {
     170                subtitlefile = a.argv()[argpos + 1];
     171                ++argpos;
     172            }
     173            else
     174            {
     175                cerr << "Missing argument to -t/--subtitle option\n";
     176                usage(a.argv()[0]);
     177                return TRANSCODE_EXIT_INVALID_CMDLINE;
     178            }
     179        }
    164180        else if (!strcmp(a.argv()[argpos],"-V"))
    165181        {
    166182            if (a.argc() > argpos)
     
    509525           check_func = &CheckJobQueue;
    510526        }
    511527        MPEG2fixup *m2f = new MPEG2fixup(infile.ascii(), outfile.ascii(),
     528                                         subtitlefile.ascii(),
    512529                                         &deleteMap, NULL, false, false, 20,
    513530                                         showprogress, otype, update_func,
    514531                                         check_func);
  • programs/mythtranscode/mpeg2fix.h

     
    77#include <qvaluelist.h>
    88#include <qstringlist.h>
    99#include <qdatetime.h>
     10#include <qfile.h>
    1011
    1112#include "transcodedefs.h"
    1213
     
    2425#include "../libmythmpeg2/mpeg2.h"
    2526}
    2627
     28#include "../libmythtv/teletextdecoder.h"
     29#include "srttypeteletext.h"
     30
    2731enum MPFDisplayMask {
    2832    MPF_IMPORTANT = 0x0001,
    2933    MPF_GENERAL   = 0x0002,
     
    131135class MPEG2fixup
    132136{
    133137  public:
    134     MPEG2fixup(const char *inf, const char *outf,
     138    MPEG2fixup(const char *inf, const char *outf, const char *subtitlef,
    135139               QMap<long long, int> *deleteMap, const char *fmt, int norp,
    136140               int fixPTS, int maxf, bool showprog, int otype,
    137141               void (*update_func)(float) = NULL, int (*check_func)() = NULL);
     
    154158    MPEG2replex rx;
    155159
    156160  private:
     161    void ProcessDVBDataPacket();
    157162    int FindMPEG2Header(uint8_t *buf, int size, uint8_t code);
    158163    void InitReplex();
    159164    void FrameInfo(MPEG2frame *f);
     
    220225    bool use_secondary;
    221226
    222227    QPtrList<MPEG2frame> vFrame;
     228    QPtrList<MPEG2frame> sFrame;
    223229    QMap<int, QPtrList<MPEG2frame> > aFrame;
    224230    QPtrQueue<MPEG2frame> framePool;
    225231    QPtrQueue<MPEG2frame> unreadFrames;
     
    239245    int aud_stream_count;
    240246    int64_t ptsIncrement;
    241247    int64_t ptsOffset;  //was initPTS
     248   
     249    int subtitle_language;
     250    int subtitle_magazine;
     251    int subtitle_pagenum;
     252    int aubtitle_lang_idx;
     253    int subtitle_id;
    242254
    243255    int discard;
    244256    //control options
    245     int no_repeat, fix_PTS, maxframes;
     257    int no_repeat, fix_PTS, maxframes; 
    246258    QString infile;
     259    QString subtitlefile;
    247260    const char *format;
    248261
    249262    //complete?
     
    257270    int framenum;
    258271    int status_update_time;
    259272    uint64_t last_written_pos;
     273   
     274    TeletextDecoder  *ttd;
     275    SRTTypeTeletext *ttd_viewer;
    260276};
    261277
    262278#ifdef NO_MYTH