2
* Copyright (C) 2000-2006 the xine project
4
* This file is part of xine, a free video player.
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.
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.
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
20
* demultiplexer for xineliboutput (xvdr)
29
#include <xine/xine_internal.h>
30
#include <xine/xineutils.h>
31
#include <xine/demux.h>
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"
40
#include "demux_xvdr_tsdata.h"
53
static const char log_module_demux_xvdr[] = "[demux_vdr] ";
54
#define LOG_MODULENAME log_module_demux_xvdr
55
#define SysLogLevel iSysLogLevel
57
#include "../logdefs.h"
65
#define DISC_TRESHOLD 90000
66
#define WRAP_THRESHOLD 120000
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) )
75
typedef struct demux_xvdr_s {
76
demux_plugin_t demux_plugin;
78
xine_stream_t *stream;
79
fifo_buffer_t *audio_fifo;
80
fifo_buffer_t *video_fifo;
82
input_plugin_t *input;
84
ts_data_t *ts_data; /* MPEG-TS stuff */
91
uint32_t subtitle_type;
93
/* current buf_element */
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;
108
demux_class_t demux_class;
110
/* class-wide, global variables here */
113
config_values_t *config;
114
} demux_xvdr_class_t;
117
static const char * get_decoder_name(xine_t *xine, int video_type)
119
int streamtype = (video_type >> 16) & 0xFF;
120
plugin_node_t *node = xine->plugin_catalog->video_decoder_map[streamtype][0];
122
plugin_info_t *info = node->info;
129
static void detect_video_decoders(demux_xvdr_t *this)
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");
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");
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);
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);
150
static void pts_wrap_workaround(demux_xvdr_t *this, buf_element_t *buf, int video)
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));
160
/* PTS wrap workaround */
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);
173
static void check_newpts(demux_xvdr_t *this, buf_element_t *buf, int video )
175
pts_wrap_workaround(this, buf, video);
178
int64_t diff = buf->pts - this->last_pts[video];
180
if (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD)) {
182
if (this->buf_flag_seek) {
183
_x_demux_control_newpts(this->stream, buf->pts, BUF_FLAG_SEEK);
184
this->buf_flag_seek = 0;
186
_x_demux_control_newpts(this->stream, buf->pts, 0);
188
this->send_newpts = 0;
190
this->last_pts[1-video] = 0;
193
this->last_pts[video] = buf->pts;
197
static void put_control_buf(fifo_buffer_t *buffer, fifo_buffer_t *pool, int cmd)
199
buf_element_t *buf = pool->buffer_pool_try_alloc(pool);
202
buffer->put(buffer, buf);
207
* post_sequence_end()
209
* Add MPEG2 or H.264 sequence end code to fifo buffer
211
static void post_sequence_end(fifo_buffer_t *fifo, uint32_t video_type)
213
buf_element_t *buf = fifo->buffer_pool_try_alloc(fifo);
215
buf->type = video_type;
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);
229
* Signal end of video frame to decoder.
231
* This function is used with:
232
* - FFmpeg mpeg2 decoder
233
* - FFmpeg and CoreAVC H.264 decoders
234
* - NOT with libmpeg2 mpeg decoder
236
static void post_frame_end(demux_xvdr_t *this, buf_element_t *vid_buf)
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);
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);
246
LOGERR("post_frame_end(): get_buf_element() failed !");
251
cbuf->type = this->video_type;
252
cbuf->decoder_flags = BUF_FLAG_FRAME_END;
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)) {
258
/* reset decoder buffer */
259
cbuf->decoder_flags |= BUF_FLAG_FRAME_START;
261
/* Fill xine_bmiheader for CoreAVC / H.264 */
263
if (this->video_type == BUF_VIDEO_H264 && this->coreavc_h264_decoder) {
264
xine_bmiheader *bmi = (xine_bmiheader*) cbuf->content;
266
cbuf->decoder_flags |= BUF_FLAG_HEADER;
267
cbuf->decoder_flags |= BUF_FLAG_STDHEADER; /* CoreAVC: buffer contains bmiheader */
268
cbuf->size = sizeof(xine_bmiheader);
270
memset (bmi, 0, sizeof(xine_bmiheader));
272
bmi->biSize = sizeof(xine_bmiheader);
273
bmi->biWidth = size.width;
274
bmi->biHeight = size.height;
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;
283
bmi->biClrImportant = 0;
286
/* Set aspect ratio for ffmpeg mpeg2 / CoreAVC H.264 decoder
287
* (not for FFmpeg H.264 or libmpeg2 mpeg2 decoders)
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;
299
cbuf->decoder_info[1] = size.pixel_aspect.num * size.width;
300
cbuf->decoder_info[2] = size.pixel_aspect.den * size.height;
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);
307
this->bih_posted = 1;
311
this->video_fifo->put (this->video_fifo, cbuf);
314
static void track_audio_stream_change(demux_xvdr_t *this, buf_element_t *buf)
316
#if !defined(BUF_CONTROL_RESET_TRACK_MAP)
317
# warning xine-lib is older than 1.1.2. Multiple audio streams are not supported.
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,
324
BUF_CONTROL_RESET_TRACK_MAP);
329
static void demux_xvdr_fwd_buf(demux_xvdr_t *this, buf_element_t *buf)
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);
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);
346
buf->free_buffer (buf);
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);
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));
369
this->audio_fifo->put (this->audio_fifo, cbuf);
371
this->video_fifo->put (this->video_fifo, buf);
375
LOGMSG("Unhandled buffer type %08x", buf->type);
376
buf->free_buffer (buf);
379
static void demux_xvdr_parse_pack (demux_xvdr_t *this)
381
buf_element_t *buf = NULL;
384
buf = this->input->read_block (this->input, this->video_fifo, 8128);
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);
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);
407
p = buf->content; /* len = this->blocksize; */
408
buf->decoder_flags = 0;
411
demux_xvdr_parse_ts (this, buf);
414
if (DATA_IS_PES(p)) {
415
demux_xvdr_parse_pes (this, buf);
419
LOGMSG("Header %02x %02x %02x (should be 0x000001 or 0x47)", p[0], p[1], p[2]);
420
buf->free_buffer (buf);
424
static void demux_xvdr_parse_pes (demux_xvdr_t *this, buf_element_t *buf)
426
uint8_t *p = buf->content;
429
this->stream_id = p[3];
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);
440
LOGMSG("Unrecognised PES stream 0x%02x", this->stream_id);
441
buf->free_buffer (buf);
449
LOGMSG("error! freeing buffer.");
450
buf->free_buffer (buf);
454
* demux_xvdr_parse_ts()
458
static void demux_xvdr_parse_ts (demux_xvdr_t *this, buf_element_t *buf)
461
this->ts_data = calloc(1, sizeof(ts_data_t));
463
ts_data_t *ts_data = this->ts_data;
464
fifo_buffer_t *src_fifo = buf->source;
466
while (buf->size >= TS_SIZE) {
468
unsigned int ts_pid = ts_PID(buf->content);
474
ts_data_flush(ts_data);
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);
485
else if (ts_pid == ts_data->pmt_pid) {
487
ts_data_flush(ts_data);
489
if (ts_parse_pmt(&ts_data->pmt, ts_data->program_number, buf->content)) {
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);
495
this->video_type = (ts_data->pmt.video_type == ISO_14496_PART10_VIDEO) ?
496
BUF_VIDEO_H264 : BUF_VIDEO_MPEG;
498
/* Inform UI of channels changes */
500
event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
501
event.data_length = 0;
502
xine_event_send(this->stream, &event);
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);
511
this->pts = vbuf->pts;
512
check_newpts( this, vbuf, PTS_VIDEO );
514
this->stream->video_fifo->put(this->stream->video_fifo, vbuf);
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);
527
this->pts = abuf->pts;
528
check_newpts( this, abuf, PTS_AUDIO );
529
track_audio_stream_change (this, abuf);
531
this->stream->audio_fifo->put(this->stream->audio_fifo, abuf);
538
/* demux subtitles */
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);
545
this->stream->video_fifo->put(this->stream->video_fifo, sbuf);
552
LOGMSG("Got unknown TS packet, pid = %d", ts_pid);
556
buf->content += TS_SIZE;
557
buf->size -= TS_SIZE;
560
buf->free_buffer(buf);
563
static int32_t parse_padding_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
565
buf->free_buffer (buf);
569
/* FIXME: Extension data is not parsed, and is also not skipped. */
571
static int32_t parse_pes_for_pts(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
575
this->packet_len = p[4] << 8 | p[5];
577
if ((p[6] & 0xC0) != 0x80 /* mpeg1 */) {
579
p += 6; /* packet_len -= 6; */
581
while ((p[0] & 0x80) == 0x80) {
587
if ((p[0] & 0xc0) == 0x40) {
588
/* STD_buffer_scale, STD_buffer_size */
591
this->packet_len -= 2;
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 ;
605
this->packet_len -=5;
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 ;
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 ;
622
this->packet_len -= 10;
631
} else { /* mpeg 2 */
634
if ((p[6] & 0xC0) != 0x80) {
635
LOGMSG("warning: PES header reserved 10 bits not found");
636
buf->free_buffer(buf);
641
/* check PES scrambling_control */
642
if ((p[6] & 0x30) != 0) {
643
LOGMSG("encrypted PES ?");
644
buf->free_buffer(buf);
648
if (p[7] & 0x80) { /* pts avail */
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 ;
659
if (p[7] & 0x40) { /* dts avail */
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 ;
673
this->packet_len -= header_len + 3;
674
return header_len + 9;
679
#if defined(TEST_DVB_SPU)
683
* DVB subtitle stream demuxing
685
static int32_t parse_dvb_spu(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf, int substream_header_len)
687
uint spu_id = p[0] & 0x1f;
688
_x_select_spu_channel(this->stream, spu_id);
690
# ifdef VDR_SUBTITLES
691
if (substream_header_len == 1) {
695
# endif /* VDR_SUBTITLES */
697
/* Skip substream header */
698
p += substream_header_len;
700
buf->size = this->packet_len - substream_header_len;
702
/* Special buffer when payload packet changes */
704
buf_element_t *cbuf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
705
int page_id = (*(p+4) << 8) | *(p+5);
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;
711
cbuf->type = BUF_SPU_DVB + spu_id;
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;
718
this->video_fifo->put (this->video_fifo, cbuf);
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 (?) */
725
this->video_fifo->put (this->video_fifo, buf);
730
int detect_dvb_spu(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
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]);
736
/* If PES packet has PTS, it starts new subtitle (ES) packet. */
739
this->subtitle_type = 0;
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);
750
# endif /* VDR_SUBTITLES */
752
/* Start of subtitle packet. Guess substream type */
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");
761
this->subtitle_type = BUF_SPU_DVD;
762
LOGMSG(" -> DV? SPU -> DVD");
767
if (this->subtitle_type == BUF_SPU_DVD)
768
return this->packet_len;
771
return parse_dvb_spu(this, p, buf, 4);
774
#endif /* TEST_DVB_SPU */
776
static int32_t parse_private_stream_1(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
781
result = parse_pes_for_pts(this, p, buf);
782
if (result < 0) return -1;
787
if ((p[0] & 0xE0) == 0x20) {
788
spu_id = (p[0] & 0x1f);
790
if (this->pts <= 0 && !this->subtitle_type) {
791
/* need whole ES packet (after seek etc.) */
792
buf->free_buffer(buf);
797
if (detect_dvb_spu(this, p, buf) < 0)
799
#endif /* TEST_DVB_SPU */
800
this->subtitle_type = BUF_SPU_DVD;
804
buf->size = this->packet_len-1;
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;
812
this->video_fifo->put (this->video_fifo, buf);
817
if ((p[0]&0xF0) == 0x80) {
819
track = p[0] & 0x0F; /* hack : ac3 track */
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 */
825
buf->size = this->packet_len-4;
827
buf->type = BUF_AUDIO_DTS + (track & 0x07); /* DVDs only have 8 tracks */
829
buf->type = BUF_AUDIO_A52 + track;
831
buf->pts = this->pts;
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);
839
buf->free_buffer(buf);
843
} else if ((p[0]&0xf0) == 0xa0) {
846
int number_of_frame_headers;
847
int first_access_unit_pointer;
848
int audio_frame_number;
855
* found in http://members.freemail.absa.co.za/ginggs/dvd/mpeg2_lpcm.txt
856
* appears to be correct.
860
number_of_frame_headers = p[1];
861
/* unknown = p[2]; */
862
first_access_unit_pointer = p[3];
863
audio_frame_number = p[4];
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? */
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;
883
dynamic_range = p[6];
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];
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;
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);
903
buf->free_buffer(buf);
908
buf->free_buffer(buf);
915
* Detect video codec (MPEG2 or H.264)
917
static int detect_h264(uint8_t *data)
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;
926
LOGDBG("H.264 scanner: Possible MPEG2 start code PICTURE (0x00)");
927
return BUF_VIDEO_MPEG;
929
if (data[3] >= 0x80) {
930
LOGDBG("H.264 scanner: Possible MPEG2 start code (0x%02x)", data[3]);
931
return BUF_VIDEO_MPEG;
933
LOGMSG("H.264 scanner: Unregonized header 00 00 01 %02x", data[3]);
939
static int32_t parse_video_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
943
result = parse_pes_for_pts(this, p, buf);
944
if (result < 0) return -1;
948
if (this->video_type == 0) {
949
this->video_type = detect_h264(p);
952
buf->type = this->video_type ?: BUF_VIDEO_MPEG;
953
buf->pts = this->pts;
954
buf->decoder_info[0] = this->pts - this->dts;
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);
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. */
974
else if (this->video_type == BUF_VIDEO_H264) {
975
/* Access Unit Delimiter */
977
post_frame_end (this, buf);
979
/* Check for end of still image.
980
VDR ensures that H.264 still images end with an end of sequence NAL unit */
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;
991
buf->size = this->packet_len;
993
check_newpts( this, buf, PTS_VIDEO );
995
this->video_fifo->put (this->video_fifo, buf);
1000
static int32_t parse_audio_stream(demux_xvdr_t *this, uint8_t *p, buf_element_t *buf)
1005
result = parse_pes_for_pts(this, p, buf);
1006
if (result < 0) return -1;
1010
track = this->stream_id & 0x1f;
1013
buf->size = this->packet_len;
1014
buf->type = BUF_AUDIO_MPEG + track;
1015
buf->pts = this->pts;
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);
1022
buf->free_buffer(buf);
1032
static int demux_xvdr_send_chunk (demux_plugin_t *this_gen)
1034
demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
1036
demux_xvdr_parse_pack(this);
1038
return this->status;
1041
static void demux_xvdr_dispose (demux_plugin_t *this_gen)
1043
demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
1045
LOGDBG("demux_xvdr_dispose()");
1047
ts_data_dispose(&this->ts_data);
1052
static int demux_xvdr_get_status (demux_plugin_t *this_gen)
1054
demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
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);
1063
return this->status;
1066
static void demux_xvdr_send_headers (demux_plugin_t *this_gen)
1068
demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
1070
this->video_fifo = this->stream->video_fifo;
1071
this->audio_fifo = this->stream->audio_fifo;
1077
_x_demux_control_start(this->stream);
1079
this->status = DEMUX_OK;
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);
1087
static int demux_xvdr_seek (demux_plugin_t *this_gen,
1088
off_t start_pos, int start_time, int playing)
1090
demux_xvdr_t *this = (demux_xvdr_t *) this_gen;
1093
* now start demuxing
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);
1104
this->buf_flag_seek = 0;
1105
this->status = DEMUX_OK;
1106
this->last_pts[0] = 0;
1107
this->last_pts[1] = 0;
1109
this->buf_flag_seek = 1;
1110
this->last_vpts = INT64_C(-1);
1111
_x_demux_flush_engine(this->stream);
1114
return this->status;
1121
static int demux_xvdr_get_stream_length (demux_plugin_t *this_gen)
1126
static uint32_t demux_xvdr_get_capabilities(demux_plugin_t *this_gen)
1128
return DEMUX_CAP_NOCAP;
1131
static int demux_xvdr_get_optional_data(demux_plugin_t *this_gen,
1132
void *data, int data_type)
1134
return DEMUX_OPTIONAL_UNSUPPORTED;
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)
1141
input_plugin_t *input = (input_plugin_t *) input_gen;
1143
const char *mrl = input->get_mrl(input);
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))
1152
this = calloc(1, sizeof(demux_xvdr_t));
1153
this->stream = stream;
1154
this->input = input;
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;
1166
this->status = DEMUX_FINISHED;
1168
detect_video_decoders(this);
1170
return &this->demux_plugin;
1173
#if DEMUXER_PLUGIN_IFACE_VERSION < 27
1174
static const char *demux_xvdr_get_description (demux_class_t *this_gen)
1176
return MRL_ID " demux plugin";
1179
static const char *demux_xvdr_get_identifier (demux_class_t *this_gen)
1184
static const char *demux_xvdr_get_extensions (demux_class_t *this_gen)
1189
static const char *demux_xvdr_get_mimetypes (demux_class_t *this_gen)
1194
static void demux_xvdr_class_dispose (demux_class_t *this_gen)
1196
demux_xvdr_class_t *this = (demux_xvdr_class_t *) this_gen;
1202
void *demux_xvdr_init_class (xine_t *xine, void *data)
1204
demux_xvdr_class_t *this;
1206
this = calloc(1, sizeof(demux_xvdr_class_t));
1207
this->config = xine->config;
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;
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 =
1228
this->demux_class.dispose = default_demux_class_dispose;