summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/demuxers/demux_mpeg_pes.c28
-rw-r--r--src/demuxers/demux_ts.c103
2 files changed, 118 insertions, 13 deletions
diff --git a/src/demuxers/demux_mpeg_pes.c b/src/demuxers/demux_mpeg_pes.c
index 5ad959d51..8d1f4b8af 100644
--- a/src/demuxers/demux_mpeg_pes.c
+++ b/src/demuxers/demux_mpeg_pes.c
@@ -949,6 +949,34 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
}
return this->packet_len + result;
+ /* EVOB AC3/E-AC-3 */
+ } else if ((p[0]&0xf0) == 0xc0) {
+
+ track = p[0] & 0x0F; /* hack : ac3 track */
+ buf->decoder_info[1] = p[1]; /* Number of frame headers */
+ buf->decoder_info[2] = p[2] << 8 | p[3]; /* First access unit pointer */
+
+ buf->content = p+4;
+ buf->size = this->packet_len-4;
+ if (p[4] == 0x0b && p[5] == 0x77 && ((p[9] >> 3) & 0x1f) <= 8) {
+ buf->type = BUF_AUDIO_A52 + track;
+ } else {
+ buf->type = BUF_AUDIO_EAC3 + track;
+ buf->decoder_flags |= BUF_FLAG_FRAME_END;
+ }
+ buf->pts = this->pts;
+ if( !this->preview_mode )
+ check_newpts( this, this->pts, PTS_AUDIO );
+
+ if(this->audio_fifo) {
+ this->audio_fifo->put (this->audio_fifo, buf);
+ lprintf ("A52/EAC3 PACK put on fifo\n");
+
+ } else {
+ buf->free_buffer(buf);
+ }
+ return this->packet_len + result;
+
} else if ((p[0]&0xf0) == 0xa0) {
int pcm_offset;
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
index 4736a9c82..45e822075 100644
--- a/src/demuxers/demux_ts.c
+++ b/src/demuxers/demux_ts.c
@@ -212,6 +212,16 @@
#define ISO13522_STREAM 0xF3
#define PROG_STREAM_DIR 0xFF
+/* descriptors in PMT stream info */
+#define DESCRIPTOR_REG_FORMAT 0x05
+#define DESCRIPTOR_LANG 0x0a
+#define DESCRIPTOR_TELETEXT 0x56
+#define DESCRIPTOR_DVBSUB 0x59
+#define DESCRIPTOR_AC3 0x6a
+#define DESCRIPTOR_EAC3 0x7a
+#define DESCRIPTOR_DTS 0x7b
+#define DESCRIPTOR_AAC 0x7c
+
typedef enum
{
ISO_11172_VIDEO = 0x01, /* ISO/IEC 11172 Video */
@@ -254,6 +264,17 @@
#define PTS_AUDIO 0
#define PTS_VIDEO 1
+/* bitrate estimation */
+#define TBRE_MIN_TIME ( 2 * 90000)
+#define TBRE_TIME (480 * 90000)
+
+#define TBRE_MODE_PROBE 0
+#define TBRE_MODE_AUDIO_PTS 1
+#define TBRE_MODE_AUDIO_PCR 2
+#define TBRE_MODE_PCR 3
+#define TBRE_MODE_DONE 4
+
+
#undef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#undef MAX
@@ -393,8 +414,50 @@ typedef struct {
off_t frame_pos; /* current ts packet position in input stream (bytes from beginning) */
+ /* bitrate estimation */
+ off_t tbre_bytes, tbre_lastpos;
+ int64_t tbre_time, tbre_lasttime;
+ unsigned int tbre_mode, tbre_pid;
+
} demux_ts_t;
+
+static void demux_ts_tbre_reset (demux_ts_t *this) {
+ if (this->tbre_time <= TBRE_TIME) {
+ this->tbre_pid = INVALID_PID;
+ this->tbre_mode = TBRE_MODE_PROBE;
+ }
+}
+
+static void demux_ts_tbre_update (demux_ts_t *this, int mode, int64_t now) {
+ /* select best available timesource on the fly */
+ if ((mode < this->tbre_mode) || (now <= 0))
+ return;
+
+ if (mode == this->tbre_mode) {
+ /* skip discontinuities */
+ int64_t diff = now - this->tbre_lasttime;
+ if ((diff < 0 ? -diff : diff) < 220000) {
+ /* add this step */
+ this->tbre_bytes += this->frame_pos - this->tbre_lastpos;
+ this->tbre_time += diff;
+ /* update bitrate */
+ if (this->tbre_time > TBRE_MIN_TIME)
+ this->rate = this->tbre_bytes * 90000 / this->tbre_time;
+ /* stop analyzing */
+ if (this->tbre_time > TBRE_TIME)
+ this->tbre_mode = TBRE_MODE_DONE;
+ }
+ } else {
+ /* upgrade timesource */
+ this->tbre_mode = mode;
+ }
+
+ /* remember where and when */
+ this->tbre_lastpos = this->frame_pos;
+ this->tbre_lasttime = now;
+}
+
/* redefine abs as macro to handle 64-bit diffs.
i guess llabs may not be available everywhere */
#define abs(x) ( ((x)<0) ? -(x) : (x) )
@@ -1065,8 +1128,14 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
m->input_normpos = (double)this->frame_pos * 65535.0 / length;
}
if (this->rate) {
- m->input_time = this->frame_pos * 1000 / (this->rate * 50);
+ m->input_time = this->frame_pos * 1000 / this->rate;
}
+
+ /* rate estimation */
+ if ((this->tbre_pid == INVALID_PID) && (this->audio_fifo == m->fifo))
+ this->tbre_pid = m->pid;
+ if (m->pid == this->tbre_pid)
+ demux_ts_tbre_update (this, TBRE_MODE_AUDIO_PTS, m->pts);
}
} else if (!m->corrupted_pes) { /* no pus -- PES packet continuation */
@@ -1129,7 +1198,7 @@ static void demux_ts_get_lang_desc(demux_ts_t *this, char *dest,
while (d < (data + length))
{
- if (d[0] == 10 && d[1] >= 4)
+ if (d[0] == DESCRIPTOR_LANG && d[1] >= 4)
{
memcpy(dest, d + 2, 3);
@@ -1154,7 +1223,7 @@ static void demux_ts_get_reg_desc(demux_ts_t *this, uint32_t *dest,
while (d < (data + length))
{
- if (d[0] == 5 && d[1] >= 4)
+ if (d[0] == DESCRIPTOR_REG_FORMAT && d[1] >= 4)
{
*dest = (d[2] << 24) | (d[3] << 16) | (d[4] << 8) | d[5];
@@ -1469,12 +1538,13 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
break;
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)) {
+ if (((stream[i] == DESCRIPTOR_AC3) || (stream[i] == DESCRIPTOR_EAC3)) &&
+ (this->audio_tracks_count < MAX_AUDIO_TRACKS)) {
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
- if (stream[i] == 0x6a)
+ if (stream[i] == DESCRIPTOR_AC3)
demux_ts_pes_new(this, this->media_num, pid,
this->audio_fifo, STREAM_AUDIO_AC3);
else
@@ -1491,7 +1561,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
}
}
/* Teletext */
- else if (stream[i] == 0x56)
+ else if (stream[i] == DESCRIPTOR_TELETEXT)
{
#ifdef TS_PMT_LOG
printf ("demux_ts: PMT Teletext, pid: 0x%.4x type %2.2x\n", pid, stream[0]);
@@ -1504,7 +1574,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
}
/* DVBSUB */
- else if (stream[i] == 0x59)
+ else if (stream[i] == DESCRIPTOR_DVBSUB)
{
int pos;
for (pos = i + 2;
@@ -1644,6 +1714,8 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
if ( this->stream->spu_channel>=0 && this->spu_langs_count>0 )
demux_ts_update_spu_channel( this );
+ demux_ts_tbre_reset (this);
+
/* Inform UI of channels changes */
xine_event_t ui_event;
ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
@@ -1983,7 +2055,11 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
if( adaptation_field_control & 0x2 ){
uint32_t adaptation_field_length = originalPkt[4];
if (adaptation_field_length > 0) {
- demux_ts_adaptation_field_parse (originalPkt+5, adaptation_field_length);
+ int64_t pcr = demux_ts_adaptation_field_parse (originalPkt+5, adaptation_field_length);
+ if (pid == this->pcr_pid)
+ demux_ts_tbre_update (this, TBRE_MODE_PCR, pcr);
+ else if (pid == this->tbre_pid)
+ demux_ts_tbre_update (this, TBRE_MODE_AUDIO_PCR, pcr);
}
/*
* Skip adaptation header.
@@ -2213,9 +2289,7 @@ static int demux_ts_seek (demux_plugin_t *this_gen,
if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) {
if ((!start_pos) && (start_time)) {
- start_pos = start_time;
- start_pos *= this->rate;
- start_pos *= 50;
+ start_pos = (int64_t)start_time * this->rate / 1000;
}
this->input->seek (this->input, start_pos, SEEK_SET);
@@ -2246,6 +2320,8 @@ static int demux_ts_seek (demux_plugin_t *this_gen,
}
+ demux_ts_tbre_reset (this);
+
return this->status;
}
@@ -2255,7 +2331,7 @@ static int demux_ts_get_stream_length (demux_plugin_t *this_gen) {
if (this->rate)
return (int)((int64_t) this->input->get_length (this->input)
- * 1000 / (this->rate * 50));
+ * 1000 / this->rate);
else
return 0;
}
@@ -2412,7 +2488,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->audio_tracks_count = 0;
this->last_pmt_crc = 0;
- this->rate = 16000; /* FIXME */
+ this->rate = 1000000; /* byte/sec */
+ this->tbre_pid = INVALID_PID;
this->status = DEMUX_FINISHED;