summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2011-09-26 00:26:43 +0100
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2011-09-26 00:26:43 +0100
commita15f6b82252b5afb81486e6f0e9e10e5e2e5ece5 (patch)
tree099b1d6cc559c3858ad95c9f1dbd56175c5e689f
parentb097a80fb2d9100e02f2fdaf62fe3d408f73763f (diff)
parent752c9d69932238731394c2b86c458b3213d85b97 (diff)
downloadxine-lib-a15f6b82252b5afb81486e6f0e9e10e5e2e5ece5.tar.gz
xine-lib-a15f6b82252b5afb81486e6f0e9e10e5e2e5ece5.tar.bz2
Merge from 1.1. (Needs some testing.)
--HG-- rename : src/xine-engine/buffer.h => include/xine/buffer.h
-rw-r--r--debian/control2
-rw-r--r--include/xine/buffer.h1
-rw-r--r--m4/attributes.m410
-rw-r--r--src/combined/ffmpeg/ff_audio_decoder.c40
-rw-r--r--src/combined/ffmpeg/ff_video_decoder.c124
-rw-r--r--src/combined/ffmpeg/xine_audio.list1
-rw-r--r--src/demuxers/demux_ts.c303
-rw-r--r--src/input/net_buf_ctrl.c370
-rw-r--r--src/xine-engine/buffer_types.c8
-rw-r--r--src/xine-engine/events.c4
-rw-r--r--src/xine-engine/xine.c16
11 files changed, 546 insertions, 333 deletions
diff --git a/debian/control b/debian/control
index f21a303e4..34f3676c5 100644
--- a/debian/control
+++ b/debian/control
@@ -17,7 +17,7 @@ Build-Depends: debhelper (>= 5.0.1), binutils (>= 2.12.90.0.9), pkg-config,
libasound2-dev [!kfreebsd-i386 !kfreebsd-amd64 !hurd-i386],
libcam-dev [kfreebsd-i386 kfreebsd-amd64],
libaa1-dev, libcaca-dev, libmodplug-dev,
- libjack-jackd2-dev | libjack0.100.0-dev, libpulse-dev, libartsc0-dev,
+ libjack-jackd2-dev | libjack0.100.0-dev, libpulse-dev,
graphicsmagick-libmagick-dev-compat | libmagick9-dev | libmagick-dev | libmagickwand-dev,
libpng12-dev, libfreetype6-dev,
libogg-dev, libvorbis-dev, libtheora-dev,
diff --git a/include/xine/buffer.h b/include/xine/buffer.h
index 95cdcb69a..bf5d2a98a 100644
--- a/include/xine/buffer.h
+++ b/include/xine/buffer.h
@@ -268,6 +268,7 @@ extern "C" {
#define BUF_AUDIO_AMR_NB 0x033F0000
#define BUF_AUDIO_AMR_WB 0x03400000
#define BUF_AUDIO_EAC3 0x03410000
+#define BUF_AUDIO_AAC_LATM 0x03420000
/*@}*/
/**
diff --git a/m4/attributes.m4 b/m4/attributes.m4
index 4f0442865..3d9c256a0 100644
--- a/m4/attributes.m4
+++ b/m4/attributes.m4
@@ -39,7 +39,7 @@ AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [
AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]),
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
- AC_COMPILE_IFELSE([int a;],
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])],
[eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_cflags_$1])='no'"])
CFLAGS="$ac_save_CFLAGS"
@@ -89,7 +89,7 @@ AC_DEFUN([CC_CHECK_LDFLAGS], [
AS_TR_SH([cc_cv_ldflags_$1]),
[ac_save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $1"
- AC_LINK_IFELSE([int main() { return 1; }],
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])],
[eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_ldflags_$1])="])
LDFLAGS="$ac_save_LDFLAGS"
@@ -154,7 +154,7 @@ AC_DEFUN([CC_CHECK_ATTRIBUTE], [
AS_TR_SH([cc_cv_attribute_$1]),
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $cc_cv_werror"
- AC_COMPILE_IFELSE([$3],
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
[eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
CFLAGS="$ac_save_CFLAGS"
@@ -302,11 +302,11 @@ AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $cc_cv_werror"
for cc_attribute_align_try in 64 32 16 8 4 2; do
- AC_COMPILE_IFELSE([
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int main() {
static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
return c;
- }], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
+ }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
done
CFLAGS="$ac_save_CFLAGS"
])
diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c
index db2dc8fa2..f2d1ca93f 100644
--- a/src/combined/ffmpeg/ff_audio_decoder.c
+++ b/src/combined/ffmpeg/ff_audio_decoder.c
@@ -114,7 +114,7 @@ static void *realloc16 (void *m, size_t s) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
_("ffmpeg_audio_dec: increasing buffer to %d to avoid overflow.\n"),
this->bufsize);
- this->buf = realloc16 (this->buf, this->bufsize);
+ this->buf = realloc16 (this->buf, this->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
}
}
@@ -127,14 +127,13 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
int out;
audio_buffer_t *audio_buffer;
int bytes_to_send;
- unsigned int codec_type = buf->type & 0xFFFF0000;
+ unsigned int codec_type = buf->type & (BUF_MAJOR_MASK | BUF_DECODER_MASK);
- if ( (buf->decoder_flags & BUF_FLAG_HEADER) &&
- !(buf->decoder_flags & BUF_FLAG_SPECIAL) ) {
+ if ( (buf->decoder_flags & (BUF_FLAG_HEADER | BUF_FLAG_SPECIAL)) == BUF_FLAG_HEADER ) {
/* accumulate init data */
ff_audio_ensure_buffer_size(this, this->size + buf->size);
- memcpy(this->buf + this->size, buf->content, buf->size);
+ xine_fast_memcpy(this->buf + this->size, buf->content, buf->size);
this->size += buf->size;
if (buf->decoder_flags & BUF_FLAG_FRAME_END) {
@@ -321,27 +320,36 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
if (!this->output_open) {
if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) {
+ int ret;
+
decode_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
#if AVAUDIO > 2
av_init_packet (&avpkt);
avpkt.data = (uint8_t *)&this->buf[0];
avpkt.size = this->size;
avpkt.flags = AV_PKT_FLAG_KEY;
- avcodec_decode_audio3 (this->context,
- (int16_t *)this->decode_buffer,
- &decode_buffer_size, &avpkt);
+ ret = avcodec_decode_audio3 (this->context,
+ (int16_t *)this->decode_buffer,
+ &decode_buffer_size, &avpkt);
#else
- avcodec_decode_audio2 (this->context,
- (int16_t *)this->decode_buffer,
- &decode_buffer_size,
- &this->buf[0],
- this->size);
+ ret = avcodec_decode_audio2 (this->context,
+ (int16_t *)this->decode_buffer,
+ &decode_buffer_size,
+ &this->buf[0],
+ this->size);
#endif
this->audio_bits = this->context->bits_per_sample;
this->audio_sample_rate = this->context->sample_rate;
this->audio_channels = this->context->channels;
- if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels)
+ if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ _("ffmpeg_audio_dec: cannot read codec parameters from packet (error=%d)\n"), ret);
+
+ /* We can't use this packet, so we must discard it
+ * and wait for another one. */
+ this->size = 0;
return;
+ }
}
this->output_open = (this->stream->audio_out->open) (this->stream->audio_out,
this->stream, this->audio_bits, this->audio_sample_rate,
@@ -355,6 +363,10 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* time to decode a frame */
offset = 0;
+
+ /* pad input data */
+ memset(&this->buf[this->size], 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
while (this->size>0) {
decode_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
#if AVAUDIO > 2
diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c
index 5e4967f6c..03a4b8cac 100644
--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -65,6 +65,10 @@
# define pp_mode pp_mode_t
#endif
+#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 112)
+# define DEPRECATED_AVCODEC_THREAD_INIT 1
+#endif
+
typedef struct ff_video_decoder_s ff_video_decoder_t;
typedef struct ff_video_class_s {
@@ -354,7 +358,10 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
if (this->class->thread_count > 1) {
if (this->codec->id != CODEC_ID_SVQ3
- && avcodec_thread_init(this->context, this->class->thread_count) != -1)
+#ifndef DEPRECATED_AVCODEC_THREAD_INIT
+ && avcodec_thread_init(this->context, this->class->thread_count) != -1
+#endif
+ )
this->context->thread_count = this->class->thread_count;
}
@@ -844,6 +851,59 @@ static void ff_check_bufsize (ff_video_decoder_t *this, int size) {
}
}
+static int ff_vc1_find_header(ff_video_decoder_t *this, buf_element_t *buf)
+{
+ uint8_t *p = buf->content;
+
+ if (!p[0] && !p[1] && p[2] == 1 && p[3] == 0x0f) {
+ int i;
+
+ this->context->extradata = calloc(1, buf->size);
+ this->context->extradata_size = 0;
+
+ for (i = 0; i < buf->size && i < 128; i++) {
+ if (!p[i] && !p[i+1] && p[i+2]) {
+ lprintf("00 00 01 %02x at %d\n", p[i+3], i);
+ if (p[i+3] != 0x0e && p[i+3] != 0x0f)
+ break;
+ }
+ this->context->extradata[i] = p[i];
+ this->context->extradata_size++;
+ }
+
+ lprintf("ff_video_decoder: found VC1 sequence header\n");
+ return 1;
+ }
+
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "ffmpeg_video_dec: VC1 extradata missing !\n");
+ return 0;
+}
+
+static int ff_check_extradata(ff_video_decoder_t *this, unsigned int codec_type, buf_element_t *buf)
+{
+ if (this->context && this->context->extradata)
+ return 1;
+
+ switch (codec_type) {
+ case BUF_VIDEO_VC1:
+ return ff_vc1_find_header(this, buf);
+ default:;
+ }
+
+ return 1;
+}
+
+static void ff_init_mpeg12_mode(ff_video_decoder_t *this)
+{
+ this->is_mpeg12 = 1;
+ if ( this->mpeg_parser == NULL ) {
+ this->mpeg_parser = calloc(1, sizeof(mpeg_parser_t));
+ mpeg_parser_init(this->mpeg_parser);
+ this->decoder_init_mode = 0;
+ }
+}
+
static void ff_handle_preview_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
int codec_type;
@@ -851,14 +911,14 @@ static void ff_handle_preview_buffer (ff_video_decoder_t *this, buf_element_t *b
codec_type = buf->type & 0xFFFF0000;
if (codec_type == BUF_VIDEO_MPEG) {
- this->is_mpeg12 = 1;
- if ( this->mpeg_parser == NULL ) {
- this->mpeg_parser = calloc(1, sizeof(mpeg_parser_t));
- mpeg_parser_init(this->mpeg_parser);
- }
+ ff_init_mpeg12_mode(this);
}
if (this->decoder_init_mode && !this->is_mpeg12) {
+
+ if (!ff_check_extradata(this, codec_type, buf))
+ return;
+
init_video_codec(this, codec_type);
init_postprocess(this);
this->decoder_init_mode = 0;
@@ -1024,6 +1084,11 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
lprintf("handle_mpeg12_buffer\n");
+ if (!this->is_mpeg12) {
+ /* initialize mpeg parser */
+ ff_init_mpeg12_mode(this);
+ }
+
while ((size > 0) || (flush == 1)) {
uint8_t *current;
@@ -1198,49 +1263,6 @@ static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts)
}
}
-static int ff_vc1_find_header(ff_video_decoder_t *this, buf_element_t *buf)
-{
- uint8_t *p = buf->content;
-
- if (!p[0] && !p[1] && p[2] == 1 && p[3] == 0x0f) {
- int i;
-
- this->context->extradata = calloc(1, buf->size);
- this->context->extradata_size = 0;
-
- for (i = 0; i < buf->size && i < 128; i++) {
- if (!p[i] && !p[i+1] && p[i+2]) {
- lprintf("00 00 01 %02x at %d\n", p[i+3], i);
- if (p[i+3] != 0x0e && p[i+3] != 0x0f)
- break;
- }
- this->context->extradata[i] = p[i];
- this->context->extradata_size++;
- }
-
- lprintf("ff_video_decoder: found VC1 sequence header\n");
- return 1;
- }
-
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "ffmpeg_video_dec: VC1 extradata missing !\n");
- return 0;
-}
-
-static int ff_check_extradata(ff_video_decoder_t *this, unsigned int codec_type, buf_element_t *buf)
-{
- if (this->context && this->context->extradata)
- return 1;
-
- switch (codec_type) {
- case BUF_VIDEO_VC1:
- return ff_vc1_find_header(this, buf);
- default:;
- }
-
- return 1;
-}
-
static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
uint8_t *chunk_buf = this->buf;
AVRational avr00 = {0, 1};
@@ -1249,7 +1271,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
if (!this->decoder_ok) {
if (this->decoder_init_mode) {
- int codec_type = buf->type & 0xFFFF0000;
+ int codec_type = buf->type & (BUF_MAJOR_MASK | BUF_DECODER_MASK);
if (!ff_check_extradata(this, codec_type, buf))
return;
@@ -1569,7 +1591,7 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
if (buf->pts)
this->pts = buf->pts;
- if (this->is_mpeg12) {
+ if ((buf->type & 0xFFFF0000) == BUF_VIDEO_MPEG) {
ff_handle_mpeg12_buffer(this, buf);
} else {
ff_handle_buffer(this, buf);
diff --git a/src/combined/ffmpeg/xine_audio.list b/src/combined/ffmpeg/xine_audio.list
index 796917dfe..8a40c29cb 100644
--- a/src/combined/ffmpeg/xine_audio.list
+++ b/src/combined/ffmpeg/xine_audio.list
@@ -41,6 +41,7 @@ WAVPACK WAVPACK WavPack
AMR_NB AMR_NB AMR narrow band
AMR_WB AMR_WB AMR wide band
EAC3 EAC3 E-AC-3
+AAC_LATM AAC_LATM AAC LATM
# disabled codecs (ref. configure.ac)
! AAC
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
index 49880f9a2..74840885d 100644
--- a/src/demuxers/demux_ts.c
+++ b/src/demuxers/demux_ts.c
@@ -277,11 +277,10 @@ typedef struct {
int64_t pts;
buf_element_t *buf;
unsigned int counter;
+ unsigned int numPreview;
uint16_t descriptor_tag; /* +0x100 for PES stream IDs (no available TS descriptor tag?) */
- int64_t packet_count;
int corrupted_pes;
uint32_t buffered_bytes;
- int autodetected;
} demux_ts_media;
@@ -352,17 +351,12 @@ typedef struct {
* and audio PIDs, we keep the index of the corresponding entry
* inthe media[] array.
*/
- unsigned int programNumber;
- unsigned int pcrPid;
- unsigned int pid;
- unsigned int pid_count;
unsigned int videoPid;
unsigned int videoMedia;
demux_ts_audio_track audio_tracks[MAX_AUDIO_TRACKS];
int audio_tracks_count;
- int send_end_buffers;
int64_t last_pts[2];
int send_newpts;
int buf_flag_seek;
@@ -390,8 +384,6 @@ typedef struct {
uint8_t buf[BUF_SIZE]; /* == PKT_SIZE * NPKT_PER_READ */
- int numPreview;
-
} demux_ts_t;
/* redefine abs as macro to handle 64-bit diffs.
@@ -634,7 +626,7 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
*/
program_count = 0;
for (program = pkt + 13;
- program < pkt + 13 + section_length - 9;
+ (program < pkt + 13 + section_length - 9) && (program_count < MAX_PMTS);
program += 4) {
program_number = ((unsigned int)program[0] << 8) | program[1];
pmt_pid = (((unsigned int)program[2] & 0x1f) << 8) | program[3];
@@ -646,18 +638,14 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
continue;
/*
- * If we have yet to learn our program number, then learn it,
- * use this loop to eventually add support for dynamically changing
- * PATs.
+ * Add the program number to the table if we haven't already
+ * seen it. The order of the program numbers is assumed not
+ * to change between otherwise identical PATs.
*/
- program_count = 0;
-
- while ((this->program_number[program_count] != INVALID_PROGRAM) &&
- (this->program_number[program_count] != program_number) &&
- (program_count+1 < MAX_PMTS ) ) {
- program_count++;
+ if (this->program_number[program_count] != program_number) {
+ this->program_number[program_count] = program_number;
+ this->pmt_pid[program_count] = INVALID_PID;
}
- this->program_number[program_count] = program_number;
/* force PMT reparsing when pmt_pid changes */
if (this->pmt_pid[program_count] != pmt_pid) {
@@ -681,21 +669,32 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
this->program_number[program_count],
this->pmt_pid[program_count]);
#endif
+
+ ++program_count;
+ }
+
+ /* Add "end of table" markers. */
+ if (program_count < MAX_PMTS) {
+ this->program_number[program_count] = INVALID_PROGRAM;
+ this->pmt_pid[program_count] = INVALID_PID;
}
}
static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
- uint8_t *buf, int packet_len,
- xine_stream_t *stream) {
+ uint8_t *buf, int packet_len) {
unsigned char *p;
uint32_t header_len;
int64_t pts;
uint32_t stream_id;
- int pkt_len;
+
+ if (packet_len < 9) {
+ xprintf (xine, XINE_VERBOSITY_DEBUG,
+ "demux_ts: too short PES packet header (%d bytes)\n", packet_len);
+ return 0;
+ }
p = buf;
- pkt_len = packet_len;
/* we should have a PES packet here */
@@ -705,14 +704,14 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
return 0 ;
}
- packet_len -= 6;
/* packet_len = p[4] << 8 | p[5]; */
stream_id = p[3];
+ header_len = p[8];
- if (packet_len==0)
- {
+ /* sometimes corruption on header_len causes segfault in memcpy below */
+ if (header_len + 9 > packet_len) {
xprintf (xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: error pes length 0\n");
+ "demux_ts: illegal value for PES_header_data_length (0x%x)\n", header_len);
return 0;
}
@@ -723,6 +722,10 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
if (p[7] & 0x80) { /* pts avail */
+ if (header_len < 5) {
+ return 0;
+ }
+
pts = (int64_t)(p[ 9] & 0x0E) << 29 ;
pts |= p[10] << 22 ;
pts |= (p[11] & 0xFE) << 14 ;
@@ -747,17 +750,8 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
m->pts = pts;
- header_len = p[8];
-
- /* sometimes corruption on header_len causes segfault in memcpy below */
- if (header_len + 9 > pkt_len) {
- xprintf (xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: illegal value for PES_header_data_length (0x%x)\n", header_len);
- return 0;
- }
-
p += header_len + 9;
- packet_len -= header_len + 3;
+ packet_len -= header_len + 9;
if (m->descriptor_tag == STREAM_VIDEO_VC1) {
m->content = p;
@@ -797,7 +791,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
return 1;
} else if((m->descriptor_tag == STREAM_AUDIO_AC3) || /* ac3 - raw */
- (p[0] == 0x0B && p[1] == 0x77)) { /* ac3 - syncword */
+ (packet_len > 1 && p[0] == 0x0B && p[1] == 0x77)) { /* ac3 - syncword */
m->content = p;
m->size = packet_len;
m->type |= BUF_AUDIO_A52;
@@ -817,8 +811,15 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
m->type |= BUF_AUDIO_DTS;
return 1;
+ } else if (packet_len < 2) {
+ return 0;
+
} else if (m->descriptor_tag == HDMV_AUDIO_80_PCM) {
+ if (packet_len < 4) {
+ return 0;
+ }
+
m->content = p + 4;
m->size = packet_len - 4;
m->type |= BUF_AUDIO_LPCM_BE;
@@ -848,6 +849,10 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
return 1;
} else if ((p[0] & 0xF0) == 0x80) {
+ if (packet_len < 4) {
+ return 0;
+ }
+
m->content = p+4;
m->size = packet_len - 4;
m->type |= BUF_AUDIO_A52;
@@ -864,13 +869,17 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
}
}
+ if (packet_len < pcm_offset) {
+ return 0;
+ }
+
m->content = p+pcm_offset;
m->size = packet_len-pcm_offset;
m->type |= BUF_AUDIO_LPCM_BE;
return 1;
}
- } else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) {
+ } else if ((stream_id & 0xf0) == 0xe0) {
m->content = p;
m->size = packet_len;
@@ -907,10 +916,13 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
m->type |= BUF_AUDIO_MPEG;
break;
case ISO_13818_PART7_AUDIO:
- case ISO_14496_PART3_AUDIO:
lprintf ("demux_ts: found AAC audio track.\n");
m->type |= BUF_AUDIO_AAC;
break;
+ case ISO_14496_PART3_AUDIO:
+ lprintf ("demux_ts: found AAC LATM audio track.\n");
+ m->type |= BUF_AUDIO_AAC_LATM;
+ break;
default:
lprintf ("demux_ts: unknown audio type: %d, defaulting to MPEG.\n", m->descriptor_tag);
m->type |= BUF_AUDIO_MPEG;
@@ -929,6 +941,14 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
/*
+ * Track how many of these types of packets we have seen in this stream.
+ */
+static inline unsigned get_preview_frame_number(unsigned *numPreview, unsigned limit) {
+ unsigned preview = *numPreview;
+ return (preview < limit) ? ++(*numPreview) : preview;
+}
+
+/*
* buffer arriving pes data
*/
static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
@@ -958,26 +978,45 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
m->counter++;
if (pus) { /* new PES packet */
-
if (m->buffered_bytes) {
+ unsigned previewLimit = 0;
+
m->buf->content = m->buf->mem;
m->buf->size = m->buffered_bytes;
m->buf->type = m->type;
- if( (m->buf->type & 0xffff0000) == BUF_SPU_DVD ) {
- m->buf->decoder_flags |= BUF_FLAG_SPECIAL;
- m->buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE;
- m->buf->decoder_info[2] = SPU_DVD_SUBTYPE_PACKAGE;
+
+ switch (m->type & BUF_MAJOR_MASK) {
+ case BUF_SPU_BASE:
+ if( (m->buf->type & (BUF_MAJOR_MASK | BUF_DECODER_MASK)) == BUF_SPU_DVB ) {
+ /* TODO: DVBSUB handling needed? */
+ }
+ break;
+
+ case BUF_VIDEO_BASE:
+ previewLimit = 5;
+ break;
+
+ case BUF_AUDIO_BASE:
+ previewLimit = 2;
+ break;
+
+ default:
+ break;
}
- else {
- if (this->numPreview<5)
- ++this->numPreview;
- if ( this->numPreview==1 )
- m->buf->decoder_flags=BUF_FLAG_HEADER | BUF_FLAG_FRAME_END;
- else if ( this->numPreview<5 )
- m->buf->decoder_flags=BUF_FLAG_PREVIEW;
- else
- m->buf->decoder_flags |= BUF_FLAG_FRAME_END;
+
+ if (previewLimit != 0) {
+ unsigned numPreview;
+
+ numPreview = get_preview_frame_number(&m->numPreview, previewLimit);
+
+ if (numPreview == 1)
+ m->buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_FRAME_END;
+ else if (numPreview < previewLimit)
+ m->buf->decoder_flags = BUF_FLAG_PREVIEW;
+ else
+ m->buf->decoder_flags |= BUF_FLAG_FRAME_END;
}
+
m->buf->pts = m->pts;
m->buf->decoder_info[0] = 1;
@@ -997,20 +1036,13 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
/* allocate the buffer here, as pes_header needs a valid buf for dvbsubs */
m->buf = m->fifo->buffer_pool_alloc(m->fifo);
- if (!demux_ts_parse_pes_header(this->stream->xine, m, ts, len, this->stream)) {
+ if (!demux_ts_parse_pes_header(this->stream->xine, m, ts, len)) {
m->buf->free_buffer(m->buf);
m->buf = NULL;
- if (m->corrupted_pes > CORRUPT_PES_THRESHOLD && m->autodetected) {
- if (this->videoPid == m->pid) {
- this->videoPid = INVALID_PID;
- this->last_pmt_crc = 0;
- }
- } else {
- m->corrupted_pes++;
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: PID 0x%.4x: corrupted pes encountered\n", m->pid);
- }
+ m->corrupted_pes++;
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_ts: PID 0x%.4x: corrupted pes encountered\n", m->pid);
} else {
m->corrupted_pes = 0;
@@ -1065,6 +1097,7 @@ static void demux_ts_pes_new(demux_ts_t*this,
if (m->buf != NULL) m->buf->free_buffer(m->buf);
m->buf = NULL;
m->counter = INVALID_CC;
+ m->numPreview = 0;
m->descriptor_tag = descriptor;
m->corrupted_pes = 1;
m->buffered_bytes = 0;
@@ -1135,6 +1168,15 @@ static inline int ts_payloadsize(unsigned char * tsp)
return 184;
}
+/* check if an apid is in the list of known apids */
+static int apid_check(demux_ts_t*this, unsigned int pid) {
+ int i;
+ for (i = 0; i < this->audio_tracks_count; i++) {
+ if (this->audio_tracks[i].pid == pid)
+ return i;
+ }
+ return -1;
+}
/*
* NAME demux_ts_parse_pmt
@@ -1181,7 +1223,7 @@ static void demux_ts_parse_pmt (demux_ts_t *this,
pkt+=pkt[4]; /* pointer to start of section */
offset=1;
- if (this->pmt[program_count] != NULL) free(this->pmt[program_count]);
+ free(this->pmt[program_count]);
this->pmt[program_count] = (uint8_t *) calloc(4096, sizeof(unsigned char));
this->pmt_write_ptr[program_count] = this->pmt[program_count];
@@ -1384,14 +1426,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
case ISO_13818_PART7_AUDIO:
case ISO_14496_PART3_AUDIO:
if (this->audio_tracks_count < MAX_AUDIO_TRACKS) {
- int i, found = 0;
- for(i = 0; i < this->audio_tracks_count; i++) {
- if(this->audio_tracks[i].pid == pid) {
- found = 1;
- break;
- }
- }
- if(!found) {
+ if (apid_check(this, pid) < 0) {
#ifdef TS_PMT_LOG
printf ("demux_ts: PMT audio pid 0x%.4x type %2.2x\n", pid, stream[0]);
#endif
@@ -1422,14 +1457,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
case ISO_13818_PES_PRIVATE:
for (i = 5; i < coded_length; i += stream[i+1] + 2) {
if (((stream[i] == 0x6a) || (stream[i] == 0x7a)) && (this->audio_tracks_count < MAX_AUDIO_TRACKS)) {
- int j, found = 0;
- for(j = 0; j < this->audio_tracks_count; j++) {
- if(this->audio_tracks[i].pid == pid) {
- found = 1;
- break;
- }
- }
- if (!found) {
+ if (apid_check(this, pid) < 0) {
#ifdef TS_PMT_LOG
printf ("demux_ts: PMT AC3 audio pid 0x%.4x type %2.2x\n", pid, stream[0]);
#endif
@@ -1548,14 +1576,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
* FIXME: This will need expanding if we ever see a DTS or other media format here.
*/
if ((this->audio_tracks_count < MAX_AUDIO_TRACKS) && (stream[0] >= 0x80) ) {
- int i, found = 0;
- for(i = 0; i < this->audio_tracks_count; i++) {
- if(this->audio_tracks[i].pid == pid) {
- found = 1;
- break;
- }
- }
- if(!found) {
+ if (apid_check(this,pid) < 0) {
uint32_t format_identifier=0;
demux_ts_get_reg_desc(this, &format_identifier,
stream + 5, stream_info_length);
@@ -1591,6 +1612,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
section_length -= coded_length;
}
+#if 0
/*
* Get the current PCR PID.
*/
@@ -1606,6 +1628,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
#endif
this->pcrPid = pid;
}
+#endif
if ( this->stream->spu_channel>=0 && this->spu_langs_count>0 )
demux_ts_update_spu_channel( this );
@@ -1801,6 +1824,9 @@ static int64_t demux_ts_adaptation_field_parse(uint8_t *data,
}
#endif
if(PCR_flag) {
+ if (adaptation_field_length < offset + 6)
+ return 0;
+
PCR = (((int64_t) data[offset]) & 0xFF) << 25;
PCR += (int64_t) ((data[offset+1] & 0xFF) << 17);
PCR += (int64_t) ((data[offset+2] & 0xFF) << 9);
@@ -1815,6 +1841,9 @@ static int64_t demux_ts_adaptation_field_parse(uint8_t *data,
offset+=6;
}
if(OPCR_flag) {
+ if (adaptation_field_length < offset + 6)
+ return PCR;
+
OPCR = data[offset] << 25;
OPCR |= data[offset+1] << 17;
OPCR |= data[offset+2] << 9;
@@ -1844,16 +1873,6 @@ static int64_t demux_ts_adaptation_field_parse(uint8_t *data,
return PCR;
}
-/* check if an apid is in the list of known apids */
-static int apid_check(demux_ts_t*this, unsigned int pid) {
- int i;
- for(i=0; i<this->audio_tracks_count; i++) {
- if(this->audio_tracks[i].pid == pid)
- return i;
- }
- return -1;
-}
-
/* transport stream packet layer */
static void demux_ts_parse_packet (demux_ts_t*this) {
@@ -1922,8 +1941,10 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
for (i=0; i < this->scrambled_npids; i++) {
if (this->scrambled_pids[i] == pid) return;
}
- this->scrambled_pids[this->scrambled_npids] = pid;
- this->scrambled_npids++;
+ if (this->scrambled_npids < MAX_PIDS) {
+ this->scrambled_pids[this->scrambled_npids] = pid;
+ this->scrambled_npids++;
+ }
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: PID 0x%.4x is scrambled!\n", pid);
return;
@@ -1970,69 +1991,10 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
program_count++;
}
- if (payload_unit_start_indicator && this->media_num < MAX_PIDS){
- int pes_stream_id;
- if (pid == 0) {
- demux_ts_parse_pat (this, originalPkt, originalPkt+data_offset-4,
- payload_unit_start_indicator);
- return;
- }
- program_count = 0;
- pes_stream_id = originalPkt[data_offset+3];
-
-#ifdef TS_HEADER_LOG
- printf("demux_ts:ts_pes_header:stream_id=0x%.2x\n",pes_stream_id);
-#endif
-
- if ( (pes_stream_id >= VIDEO_STREAM_S) && (pes_stream_id <= VIDEO_STREAM_E) ) {
- if ( this->videoPid == INVALID_PID) {
- int i, found = 0;
- for(i = 0; i < this->media_num; i++) {
- if (this->media[i].pid == pid) {
- found = 1;
- break;
- }
- }
-
- if (found && (this->media[i].corrupted_pes == 0)) {
- this->videoPid = pid;
- this->videoMedia = i;
- } else if (!found) {
- this->videoPid = pid;
- this->videoMedia = this->media_num;
- this->media[this->videoMedia].autodetected = 1;
- demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, 0x100 + pes_stream_id);
- }
-
- if (this->videoPid != INVALID_PID) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: auto-detected video pid 0x%.4x\n", pid);
- }
- }
- } else if ( (pes_stream_id >= AUDIO_STREAM_S) && (pes_stream_id <= AUDIO_STREAM_E) ) {
- if (this->audio_tracks_count < MAX_AUDIO_TRACKS) {
- int i, found = 0;
- for(i = 0; i < this->audio_tracks_count; i++) {
- if(this->audio_tracks[i].pid == pid) {
- found = 1;
- break;
- }
- }
- if(!found) {
-#ifdef TS_PMT_LOG
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: auto-detected audio pid 0x%.4x\n", pid);
-#endif
- /* store PID, index and stream no. */
- this->audio_tracks[this->audio_tracks_count].pid = pid;
- this->audio_tracks[this->audio_tracks_count].media_index = this->media_num;
- this->media[this->media_num].type = this->audio_tracks_count;
- demux_ts_pes_new(this, this->media_num++, pid,
- this->audio_fifo, 0x100 + pes_stream_id);
- this->audio_tracks_count++;
- }
- }
- }
+ if (payload_unit_start_indicator && (this->media_num < MAX_PIDS) && (pid == 0)) {
+ demux_ts_parse_pat(this, originalPkt, originalPkt+data_offset-4,
+ payload_unit_start_indicator);
+ return;
}
if (data_len > PKT_SIZE) {
@@ -2194,7 +2156,6 @@ static void demux_ts_send_headers (demux_plugin_t *this_gen) {
this->status = DEMUX_OK ;
- this->send_end_buffers = 1;
this->scrambled_npids = 0;
/* DVBSUB */
@@ -2382,7 +2343,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->stream = stream;
this->input = input;
this->class = class_gen;
- this->blockSize = PKT_SIZE;
this->demux_plugin.send_headers = demux_ts_send_headers;
this->demux_plugin.send_chunk = demux_ts_send_chunk;
@@ -2400,7 +2360,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
for (i = 0; i < MAX_PIDS; i++) {
this->media[i].pid = INVALID_PID;
this->media[i].buf = NULL;
- this->media[i].autodetected = 0;
}
for (i = 0; i < MAX_PMTS; i++) {
@@ -2410,8 +2369,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->pmt_write_ptr[i] = NULL;
}
- this->programNumber = INVALID_PROGRAM;
- this->pcrPid = INVALID_PID;
this->scrambled_npids = 0;
this->videoPid = INVALID_PID;
this->audio_tracks_count = 0;
@@ -2434,8 +2391,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->pkt_offset = (hdmv > 0) ? 4 : 0;
this->pkt_size = PKT_SIZE + this->pkt_offset;
- this->numPreview=0;
-
return &this->demux_plugin;
}
@@ -2459,7 +2414,7 @@ static void *init_class (xine_t *xine, void *data) {
* mrl formats: the content is exactly the same but the input plugin
* uses a different tuning algorithm [Pragma]
*/
- this->demux_class.extensions = "ts m2t trp dvb:// dvbs:// dvbc:// dvbt://";
+ this->demux_class.extensions = "ts m2t trp m2ts mts dvb:// dvbs:// dvbc:// dvbt://";
this->demux_class.dispose = default_demux_class_dispose;
this->av_crc = av_crc_get_table(AV_CRC_32_IEEE);
diff --git a/src/input/net_buf_ctrl.c b/src/input/net_buf_ctrl.c
index d777a0cc9..81165afcf 100644
--- a/src/input/net_buf_ctrl.c
+++ b/src/input/net_buf_ctrl.c
@@ -36,6 +36,8 @@
*/
+#define LOG_DVBSPEED
+
#include "net_buf_ctrl.h"
#define DEFAULT_HIGH_WATER_MARK 5000 /* in 1/1000 s */
@@ -79,6 +81,18 @@ struct nbc_s {
int audio_in_disc;
pthread_mutex_t mutex;
+
+ /* follow live dvb delivery speed.
+ 0 = fix disabled
+ 1 = play at normal speed
+ 2 = play 0.5% slower to fill video fifo
+ 3 = play 0.5% faster to empty video fifo
+ 4..6 = same as 1..3 but watch audio fifo instead
+ 7 = pause */
+ int dvbspeed;
+ int dvbs_center, dvbs_width, dvbs_audio_fill, dvbs_video_fill;
+ int64_t dvbs_audio_in, dvbs_audio_out;
+ int64_t dvbs_video_in, dvbs_video_out;
};
static void report_progress (xine_stream_t *stream, int p) {
@@ -112,6 +126,190 @@ static void nbc_set_speed_normal (nbc_t *this) {
stream->xine->clock->set_option (stream->xine->clock, CLOCK_SCR_ADJUSTABLE, 1);
}
+static void dvbspeed_init (nbc_t *this) {
+ const char *mrl;
+ if (this->stream && this->stream->input_plugin) {
+ mrl = this->stream->input_plugin->get_mrl (this->stream->input_plugin);
+ if (mrl) {
+ /* detect Kaffeine: fifo://~/.kde4/share/apps/kaffeine/dvbpipe.m2t */
+ if ((strcasestr (mrl, "/dvbpipe.")) ||
+ ((!strncasecmp (mrl, "dvb", 3)) &&
+ ((mrl[3] == ':') || (mrl[3] && (mrl[4] == ':'))))) {
+ this->dvbs_center = 2 * 90000;
+ this->dvbs_width = 90000;
+ this->dvbs_audio_in = this->dvbs_audio_out = this->dvbs_audio_fill = 0;
+ this->dvbs_video_in = this->dvbs_video_out = this->dvbs_video_fill = 0;
+ this->dvbspeed = 7;
+#ifdef LOG_DVBSPEED
+ /* I'm using plain printf because kaffeine sets verbosity to 0 */
+ printf ("net_buf_ctrl: dvbspeed mode\n");
+#endif
+#if 1
+ /* somewhat rude but saves user a lot of frustration */
+ if (this->stream) {
+ xine_t *xine = this->stream->xine;
+ config_values_t *config = xine->config;
+ xine_cfg_entry_t entry;
+ if (xine_config_lookup_entry (xine, "audio.synchronization.slow_fast_audio",
+ &entry) && (entry.num_value == 0)) {
+ config->update_num (config, "audio.synchronization.slow_fast_audio", 1);
+#ifdef LOG_DVBSPEED
+ printf ("net_buf_ctrl: slow/fast audio playback enabled\n");
+#endif
+ }
+ if (xine_config_lookup_entry (xine, "engine.buffers.video_num_buffers",
+ &entry) && (entry.num_value < 1800)) {
+ config->update_num (config, "engine.buffers.video_num_buffers", 1800);
+#ifdef LOG_DVBSPEED
+ printf ("net_buf_ctrl: enlarged video fifo to 1800 buffers\n");
+#endif
+ }
+ }
+#endif
+ }
+ }
+ }
+}
+
+static void dvbspeed_close (nbc_t *this) {
+ if (((0xec >> this->dvbspeed) & 1) && this->stream)
+ _x_set_fine_speed (this->stream, XINE_FINE_SPEED_NORMAL);
+#ifdef LOG_DVBSPEED
+ if (this->dvbspeed) printf ("net_buf_ctrl: dvbspeed OFF\n");
+#endif
+ this->dvbspeed = 0;
+}
+
+static void dvbspeed_put (nbc_t *this, fifo_buffer_t * fifo, buf_element_t *b) {
+ int64_t diff, *last;
+ int *fill;
+ int used, mode;
+ const char *name;
+ /* select vars */
+ if (fifo == this->video_fifo) {
+ last = &this->dvbs_video_in;
+ fill = &this->dvbs_video_fill;
+ mode = 0x71;
+ name = "video";
+ } else if (fifo == this->audio_fifo) {
+ last = &this->dvbs_audio_in;
+ fill = &this->dvbs_audio_fill;
+ mode = 0x0f;
+ name = "audio";
+ } else return;
+ /* update fifo fill time */
+ if (b->pts && (b->decoder_flags & BUF_FLAG_FRAME_START)) {
+ if (*last) {
+ diff = b->pts - *last;
+ if ((diff > -220000) && (diff < 220000)) *fill += diff;
+ }
+ *last = b->pts;
+ }
+ /* take actions */
+ if ((mode >> this->dvbspeed) & 1) return;
+ used = fifo->fifo_size;
+ switch (this->dvbspeed) {
+ case 1:
+ case 4:
+ if ((*fill > this->dvbs_center + this->dvbs_width) ||
+ (100 * used > 98 * fifo->buffer_pool_capacity)) {
+ _x_set_fine_speed (this->stream, XINE_FINE_SPEED_NORMAL * 201 / 200);
+ this->dvbspeed += 2;
+#ifdef LOG_DVBSPEED
+ printf ("net_buf_ctrl: dvbspeed 100.5%% @ %s %d ms %d buffers\n",
+ name, (int)*fill / 90, used);
+#endif
+ }
+ break;
+ case 7:
+ if (_x_get_fine_speed (this->stream)) {
+ /* Pause on first a/v buffer. Decoder headers went through at this time
+ already, and xine_play is done waiting for that */
+ _x_set_fine_speed (this->stream, 0);
+#ifdef LOG_DVBSPEED
+ printf ("net_buf_ctrl: prebuffering...\n");
+#endif
+ break;
+ }
+ /* DVB streams usually mux video > 0.5 seconds earlier than audio
+ to give slow TVs time to decode and present in sync. Take care
+ of unusual high delays of some DVB-T streams */
+ if (this->dvbs_audio_in && this->dvbs_video_in) {
+ int64_t d = this->dvbs_video_in - this->dvbs_audio_in + 110000;
+ if ((d < 3 * 90000) && (d > this->dvbs_center)) this->dvbs_center = d;
+ }
+ /* fall through */
+ case 2:
+ case 5:
+ if ((*fill > this->dvbs_center) || (100 * used > 73 * fifo->buffer_pool_capacity)) {
+ _x_set_fine_speed (this->stream, XINE_FINE_SPEED_NORMAL);
+ this->dvbspeed = (mode & 0x10) ? 1 : 4;
+#ifdef LOG_DVBSPEED
+ printf ("net_buf_ctrl: dvbspeed 100%% @ %s %d ms %d buffers\n",
+ name, (int)*fill / 90, used);
+#endif
+ /* dont let low bitrate radio switch speed too often */
+ if (used < 30) this->dvbs_width = 135000;
+ }
+ break;
+ }
+}
+
+static void dvbspeed_get (nbc_t *this, fifo_buffer_t * fifo, buf_element_t *b) {
+ int64_t diff, *last;
+ int *fill;
+ int used, mode;
+ const char *name;
+ /* select vars */
+ if (fifo == this->video_fifo) {
+ last = &this->dvbs_video_out;
+ fill = &this->dvbs_video_fill;
+ mode = 0x71;
+ name = "video";
+ } else if (fifo == this->audio_fifo) {
+ last = &this->dvbs_audio_out;
+ fill = &this->dvbs_audio_fill;
+ mode = 0x0f;
+ name = "audio";
+ } else return;
+ /* update fifo fill time */
+ if (b->pts && (b->decoder_flags & BUF_FLAG_FRAME_START)) {
+ if (*last) {
+ diff = b->pts - *last;
+ if ((diff > -220000) && (diff < 220000)) *fill -= diff;
+ }
+ *last = b->pts;
+ }
+ /* take actions */
+ used = fifo->fifo_size;
+ if (((mode >> this->dvbspeed) & 1) || !*fill) return;
+ switch (this->dvbspeed) {
+ case 1:
+ case 4:
+ if ((*fill < this->dvbs_center - this->dvbs_width) &&
+ (100 * used < 38 * fifo->buffer_pool_capacity)) {
+ _x_set_fine_speed (this->stream, XINE_FINE_SPEED_NORMAL * 199 / 200);
+ this->dvbspeed += 1;
+#ifdef LOG_DVBSPEED
+ printf ("net_buf_ctrl: dvbspeed 99.5%% @ %s %d ms %d buffers\n",
+ name, (int)*fill / 90, used);
+#endif
+ }
+ break;
+ case 3:
+ case 6:
+ if ((*fill < this->dvbs_center) && (100 * used < 73 * fifo->buffer_pool_capacity)) {
+ _x_set_fine_speed (this->stream, XINE_FINE_SPEED_NORMAL);
+ this->dvbspeed -= 2;
+#ifdef LOG_DVBSPEED
+ printf ("net_buf_ctrl: dvbspeed 100%% @ %s %d ms %d buffers\n",
+ name, (int)*fill / 90, used);
+#endif
+ }
+ break;
+ }
+}
+
static void display_stats (nbc_t *this) {
static const char buffering[2][4] = {" ", "buf"};
static const char enabled[2][4] = {"off", "on "};
@@ -304,69 +502,73 @@ static void nbc_put_cb (fifo_buffer_t *fifo,
if (this->enabled) {
- nbc_compute_fifo_length(this, fifo, buf, FIFO_PUT);
-
- if (this->buffering) {
-
- has_video = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO);
- has_audio = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO);
- /* restart playing if high_water_mark is reached by all fifos
- * do not restart if has_video and has_audio are false to avoid
- * a yoyo effect at the beginning of the stream when these values
- * are not yet known.
- *
- * be sure that the next buffer_pool_alloc() call will not deadlock,
- * we need at least 2 buffers (see buffer.c)
- */
- if ((((!has_video) || (this->video_fifo_length > this->high_water_mark)) &&
- ((!has_audio) || (this->audio_fifo_length > this->high_water_mark)) &&
- (has_video || has_audio))) {
+ if (this->dvbspeed)
+ dvbspeed_put (this, fifo, buf);
+ else {
+ nbc_compute_fifo_length(this, fifo, buf, FIFO_PUT);
+
+ if (this->buffering) {
+
+ has_video = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO);
+ has_audio = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO);
+ /* restart playing if high_water_mark is reached by all fifos
+ * do not restart if has_video and has_audio are false to avoid
+ * a yoyo effect at the beginning of the stream when these values
+ * are not yet known.
+ *
+ * be sure that the next buffer_pool_alloc() call will not deadlock,
+ * we need at least 2 buffers (see buffer.c)
+ */
+ if ((((!has_video) || (this->video_fifo_length > this->high_water_mark)) &&
+ ((!has_audio) || (this->audio_fifo_length > this->high_water_mark)) &&
+ (has_video || has_audio))) {
- this->progress = 100;
- report_progress (this->stream, 100);
- this->buffering = 0;
+ this->progress = 100;
+ report_progress (this->stream, 100);
+ this->buffering = 0;
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_put_cb: stops buffering\n");
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_put_cb: stops buffering\n");
- nbc_set_speed_normal(this);
+ nbc_set_speed_normal(this);
- this->high_water_mark += this->high_water_mark / 2;
+ this->high_water_mark += this->high_water_mark / 2;
- } else {
- /* compute the buffering progress
- * 50%: video
- * 50%: audio */
- video_p = ((this->video_fifo_length * 50) / this->high_water_mark);
- if (video_p > 50) video_p = 50;
- audio_p = ((this->audio_fifo_length * 50) / this->high_water_mark);
- if (audio_p > 50) audio_p = 50;
-
- if ((has_video) && (has_audio)) {
- progress = video_p + audio_p;
- } else if (has_video) {
- progress = 2 * video_p;
} else {
- progress = 2 * audio_p;
- }
-
- /* if the progress can't be computed using the fifo length,
- use the number of buffers */
- if (!progress) {
- video_p = this->video_fifo_fill;
- audio_p = this->audio_fifo_fill;
- progress = (video_p > audio_p) ? video_p : audio_p;
- }
-
- if (progress > this->progress) {
- report_progress (this->stream, progress);
- this->progress = progress;
+ /* compute the buffering progress
+ * 50%: video
+ * 50%: audio */
+ video_p = ((this->video_fifo_length * 50) / this->high_water_mark);
+ if (video_p > 50) video_p = 50;
+ audio_p = ((this->audio_fifo_length * 50) / this->high_water_mark);
+ if (audio_p > 50) audio_p = 50;
+
+ if ((has_video) && (has_audio)) {
+ progress = video_p + audio_p;
+ } else if (has_video) {
+ progress = 2 * video_p;
+ } else {
+ progress = 2 * audio_p;
+ }
+
+ /* if the progress can't be computed using the fifo length,
+ use the number of buffers */
+ if (!progress) {
+ video_p = this->video_fifo_fill;
+ audio_p = this->audio_fifo_fill;
+ progress = (video_p > audio_p) ? video_p : audio_p;
+ }
+
+ if (progress > this->progress) {
+ report_progress (this->stream, progress);
+ this->progress = progress;
+ }
}
}
- }
- if(this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- display_stats(this);
+ if(this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ display_stats(this);
- report_stats(this, 0);
+ report_stats(this, 0);
+ }
}
} else {
@@ -384,7 +586,8 @@ static void nbc_put_cb (fifo_buffer_t *fifo,
this->audio_last_pts = 0;
this->video_fifo_length = 0;
this->audio_fifo_length = 0;
- nbc_set_speed_pause(this);
+ dvbspeed_init (this);
+ if (!this->dvbspeed) nbc_set_speed_pause(this);
this->progress = 0;
report_progress (this->stream, progress);
}
@@ -398,6 +601,7 @@ static void nbc_put_cb (fifo_buffer_t *fifo,
case BUF_CONTROL_END:
case BUF_CONTROL_QUIT:
lprintf("BUF_CONTROL_END\n");
+ dvbspeed_close (this);
if (this->enabled) {
/* end of stream :
* - disable the nbc
@@ -458,36 +662,40 @@ static void nbc_get_cb (fifo_buffer_t *fifo,
if (this->enabled) {
- nbc_compute_fifo_length(this, fifo, buf, FIFO_GET);
-
- if (!this->buffering) {
- /* start buffering if one fifo is empty
- */
- int has_video = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO);
- int has_audio = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO);
- if (((this->video_fifo_length == 0) && has_video) ||
- ((this->audio_fifo_length == 0) && has_audio)) {
- /* do not pause if a fifo is full to avoid yoyo (play-pause-play-pause) */
- if ((this->video_fifo_free > FULL_FIFO_MARK) &&
- (this->audio_fifo_free > FULL_FIFO_MARK)) {
- this->buffering = 1;
- this->progress = 0;
- report_progress (this->stream, 0);
-
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "\nnet_buf_ctrl: nbc_get_cb: starts buffering, vid: %d, aud: %d\n",
- this->video_fifo_fill, this->audio_fifo_fill);
- nbc_set_speed_pause(this);
+ if (this->dvbspeed)
+ dvbspeed_get (this, fifo, buf);
+ else {
+ nbc_compute_fifo_length(this, fifo, buf, FIFO_GET);
+
+ if (!this->buffering) {
+ /* start buffering if one fifo is empty
+ */
+ int has_video = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO);
+ int has_audio = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO);
+ if (((this->video_fifo_length == 0) && has_video) ||
+ ((this->audio_fifo_length == 0) && has_audio)) {
+ /* do not pause if a fifo is full to avoid yoyo (play-pause-play-pause) */
+ if ((this->video_fifo_free > FULL_FIFO_MARK) &&
+ (this->audio_fifo_free > FULL_FIFO_MARK)) {
+ this->buffering = 1;
+ this->progress = 0;
+ report_progress (this->stream, 0);
+
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "\nnet_buf_ctrl: nbc_get_cb: starts buffering, vid: %d, aud: %d\n",
+ this->video_fifo_fill, this->audio_fifo_fill);
+ nbc_set_speed_pause(this);
+ }
}
+ } else {
+ nbc_set_speed_pause(this);
}
- } else {
- nbc_set_speed_pause(this);
- }
- if(this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- display_stats(this);
+ if(this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ display_stats(this);
- report_stats(this, 1);
+ report_stats(this, 1);
+ }
}
} else {
/* discontinuity management */
diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c
index 6f45672ee..55661c381 100644
--- a/src/xine-engine/buffer_types.c
+++ b/src/xine-engine/buffer_types.c
@@ -1194,6 +1194,14 @@ static const audio_db_t audio_db[] = {
BUF_AUDIO_EAC3,
"E-AC-3"
},
+{
+ {
+ ME_FOURCC('M', 'P', '4', 'L'),
+ 0
+ },
+ BUF_AUDIO_AAC_LATM,
+ "AAC LATM"
+},
{ { 0 }, 0, "last entry" }
};
diff --git a/src/xine-engine/events.c b/src/xine-engine/events.c
index 11d6e8bd7..5bd827c45 100644
--- a/src/xine-engine/events.c
+++ b/src/xine-engine/events.c
@@ -111,6 +111,8 @@ xine_event_queue_t *xine_event_new_queue (xine_stream_t *stream) {
xine_event_queue_t *queue;
+ _x_refcounter_inc(stream->refcounter);
+
queue = malloc (sizeof (xine_event_queue_t));
pthread_mutex_init (&queue->lock, NULL);
@@ -186,6 +188,8 @@ void xine_event_dispose_queue (xine_event_queue_t *queue) {
free (queue->listener_thread);
}
+ _x_refcounter_dec(stream->refcounter);
+
/*
* clean up pending events
*/
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 6e5001f35..d3a75623b 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -1519,6 +1519,14 @@ static void xine_dispose_internal (xine_stream_t *stream) {
xine_list_iterator_t *ite;
lprintf("stream: %p\n", stream);
+
+ pthread_mutex_lock(&stream->xine->streams_lock);
+ ite = xine_list_find(stream->xine->streams, stream);
+ if (ite) {
+ xine_list_remove(stream->xine->streams, ite);
+ }
+ pthread_mutex_unlock(&stream->xine->streams_lock);
+
pthread_mutex_destroy (&stream->info_mutex);
pthread_mutex_destroy (&stream->meta_mutex);
pthread_mutex_destroy (&stream->frontend_lock);
@@ -1537,13 +1545,6 @@ static void xine_dispose_internal (xine_stream_t *stream) {
xine_list_delete(stream->event_queues);
- pthread_mutex_lock(&stream->xine->streams_lock);
- ite = xine_list_find(stream->xine->streams, stream);
- if (ite) {
- xine_list_remove(stream->xine->streams, ite);
- }
- pthread_mutex_unlock(&stream->xine->streams_lock);
-
_x_refcounter_dispose(stream->refcounter);
free (stream->current_extra_info);
@@ -1581,6 +1582,7 @@ void xine_dispose (xine_stream_t *stream) {
if (stream->osd_renderer)
stream->osd_renderer->close( stream->osd_renderer );
+ /* Remove the reference that the stream was created with. */
_x_refcounter_dec(stream->refcounter);
}