~ubuntu-branches/ubuntu/lucid/vdr-plugin-xineliboutput/lucid

« back to all changes in this revision

Viewing changes to xine/demux_xvdr.c

  • Committer: Bazaar Package Importer
  • Author(s): Tobias Grimm
  • Date: 2009-11-09 00:34:53 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091109003453-opclaj97aq8e85mw
Tags: 1.0.4+cvs20091016.1108-3
* Removed non-standard shebang line from debian/rules (Closes: #552662)
* Added README.source

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2000-2006 the xine project
 
3
 *
 
4
 * This file is part of xine, a free video player.
 
5
 *
 
6
 * xine is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * xine is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 
19
 *
 
20
 * demultiplexer for xineliboutput (xvdr)
 
21
 */
 
22
 
 
23
#include <stdlib.h>
 
24
#include <stdio.h>
 
25
#include <fcntl.h>
 
26
#include <unistd.h>
 
27
#include <string.h>
 
28
 
 
29
#include <xine/xine_internal.h>
 
30
#include <xine/xineutils.h>
 
31
#include <xine/demux.h>
 
32
 
 
33
#include "../xine_input_vdr_mrl.h"
 
34
#include "../tools/mpeg.h"
 
35
#include "../tools/h264.h"
 
36
#include "../tools/pes.h"
 
37
#include "../tools/ts.h"
 
38
 
 
39
#include "ts2es.h"
 
40
#include "demux_xvdr_tsdata.h"
 
41
 
 
42
/*
 
43
 * features
 
44
 */
 
45
 
 
46
#define VDR_SUBTITLES
 
47
#define TEST_DVB_SPU
 
48
 
 
49
/*
 
50
 * logging
 
51
 */
 
52
 
 
53
static const char log_module_demux_xvdr[] = "[demux_vdr] ";
 
54
#define LOG_MODULENAME log_module_demux_xvdr
 
55
#define SysLogLevel    iSysLogLevel
 
56
 
 
57
#include "../logdefs.h"
 
58
 
 
59
#define LOGSPU(x...)
 
60
 
 
61
/*
 
62
 * constants
 
63
 */
 
64
 
 
65
#define DISC_TRESHOLD       90000
 
66
#define WRAP_THRESHOLD     120000
 
67
#define PTS_AUDIO 0
 
68
#define PTS_VIDEO 1
 
69
 
 
70
 
 
71
/* redefine abs as macro to handle 64-bit diffs.
 
72
   i guess llabs may not be available everywhere */
 
73
#define abs(x) ( ((x)<0) ? -(x) : (x) )
 
74
 
 
75
typedef struct demux_xvdr_s {
 
76
  demux_plugin_t        demux_plugin;
 
77
 
 
78
  xine_stream_t        *stream;
 
79
  fifo_buffer_t        *audio_fifo;
 
80
  fifo_buffer_t        *video_fifo;
 
81
 
 
82
  input_plugin_t       *input;
 
83
 
 
84
  ts_data_t            *ts_data;        /* MPEG-TS stuff */
 
85
 
 
86
  int64_t               last_pts[2];
 
87
  int64_t               last_vpts;
 
88
  int                   status;
 
89
  uint32_t              video_type;
 
90
  uint32_t              audio_type;
 
91
  uint32_t              subtitle_type;
 
92
 
 
93
  /* current buf_element */
 
94
  int64_t               pts;
 
95
  int64_t               dts;
 
96
  uint32_t              packet_len;
 
97
  uint8_t               stream_id;
 
98
 
 
99
  uint8_t               send_newpts          : 1;
 
100
  uint8_t               buf_flag_seek        : 1;
 
101
  uint8_t               ffmpeg_mpeg2_decoder : 1;
 
102
  uint8_t               coreavc_h264_decoder : 1;
 
103
  uint8_t               bih_posted           : 1;
 
104
} demux_xvdr_t ;
 
105
 
 
106
typedef struct {
 
107
 
 
108
  demux_class_t     demux_class;
 
109
 
 
110
  /* class-wide, global variables here */
 
111
 
 
112
  xine_t           *xine;
 
113
  config_values_t  *config;
 
114
} demux_xvdr_class_t;
 
115
 
 
116
 
 
117
static const char * get_decoder_name(xine_t *xine, int video_type)
 
118
{
 
119
  int streamtype = (video_type >> 16) & 0xFF;
 
120
  plugin_node_t *node = xine->plugin_catalog->video_decoder_map[streamtype][0];
 
121
  if (node) {
 
122
    plugin_info_t *info = node->info;
 
123
    if (info)
 
124
      return info->id;
 
125
  }
 
126
  return "";
 
127
}
 
128
 
 
129
static void detect_video_decoders(demux_xvdr_t *this)
 
130
{
 
131
  if (!strcmp(get_decoder_name(this->stream->xine, BUF_VIDEO_MPEG), "ffmpegvideo"))
 
132
    this->ffmpeg_mpeg2_decoder = 1;
 
133
  LOGMSG("Using decoder \"%s\" for mpeg2 video",
 
134
         this->ffmpeg_mpeg2_decoder ? "FFmpeg" : "libmpeg2");
 
135
 
 
136
  if (!strcmp(get_decoder_name(this->stream->xine, BUF_VIDEO_H264), "dshowserver"))
 
137
    this->coreavc_h264_decoder = 1;
 
138
  LOGMSG("Using decoder \"%s\" for H.264 video",
 
139
         this->coreavc_h264_decoder ? "dshowserver (CoreAVC)" : "FFmpeg");
 
140
}
 
141
 
 
142
static void demux_xvdr_parse_ts(demux_xvdr_t *this, buf_element_t *buf);
 
143
static void demux_xvdr_parse_pes(demux_xvdr_t *this, buf_element_t *buf);
 
144
 
 
145
static int32_t parse_video_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf);
 
146
static int32_t parse_audio_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf);
 
147
static int32_t parse_private_stream_1(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf);
 
148
static int32_t parse_padding_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf);
 
149
 
 
150
static void pts_wrap_workaround(demux_xvdr_t *this, buf_element_t *buf, int video)
 
151
{
 
152
#ifdef LOG_PES_AV_DIFF
 
153
  static int64_t vpts = 0, apts = 0;
 
154
  if (video) vpts = buf->pts;
 
155
  else apts = buf->pts;
 
156
  if (vpts > 0 && apts > 0)
 
157
    LOGMSG("pts diff [%d] %d", video, (int)(vpts - apts));
 
158
#endif
 
159
 
 
160
  /* PTS wrap workaround */
 
161
  if (buf->pts >= 0) {
 
162
    if (video)
 
163
      this->last_vpts = buf->pts;
 
164
    else if (buf->pts        > INT64_C( 0x40400000 ) &&
 
165
             this->last_vpts < INT64_C( 0x40000000 ) &&
 
166
             this->last_vpts > INT64_C( 0 )) {
 
167
      LOGMSG("VIDEO pts wrap before AUDIO, ignoring audio pts %" PRId64, buf->pts);
 
168
      buf->pts = INT64_C(0);
 
169
    }
 
170
  }
 
171
}
 
