summaryrefslogtreecommitdiff
path: root/src/demuxers/demux_mpeg_block.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers/demux_mpeg_block.c')
-rw-r--r--src/demuxers/demux_mpeg_block.c200
1 files changed, 100 insertions, 100 deletions
diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c
index 55eb0ce81..aa5294e8b 100644
--- a/src/demuxers/demux_mpeg_block.c
+++ b/src/demuxers/demux_mpeg_block.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2000-2006 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -20,7 +20,7 @@
* demultiplexer for mpeg 1/2 program streams
* used with fixed blocksize devices (like dvd/vcd)
*/
-
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -44,7 +44,7 @@
#define NUM_PREVIEW_BUFFERS 250
#define DISC_TRESHOLD 90000
-#define WRAP_THRESHOLD 120000
+#define WRAP_THRESHOLD 120000
#define PTS_AUDIO 0
#define PTS_VIDEO 1
@@ -56,14 +56,14 @@
typedef struct demux_mpeg_block_s {
demux_plugin_t demux_plugin;
- xine_stream_t *stream;
+ xine_stream_t *stream;
fifo_buffer_t *audio_fifo;
fifo_buffer_t *video_fifo;
input_plugin_t *input;
int status;
-
+
int blocksize;
int rate;
@@ -123,30 +123,30 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_block_t *this, uint8_
/* OK, i think demux_mpeg_block discontinuity handling demands some
explanation:
-
+
- The preferred discontinuity handling/detection for DVD is based on
NAV packets information. Most of the time it will provide us very
accurate and reliable information.
-
+
- Has been shown that sometimes a DVD discontinuity may happen before
a new NAV packet arrives (seeking?). To avoid sending wrong PTS to
decoders we _used_ to check for SCR discontinuities. Unfortunately
some VCDs have very broken SCR values causing false triggering.
-
+
- To fix the above problem (also note that VCDs don't have NAV
packets) we fallback to the same PTS-based wrap detection as used
in demux_mpeg. The only trick is to not send discontinuity information
if NAV packets have already done the job.
-
+
[Miguel 02-05-2002]
*/
static void check_newpts( demux_mpeg_block_t *this, int64_t pts, int video )
{
int64_t diff;
-
+
diff = pts - this->last_pts[video];
-
+
if( pts && (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) {
/* check if pts is outside nav pts range. any stream without nav must enter here. */
@@ -164,10 +164,10 @@ static void check_newpts( demux_mpeg_block_t *this, int64_t pts, int video )
} else {
lprintf("no wrap detected\n" );
}
-
+
this->last_pts[1-video] = 0;
}
-
+
if( pts )
this->last_pts[video] = pts;
}
@@ -220,9 +220,9 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
buf->decoder_flags = BUF_FLAG_PREVIEW;
else
buf->decoder_flags = 0;
-
+
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
while(p < (buf->content + this->blocksize)) {
@@ -435,7 +435,7 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_block_t *this, uint8_
return 12;
} else { /* mpeg2 */
-
+
int num_stuffing_bytes;
/* system_clock_reference */
@@ -499,7 +499,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_
* the NAV packet for a much more accurate timing */
if (buf->extra_info->input_time) {
int64_t cell_time, frames;
-
+
cell_time = (p[7+0x18] >> 4 ) * 10 * 60 * 60 * 1000;
cell_time += (p[7+0x18] & 0x0f) * 60 * 60 * 1000;
cell_time += (p[7+0x19] >> 4 ) * 10 * 60 * 1000;
@@ -508,7 +508,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_
cell_time += (p[7+0x1a] & 0x0f) * 1000;
frames = ((p[7+0x1b] & 0x30) >> 4) * 10;
frames += ((p[7+0x1b] & 0x0f) ) ;
-
+
if (p[7+0x1b] & 0x80)
cell_time += (frames * 1000)/25;
else
@@ -518,7 +518,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_
this->last_cell_pos = this->input->get_current_pos (this->input);
this->last_begin_time = buf->extra_info->input_time;
}
-
+
lprintf ("NAV packet, start pts = %"PRId64", end_pts = %"PRId64"\n",
start_pts, end_pts);
@@ -569,14 +569,14 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme
}
if (this->rate && !buf->extra_info->input_time)
- buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
+ buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
* 1000 / (this->rate * 50));
if (this->mpeg1) {
header_len = 6;
p += 6; /* packet_len -= 6; */
while ((p[0] & 0x80) == 0x80) {
- p++;
+ p++;
header_len++;
this->packet_len--;
/* printf ("stuffing\n");*/
@@ -589,9 +589,9 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme
this->packet_len -= 2;
}
- this->pts = 0;
+ this->pts = 0;
this->dts = 0;
-
+
if ((p[0] & 0xf0) == 0x20) {
this->pts = (int64_t)(p[ 0] & 0x0E) << 29 ;
this->pts |= p[ 1] << 22 ;
@@ -608,19 +608,19 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme
this->pts |= (p[ 2] & 0xFE) << 14 ;
this->pts |= p[ 3] << 7 ;
this->pts |= (p[ 4] & 0xFE) >> 1 ;
-
+
this->dts = (int64_t)(p[ 5] & 0x0E) << 29 ;
this->dts |= p[ 6] << 22 ;
this->dts |= (p[ 7] & 0xFE) << 14 ;
this->dts |= p[ 8] << 7 ;
this->dts |= (p[ 9] & 0xFE) >> 1 ;
-
+
p += 10;
header_len += 10;
this->packet_len -= 10;
return header_len;
} else {
- p++;
+ p++;
header_len++;
this->packet_len--;
return header_len;
@@ -664,13 +664,13 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme
this->pts = 0;
if (p[7] & 0x40) { /* dts avail */
-
+
this->dts = (int64_t)(p[14] & 0x0E) << 29 ;
this->dts |= p[15] << 22 ;
this->dts |= (p[16] & 0xFE) << 14 ;
this->dts |= p[17] << 7 ;
this->dts |= (p[18] & 0xFE) >> 1 ;
-
+
} else
this->dts = 0;
@@ -699,16 +699,16 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
buf->content = p+1;
buf->size = this->packet_len-1;
-
+
buf->type = BUF_SPU_DVD + spu_id;
buf->decoder_flags |= BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE;
buf->decoder_info[2] = SPU_DVD_SUBTYPE_PACKAGE;
buf->pts = this->pts;
-
- this->video_fifo->put (this->video_fifo, buf);
+
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU PACK put on fifo\n");
-
+
return -1;
}
@@ -724,9 +724,9 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
if( !preview_mode )
check_newpts( this, this->pts, PTS_VIDEO );
*/
- this->video_fifo->put (this->video_fifo, buf);
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU SVCD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id);
-
+
return -1;
}
@@ -741,29 +741,29 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
/* this is probably wrong:
if( !preview_mode )
check_newpts( this, this->pts, PTS_VIDEO );
- */
- this->video_fifo->put (this->video_fifo, buf);
+ */
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU CVD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id);
-
+
return -1;
}
if ((p[0]&0xF0) == 0x80) {
-
+
track = p[0] & 0x0F; /* hack : ac3 track */
- /* Number of frame headers
+ /* Number of frame headers
*
* Describes the number of a52 frame headers that start in this pack (One pack per DVD sector).
*
* Likely values: 1 or 2.
*/
buf->decoder_info[1] = p[1];
- /* First access unit pointer.
+ /* First access unit pointer.
*
* Describes the byte offset within this pack to the beginning of the first A52 frame header.
* The PTS from this pack applies to the beginning of the first A52 frame that starts in this pack.
- * Any bytes before this offset should be considered to belong to the previous A52 frame.
+ * Any bytes before this offset should be considered to belong to the previous A52 frame.
* and therefore be tagged with a PTS value derived from the previous pack.
*
* Likely values: Anything from 1 to the size of an A52 frame.
@@ -864,7 +864,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
buf->free_buffer(buf);
return -1;
}
-
+
} else if ((p[0]&0xf0) == 0xa0) {
int pcm_offset;
@@ -911,7 +911,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
buf->decoder_flags |= BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG;
buf->decoder_info[2] = p[5];
-
+
pcm_offset = 7;
buf->content = p+pcm_offset;
@@ -930,7 +930,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
buf->free_buffer(buf);
return -1;
}
-
+
}
/* Some new streams have been encountered.
1) DVD+RW disc recorded with a Philips DVD recorder: - new unknown sub-stream id of 0xff
@@ -1003,10 +1003,10 @@ static int demux_mpeg_block_send_chunk (demux_plugin_t *this_gen) {
}
#ifdef ESTIMATE_RATE_FIXED
-/*!
- Estimate bitrate by looking inside the MPEG file for presentation
- time stamps (PTS) and computing how far apart these are
- in bytes and in time.
+/*!
+ Estimate bitrate by looking inside the MPEG file for presentation
+ time stamps (PTS) and computing how far apart these are
+ in bytes and in time.
On failure return 0.
@@ -1037,23 +1037,23 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
int rate=0; /* The return rate value */
int stream_id;
- /* We can't estimate by sampling if we don't thave the ability to
+ /* We can't estimate by sampling if we don't thave the ability to
randomly access the and more importantly reset after accessessing. */
if (!(this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE))
return 0;
mpeg_length= this->input->get_length (this->input);
- step = TRUNC((mpeg_length/MAX_SAMPLES), blocksize);
+ step = TRUNC((mpeg_length/MAX_SAMPLES), blocksize);
if (step <= 0) step = blocksize; /* avoid endless loop for tiny files */
pos = step;
/* At this point "pos", and "step" are a multiple of blocksize and
they should continue to be so throughout.
*/
-
+
this->input->seek (this->input, pos, SEEK_SET);
- while ( (buf = this->input->read_block (this->input, this->video_fifo, blocksize))
+ while ( (buf = this->input->read_block (this->input, this->video_fifo, blocksize))
&& count < MAX_SAMPLES && reads++ < MAX_READS ) {
p = buf->content; /* len = this->mnBlocksize; */
@@ -1062,9 +1062,9 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
is_mpeg1 = (p[4] & 0x40) == 0;
- if (is_mpeg1)
+ if (is_mpeg1)
p += 12;
- else
+ else
p += 14 + (p[0xD] & 0x07);
}
@@ -1081,7 +1081,7 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
}
stream_id = p[3];
- pts = 0;
+ pts = 0;
if ((stream_id < 0xbc) || ((stream_id & 0xf0) != 0xe0)) {
pos += (off_t) blocksize;
@@ -1111,18 +1111,18 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
pts |= (p[ 2] & 0xFE) << 14 ;
pts |= p[ 3] << 7 ;
pts |= (p[ 4] & 0xFE) >> 1 ;
- }
+ }
}
} else { /* mpeg 2 */
-
+
if (p[7] & 0x80) { /* pts avail */
-
+
pts = (int64_t)(p[ 9] & 0x0E) << 29 ;
pts |= p[10] << 22 ;
pts |= (p[11] & 0xFE) << 14 ;
pts |= p[12] << 7 ;
pts |= (p[13] & 0xFE) >> 1 ;
-
+
} else
pts = 0;
}
@@ -1132,16 +1132,16 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
if ( (pos>last_pos) && (pts>last_pts) ) {
int cur_rate;
-
+
cur_rate = ((pos - last_pos)*90000) / ((pts - last_pts) * 50);
-
+
rate = (count * rate + cur_rate) / (count+1);
count ++;
-
+
/*
- printf ("demux_mpeg_block: stream_id %02x, pos: %"PRId64", pts: %d, cur_rate = %d, overall rate : %d\n",
- stream_id, pos, pts, cur_rate, rate);
+ printf ("demux_mpeg_block: stream_id %02x, pos: %"PRId64", pts: %d, cur_rate = %d, overall rate : %d\n",
+ stream_id, pos, pts, cur_rate, rate);
*/
}
@@ -1165,14 +1165,14 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
lprintf("est_rate=%d\n",rate);
return rate;
-
+
}
#endif /*ESTIMATE_RATE_FIXED*/
static void demux_mpeg_block_dispose (demux_plugin_t *this_gen) {
demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen;
-
+
free (this);
}
@@ -1182,7 +1182,7 @@ static int demux_mpeg_block_get_status (demux_plugin_t *this_gen) {
return this->status;
}
-static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this,
+static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this,
input_plugin_t *input)
{
uint8_t scratch[4];
@@ -1196,10 +1196,10 @@ static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this,
input->seek(input, 2324, SEEK_SET);
if (input->read(input, scratch, 4) != 4)
return 0;
- if (scratch[0] || scratch[1]
- || (scratch[2] != 0x01) || (scratch[3] != 0xba))
+ if (scratch[0] || scratch[1]
+ || (scratch[2] != 0x01) || (scratch[3] != 0xba))
return 0;
-
+
return 2324;
} else
return 2048;
@@ -1219,34 +1219,34 @@ static void demux_mpeg_block_send_headers (demux_plugin_t *this_gen) {
if (!this->blocksize)
return;
}
-
- /*
+
+ /*
* send start buffer
*/
-
+
_x_demux_control_start(this->stream);
-
+
#ifdef USE_ILL_ADVISED_ESTIMATE_RATE_INITIALLY
- if (!this->rate)
+ if (!this->rate)
this->rate = demux_mpeg_block_estimate_rate (this);
-#else
+#else
/* Set to Use rate given in by stream initially. */
- this->rate = 0;
+ this->rate = 0;
#endif
-
+
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
-
+
int num_buffers = NUM_PREVIEW_BUFFERS;
-
+
this->input->seek (this->input, 0, SEEK_SET);
-
+
this->status = DEMUX_OK ;
while ( (num_buffers>0) && (this->status == DEMUX_OK) ) {
-
+
demux_mpeg_block_parse_pack(this, 1);
num_buffers --;
}
- }
+ }
/* else FIXME: implement preview generation from PREVIEW data */
this->status = DEMUX_OK;
@@ -1265,19 +1265,19 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen,
this->input->get_length (this->input) );
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
-
+
if (start_pos) {
start_pos /= (off_t) this->blocksize;
start_pos *= (off_t) this->blocksize;
-
+
this->input->seek (this->input, start_pos, SEEK_SET);
} else if (start_time) {
-
+
if( this->input->seek_time ) {
this->input->seek_time (this->input, start_time, SEEK_SET);
} else {
start_time /= 1000;
-
+
if (this->last_cell_time) {
start_pos = start_time - (this->last_cell_time + this->last_begin_time)/1000;
start_pos *= this->rate;
@@ -1290,20 +1290,20 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen,
}
start_pos /= (off_t) this->blocksize;
start_pos *= (off_t) this->blocksize;
-
+
this->input->seek (this->input, start_pos, SEEK_SET);
}
} else
this->input->seek (this->input, 0, SEEK_SET);
}
-
+
/*
* now start demuxing
*/
this->last_cell_time = 0;
this->send_newpts = 1;
if( !playing ) {
-
+
this->buf_flag_seek = 0;
this->nav_last_end_pts = this->nav_last_start_pts = 0;
this->status = DEMUX_OK ;
@@ -1314,7 +1314,7 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen,
this->nav_last_end_pts = this->nav_last_start_pts = 0;
_x_demux_flush_engine(this->stream);
}
-
+
return this->status;
}
@@ -1332,7 +1332,7 @@ static void demux_mpeg_block_accept_input (demux_mpeg_block_t *this,
lprintf ("mrl %s is new\n", this->cur_mrl);
- }
+ }
else {
lprintf ("mrl %s is known, bitrate: %d\n",
this->cur_mrl, this->rate * 50 * 8);
@@ -1346,7 +1346,7 @@ static int demux_mpeg_block_get_stream_length (demux_plugin_t *this_gen) {
* find input plugin
*/
- if (this->rate)
+ if (this->rate)
return (int)((int64_t) 1000 * this->input->get_length (this->input) /
(this->rate * 50));
else
@@ -1371,7 +1371,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this = calloc(1, sizeof(demux_mpeg_block_t));
this->stream = stream;
this->input = input;
-
+
this->demux_plugin.send_headers = demux_mpeg_block_send_headers;
this->demux_plugin.send_chunk = demux_mpeg_block_send_chunk;
this->demux_plugin.seek = demux_mpeg_block_seek;
@@ -1386,9 +1386,9 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
lprintf ("open_plugin:detection_method=%d\n",
stream->content_detection_method);
-
+
switch (stream->content_detection_method) {
-
+
case METHOD_BY_CONTENT: {
/* use demux_mpeg for non-block devices */
@@ -1551,7 +1551,7 @@ static const demuxer_info_t demux_info_mpeg_block = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "mpeg_block", XINE_VERSION_CODE, &demux_info_mpeg_block, init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};