summaryrefslogtreecommitdiff
path: root/src/demuxers
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers')
-rw-r--r--src/demuxers/demux_mpgaudio.c50
-rw-r--r--src/demuxers/demux_wav.c14
2 files changed, 55 insertions, 9 deletions
diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c
index 3c3576fd2..a87de5f97 100644
--- a/src/demuxers/demux_mpgaudio.c
+++ b/src/demuxers/demux_mpgaudio.c
@@ -65,11 +65,13 @@
/* Xing header stuff */
#define XING_TAG FOURCC_TAG('X', 'i', 'n', 'g')
#define INFO_TAG FOURCC_TAG('I', 'n', 'f', 'o')
+#define LAME_TAG FOURCC_TAG('L', 'A', 'M', 'E')
#define XING_FRAMES_FLAG 0x0001
#define XING_BYTES_FLAG 0x0002
#define XING_TOC_FLAG 0x0004
#define XING_VBR_SCALE_FLAG 0x0008
#define XING_TOC_LENGTH 100
+#define LAME_HEADER_LENGTH 0xC0
/* Xing header stuff */
#define VBRI_TAG FOURCC_TAG('V', 'B', 'R', 'I')
@@ -96,6 +98,10 @@ typedef struct {
uint32_t stream_size;
uint8_t toc[XING_TOC_LENGTH];
uint32_t vbr_scale;
+
+ /* Lame extension */
+ uint16_t start_delay;
+ uint16_t end_delay;
} xing_header_t;
/* Vbri Vbr Header struct */
@@ -402,9 +408,21 @@ static xing_header_t *XINE_MALLOC parse_xing_header(mpg_audio_frame_t *frame,
xing->vbr_scale = -1;
if (xing->flags & XING_VBR_SCALE_FLAG) {
if (ptr >= (buf + bufsize - 4)) goto exit_error;
- xing->vbr_scale = _X_BE_32(ptr);
+ xing->vbr_scale = _X_BE_32(ptr); ptr += 4;
lprintf("vbr_scale: %d\n", xing->vbr_scale);
}
+
+ /* LAME extension */
+ /* see http://gabriel.mp3-tech.org/mp3infotag.html */
+ ptr -= 0x9C; /* move offset to match LAME header specs */
+ if (ptr + LAME_HEADER_LENGTH >= (buf + bufsize - 4)) goto exit_error;
+ if (_X_BE_32(&ptr[0x9C]) == LAME_TAG) {
+ lprintf("Lame header found\n");
+ xing->start_delay = (ptr[0xb1] << 4) | (ptr[0xb2] >> 4);
+ xing->end_delay = ((ptr[0xb2] & 0x0f) << 4) | ptr[0xb3];
+ lprintf("start delay : %d samples\n", xing->start_delay);
+ lprintf("end delay : %d samples\n", xing->end_delay);
+ }
} else {
lprintf("Xing header not found\n");
}
@@ -613,7 +631,22 @@ static int parse_frame_payload(demux_mpgaudio_t *this,
buf->size = this->cur_frame.size;
buf->type = BUF_AUDIO_MPEG;
buf->decoder_info[0] = 1;
- buf->decoder_flags = decoder_flags|BUF_FLAG_FRAME_END;
+ buf->decoder_flags = decoder_flags | BUF_FLAG_FRAME_END;
+
+ /* send encoder padding */
+ if (this->xing_header) {
+ if (frame_pos == this->mpg_frame_start) {
+ lprintf("sending a start padding of %d samples.\n", this->xing_header->start_delay);
+ buf->decoder_flags = buf->decoder_flags | BUF_FLAG_AUDIO_PADDING;
+ buf->decoder_info[1] = this->xing_header->start_delay;
+ buf->decoder_info[2] = 0;
+ } else if ((frame_pos + this->cur_frame.size) == this->mpg_frame_end) {
+ lprintf("sending a end padding of %d samples.\n", this->xing_header->end_delay);
+ buf->decoder_flags = buf->decoder_flags | BUF_FLAG_AUDIO_PADDING;
+ buf->decoder_info[1] = 0;
+ buf->decoder_info[2] = this->xing_header->end_delay;
+ }
+ }
lprintf("send buffer: size=%d, pts=%"PRId64"\n", buf->size, pts);
this->audio_fifo->put(this->audio_fifo, buf);
@@ -768,9 +801,18 @@ static int demux_mpgaudio_send_chunk (demux_plugin_t *this_gen) {
demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen;
- if (!demux_mpgaudio_next (this, 0, 0))
- this->status = DEMUX_FINISHED;
+ if (!demux_mpgaudio_next (this, 0, 0)) {
+ /* Hack: send 8 zero bytes to flush the libmad decoder */
+ buf_element_t *buf;
+ buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
+ buf->type = BUF_AUDIO_MPEG;
+ buf->decoder_flags = BUF_FLAG_FRAME_END;
+ buf->size = 8;
+ memset(buf->content, 0, buf->size);
+ this->audio_fifo->put(this->audio_fifo, buf);
+ this->status = DEMUX_FINISHED;
+ }
return this->status;
}
diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c
index 5f39395ad..99c50ad67 100644
--- a/src/demuxers/demux_wav.c
+++ b/src/demuxers/demux_wav.c
@@ -66,6 +66,7 @@ typedef struct {
off_t data_start;
off_t data_size;
+ int send_newpts;
int seek_flag; /* this is set when a seek just occurred */
} demux_wav_t;
@@ -186,9 +187,9 @@ static int demux_wav_send_chunk(demux_plugin_t *this_gen) {
current_pts *= 90000;
current_pts /= this->wave->nAvgBytesPerSec;
- if (this->seek_flag) {
- _x_demux_control_newpts(this->stream, current_pts, BUF_FLAG_SEEK);
- this->seek_flag = 0;
+ if (this->send_newpts) {
+ _x_demux_control_newpts(this->stream, current_pts, this->seek_flag);
+ this->send_newpts = this->seek_flag = 0;
}
while (remaining_sample_bytes) {
@@ -289,10 +290,13 @@ static int demux_wav_seek (demux_plugin_t *this_gen,
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
- this->seek_flag = 1;
this->status = DEMUX_OK;
- _x_demux_flush_engine (this->stream);
+ this->send_newpts = 1;
+ if (playing) {
+ this->seek_flag = 1;
+ _x_demux_flush_engine (this->stream);
+ }
/* if input is non-seekable, do not proceed with the rest of this
* seek function */
if (!INPUT_IS_SEEKABLE(this->input))