172
 
 
173
static void check_newpts(demux_xvdr_t *this, buf_element_t *buf, int video )
 
174
{
 
175
  pts_wrap_workaround(this, buf, video);
 
176
 
 
177
  if (buf->pts) {
 
178
    int64_t diff = buf->pts - this->last_pts[video];
 
179
 
 
180
    if (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD)) {
 
181
 
 
182
      if (this->buf_flag_seek) {
 
183
        _x_demux_control_newpts(this->stream, buf->pts, BUF_FLAG_SEEK);
 
184
        this->buf_flag_seek = 0;
 
185
      } else {
 
186
        _x_demux_control_newpts(this->stream, buf->pts, 0);
 
187
      }
 
188
      this->send_newpts = 0;
 
189
 
 
190
      this->last_pts[1-video] = 0;
 
191
    }
 
192
 
 
193
    this->last_pts[video] = buf->pts;
 
194
  }
 
195
}
 
196
 
 
197
static void put_control_buf(fifo_buffer_t *buffer, fifo_buffer_t *pool, int cmd)
 
198
{
 
199
  buf_element_t *buf = pool->buffer_pool_try_alloc(pool);
 
200
  if(buf) {
 
201
    buf->type = cmd;
 
202
    buffer->put(buffer, buf);
 
203
  }
 
204
}
 
205
 
 
206
/*
 
207
 * post_sequence_end()
 
208
 *
 
209
 * Add MPEG2 or H.264 sequence end code to fifo buffer
 
210
 */
 
211
static void post_sequence_end(fifo_buffer_t *fifo, uint32_t video_type)
 
212
{
 
213
  buf_element_t *buf = fifo->buffer_pool_try_alloc(fifo);
 
214
  if (buf) {
 
215
    buf->type = video_type;
 
216
    buf->size = 4;
 
217
    buf->decoder_flags = BUF_FLAG_FRAME_END;
 
218
    buf->content[0] = 0x00;
 
219
    buf->content[1] = 0x00;
 
220
    buf->content[2] = 0x01;
 
221
    buf->content[3] = (video_type == BUF_VIDEO_H264) ? NAL_END_SEQ : 0xB7;
 
222
    fifo->put(fifo, buf);
 
223
  }
 
224
}
 
225
 
 
226
/*
 
227
 * post_frame_end()
 
228
 *
 
229
 * Signal end of video frame to decoder.
 
230
 *
 
231
 * This function is used with:
 
232
 *  - FFmpeg mpeg2 decoder
 
233
 *  - FFmpeg and CoreAVC H.264 decoders
 
234
 *  - NOT with libmpeg2 mpeg decoder
 
235
 */
 
236
static void post_frame_end(demux_xvdr_t *this, buf_element_t *vid_buf)
 
237
{
 
238
  buf_element_t *cbuf = this->video_fifo->buffer_pool_try_alloc (this->video_fifo) ?:
 
239
                        this->audio_fifo->buffer_pool_try_alloc (this->audio_fifo);
 
240
 
 
241
  if (!cbuf) {
 
242
    LOGMSG("post_frame_end(): buffer_pool_try_alloc() failed, retrying");
 
243
    xine_usec_sleep (10*1000);
 
244
    cbuf = this->video_fifo->buffer_pool_try_alloc (this->video_fifo);
 
245
    if (!cbuf) {
 
246
      LOGERR("post_frame_end(): get_buf_element() failed !");
 
247
      return;
 
248
    }
 
249
  }
 
250
 
 
251
  cbuf->type          = this->video_type;
 
252
  cbuf->decoder_flags = BUF_FLAG_FRAME_END;
 
253
 
 
254
  if (!this->bih_posted) {
 
255
    video_size_t size = {0};
 
256
    if (pes_get_video_size(vid_buf->content, vid_buf->size, &size, this->video_type == BUF_VIDEO_H264)) {
 
257
 
 
258
      /* reset decoder buffer */
 
259
      cbuf->decoder_flags |= BUF_FLAG_FRAME_START;
 
260
 
 
261
      /* Fill xine_bmiheader for CoreAVC / H.264 */
 
262
 
 
263
      if (this->video_type == BUF_VIDEO_H264 && this->coreavc_h264_decoder) {
 
264
        xine_bmiheader *bmi = (xine_bmiheader*) cbuf->content;
 
265
 
 
266
        cbuf->decoder_flags |= BUF_FLAG_HEADER;
 
267
        cbuf->decoder_flags |= BUF_FLAG_STDHEADER;   /* CoreAVC: buffer contains bmiheader */
 
268
        cbuf->size           = sizeof(xine_bmiheader);
 
269
 
 
270
        memset (bmi, 0, sizeof(xine_bmiheader));
 
271
 
 
272
        bmi->biSize   = sizeof(xine_bmiheader);
 
273
        bmi->biWidth  = size.width;
 
274
        bmi->biHeight = size.height;
 
275
 
 
276
        bmi->biPlanes        = 1;
 
277
        bmi->biBitCount      = 24;
 
278
        bmi->biCompression   = 0x34363248;
 
279
        bmi->biSizeImage     = 0;
 
280
        bmi->biXPelsPerMeter = size.pixel_aspect.num;
 
281
        bmi->biYPelsPerMeter = size.pixel_aspect.den;
 
282
        bmi->biClrUsed       = 0;
 
283
        bmi->biClrImportant  = 0;
 
284
      }
 
285
 
 
286
      /* Set aspect ratio for ffmpeg mpeg2 / CoreAVC H.264 decoder
 
287
       * (not for FFmpeg H.264 or libmpeg2 mpeg2 decoders)
 
288
       */
 
289
 
 
290
      if (size.pixel_aspect.num &&
 
291
          (this->video_type != BUF_VIDEO_H264 || this->coreavc_h264_decoder)) {
 
292
        cbuf->decoder_flags |= BUF_FLAG_HEADER;
 
293
        cbuf->decoder_flags |= BUF_FLAG_ASPECT;
 
294
        /* pixel ratio -> frame ratio */
 
295
        if (size.pixel_aspect.num > size.height) {
 
296
          cbuf->decoder_info[1] = size.pixel_aspect.num / size.height;
 
297
          cbuf->decoder_info[2] = size.pixel_aspect.den / size.width;
 
298
        } else {
 
299
          cbuf->decoder_info[1] = size.pixel_aspect.num * size.width;
 
300
          cbuf->decoder_info[2] = size.pixel_aspect.den * size.height;
 
301
        }
 
302
      }
 
303
 
 
304
      LOGDBG("post_frame_end: video width %d, height %d, pixel aspect %d:%d",
 
305
             size.width, size.height, size.pixel_aspect.num, size.pixel_aspect.den);
 
306
 
 
307
      this->bih_posted = 1;
 
308
    }
 
309
  }
 
310
 
 
311
  this->video_fifo->put (this->video_fifo, cbuf);
 
312
}
 
