# HG changeset patch # User reimar # Date 1278957845 0 # Node ID 66795d9dcb5160ab26fb4855e59932903033a6d7 # Parent fa6671a1b8dcf52770b8076813db82c107f0850d Improve MPEG-TS subtitle support: make it use the infrastructure for subtitle handling so e.g. switching subtitles at runtime works and add support for PGS subtitles. diff -r fa6671a1b8dc -r 66795d9dcb51 libmpdemux/demux_ts.c --- a/libmpdemux/demux_ts.c Mon Jul 12 17:43:37 2010 +0000 +++ b/libmpdemux/demux_ts.c Mon Jul 12 18:04:05 2010 +0000 @@ -60,7 +60,7 @@ int ts_keep_broken=0; off_t ts_probe = 0; int audio_substream_id = -1; -extern char *dvdsub_lang, *audio_lang; //for -alang +extern char *audio_lang; //for -alang typedef enum { @@ -82,6 +82,7 @@ SPU_DVD = 0x3000000, SPU_DVB = 0x3000001, SPU_TELETEXT = 0x3000002, + SPU_PGS = 0x3000003, PES_PRIVATE1 = 0xBD00000, SL_PES_STREAM = 0xD000000, SL_SECTION = 0xD100000, @@ -236,6 +237,7 @@ int keep_broken; int last_aid; int last_vid; + int last_sid; char packet[TS_FEC_PACKET_SIZE]; TS_stream_info vstr, astr; } ts_priv_t; @@ -282,6 +284,7 @@ switch (type) { case SPU_DVD: case SPU_DVB: + case SPU_PGS: case SPU_TELETEXT: return 1; } @@ -395,6 +398,23 @@ } } } + + if(IS_SUB(es->type) && priv->last_sid+1 < MAX_S_STREAMS) + { + sh_sub_t *sh = new_sh_sub_sid(demuxer, priv->last_sid, es->pid, pid_lang_from_pmt(priv, es->pid)); + if (sh) { + switch (es->type) { + case SPU_DVD: + sh->type = 'v'; break; + case SPU_PGS: + sh->type = 'p'; break; + } + priv->ts.streams[es->pid].id = priv->last_aid; + priv->ts.streams[es->pid].sh = sh; + priv->ts.streams[es->pid].type = TYPE_AUDIO; + priv->last_sid++; + } + } } static int ts_check_file(demuxer_t * demuxer) @@ -597,7 +617,7 @@ typedef struct { int32_t atype, vtype, stype; //types int32_t apid, vpid, spid; //stream ids - char slang[4], alang[4]; //languages + char alang[4]; //languages uint16_t prog; off_t probe; } tsdemux_init_t; @@ -766,9 +786,6 @@ } else if(is_sub) { - mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_SUBTITLE_ID=%d\n", es.pid); - if (es.lang[0] > 0) - mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_SID_%d_LANG=%s\n", es.pid, es.lang); chosen_pid = (req_spid == es.pid); if((! chosen_pid) && (req_spid > 0)) continue; @@ -1045,14 +1062,6 @@ params.prog = ts_prog; params.probe = ts_probe; - if(dvdsub_lang != NULL) - { - strncpy(params.slang, dvdsub_lang, 3); - params.slang[3] = 0; - } - else - memset(params.slang, 0, 4); - if(audio_lang != NULL) { strncpy(params.alang, audio_lang, 3); @@ -1454,7 +1463,7 @@ int ssid = parse_pes_extension_fields(p, pkt_len); if((audio_substream_id!=-1) && (ssid != audio_substream_id)) return 0; - if(ssid == 0x72 && type_from_pmt != AUDIO_DTS) + if(ssid == 0x72 && type_from_pmt != AUDIO_DTS && type_from_pmt != SPU_PGS) es->type = type_from_pmt = AUDIO_TRUEHD; } @@ -1479,6 +1488,14 @@ */ + if(type_from_pmt == SPU_PGS) + { + es->start = p; + es->size = packet_len; + es->type = SPU_PGS; + es->payload_size -= packet_len; + return 1; + } if( (type_from_pmt == AUDIO_A52) || /* A52 - raw */ (packet_len >= 2 && p[0] == 0x0B && p[1] == 0x77) /* A52 - syncword */ @@ -2568,6 +2585,9 @@ case 0x86: pmt->es[idx].type = AUDIO_DTS; break; + case 0x90: + pmt->es[idx].type = SPU_PGS; + break; case 0xD1: pmt->es[idx].type = VIDEO_DIRAC; break; @@ -2943,14 +2963,9 @@ // PES CONTENT STARTS HERE if(! probe) { - if((is_video || is_audio) && is_start && !priv->ts.streams[pid].sh) + if((is_video || is_audio || is_sub) && is_start) ts_add_stream(demuxer, tss); - if((pid == demuxer->sub->id)) //or the lang is right - { - pid_type = SPU_DVD; - } - if(is_video && (demuxer->video->id == priv->ts.streams[pid].id)) { ds = demuxer->video; @@ -2969,38 +2984,11 @@ buffer_size = &priv->fifo[0].buffer_size; si = &priv->astr; } - else if(is_sub - || IS_SUB(pid_type)) + else if(is_sub) { - //SUBS are infrequent, so the initial detection may fail - // and we may need to add them at play-time - if(demuxer->sub->id == -1) - { - uint16_t p; - p = progid_for_pid(priv, tss->pid, priv->prog); - - if(p == priv->prog) - { - int asgn = 0; - uint8_t *lang; - - if(dvdsub_lang) - { - if ((lang = pid_lang_from_pmt(priv, pid))) - asgn = (strncmp(lang, dvdsub_lang, 3) == 0); - } - else //no language specified with -slang - asgn = 1; - - if(asgn) - { - demuxer->sub->id = tss->pid; - mp_msg(MSGT_DEMUX, MSGL_INFO, "CHOSEN SUBs pid 0x%x (%d) FROM PROG %d\n", tss->pid, tss->pid, priv->prog); - } - } - } - - if(demuxer->sub->id == tss->pid) + sh_sub_t *sh_sub = demuxer->sub->sh; + + if(sh_sub && sh_sub->sid == tss->pid) { ds = demuxer->sub;