diff options
| author | phintuka <phintuka> | 2009-02-13 14:56:41 +0000 | 
|---|---|---|
| committer | phintuka <phintuka> | 2009-02-13 14:56:41 +0000 | 
| commit | 2a2c4a9c3c44d2669ff817a98460058390b0a346 (patch) | |
| tree | 1587e99284ab4f257d0c01e1e16a434088d669e4 | |
| parent | f2590cff84394d1385acf41a5f2c09994482c1a5 (diff) | |
| download | xineliboutput-2a2c4a9c3c44d2669ff817a98460058390b0a346.tar.gz xineliboutput-2a2c4a9c3c44d2669ff817a98460058390b0a346.tar.bz2 | |
Moved (DVB) SPU detection and demuxing from input plugin
| -rw-r--r-- | xine/demux_xvdr.c | 110 | 
1 files changed, 109 insertions, 1 deletions
| diff --git a/xine/demux_xvdr.c b/xine/demux_xvdr.c index 5327955d..a2909674 100644 --- a/xine/demux_xvdr.c +++ b/xine/demux_xvdr.c @@ -33,6 +33,10 @@  #include "../xine_input_vdr_mrl.h"  #include "../tools/pes.h" +#define VDR_SUBTITLES +#define TEST_DVB_SPU +#define LOGSPU(x...) +  static const char log_module_demux_xvdr[] = "[demux_vdr] ";  #define LOG_MODULENAME log_module_demux_xvdr  #define SysLogLevel    iSysLogLevel @@ -75,6 +79,7 @@ typedef struct demux_xvdr_s {    uint32_t              last_audio_stream_id;    int64_t               last_vpts; +  uint8_t               dvd_subtitles : 1;  } demux_xvdr_t ;  typedef struct { @@ -358,6 +363,103 @@ static int32_t parse_pes_for_pts(demux_xvdr_t *this, uint8_t *p, buf_element_t *    return 0;  } +#if defined(TEST_DVB_SPU) +/* + * parse_dvb_spu() + * + * DVB subtitle stream demuxing + */ +static int32_t parse_dvb_spu(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf, int substream_header_len) +{ +  uint spu_id = p[0] & 0x1f; +  _x_select_spu_channel(this->stream, spu_id); + +# ifdef VDR_SUBTITLES +  if (substream_header_len == 1) { +    p--; +    this->packet_len++; +  } +# endif /* VDR_SUBTITLES */ + +  /* Skip substream header */ +  p += substream_header_len; +  buf->content = p; +  buf->size    = this->packet_len - substream_header_len; + +  /* Special buffer when payload packet changes */ +  if (this->pts > 0) { +    buf_element_t *cbuf = this->video_fifo->buffer_pool_alloc(this->video_fifo); +    int page_id         = (*(p+4) << 8) | *(p+5); + +    spu_dvb_descriptor_t *spu_descriptor = (spu_dvb_descriptor_t *) cbuf->content; +    memset(spu_descriptor, 0, sizeof(spu_dvb_descriptor_t)); +    spu_descriptor->comp_page_id = page_id; + +    cbuf->type = BUF_SPU_DVB + spu_id; +    cbuf->size = 0; +    cbuf->decoder_flags   = BUF_FLAG_SPECIAL; +    cbuf->decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR; +    cbuf->decoder_info[2] = sizeof(spu_dvb_descriptor_t); +    cbuf->decoder_info_ptr[2] = spu_descriptor; + +    this->video_fifo->put (this->video_fifo, cbuf); +  } + +  buf->type      = BUF_SPU_DVB + spu_id; +  buf->pts       = this->pts; +  buf->decoder_info[2] = this->pts > 0 ? 0xffff : 0; /* hack - size unknown here (?) */ + +  this->video_fifo->put (this->video_fifo, buf); + +  return -1; +} + +int detect_dvb_spu(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf) +{ +  LOGSPU("%s%02x %02x %02x %02x   %02x %02x %02x %02x", +         this->pts>0?"* ":"  ",p[0], p[1], p[2], p[3], +         p[4], p[5], p[6], p[7]); + +  /* If PES packet has PTS, it starts new subtitle (ES) packet. */ +  if (this->pts > 0) { +    /* Reset SPU type */ +    this->dvd_subtitles = 0; +  } + +# ifdef VDR_SUBTITLES +  /* Compatibility mode for old subtitles plugin */ +  if (!this->dvd_subtitles) { +    if ((buf->content[7] & 0x01) && (p[-3] & 0x81) == 0x01 && p[-2] == 0x81) { +      LOGDBG("DVB SPU: Old vdr-subtitles compability mode"); +      return parse_dvb_spu(this, p, buf, 1); +    } +  } +# endif /* VDR_SUBTITLES */ + +  /* Start of subtitle packet. Guess substream type */ +  if (this->pts > 0) { +    if (p[4] == 0x20 && p[5] == 0x00 && (p[6] == 0x0f || p[4] == 0x0f)) { +      this->dvd_subtitles = 0; +      LOGSPU(" -> DVB SPU"); +    } else if (p[2] || (p[3] & 0xfe)) { +      this->dvd_subtitles = 1; +      LOGSPU(" -> DVD SPU"); +    } else { +      this->dvd_subtitles = 1; +      LOGMSG(" -> DV? SPU -> DVD"); +    } +  } + +  /* DVD SPU ? */ +  if (this->dvd_subtitles) +    return this->packet_len; + +  /* DVB SPU */ +  return parse_dvb_spu(this, p, buf, 4); +} + +#endif /* TEST_DVB_SPU */ +  static int32_t parse_private_stream_1(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)  {    int track, spu_id; @@ -368,10 +470,16 @@ static int32_t parse_private_stream_1(demux_xvdr_t *this, uint8_t *p, buf_elemen    p += result; -  /* DVD SPU */ +  /* SPU */    if ((p[0] & 0xE0) == 0x20) {      spu_id = (p[0] & 0x1f); +#ifdef TEST_DVB_SPU +    if (detect_dvb_spu(this, p, buf) < 0) +      return -1; +#endif /* TEST_DVB_SPU */ + +    /* DVD SPU */      buf->content   = p+1;      buf->size      = this->packet_len-1; | 
