diff options
Diffstat (limited to 'src/demuxers')
-rw-r--r-- | src/demuxers/demux_mpgaudio.c | 50 | ||||
-rw-r--r-- | src/demuxers/demux_wav.c | 14 |
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)) |