static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { mad_decoder_t *this = (mad_decoder_t *) this_gen; int bytes_in_buffer_at_pts; lprintf ("decode data, size: %d, decoder_flags: %d\n", buf->size, buf->decoder_flags); if (buf->size>(INPUT_BUF_SIZE-this->bytes_in_buffer)) { xprintf (this->xstream->xine, XINE_VERBOSITY_DEBUG, "libmad: ALERT input buffer too small (%d bytes, %d avail)!\n", buf->size, INPUT_BUF_SIZE-this->bytes_in_buffer); buf->size = INPUT_BUF_SIZE-this->bytes_in_buffer; } if ((buf->decoder_flags & BUF_FLAG_HEADER) == 0) { /* reset decoder on leaving preview mode */ if ((buf->decoder_flags & BUF_FLAG_PREVIEW) == 0) { if (this->preview_mode) { mad_reset (this_gen); } } else { this->preview_mode = 1; } bytes_in_buffer_at_pts = this->bytes_in_buffer; xine_fast_memcpy (&this->buffer[this->bytes_in_buffer], buf->content, buf->size); this->bytes_in_buffer += buf->size; /* printf ("libmad: decode data - doing it\n"); */ mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); if (this->bytes_in_buffer < MAD_MIN_SIZE && buf->pts == 0) return; if (!this->needs_more_data) { this->pts = buf->pts; if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) { this->start_padding = buf->decoder_info[1]; this->end_padding = buf->decoder_info[2]; } else { this->start_padding = 0; this->end_padding = 0; } } while (1) { if (mad_frame_decode (&this->frame, &this->stream) != 0) { if (this->stream.next_frame) { int num_bytes = this->buffer + this->bytes_in_buffer - this->stream.next_frame; /* printf("libmad: MAD_ERROR_BUFLEN\n"); */ memmove(this->buffer, this->stream.next_frame, num_bytes); this->bytes_in_buffer = num_bytes; } switch (this->stream.error) { case MAD_ERROR_BUFLEN: /* libmad wants more data */ this->needs_more_data = 1; return; default: lprintf ("error 0x%04X, mad_stream_buffer %d bytes\n", this->stream.error, this->bytes_in_buffer); mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); } } else { int mode = (this->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? AO_CAP_MODE_MONO : AO_CAP_MODE_STEREO; if (!this->output_open || (this->output_sampling_rate != this->frame.header.samplerate) || (this->output_mode != mode)) { lprintf ("audio sample rate %d mode %08x\n", this->frame.header.samplerate, mode); /* the mpeg audio demuxer can set audio bitrate */ if (! _x_stream_info_get(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE)) { _x_stream_info_set(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE, this->frame.header.bitrate); } /* the mpeg audio demuxer can set this meta info */ if (! _x_meta_info_get(this->xstream, XINE_META_INFO_AUDIOCODEC)) { switch (this->frame.header.layer) { case MAD_LAYER_I: _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 1 (lib: MAD)"); break; case MAD_LAYER_II: _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 2 (lib: MAD)"); break; case MAD_LAYER_III: _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 3 (lib: MAD)"); break; default: _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio (lib: MAD)"); } } if (this->output_open) { this->xstream->audio_out->close (this->xstream->audio_out, this->xstream); this->output_open = 0; } if (!this->output_open) { this->output_open = (this->xstream->audio_out->open) (this->xstream->audio_out, this->xstream, 16, this->frame.header.samplerate, mode) ; } if (!this->output_open) { return; } this->output_sampling_rate = this->frame.header.samplerate; this->output_mode = mode; } mad_synth_frame (&this->synth, &this->frame); if ( (buf->decoder_flags & BUF_FLAG_PREVIEW) == 0 ) { unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; struct mad_pcm *pcm = &this->synth.pcm; audio_buffer_t *audio_buffer; uint16_t *output; int bitrate; int pts_offset; audio_buffer = this->xstream->audio_out->get_buffer (this->xstream->audio_out); output = audio_buffer->mem; nchannels = pcm->channels; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; /* padding */ if (this->start_padding || this->end_padding) { /* check padding validity */ if (nsamples < (this->start_padding + this->end_padding)) { lprintf("invalid padding data"); this->start_padding = 0; this->end_padding = 0; } lprintf("nsamples=%d, start_padding=%d, end_padding=%d\n", nsamples, this->start_padding, this->end_padding); nsamples -= this->start_padding + this->end_padding; left_ch += this->start_padding; right_ch += this->start_padding; } audio_buffer->num_frames = nsamples; audio_buffer->vpts = this->pts; while (nsamples--) { /* output sample(s) in 16-bit signed little-endian PCM */ *output++ = scale(*left_ch++); if (nchannels == 2) *output++ = scale(*right_ch++); } audio_buffer->num_frames = pcm->length; /* pts computing */ if (this->frame.header.bitrate > 0) { bitrate = this->frame.header.bitrate; } else { bitrate = _x_stream_info_get(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE); lprintf("offset %d bps\n", bitrate); } audio_buffer->vpts = buf->pts; if (audio_buffer->vpts && (bitrate > 0)) { pts_offset = (bytes_in_buffer_at_pts * 8 * 90) / (bitrate / 1000); lprintf("pts: %"PRId64", offset: %d pts, %d bytes\n", buf->pts, pts_offset, bytes_in_buffer_at_pts); if (audio_buffer->vpts < pts_offset) pts_offset = audio_buffer->vpts; audio_buffer->vpts -= pts_offset; } this->xstream->audio_out->put_buffer (this->xstream->audio_out, audio_buffer, this->xstream); this->pts = buf->pts; buf->pts = 0; if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) { this->start_padding = buf->decoder_info[1]; this->end_padding = buf->decoder_info[2]; buf->decoder_info[1] = 0; buf->decoder_info[2] = 0; } else { this->start_padding = 0; this->end_padding = 0; } } lprintf ("decode worked\n"); } } } }
static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { mad_decoder_t *this = (mad_decoder_t *) this_gen; #ifdef LOG printf ("libmad: decode data, decoder_flags: %d\n", buf->decoder_flags); #endif if (buf->size>(INPUT_BUF_SIZE-this->bytes_in_buffer)) { printf ("libmad: ALERT input buffer too small (%d bytes, %d avail)!\n", buf->size, INPUT_BUF_SIZE-this->bytes_in_buffer); buf->size = INPUT_BUF_SIZE-this->bytes_in_buffer; } if ((buf->decoder_flags & BUF_FLAG_HEADER) == 0) { /* reset decoder on leaving preview mode */ if ((buf->decoder_flags & BUF_FLAG_PREVIEW) == 0) { if (this->preview_mode) { mad_reset (this_gen); } } else { this->preview_mode = 1; } xine_fast_memcpy (&this->buffer[this->bytes_in_buffer], buf->content, buf->size); this->bytes_in_buffer += buf->size; /* printf ("libmad: decode data - doing it\n"); */ mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); while (1) { if (mad_frame_decode (&this->frame, &this->stream) != 0) { if (this->stream.next_frame) { int num_bytes = this->buffer + this->bytes_in_buffer - this->stream.next_frame; /* printf("libmad: MAD_ERROR_BUFLEN\n"); */ memmove(this->buffer, this->stream.next_frame, num_bytes); this->bytes_in_buffer = num_bytes; } switch (this->stream.error) { case MAD_ERROR_BUFLEN: return; default: mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); } } else { int mode = (this->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? AO_CAP_MODE_MONO : AO_CAP_MODE_STEREO; if (!this->output_open || (this->output_sampling_rate != this->frame.header.samplerate) || (this->output_mode != mode)) { #ifdef LOG printf ("libmad: audio sample rate %d mode %08x\n", this->frame.header.samplerate, mode); #endif this->xstream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = this->frame.header.bitrate; switch (this->frame.header.layer) { case MAD_LAYER_I: this->xstream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("MPEG audio layer 1"); break; case MAD_LAYER_II: this->xstream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("MPEG audio layer 2"); break; case MAD_LAYER_III: this->xstream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("MPEG audio layer 3"); break; default: this->xstream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("MPEG audio"); } if (this->output_open) { this->xstream->audio_out->close (this->xstream->audio_out, this->xstream); this->output_open = 0; } if (!this->output_open) { this->output_open = this->xstream->audio_out->open(this->xstream->audio_out, this->xstream, 16, this->frame.header.samplerate, mode) ; } if (!this->output_open) { return; } this->output_sampling_rate = this->frame.header.samplerate; this->output_mode = mode; } mad_synth_frame (&this->synth, &this->frame); if ( (buf->decoder_flags & BUF_FLAG_PREVIEW) == 0 ) { unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; struct mad_pcm *pcm = &this->synth.pcm; audio_buffer_t *audio_buffer; uint16_t *output; audio_buffer = this->xstream->audio_out->get_buffer (this->xstream->audio_out); output = audio_buffer->mem; nchannels = pcm->channels; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; while (nsamples--) { /* output sample(s) in 16-bit signed little-endian PCM */ *output++ = scale(*left_ch++); if (nchannels == 2) *output++ = scale(*right_ch++); } audio_buffer->num_frames = pcm->length; audio_buffer->vpts = buf->pts; this->xstream->audio_out->put_buffer (this->xstream->audio_out, audio_buffer, this->xstream); buf->pts = 0; } #ifdef LOG printf ("libmad: decode worked\n"); #endif } } } }