313
 
 
314
static void track_audio_stream_change(demux_xvdr_t *this, buf_element_t *buf)
 
315
{
 
316
#if !defined(BUF_CONTROL_RESET_TRACK_MAP)
 
317
#  warning xine-lib is older than 1.1.2. Multiple audio streams are not supported.
 
318
#else
 
319
  if (this->audio_type != buf->type) {
 
320
    LOGDBG("audio stream changed: %08x -> %08x", this->audio_type, buf->type);
 
321
    this->audio_type = buf->type;
 
322
    put_control_buf(this->audio_fifo,
 
323
                    this->audio_fifo,
 
324
                    BUF_CONTROL_RESET_TRACK_MAP);
 
325
  }
 
326
#endif
 
327
}
 
328
 
 
329
static void demux_xvdr_fwd_buf(demux_xvdr_t *this, buf_element_t *buf)
 
330
{
 
331
  /* demuxed video --> video_fifo */
 
332
  if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE) {
 
333
    this->video_type = buf->type;
 
334
    check_newpts (this, buf, PTS_VIDEO);
 
335
    this->video_fifo->put (this->video_fifo, buf);
 
336
    return;
 
337
  }
 
338
 
 
339
  /* demuxed audio --> audio_fifo */
 
340
  if ((buf->type & BUF_MAJOR_MASK) == BUF_AUDIO_BASE) {
 
341
    if (this->audio_fifo) {
 
342
      check_newpts (this, buf, PTS_AUDIO);
 
343
      track_audio_stream_change (this, buf);
 
344
      this->audio_fifo->put (this->audio_fifo, buf);
 
345
    } else {
 
346
      buf->free_buffer (buf);
 
347
    }
 
348
    return;
 
349
  }
 
350
 
 
351
  /* decoder flush --> video_fifo */
 
352
  if (buf->type == BUF_CONTROL_FLUSH_DECODER) {
 
353
    /* append sequence end code */
 
354
    post_sequence_end (this->video_fifo, this->video_type);
 
355
    this->video_fifo->put (this->video_fifo, buf);
 
356
    return;
 
357
  }
 
358
 
 
359
  /* control buffer --> both fifos */
 
360
  if ((buf->type & BUF_MAJOR_MASK) == BUF_CONTROL_BASE) {
 
361
    if (this->audio_fifo) {
 
362
      /* duplicate goes to audio fifo */
 
363
      buf_element_t *cbuf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
 
364
      cbuf->type = buf->type;
 
365
      cbuf->decoder_flags = buf->decoder_flags;
 
366
      memcpy (cbuf->decoder_info,     buf->decoder_info,     sizeof(cbuf->decoder_info));
 
367
      memcpy (cbuf->decoder_info_ptr, buf->decoder_info_ptr, sizeof(cbuf->decoder_info_ptr));
 
368
 
 
369
      this->audio_fifo->put (this->audio_fifo, cbuf);
 
370
    }
 
371
    this->video_fifo->put (this->video_fifo, buf);
 
372
    return;
 
373
  }
 
374
 
 
375
  LOGMSG("Unhandled buffer type %08x", buf->type);
 
376
  buf->free_buffer (buf);
 
377
}
 
378
 
 
379
static void demux_xvdr_parse_pack (demux_xvdr_t *this)
 
380
{
 
381
  buf_element_t *buf = NULL;
 
382
  uint8_t       *p;
 
383
 
 
384
  buf = this->input->read_block (this->input, this->video_fifo, 8128);
 
385
 
 
386
  if (!buf) {
 
387
    if (errno == EINTR) {
 
388
      /* very verbose logging ? */
 
389
      if (iSysLogLevel >= SYSLOGLEVEL_VERBOSE)
 
390
        LOGDBG("input->read_block() was interrupted");
 
391
    } else if (errno != EAGAIN) {
 
392
      LOGDBG("DEMUX_FINISHED (input returns NULL with error)");
 
393
      this->status = DEMUX_FINISHED;
 
394
      ts_data_dispose(&this->ts_data);
 
395
    }
 
396
    return;
 
397
  }
 
398
 
 
399
  /* If this is not a block for the demuxer, pass it
 
400
   * straight through. */
 
401
  if (buf->type != BUF_DEMUX_BLOCK) {
 
402
    ts_data_flush (this->ts_data);
 
403
    demux_xvdr_fwd_buf (this, buf);
 
404
    return;
 
405
  }
 
406
 
 
407
  p = buf->content; /* len = this->blocksize; */
 
408
  buf->decoder_flags = 0;
 
409
 
 
410
  if (DATA_IS_TS(p)) {
 
411
    demux_xvdr_parse_ts (this, buf);
 
412
    return;
 
413
  }
 
414
  if (DATA_IS_PES(p)) {
 
415
    demux_xvdr_parse_pes (this, buf);
 
416
    return;
 
417
  }
 
418
 
 
419
  LOGMSG("Header %02x %02x %02x (should be 0x000001 or 0x47)", p[0], p[1], p[2]);
 
420
  buf->free_buffer (buf);
 
421
  return;
 
422
}
 
423
 
 
424
static void demux_xvdr_parse_pes (demux_xvdr_t *this, buf_element_t *buf)
 
425
{
 
426
  uint8_t       *p = buf->content;
 
427
  int32_t        result;
 
428
 
 
429
  this->stream_id  = p[3];
 
430
 
 
431
  if (IS_VIDEO_PACKET(p)) {
 
432
    result = parse_video_stream(this, p, buf);
 
433
  } else if (IS_MPEG_AUDIO_PACKET(p)) {
 
434
    result = parse_audio_stream(this, p, buf);
 
435
  } else if (IS_PADDING_PACKET(p)) {
 
436
    result = parse_padding_stream(this, p, buf);
 
437
  } else if (IS_PS1_PACKET(p)) {
 
438
    result = parse_private_stream_1(this, p, buf);
 
439
  } else {
 
440
    LOGMSG("Unrecognised PES stream 0x%02x", this->stream_id);
 
441
    buf->free_buffer (buf);
 
442
    return;
 
443
  }
 
444
 
 
445
  if (result < 0) {
 
446
    return;
 
447
  }
 
448
 
 
449
  LOGMSG("error! freeing buffer.");
 
450
  buf->free_buffer (buf);
 
451
}
 
