diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/demuxers/demux_film.c | 90 |
1 files changed, 85 insertions, 5 deletions
diff --git a/src/demuxers/demux_film.c b/src/demuxers/demux_film.c index a51666b8d..07223405e 100644 --- a/src/demuxers/demux_film.c +++ b/src/demuxers/demux_film.c @@ -21,7 +21,7 @@ * For more information on the FILM file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_film.c,v 1.55 2003/01/20 05:10:04 tmmm Exp $ + * $Id: demux_film.c,v 1.56 2003/02/01 19:44:06 tmmm Exp $ */ #ifdef HAVE_CONFIG_H @@ -90,6 +90,7 @@ typedef struct { unsigned int sample_rate; unsigned int audio_bits; unsigned int audio_channels; + unsigned char *interleave_buffer; /* playback information */ unsigned int frequency; @@ -315,6 +316,12 @@ static int open_film_file(demux_film_t *film) { */ if (chunk_size == film->sample_count * 16) i += 16; + + /* allocate enough space in the interleave preload buffer for the + * first chunk (which will be more than enough for successive chunks) */ + if (film->audio_type) + film->interleave_buffer = + xine_xmalloc(film->sample_table[0].sample_size); break; default: @@ -336,10 +343,11 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { demux_film_t *this = (demux_film_t *) this_gen; buf_element_t *buf = NULL; unsigned int cvid_chunk_size; - unsigned int i, j; + unsigned int i, j, k; int fixed_cvid_header; unsigned int remaining_sample_bytes; int first_buf; + int interleave_index; i = this->current_sample; @@ -497,14 +505,16 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { buf->size, buf->pts, buf->decoder_info[0]); this->video_fifo->put(this->video_fifo, buf); } - } else if( this->audio_fifo ) { - /* load an audio sample and packetize it */ + } else if(this->audio_fifo && this->audio_channels == 1) { + + /* load an mono audio sample and packetize it */ remaining_sample_bytes = this->sample_table[i].sample_size; this->input->seek(this->input, this->sample_table[i].sample_offset, SEEK_SET); first_buf = 1; while (remaining_sample_bytes) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = this->audio_type; buf->extra_info->input_pos = @@ -550,11 +560,80 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { if (!remaining_sample_bytes) buf->decoder_flags |= BUF_FLAG_FRAME_END; - debug_film_demux(" sending audio buf with %d bytes, %lld pts, %d duration\n", + debug_film_demux(" sending mono audio buf with %d bytes, %lld pts, %d duration\n", buf->size, buf->pts, buf->decoder_info[0]); this->audio_fifo->put(this->audio_fifo, buf); } + } else if(this->audio_fifo && this->audio_channels == 2) { + + /* load an entire stereo sample and interleave the channels */ + + /* load the whole chunk into the buffer */ + if (this->input->read(this->input, this->interleave_buffer, + this->sample_table[i].sample_size) != this->sample_table[i].sample_size) { + this->status = DEMUX_FINISHED; + return this->status; + } + + /* proceed to de-interleave into individual buffers */ + remaining_sample_bytes = this->sample_table[i].sample_size / 2; + interleave_index = 0; + first_buf = 1; + while (remaining_sample_bytes) { + + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = this->audio_type; + buf->extra_info->input_pos = + this->sample_table[i].sample_offset - this->data_start; + buf->extra_info->input_length = this->data_size; + + /* special hack to accomodate linear PCM decoder: only the first + * buffer gets the real pts */ + if (first_buf) { + buf->pts = this->sample_table[i].pts; + first_buf = 0; + } else + buf->pts = 0; + buf->extra_info->input_time = buf->pts / 90; + + if (remaining_sample_bytes > buf->max_size / 2) + buf->size = buf->max_size; + else + buf->size = remaining_sample_bytes * 2; + remaining_sample_bytes -= buf->size / 2; + + if (this->audio_bits == 16) { + for (j = 0, k = interleave_index; j < buf->size; j += 4, k += 2) { + buf->content[j] = this->interleave_buffer[k]; + buf->content[j + 1] = this->interleave_buffer[k + 1]; + } + for (j = 2, + k = interleave_index + this->sample_table[i].sample_size / 2; + j < buf->size; j += 4, k += 2) { + buf->content[j] = this->interleave_buffer[k]; + buf->content[j + 1] = this->interleave_buffer[k + 1]; + } + interleave_index += buf->size / 2; + } else { + for (j = 0, k = interleave_index; j < buf->size; j += 2, k += 1) { + buf->content[j] = this->interleave_buffer[k]; + } + for (j = 1, + k = interleave_index + this->sample_table[i].sample_size / 2; + j < buf->size; j += 2, k += 1) { + buf->content[j] = this->interleave_buffer[k]; + } + interleave_index += buf->size / 2; + } + + if (!remaining_sample_bytes) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + + debug_film_demux(" sending stereo audio buf with %d bytes, %lld pts, %d duration\n", + buf->size, buf->pts, buf->decoder_info[0]); + this->audio_fifo->put(this->audio_fifo, buf); + } } return this->status; @@ -690,6 +769,7 @@ static void demux_film_dispose (demux_plugin_t *this_gen) { if (this->sample_table) free(this->sample_table); + free(this->interleave_buffer); free(this); } |