- if (pmd->stream.error != MAD_ERROR_BADDATAPTR)
- return 0;
- if (pmd->flags & MP3DEC_FLAG_DECODE_STARTED)
- return 0;
- /*
- * Bad data pointer at stream start. Defer decoding until the amount of
- * data we are about to skip is available again, but wait at most 60ms.
- */
- pmd->flags |= MP3DEC_FLAG_BAD_DATA;
- pmd->input_len_barrier = len;
- tv_add(now, &delay, &pmd->stream_start_barrier);
- return 1;
-}
-
-static ssize_t mp3dec(char *inbuffer, size_t len, struct filter_node *fn)
-{
- int i, ret;
- struct private_mp3dec_data *pmd = fn->private_data;
- size_t copy = PARA_MIN(len, (size_t)4096);
-
- if (fn->loaded + 16384 > fn->bufsize)
- return 0;
- if (need_bad_data_delay(pmd, len))
- return 0;
- mad_stream_buffer(&pmd->stream, (unsigned char *) inbuffer, copy);
- pmd->stream.error = 0;
-next_frame:
- ret = mad_header_decode(&pmd->frame.header, &pmd->stream);
- if (ret < 0) {
- if (pmd->stream.error != MAD_ERROR_BUFLEN &&
- pmd->stream.error != MAD_ERROR_LOSTSYNC)
- PARA_DEBUG_LOG("header decode: %s\n",
- mad_stream_errorstr(&pmd->stream));
- goto out;
- }
- fn->fc->samplerate = pmd->frame.header.samplerate;
- fn->fc->channels = MAD_NCHANNELS(&pmd->frame.header);
- ret = mad_frame_decode(&pmd->frame, &pmd->stream);
- if (ret != 0) {
- ret = handle_decode_error(pmd, len);
- if (ret < 0)
- return ret;
- if (ret == 0)
- goto out;
- ret = copy - (pmd->stream.bufend - pmd->stream.next_frame);
- PARA_NOTICE_LOG("skipping %d input bytes\n", ret);
- return ret;
- }
- mad_synth_frame(&pmd->synth, &pmd->frame);
- pmd->flags |= MP3DEC_FLAG_DECODE_STARTED;
-
- for (i = 0; i < pmd->synth.pcm.length; i++) {
- int s = MAD_TO_SHORT(pmd->synth.pcm.samples[0][i]);
- write_int16_host_endian(fn->buf + fn->loaded, s);
- fn->loaded += 2;
- if (MAD_NCHANNELS(&pmd->frame.header) == 2) { /* stereo */
- s = MAD_TO_SHORT(pmd->synth.pcm.samples[1][i]);
- write_int16_host_endian(fn->buf + fn->loaded, s);
- fn->loaded += 2;
- }
- if (fn->loaded != fn->bufsize) /* output buffer not full */
- continue;
- PARA_ERROR_LOG("output buffer full: %zd\n", fn->loaded);
- return -E_MP3DEC_OVERRUN;
- }
- if (fn->loaded + 16384 <= fn->bufsize)
- goto next_frame;
-out:
- if (pmd->stream.next_frame) { /* we still have some data */
- size_t off = pmd->stream.bufend - pmd->stream.next_frame;
- if (fn->loaded + 16384 <= fn->bufsize && off > 2048)
- goto next_frame;
- return copy - off;
- }
- return copy;