452
 
 
453
/*
 
454
 * demux_xvdr_parse_ts()
 
455
 *
 
456
 * MPEG-TS demuxing
 
457
 */
 
458
static void demux_xvdr_parse_ts (demux_xvdr_t *this, buf_element_t *buf)
 
459
{
 
460
  if (!this->ts_data)
 
461
    this->ts_data = calloc(1, sizeof(ts_data_t));
 
462
 
 
463
  ts_data_t     *ts_data  = this->ts_data;
 
464
  fifo_buffer_t *src_fifo = buf->source;
 
465
 
 
466
  while (buf->size >= TS_SIZE) {
 
467
 
 
468
    unsigned int ts_pid = ts_PID(buf->content);
 
469
 
 
470
    /* parse PAT */
 
471
    if (ts_pid == 0) {
 
472
      pat_data_t pat;
 
473
 
 
474
      ts_data_flush(ts_data);
 
475
 
 
476
      if (ts_parse_pat(&pat, buf->content)) {
 
477
        ts_data->pmt_pid        = pat.pmt_pid[0];
 
478
        ts_data->program_number = pat.program_number[0];
 
479
        if (iSysLogLevel >= SYSLOGLEVEL_VERBOSE)
 
480
          LOGDBG("Got PAT, PMT pid = %d, program = %d", ts_data->pmt_pid, ts_data->program_number);
 
481
      }
 
482
    }
 
483
 
 
484
    /* parse PMT */
 
485
    else if (ts_pid == ts_data->pmt_pid) {
 
486
 
 
487
      ts_data_flush(ts_data);
 
488
 
 
489
      if (ts_parse_pmt(&ts_data->pmt, ts_data->program_number, buf->content)) {
 
490
 
 
491
        /* PMT changed, reset ts->es converters */
 
492
        LOGMSG("PMT changed");
 
493
        ts_data_ts2es_init(&ts_data, this->stream->video_fifo, this->stream->audio_fifo);
 
494
 
 
495
        this->video_type = (ts_data->pmt.video_type == ISO_14496_PART10_VIDEO) ?
 
496
                           BUF_VIDEO_H264 : BUF_VIDEO_MPEG;
 
497
 
 
498
        /* Inform UI of channels changes */
 
499
        xine_event_t event;
 
500
        event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
 
501
        event.data_length = 0;
 
502
        xine_event_send(this->stream, &event);
 
503
      }
 
504
    }
 
505
 
 
506
    /* demux video */
 
507
    else if (ts_pid == ts_data->pmt.video_pid) {
 
508
      if (ts_data->video) {
 
509
        buf_element_t *vbuf     = ts2es_put(ts_data->video, buf->content, src_fifo);
 
510
        if (vbuf) {
 
511
          this->pts = vbuf->pts;
 
512
          check_newpts( this, vbuf, PTS_VIDEO );
 
513
 
 
514
          this->stream->video_fifo->put(this->stream->video_fifo, vbuf);
 
515
        }
 
516
      }
 
517
    }
 
518
 
 
519
    /* demux audio */
 
520
    else {
 
521
      int i, done = 0;
 
522
      for (i=0; i < ts_data->pmt.audio_tracks_count; i++)
 
523
        if (ts_pid == ts_data->pmt.audio_tracks[i].pid) {
 
524
          if (ts_data->audio[i]) {
 
525
            buf_element_t *abuf = ts2es_put(ts_data->audio[i], buf->content, src_fifo);
 
526
            if (abuf) {
 
527
              this->pts = abuf->pts;
 
528
              check_newpts( this, abuf, PTS_AUDIO );
 
529
              track_audio_stream_change (this, abuf);
 
530
 
 
531
              this->stream->audio_fifo->put(this->stream->audio_fifo, abuf);
 
532
            }
 
533
          }
 
534
          done = 1;
 
535
          break;
 
536
        }
 
537
#if 0
 
538
      /* demux subtitles */
 
539
      if (!done)
 
540
      for (i=0; i < ts_data->pmt.spu_tracks_count; i++)
 
541
        if (ts_pid == ts_data->pmt.spu_tracks[i].pid) {
 
542
          if (ts_data->spu[i]) {
 
543
            buf_element_t *sbuf = ts2es_put(ts_data->spu[i], buf->content, NULL);
 
544
            if (sbuf)
 
545
              this->stream->video_fifo->put(this->stream->video_fifo, sbuf);
 
546
          }
 
547
          done = 1;
 
548
          break;
 
549
        }
 
550
 
 
551
      if (!done)
 
552
        LOGMSG("Got unknown TS packet, pid = %d", ts_pid);
 
553
#endif
 
554
    }
 
555
 
 
556
    buf->content += TS_SIZE;
 
557
    buf->size    -= TS_SIZE;
 
558
  }
 
559
 
 
560
  buf->free_buffer(buf);
 
561
}
 
562
 
 
563
static int32_t parse_padding_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
 
564
{
 
565
  buf->free_buffer (buf);
 
566
  return -1;
 
567
}
 
568
 
 
569
/* FIXME: Extension data is not parsed, and is also not skipped. */
 
570
 
 
571
static int32_t parse_pes_for_pts(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
 
572
{
 
573
  int32_t header_len;
 
574
 
 
575
  this->packet_len = p[4] << 8 | p[5];
 
576
 
 
577
  if ((p[6] & 0xC0) != 0x80 /* mpeg1 */) {
 
578
    header_len = 6;
 
579
    p   += 6; /* packet_len -= 6; */
 
580
 
 
581
    while ((p[0] & 0x80) == 0x80) {
 
582
      p++;
 
583
      header_len++;
 
584
      this->packet_len--;
 
585
    }
 
586
 
 
587
    if ((p[0] & 0xc0) == 0x40) {
 
588
      /* STD_buffer_scale, STD_buffer_size */
 
589
      p += 2;
 
590
      header_len += 2;
 
591
      this->packet_len -= 2;
 
592
    }
 
593
 
 
594
    this->pts = 0;
 
595
    this->dts = 0;
 
596
 
 
597
    if ((p[0] & 0xf0) == 0x20) {
 
598
      this->pts  = (int64_t)(p[ 0] & 0x0E) << 29 ;
 
599
      this->pts |=  p[ 1]         << 22 ;
 
600
      this->pts |= (p[ 2] & 0xFE) << 14 ;
 
601
      this->pts |=  p[ 3]         <<  7 ;
 
602
      this->pts |= (p[ 4] & 0xFE) >>  1 ;
 
603
      p   += 5;
 
604
      header_len+= 5;
 
605
      this->packet_len -=5;
 
606
      return header_len;
 
607
    } else if ((p[0] & 0xf0) == 0x30) {
 
608
      this->pts  = (int64_t)(p[ 0] & 0x0E) << 29 ;
 
609
      this->pts |=  p[ 1]         << 22 ;
 
610
      this->pts |= (p[ 2] & 0xFE) << 14 ;
 
611
      this->pts |=  p[ 3]         <<  7 ;
 
612
      this->pts |= (p[ 4] & 0xFE) >>  1 ;
 
613
 
 
614
      this->dts  = (int64_t)(p[ 5] & 0x0E) << 29 ;
 
615
      this->dts |=  p[ 6]         << 22 ;
 
616
      this->dts |= (p[ 7] & 0xFE) << 14 ;
 
617
      this->dts |=  p[ 8]         <<  7 ;
 
618
      this->dts |= (p[ 9] & 0xFE) >>  1 ;
 
619
 
 
620
      p   += 10;
 
621
      header_len += 10;
 
622
      this->packet_len -= 10;
 
623
      return header_len;
 
624
    } else {
 
625
      p++;
 
626
      header_len++;
 
627
      this->packet_len--;
 
628
      return header_len;
 
629
    }
 
630
 
 
631
  } else { /* mpeg 2 */
 
632
 
 
633
 
 
634
    if ((p[6] & 0xC0) != 0x80) {
 
635
      LOGMSG("warning: PES header reserved 10 bits not found");
 
636
      buf->free_buffer(buf);
 
637
      return -1;
 
638
    }
 
639
 
 
640
 
 
641
    /* check PES scrambling_control */
 
642
    if ((p[6] & 0x30) != 0) {
 
643
      LOGMSG("encrypted PES ?");
 
644
      buf->free_buffer(buf);
 
645
      return -1;
 
646
    }
 
647
 
 
648
    if (p[7] & 0x80) { /* pts avail */
 
649
 
 
650
      this->pts  = (int64_t)(p[ 9] & 0x0E) << 29 ;
 
651
      this->pts |=  p[10]         << 22 ;
 
652
      this->pts |= (p[11] & 0xFE) << 14 ;
 
653
      this->pts |=  p[12]         <<  7 ;
 
654
      this->pts |= (p[13] & 0xFE) >>  1 ;
 
655
 
 
656
    } else
 
657
      this->pts = 0;
 
658
 
 
659
    if (p[7] & 0x40) { /* dts avail */
 
660
 
 
661
      this->dts  = (int64_t)(p[14] & 0x0E) << 29 ;
 
662
      this->dts |=  p[15]         << 22 ;
 
663
      this->dts |= (p[16] & 0xFE) << 14 ;
 
664
      this->dts |=  p[17]         <<  7 ;
 
665
      this->dts |= (p[18] & 0xFE) >>  1 ;
 
666
 
 
667
    } else
 
668
      this->dts = 0;
 
669
 
 
670
 
 
671
    header_len = p[8];
 
672
 
 
673
    this->packet_len -= header_len + 3;
 
674
    return header_len + 9;
 
675
  }
 
676
  return 0;
 
677
}
 
678
 
 
679
#if defined(TEST_DVB_SPU)
 
680
/*
 
681
 * parse_dvb_spu()
 
682
 *
 
683
 * DVB subtitle stream demuxing
 
684
 */
 
685
static int32_t parse_dvb_spu(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf, int substream_header_len)
 
686
{
 
687
  uint spu_id = p[0] & 0x1f;
 
688
  _x_select_spu_channel(this->stream, spu_id);
 
689
 
 
690
# ifdef VDR_SUBTITLES
 
691
  if (substream_header_len == 1) {
 
692
    p--;
 
693
    this->packet_len++;
 
694
  }
 
695
# endif /* VDR_SUBTITLES */
 
696
 
 
697
  /* Skip substream header */
 
698
  p += substream_header_len;
 
699
  buf->content = p;
 
700
  buf->size    = this->packet_len - substream_header_len;
 
701
 
 
702
  /* Special buffer when payload packet changes */
 
703
  if (this->pts > 0) {
 
704
    buf_element_t *cbuf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
 
705
    int page_id         = (*(p+4) << 8) | *(p+5);
 
706
 
 
707
    spu_dvb_descriptor_t *spu_descriptor = (spu_dvb_descriptor_t *) cbuf->content;
 
708
    memset(spu_descriptor, 0, sizeof(spu_dvb_descriptor_t));
 
709
    spu_descriptor->comp_page_id = page_id;
 
710
 
 
711
    cbuf->type = BUF_SPU_DVB + spu_id;
 
712
    cbuf->size = 0;
 
713
    cbuf->decoder_flags   = BUF_FLAG_SPECIAL;
 
714
    cbuf->decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR;
 
715
    cbuf->decoder_info[2] = sizeof(spu_dvb_descriptor_t);
 
716
    cbuf->decoder_info_ptr[2] = spu_descriptor;
 
717
 
 
718
    this->video_fifo->put (this->video_fifo, cbuf);
 
719
  }
 
720
 
 
721
  buf->type      = BUF_SPU_DVB + spu_id;
 
722
  buf->pts       = this->pts;
 
723
  buf->decoder_info[2] = this->pts > 0 ? 0xffff : 0; /* hack - size unknown here (?) */
 
724
 
 
725
  this->video_fifo->put (this->video_fifo, buf);
 
726
 
 
727
  return -1;
 
728
}
 
729
 
 
730
int detect_dvb_spu(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
 
731
{
 
732
  LOGSPU("%s%02x %02x %02x %02x   %02x %02x %02x %02x",
 
733
         this->pts>0?"* ":"  ",p[0], p[1], p[2], p[3],
 
734
         p[4], p[5], p[6], p[7]);
 
735
 
 
736
  /* If PES packet has PTS, it starts new subtitle (ES) packet. */
 
737
  if (this->pts > 0) {
 
738
    /* Reset SPU type */
 
739
    this->subtitle_type = 0;
 
740
  }
 
741
 
 
742
# ifdef VDR_SUBTITLES
 
743
  /* Compatibility mode for old subtitles plugin */
 
744
  if (this->subtitle_type != BUF_SPU_DVD) {
 
745
    if ((buf->content[7] & 0x01) && (p[-3] & 0x81) == 0x01 && p[-2] == 0x81) {
 
746
      LOGDBG("DVB SPU: Old vdr-subtitles compability mode");
 
747
      return parse_dvb_spu(this, p, buf, 1);
 
748
    }
 
749
  }
 
750
# endif /* VDR_SUBTITLES */
 
751
 
 
752
  /* Start of subtitle packet. Guess substream type */
 
753
  if (this->pts > 0) {
 
754
    if (p[4] == 0x20 && p[5] == 0x00 && (p[6] == 0x0f || p[4] == 0x0f)) {
 
755
      this->subtitle_type = BUF_SPU_DVB;
 
756
      LOGSPU(" -> DVB SPU");
 
757
    } else if (p[2] || (p[3] & 0xfe)) {
 
758
      this->subtitle_type = BUF_SPU_DVD;
 
759
      LOGSPU(" -> DVD SPU");
 
760
    } else {
 
761
      this->subtitle_type = BUF_SPU_DVD;
 
762
      LOGMSG(" -> DV? SPU -> DVD");
 
763
    }
 
764
  }
 
765
 
 
766
  /* DVD SPU ? */
 
767
  if (this->subtitle_type == BUF_SPU_DVD)
 
768
    return this->packet_len;
 
769
 
 
770
  /* DVB SPU */
 
771
  return parse_dvb_spu(this, p, buf, 4);
 
772
}
 
773
 
 
774
#endif /* TEST_DVB_SPU */
 
775
 
 
776
static int32_t parse_private_stream_1(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
 
777
{
 
778
  int track, spu_id;
 
779
  int32_t result;
 
780
 
 
781
  result = parse_pes_for_pts(this, p, buf);
 
782
  if (result < 0) return -1;
 
783
 
 
784
  p += result;
 
785
 
 
786
  /* SPU */
 
787
  if ((p[0] & 0xE0) == 0x20) {
 
788
    spu_id = (p[0] & 0x1f);
 
789
 
 
790
    if (this->pts <= 0 && !this->subtitle_type) {
 
791
      /* need whole ES packet (after seek etc.) */
 
792
      buf->free_buffer(buf);
 
793
      return -1;
 
794
    }
 
795
 
 
796
#ifdef TEST_DVB_SPU
 
797
    if (detect_dvb_spu(this, p, buf) < 0)
 
798
      return -1;
 
799
#endif /* TEST_DVB_SPU */
 
800
    this->subtitle_type = BUF_SPU_DVD;
 
801
 
 
802
    /* DVD SPU */
 
803
    buf->content   = p+1;
 
804
    buf->size      = this->packet_len-1;
 
805
 
 
806
    buf->type      = BUF_SPU_DVD + spu_id;
 
807
    buf->decoder_flags |= BUF_FLAG_SPECIAL;
 
808
    buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE;
 
809
    buf->decoder_info[2] = SPU_DVD_SUBTYPE_PACKAGE;
 
810
    buf->pts       = this->pts;
 
811
 
 
812
    this->video_fifo->put (this->video_fifo, buf);
 
813
 
 
814
    return -1;
 
815
  }
 
816
 
 
817
  if ((p[0]&0xF0) == 0x80) {
 
818
 
 
819
    track = p[0] & 0x0F; /* hack : ac3 track */
 
820
 
 
821
    buf->decoder_info[1] = p[1];             /* Number of frame headers */
 
822
    buf->decoder_info[2] = p[2] << 8 | p[3]; /* First access unit pointer */
 
823
 
 
824
    buf->content   = p+4;
 
825
    buf->size      = this->packet_len-4;
 
826
    if (track & 0x8) {
 
827
      buf->type      = BUF_AUDIO_DTS + (track & 0x07); /* DVDs only have 8 tracks */
 
828
    } else {
 
829
      buf->type      = BUF_AUDIO_A52 + track;
 
830
    }
 
831
    buf->pts       = this->pts;
 
832
 
 
833
    if (this->audio_fifo) {
 
834
      check_newpts( this, buf, PTS_AUDIO );
 
835
      track_audio_stream_change (this, buf);
 
836
      this->audio_fifo->put (this->audio_fifo, buf);
 
837
      return -1;
 
838
    } else {
 
839
      buf->free_buffer(buf);
 
840
      return -1;
 
841
    }
 
842
 
 
843
  } else if ((p[0]&0xf0) == 0xa0) {
 
844
 
 
845
    int pcm_offset;
 
846
    int number_of_frame_headers;
 
847
    int first_access_unit_pointer;
 
848
    int audio_frame_number;
 
849
    int bits_per_sample;
 
850
    int sample_rate;
 
851
    int num_channels;
 
852
    int dynamic_range;
 
853
 
 
854
    /*
 
855
     * found in http://members.freemail.absa.co.za/ginggs/dvd/mpeg2_lpcm.txt
 
856
     * appears to be correct.
 
857
     */
 
858
 
 
859
    track = p[0] & 0x0F;
 
860
    number_of_frame_headers = p[1];
 
861
    /* unknown = p[2]; */
 
862
    first_access_unit_pointer = p[3];
 
863
    audio_frame_number = p[4];
 
864
 
 
865
    /*
 
866
     * 000 => mono
 
867
     * 001 => stereo
 
868
     * 010 => 3 channel
 
869
     * ...
 
870
     * 111 => 8 channel
 
871
     */
 
872
    num_channels = (p[5] & 0x7) + 1;
 
873
    sample_rate = p[5] & 0x10 ? 96000 : 48000;
 
874
    switch ((p[5]>>6) & 3) {
 
875
    case 3: /* illegal, use 16-bits? */
 
876
      default:
 
877
        xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
 
878
                 "illegal lpcm sample format (%d), assume 16-bit samples\n", (p[5]>>6) & 3 );
 
879
      case 0: bits_per_sample = 16; break;
 
880
      case 1: bits_per_sample = 20; break;
 
881
      case 2: bits_per_sample = 24; break;
 
882
    }
 
883
    dynamic_range = p[6];
 
884
 
 
885
    /* send lpcm config byte */
 
886
    buf->decoder_flags |= BUF_FLAG_SPECIAL;
 
887
    buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG;
 
888
    buf->decoder_info[2] = p[5];
 
889
 
 
890
    pcm_offset = 7;
 
891
 
 
892
    buf->content   = p+pcm_offset;
 
893
    buf->size      = this->packet_len-pcm_offset;
 
894
    buf->type      = BUF_AUDIO_LPCM_BE + track;
 
895
    buf->pts       = this->pts;
 
896
 
 
897
    if (this->audio_fifo) {
 
898
      check_newpts( this, buf, PTS_AUDIO );
 
899
      track_audio_stream_change (this, buf);
 
900
      this->audio_fifo->put (this->audio_fifo, buf);
 
901
      return -1;
 
902
    } else {
 
903
      buf->free_buffer(buf);
 
904
      return -1;
 
905
    }
 
906
  }
 
907
 
 
908
  buf->free_buffer(buf);
 
909
  return -1;
 
910
}
 
911
 
 
912
/*
 
913
 * detect_h264()
 
914
 *
 
915
 * Detect video codec (MPEG2 or H.264)
 
916
 */
 
917
static int detect_h264(uint8_t *data)
 
918
{
 
919
  /* H.264 detection */
 
920
  if (data[0] == 0 && data[1] == 0 && data[2] == 1) {
 
921
    if (data[3] == NAL_AUD) {
 
922
      LOGMSG("H.264 scanner: Possible H.264 NAL AUD");
 
923
      return BUF_VIDEO_H264;
 
924
    }
 
925
    if (data[3] == 0) {
 
926
      LOGDBG("H.264 scanner: Possible MPEG2 start code PICTURE (0x00)");
 
927
      return BUF_VIDEO_MPEG;
 
928
    }
 
929
    if (data[3] >= 0x80) {
 
930
      LOGDBG("H.264 scanner: Possible MPEG2 start code (0x%02x)", data[3]);
 
931
      return BUF_VIDEO_MPEG;
 
932
    }
 
933
    LOGMSG("H.264 scanner: Unregonized header 00 00 01 %02x", data[3]);
 
934
  }
 
935
 
 
936
  return 0;
 
937
}
 
938
 
 
939
static int32_t parse_video_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
 
940
{
 
941
  int32_t result;
 
942
 
 
943
  result = parse_pes_for_pts(this, p, buf);
 
944
  if (result < 0) return -1;
 
945
 
 
946
  p += result;
 
947
 
 
948
  if (this->video_type == 0) {
 
949
    this->video_type = detect_h264(p);
 
950
  }
 
951
 
 
952
  buf->type      = this->video_type ?: BUF_VIDEO_MPEG;
 
953
  buf->pts       = this->pts;
 
954
  buf->decoder_info[0] = this->pts - this->dts;
 
955
 
 
956
  /* MPEG2 */
 
957
  if (this->video_type == BUF_VIDEO_MPEG) {
 
958
    /* Special handling for FFMPEG MPEG2 decoder */
 
959
    if (this->ffmpeg_mpeg2_decoder) {
 
960
      uint8_t type = pes_get_picture_type(buf->content, buf->size);
 
961
      if (type) {
 
962
        /* signal FRAME_END to decoder */
 
963
        post_frame_end(this, buf);
 
964
        /* for some reason ffmpeg mpeg2 decoder does not understand pts'es in B frames ?
 
965
         * (B-frame pts's are smaller than in previous P-frame)
 
966
         * Anyway, without this block of code B frames with pts are dropped. */
 
967
        if (type == B_FRAME)
 
968
          buf->pts = 0;
 
969
      }
 
970
    }
 
971
  }
 
972
 
 
973
  /* H.264 */
 
974
  else if (this->video_type == BUF_VIDEO_H264) {
 
975
    /* Access Unit Delimiter */
 
976
    if (IS_NAL_AUD(p))
 
977
      post_frame_end (this, buf);
 
978
 
 
979
    /* Check for end of still image.
 
980
       VDR ensures that H.264 still images end with an end of sequence NAL unit */
 
981
    if (buf->size > 4) {
 
982
      uint8_t *end = buf->content + buf->size;
 
983
      if (IS_NAL_END_SEQ(end-4)) {
 
984
        LOGMSG("post_frame_h264: Still frame ? (frame ends with end of sequence NAL unit)");
 
985
        buf->decoder_flags |= BUF_FLAG_FRAME_END;
 
986
      }
 
987
    }
 
988
  }
 
989
 
 
990
  buf->content   = p;
 
991
  buf->size      = this->packet_len;
 
992
 
 
993
  check_newpts( this, buf, PTS_VIDEO );
 
994
 
 
995
  this->video_fifo->put (this->video_fifo, buf);
 
996
 
 
997
  return -1;
 
998
}
 
999
 
 
1000
static int32_t parse_audio_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
 
1001
{
 
1002
  int track;
 
1003
  int32_t result;
 
1004
 
 
1005
  result = parse_pes_for_pts(this, p, buf);
 
1006
  if (result < 0) return -1;
 
1007
 
 
1008
  p += result;
 
1009
 
 
1010
  track = this->stream_id & 0x1f;
 
1011
 
 
1012
  buf->content   = p;
 
1013
  buf->size      = this->packet_len;
 
1014
  buf->type      = BUF_AUDIO_MPEG + track;
 
1015
  buf->pts       = this->pts;
 
1016
 
 
1017
  if (this->audio_fifo) {
 
1018
    check_newpts( this, buf, PTS_AUDIO );
 
1019
    track_audio_stream_change (this, buf);
 
1020
    this->audio_fifo->put (this->audio_fifo, buf);
 
1021
  } else {
 
1022
    buf->free_buffer(buf);
 
1023
  }
 
1024
 
 
1025
  return -1;
 
1026
}
 
1027
 
 
1028
/*
 
1029
 * interface
 
1030
 */
 
1031
 
 
1032
static int demux_xvdr_send_chunk (demux_plugin_t *this_gen)
 
1033
{
 
1034
  demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
 
1035
 
 
1036
  demux_xvdr_parse_pack(this);
 
1037
 
 
1038
  return this->status;
 
1039
}
 
1040
 
 
1041
static void demux_xvdr_dispose (demux_plugin_t *this_gen)
 
1042
{
 
1043
  demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
 
1044
 
 
1045
  LOGDBG("demux_xvdr_dispose()");
 
1046
 
 
1047
  ts_data_dispose(&this->ts_data);
 
1048
 
 
1049
  free (this);
 
1050
}
 
1051
 
 
1052
static int demux_xvdr_get_status (demux_plugin_t *this_gen)
 
1053
{
 
1054
  demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
 
1055
 
 
1056
  if (this->status != DEMUX_OK) {
 
1057
    if (this->ts_data) {
 
1058
      LOGMSG("demux_xvdr_get_status(): status != DEMUX_OK. -> freeing ts_data");
 
1059
      ts_data_dispose(&this->ts_data);
 
1060
    }
 
1061
  }
 
1062
 
 
1063
  return this->status;
 
1064
}
 
1065
 
 
1066
static void demux_xvdr_send_headers (demux_plugin_t *this_gen)
 
1067
{
 
1068
  demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
 
1069
 
 
1070
  this->video_fifo  = this->stream->video_fifo;
 
1071
  this->audio_fifo  = this->stream->audio_fifo;
 
1072
 
 
1073
  /*
 
1074
   * send start buffer
 
1075
   */
 
1076
 
 
1077
  _x_demux_control_start(this->stream);
 
1078
 
 
1079
  this->status = DEMUX_OK;
 
1080
 
 
1081
  _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
 
1082
  _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
 
1083
  _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, 5000000);
 
1084
}
 
1085
 
 
1086
 
 
1087
static int demux_xvdr_seek (demux_plugin_t *this_gen,
 
1088
                            off_t start_pos, int start_time, int playing)
 
1089
{
 
1090
  demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
 
1091
 
 
1092
  /*
 
1093
   * now start demuxing
 
1094
   */
 
1095
  this->send_newpts   = 1;
 
1096
  this->video_type    = 0;
 
1097
  this->audio_type    = 0;
 
1098
  this->subtitle_type = 0;
 
1099
  this->bih_posted    = 0;
 
1100
  ts_data_dispose(&this->ts_data);
 
1101
 
 
1102
  if (!playing) {
 
1103
 
 
1104
    this->buf_flag_seek = 0;
 
1105
    this->status        = DEMUX_OK;
 
1106
    this->last_pts[0]   = 0;
 
1107
    this->last_pts[1]   = 0;
 
1108
  } else {
 
1109
    this->buf_flag_seek = 1;
 
1110
    this->last_vpts     = INT64_C(-1);
 
1111
    _x_demux_flush_engine(this->stream);
 
1112
  }
 
1113
 
 
1114
  return this->status;
 
1115
}
 
1116
 
 
1117
/*
 
1118
 * demux class
 
1119
 */
 
1120
 
 
1121
static int demux_xvdr_get_stream_length (demux_plugin_t *this_gen)
 
1122
{
 
1123
  return 0;
 
1124
}
 
1125
 
 
1126
static uint32_t demux_xvdr_get_capabilities(demux_plugin_t *this_gen)
 
1127
{
 
1128
  return DEMUX_CAP_NOCAP;
 
1129
}
 
1130
 
 
1131
static int demux_xvdr_get_optional_data(demux_plugin_t *this_gen,
 
1132
                                        void *data, int data_type)
 
1133
{
 
1134
  return DEMUX_OPTIONAL_UNSUPPORTED;
 
1135
}
 
1136
 
 
1137
static demux_plugin_t *demux_xvdr_open_plugin (demux_class_t *class_gen,
 
1138
                                               xine_stream_t *stream,
 
1139
                                               input_plugin_t *input_gen)
 
1140
{
 
1141
  input_plugin_t *input = (input_plugin_t *) input_gen;
 
1142
  demux_xvdr_t   *this;
 
1143
  const char     *mrl = input->get_mrl(input);
 
1144
 
 
1145
  if (strncmp(mrl, MRL_ID ":/",       MRL_ID_LEN + 2 ) &&
 
1146
      strncmp(mrl, MRL_ID "+pipe://", MRL_ID_LEN + 8) &&
 
1147
      strncmp(mrl, MRL_ID "+tcp://",  MRL_ID_LEN + 7) &&
 
1148
      strncmp(mrl, MRL_ID "+udp://",  MRL_ID_LEN + 7) &&
 
1149
      strncmp(mrl, MRL_ID "+rtp://",  MRL_ID_LEN + 7))
 
1150
    return NULL;
 
1151
 
 
1152
  this         = calloc(1, sizeof(demux_xvdr_t));
 
1153
  this->stream = stream;
 
1154
  this->input  = input;
 
1155
 
 
1156
  this->demux_plugin.send_headers      = demux_xvdr_send_headers;
 
1157
  this->demux_plugin.send_chunk        = demux_xvdr_send_chunk;
 
1158
  this->demux_plugin.seek              = demux_xvdr_seek;
 
1159
  this->demux_plugin.dispose           = demux_xvdr_dispose;
 
1160
  this->demux_plugin.get_status        = demux_xvdr_get_status;
 
1161
  this->demux_plugin.get_stream_length = demux_xvdr_get_stream_length;
 
1162
  this->demux_plugin.get_capabilities  = demux_xvdr_get_capabilities;
 
1163
  this->demux_plugin.get_optional_data = demux_xvdr_get_optional_data;
 
1164
  this->demux_plugin.demux_class       = class_gen;
 
1165
 
 
1166
  this->status     = DEMUX_FINISHED;
 
1167
 
 
1168
  detect_video_decoders(this);
 
1169
 
 
1170
  return &this->demux_plugin;
 
1171
}
 
1172
 
 
1173
#if DEMUXER_PLUGIN_IFACE_VERSION < 27
 
1174
static const char *demux_xvdr_get_description (demux_class_t *this_gen)
 
1175
{
 
1176
  return MRL_ID " demux plugin";
 
1177
}
 
1178
 
 
1179
static const char *demux_xvdr_get_identifier (demux_class_t *this_gen)
 
1180
{
 
1181
  return MRL_ID;
 
1182
}
 
1183
 
 
1184
static const char *demux_xvdr_get_extensions (demux_class_t *this_gen)
 
1185
{
 
1186
  return NULL;
 
1187
}
 
1188
 
 
1189
static const char *demux_xvdr_get_mimetypes (demux_class_t *this_gen)
 
1190
{
 
1191
  return NULL;
 
1192
}
 
1193
 
 
1194
static void demux_xvdr_class_dispose (demux_class_t *this_gen)
 
1195
{
 
1196
  demux_xvdr_class_t *this = (demux_xvdr_class_t *) this_gen;
 
1197
 
 
1198
  free (this);
 
1199
}
 
1200
#endif
 
1201
 
 
1202
void *demux_xvdr_init_class (xine_t *xine, void *data)
 
1203
{
 
1204
  demux_xvdr_class_t     *this;
 
1205
 
 
1206
  this         = calloc(1, sizeof(demux_xvdr_class_t));
 
1207
  this->config = xine->config;
 
1208
  this->xine   = xine;
 
1209
 
 
1210
  this->demux_class.open_plugin     = demux_xvdr_open_plugin;
 
1211
#if DEMUXER_PLUGIN_IFACE_VERSION < 27
 
1212
  this->demux_class.get_description = demux_xvdr_get_description;
 
1213
  this->demux_class.get_identifier  = demux_xvdr_get_identifier;
 
1214
  this->demux_class.get_mimetypes   = demux_xvdr_get_mimetypes;
 
1215
  this->demux_class.get_extensions  = demux_xvdr_get_extensions;
 
1216
  this->demux_class.dispose         = demux_xvdr_class_dispose;
 
1217
#else
 
1218
  this->demux_class.description     = N_("XVDR demux plugin");
 
1219
  this->demux_class.identifier      = MRL_ID;
 
1220
  this->demux_class.mimetypes       = NULL;
 
1221
  this->demux_class.extensions      = 
 
1222
    MRL_ID":/ "
 
1223
    MRL_ID"+pipe:/ "
 
1224
    MRL_ID"+tcp:/ "
 
1225
    MRL_ID"+udp:/ "
 
1226
    MRL_ID"+rtp:/ "
 
1227
    MRL_ID"+slave:/";
 
1228
  this->demux_class.dispose         = default_demux_class_dispose;
 
1229
#endif
 
1230
 
 
1231
  return this;
 
1232
}
 
1233
 
 
1234