Beispiel #1
0
    int MP3InputStream::decodeFrames(int frames, void* samples)
    {
        int ret, rret;
        unsigned int len = frames * GetFrameSize(this);
        unsigned char *out = (unsigned char*)samples;
        size_t rb = 0, rv = 0;

        if (!mh) return 0;

        while (len > 0)
        {
            ret = mpg123_read(mh, out, len, &rv);
            rb += rv;
            out += rv;
            len -= rv;
            if (ret == MPG123_NEED_MORE)
            {
                // read the data
                m_input_length = m_file->read(m_input_buffer, INPUT_BUFFER_SIZE);
                if (m_input_length == 0) { m_eof = true; return true; }
                // feed it to mpg123
                rret = mpg123_feed(mh,m_input_buffer,m_input_length);
                if (rret != MPG123_OK) return false;    // something went wrong!
            }
        }

        return rb / GetFrameSize(this);
    }
Beispiel #2
0
static int feed_new_packet(struct dec_audio *da)
{
    struct ad_mpg123_context *con = da->priv;
    int ret;

    struct demux_packet *pkt = demux_read_packet(da->header);
    if (!pkt)
        return -1; /* EOF. */

    /* Next bytes from that presentation time. */
    if (pkt->pts != MP_NOPTS_VALUE) {
        da->pts        = pkt->pts;
        da->pts_offset = 0;
    }

    /* Have to use mpg123_feed() to avoid decoding here. */
    ret = mpg123_feed(con->handle, pkt->buffer, pkt->len);
    talloc_free(pkt);

    if (ret == MPG123_ERR)
        return -1;

    if (ret == MPG123_NEW_FORMAT)
        con->new_format = 1;

    return 0;
}
JNIEXPORT void JNICALL Java_com_axelby_mp3decoders_MPG123_feed
	(JNIEnv *env, jclass c, jlong handle, jbyteArray in_buffer, jint in_size)
{
	MP3File *mp3 = (MP3File*)handle;
	mpg123_handle *mh = mp3->handle;
	jboolean isCopy;
	jbyte* b = (*env)->GetByteArrayElements(env, in_buffer, &isCopy);

	int err = mpg123_feed(mh, b, in_size);
	if (err != MPG123_OK)
		__android_log_print(ANDROID_LOG_INFO, "podax-jni", "mpg123_feed error: %s", mpg123_plain_strerror(err));
	(*env)->ReleaseByteArrayElements(env, in_buffer, b, JNI_ABORT);

	if (mp3->rate == 0) {
		off_t frame_offset;
		unsigned char* audio;
		size_t bytes_done;
		err = mpg123_decode_frame(mh, &frame_offset, &audio, &bytes_done);
		if (err == MPG123_NEW_FORMAT) {
			int encoding;
			err = mpg123_getformat(mh, &mp3->rate, &mp3->channels, &encoding);
			if (err != MPG123_NEED_MORE && err != MPG123_OK) {
				printerr("mpg123_getformat", err);
				return;
			}

			mp3->samples_per_frame = mpg123_spf(mh);
			mp3->secs_per_frame = mpg123_tpf(mh);
		}
		if (err != MPG123_OK && err != MPG123_NEED_MORE)
			__android_log_print(ANDROID_LOG_INFO, "podax-jni", "cannot get rate: %s", mpg123_plain_strerror(err));
	}
}
Beispiel #4
0
size_t play_stream(void *buffer, size_t size, size_t nmemb, void *userp)
{
    int err;
    off_t frame_offset;
    unsigned char *audio;
    size_t done;
    ao_sample_format format;
    int channels, encoding;
    long rate;

    mpg123_feed(mh, (const unsigned char*) buffer, size * nmemb);
    do {
        err = mpg123_decode_frame(mh, &frame_offset, &audio, &done);
        switch(err) {
            case MPG123_NEW_FORMAT:
                mpg123_getformat(mh, &rate, &channels, &encoding);
                format.bits = mpg123_encsize(encoding) * BITS;
                format.rate = rate;
                format.channels = channels;
                format.byte_format = AO_FMT_NATIVE;
                format.matrix = 0;
                dev = ao_open_live(ao_default_driver_id(), &format, NULL);
                break;
            case MPG123_OK:
                ao_play(dev, audio, done);
                break;
            case MPG123_NEED_MORE:
                break;
            default:
                break;
        }
    } while(done > 0);

    return size * nmemb;
}
Beispiel #5
0
static int decode_packet(struct dec_audio *da)
{
    struct ad_mpg123_context *con = da->priv;
    int ret;

    mp_audio_set_null_data(&da->decoded);

    struct demux_packet *pkt;
    if (demux_read_packet_async(da->header, &pkt) == 0)
        return AD_WAIT;
    if (!pkt)
        return AD_EOF;

    /* Next bytes from that presentation time. */
    if (pkt->pts != MP_NOPTS_VALUE) {
        da->pts        = pkt->pts;
        da->pts_offset = 0;
    }

    /* Have to use mpg123_feed() to avoid decoding here. */
    ret = mpg123_feed(con->handle, pkt->buffer, pkt->len);
    talloc_free(pkt);

    if (ret != MPG123_OK)
        goto mpg123_fail;

    unsigned char *audio = NULL;
    size_t bytes = 0;
    ret = mpg123_decode_frame(con->handle, NULL, &audio, &bytes);

    if (ret == MPG123_NEED_MORE)
        return 0;

    if (ret != MPG123_OK && ret != MPG123_DONE && ret != MPG123_NEW_FORMAT)
        goto mpg123_fail;

    ret = set_format(da);
    if (ret != MPG123_OK)
        goto mpg123_fail;

    if (con->sample_size < 1) {
        MP_ERR(da, "no sample size\n");
        return AD_ERR;
    }

    int got_samples = bytes / con->sample_size;
    da->decoded.planes[0] = audio;
    da->decoded.samples = got_samples;

    update_info(da);
    return 0;

mpg123_fail:
    MP_ERR(da, "mpg123 decoding error: %s\n", mpg123_strerror(con->handle));
    return AD_ERR;
}
Beispiel #6
0
void rst_audio_feed(struct ausrc_st *st, const uint8_t *buf, size_t sz)
{
	int err;

	if (!st)
		return;

	err = mpg123_feed(st->mp3, buf, sz);
	if (err)
		return;

	while (MPG123_OK == decode(st))
		;
}
Beispiel #7
0
static size_t download_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
    fm_player_t *pl = (fm_player_t*) userp;
    if (pl->status == FM_PLAYER_STOP) {
        return 0;
    }
    else {
        size_t bytes = size * nmemb;
        pl->info.file_size += bytes;
        mpg123_feed(pl->mh, (unsigned char*) ptr, bytes);
        pthread_cond_signal(&pl->cond_play);
        return bytes;
    }
}
Beispiel #8
0
int Mpg123Decoder::feed(int bytes)
{
	int remaining = data_size - data_offset;

	if (remaining <= 0)
		return MPG123_DONE;

	int feed_bytes = remaining < bytes ? remaining : bytes;

	int r = mpg123_feed(handle, (unsigned char *)data->getData() + data_offset, feed_bytes);

	if (r == MPG123_OK || r == MPG123_DONE)
		data_offset += feed_bytes;

	return r;
}
Beispiel #9
0
static uint8_t * ReadMP3(Sound_t * Sound, const uint8_t * InData, size_t FileSize){
    mpg123_handle *mh;
    if(mpg123_init() != MPG123_OK || (mh = mpg123_new(NULL, NULL)) == NULL){
        mpg123_exit();
        return NULL;
    }

    long rate;
    int channels, encoding;
    unsigned samples;
    size_t OutSize;
    uint8_t * OutData;

    if(mpg123_format_none(mh) != MPG123_OK ||
        mpg123_format(mh, 44100, MPG123_MONO | MPG123_STEREO, MPG123_ENC_SIGNED_16) != MPG123_OK ||
        mpg123_open_feed(mh) != MPG123_OK ||
        mpg123_feed(mh, InData, FileSize) != MPG123_OK ||
        mpg123_set_filesize(mh, FileSize) != MPG123_OK ||
        mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ||
        (samples = mpg123_length(mh)) == 0 ||
        (OutData = (uint8_t*) malloc(OutSize = samples * channels * 2)) == NULL
    ){
        mpg123_close(mh);
        mpg123_delete(mh);
        mpg123_exit();
        return NULL;
    }

    size_t decoded;
    mpg123_read(mh, OutData, OutSize, &decoded);
    mpg123_close(mh);
    mpg123_delete(mh);
    mpg123_exit();

    if(decoded != OutSize){
        free(OutData);
        return NULL;
    }

    Sound->Channels = channels;
    Sound->SamplingRate = rate;
    Sound->BitDepth = 16;
    Sound->Duration = samples;
    Sound->Data = OutData;
    return OutData;
}
Beispiel #10
0
static void mp3_horse(PACMDRVSTREAMINSTANCE adsi,
                      const unsigned char* src, LPDWORD nsrc,
                      unsigned char* dst, LPDWORD ndst)
{
    AcmMpeg3Data*       amd = (AcmMpeg3Data*)adsi->dwDriver;
    int                 ret;
    size_t              size;
    DWORD               dpos = 0;


    if (*nsrc > 0)
    {
        ret = mpg123_feed(amd->mh, src, *nsrc);
        if (ret != MPG123_OK)
        {
            ERR("Error feeding data\n");
            *ndst = *nsrc = 0;
            return;
        }
    }

    do {
        size = 0;
        ret = mpg123_read(amd->mh, dst + dpos, *ndst - dpos, &size);
        if (ret == MPG123_ERR)
        {
            FIXME("Error occurred during decoding!\n");
            *ndst = *nsrc = 0;
            return;
        }

        if (ret == MPG123_NEW_FORMAT)
        {
            long rate;
            int channels, enc;
            mpg123_getformat(amd->mh, &rate, &channels, &enc);
            TRACE("New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
        }
        dpos += size;
        if (dpos > *ndst) break;
    } while (ret != MPG123_ERR && ret != MPG123_NEED_MORE);
    *ndst = dpos;
}
Beispiel #11
0
    bool MP3InputStream::decodeFrame()
    {
        const int frame_size = GetFrameSize(this);
        int ret, rret;
        size_t rv = 0;

        if (!mh) return false;

        while (rv < (size_t)frame_size)
        {
            ret = mpg123_read(mh, m_decode_buffer, frame_size, &rv);
            if (ret == MPG123_NEED_MORE)
            {
                // read the data
                m_input_length = m_file->read(m_input_buffer, INPUT_BUFFER_SIZE);
                if (m_input_length == 0) { m_eof = true; return true; }
                // feed it to mpg123
                rret = mpg123_feed(mh,m_input_buffer,m_input_length);
                if (rret != MPG123_OK) return false;    // something went wrong!
            }
        }


        if (m_first_frame)
        {
            int enc = 0;
            long int li;
            mpg123_getformat(mh, &li, &m_channel_count, &enc);
            m_sample_rate = (int)li;
            switch (enc)
            {
                case MPG123_ENC_SIGNED_16: m_sample_format = SF_S16; break;
                case MPG123_ENC_UNSIGNED_8: m_sample_format = SF_U8; break;
                default: return false;
            }
            m_first_frame = false;
        }

        m_buffer.write(m_decode_buffer, rv);

        return true;
    }
void UMP3Decoder::Init(const uint8*& Buffer, const uint8* BufferEnd)
{
	int encoding;
	int channels;
	long samplerate;

	mpg123_init();
	Handle = mpg123_new(NULL, &ErrorHandle);
	BlockBufferSize = mpg123_outblock(Handle);
	

	mpg123_open_feed(Handle);
	mpg123_feed(Handle, Buffer, BufferEnd - Buffer);
	mpg123_getformat(Handle, &samplerate, &channels, &encoding);
	uint32 bytesPerSample = mpg123_encsize(encoding);

	BitsPerSample = bytesPerSample * 8;
	Channels = channels;
	Samplerate = samplerate;

	UE_LOG(MP3ImporterLog, Display, TEXT("Initialized: Samplerate: %u, Channels: %u"), Samplerate, Channels);
}
Beispiel #13
0
size_t write_callback(char *delivered_data, size_t size, size_t nmemb,
                      void *user_data) {
  if (!playback_pause) {
    int err;
    off_t frame_offset;
    unsigned char *audio;
    size_t done = 1;
    ao_sample_format format;
    int channels, encoding;
    long rate;

    mpg123_feed(mh, delivered_data, size * nmemb);
    while (done > 0) {
      err = mpg123_decode_frame(mh, &frame_offset, &audio, &done);
      switch (err) {
      case MPG123_NEW_FORMAT:
        mpg123_getformat(mh, &rate, &channels, &encoding);
        format.bits = mpg123_encsize(encoding) * 8;
        format.rate = rate;
        format.channels = channels;
        format.byte_format = AO_FMT_NATIVE;
        format.matrix = 0;
        device = ao_open_live(ao_default_driver_id(), &format, NULL);
        break;
      case MPG123_OK:
        ao_play(device, audio, done);
        break;
      default:
        break;
      }
    }

    return size * nmemb;
  }
  return CURL_WRITEFUNC_PAUSE;
}
Beispiel #14
0
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************/
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    int i_err;
    block_t *p_block = pp_block ? *pp_block : NULL;
    decoder_sys_t *p_sys = p_dec->p_sys;

    if( !pp_block || !p_block )
        return NULL;

    if( p_block->i_buffer == 0 )
        return NULL;

    if( !date_Get( &p_sys->end_date ) && p_block->i_pts <= VLC_TS_INVALID )
    {
        /* We've just started the stream, wait for the first PTS. */
        msg_Dbg( p_dec, "waiting for PTS" );
        goto error;
    }

    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
    {
        date_Set( &p_sys->end_date, 0 );
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
            goto error;
    }

    /* Feed mpg123 with raw data */
    i_err = mpg123_feed( p_sys->p_handle, p_block->p_buffer,
                         p_block->i_buffer );

    if( i_err != MPG123_OK )
    {
        msg_Err( p_dec, "mpg123_feed failed: %s", mpg123_plain_strerror( i_err ) );
        goto error;
    }

    /* Get details about the stream */
    i_err = mpg123_info( p_sys->p_handle, &p_sys->frame_info );

    if( i_err == MPG123_NEED_MORE )
    {
        /* Need moar data */
        goto error;
    }
    else if( i_err != MPG123_OK )
    {
        msg_Err( p_dec, "mpg123_info failed: %s", mpg123_plain_strerror( i_err ) );
        goto error;
    }

    /* Configure the output */
    p_block->i_nb_samples = mpg123_spf( p_sys->p_handle );
    p_dec->fmt_out.i_bitrate = p_sys->frame_info.bitrate * 1000;

    switch( p_sys->frame_info.mode )
    {
        case MPG123_M_STEREO:
        case MPG123_M_JOINT:
            p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
            break;
        case MPG123_M_DUAL:
            p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
                                                     | AOUT_CHAN_DUALMONO;
            break;
        case MPG123_M_MONO:
            p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_CENTER;
            break;
        default:
            msg_Err( p_dec, "Unknown mode");
            goto error;
    }

    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels & AOUT_CHAN_PHYSMASK;

    /* Date management */
    if( p_dec->fmt_out.audio.i_rate != p_sys->frame_info.rate )
    {
        p_dec->fmt_out.audio.i_rate = p_sys->frame_info.rate;
        date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
        date_Set( &p_sys->end_date, 0 );
    }

    if( p_block->i_pts > VLC_TS_INVALID &&
        p_block->i_pts != date_Get( &p_sys->end_date ) )
    {
        date_Set( &p_sys->end_date, p_block->i_pts );
    }

    /* Request a new audio buffer */
    block_t *p_out = decoder_NewAudioBuffer( p_dec, p_block->i_nb_samples );
    if( unlikely( !p_out ) )
        goto error;

    /* Configure the buffer */
    p_out->i_nb_samples = p_block->i_nb_samples;
    p_out->i_dts = p_out->i_pts = date_Get( &p_sys->end_date );
    p_out->i_length = date_Increment( &p_sys->end_date, p_block->i_nb_samples )
        - p_out->i_pts;

    /* Make mpg123 write directly into the VLC output buffer */
    i_err = mpg123_replace_buffer( p_sys->p_handle, p_out->p_buffer, p_out->i_buffer );
    if( i_err != MPG123_OK )
    {
        msg_Err( p_dec, "could not replace buffer: %s", mpg123_plain_strerror( i_err ) );
        block_Release( p_out );
        goto error;
    }

    *pp_block = NULL; /* avoid being fed the same packet again */

    /* Do the actual decoding now */
    i_err = mpg123_decode_frame( p_sys->p_handle, NULL, NULL, NULL );
    if( i_err != MPG123_OK )
    {
        if( i_err != MPG123_NEW_FORMAT )
            msg_Err( p_dec, "mpg123_decode_frame error: %s", mpg123_plain_strerror( i_err ) );
        block_Release( p_out );
        goto error;
    }

    block_Release( p_block );
    return p_out;

error:
    block_Release( p_block );
    return NULL;
}
static GstFlowReturn
gst_mpg123_audio_dec_handle_frame (GstAudioDecoder * dec,
    GstBuffer * input_buffer)
{
  GstMpg123AudioDec *mpg123_decoder;
  int decode_error;
  unsigned char *decoded_bytes;
  size_t num_decoded_bytes;
  GstFlowReturn retval;

  mpg123_decoder = GST_MPG123_AUDIO_DEC (dec);

  g_assert (mpg123_decoder->handle != NULL);

  /* The actual decoding */
  {
    /* feed input data (if there is any) */
    if (G_LIKELY (input_buffer != NULL)) {
      GstMapInfo info;

      if (gst_buffer_map (input_buffer, &info, GST_MAP_READ)) {
        mpg123_feed (mpg123_decoder->handle, info.data, info.size);
        gst_buffer_unmap (input_buffer, &info);
      } else {
        GST_ERROR_OBJECT (mpg123_decoder, "gst_memory_map() failed");
        return GST_FLOW_ERROR;
      }
    }

    /* Try to decode a frame */
    decoded_bytes = NULL;
    num_decoded_bytes = 0;
    decode_error = mpg123_decode_frame (mpg123_decoder->handle,
        &mpg123_decoder->frame_offset, &decoded_bytes, &num_decoded_bytes);
  }

  retval = GST_FLOW_OK;

  switch (decode_error) {
    case MPG123_NEW_FORMAT:
      /* As mentioned in gst_mpg123_audio_dec_set_format(), the next audioinfo
       * is not set immediately; instead, the code waits for mpg123 to take
       * note of the new format, and then sets the audioinfo. This fixes glitches
       * with mp3s containing several format headers (for example, first half
       * using 44.1kHz, second half 32 kHz) */

      GST_LOG_OBJECT (dec,
          "mpg123 reported a new format -> setting next srccaps");

      gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes,
          num_decoded_bytes);

      /* If there is a next audioinfo, use it, then set has_next_audioinfo to
       * FALSE, to make sure gst_audio_decoder_set_output_format() isn't called
       * again until set_format is called by the base class */
      if (mpg123_decoder->has_next_audioinfo) {
        if (!gst_audio_decoder_set_output_format (dec,
                &(mpg123_decoder->next_audioinfo))) {
          GST_WARNING_OBJECT (dec, "Unable to set output format");
          retval = GST_FLOW_NOT_NEGOTIATED;
        }
        mpg123_decoder->has_next_audioinfo = FALSE;
      }

      break;

    case MPG123_NEED_MORE:
    case MPG123_OK:
      retval = gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder,
          decoded_bytes, num_decoded_bytes);
      break;

    case MPG123_DONE:
      /* If this happens, then the upstream parser somehow missed the ending
       * of the bitstream */
      GST_LOG_OBJECT (dec, "mpg123 is done decoding");
      gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes,
          num_decoded_bytes);
      retval = GST_FLOW_EOS;
      break;

    default:
    {
      /* Anything else is considered an error */
      int errcode;
      switch (decode_error) {
        case MPG123_ERR:
          errcode = mpg123_errcode (mpg123_decoder->handle);
          break;
        default:
          errcode = decode_error;
      }
      switch (errcode) {
        case MPG123_BAD_OUTFORMAT:{
          GstCaps *input_caps =
              gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (dec));
          GST_ELEMENT_ERROR (dec, STREAM, FORMAT, (NULL),
              ("Output sample format could not be used when trying to decode frame. "
                  "This is typically caused when the input caps (often the sample "
                  "rate) do not match the actual format of the audio data. "
                  "Input caps: %" GST_PTR_FORMAT, input_caps)
              );
          gst_caps_unref (input_caps);
          break;
        }
        default:{
          char const *errmsg = mpg123_plain_strerror (errcode);
          GST_ERROR_OBJECT (dec, "Reported error: %s", errmsg);
        }
      }

      retval = GST_FLOW_ERROR;
    }
  }

  return retval;
}
int _tmain(int argc, TCHAR **argv)
{
	unsigned char buf[INBUFF];
	unsigned char *audio;
	FILE *in;
	mpg123_handle *m;
	int ret, state;
	size_t inc, outc;
	off_t len, num;
	size_t bytes;
	off_t inoffset;
	size_t nrates;
	const long *rates;
	size_t i;
	inc = outc = 0;
	nrates = 0;
	rates = NULL;

	if(argc < 3)
	{
		fprintf(stderr,"Please supply in and out filenames\n");
		return -1;
	}

	mpg123_init();

	m = mpg123_new(NULL, &ret);
	if(m == NULL)
	{
		fprintf(stderr,"Unable to create mpg123 handle: %s\n", mpg123_plain_strerror(ret));
		return -1;
	}

	mpg123_param(m, MPG123_VERBOSE, 4, 0);

	ret = mpg123_param(m, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0);
	if(ret != MPG123_OK)
	{
		fprintf(stderr,"Unable to set library options: %s\n", mpg123_plain_strerror(ret));
		return -1;
	}

	// Let the seek index auto-grow and contain an entry for every frame
	ret = mpg123_param(m, MPG123_INDEX_SIZE, -1, 0);
	if(ret != MPG123_OK)
	{
		fprintf(stderr,"Unable to set index size: %s\n", mpg123_plain_strerror(ret));
		return -1;
	}

	// Use float output formats only
	ret = mpg123_format_none(m);
	if(ret != MPG123_OK)
	{
		fprintf(stderr,"Unable to disable all output formats: %s\n", mpg123_plain_strerror(ret));
		return -1;
	}
	
	mpg123_rates(&rates, &nrates);
	for(i=0; i<nrates; i++)
	{
		ret = mpg123_format(m, rates[i], MPG123_MONO | MPG123_STEREO,  MPG123_ENC_FLOAT_32);
		if(ret != MPG123_OK)
		{
			fprintf(stderr,"Unable to set float output formats: %s\n", mpg123_plain_strerror(ret));
			return -1;
		}
	}

	ret = mpg123_open_feed(m);
	if(ret != MPG123_OK)
	{
		fprintf(stderr,"Unable open feed: %s\n", mpg123_plain_strerror(ret));
		return -1;
	}

	in = _tfopen(argv[1], __T("rb"));
	if(in == NULL)
	{
		_ftprintf(stderr,__T("Unable to open input file %s\n"), argv[1]);
		return -1;
	}
	
	out = _tfopen(argv[2], __T("wb"));
	if(out == NULL)
	{
		_ftprintf(stderr,__T("Unable to open output file %s\n"), argv[2]);
		return -1;
	}
	
	while(ret = mpg123_feedseek(m, 95000, SEEK_SET, &inoffset) == MPG123_NEED_MORE)
	{
		len = fread(buf, sizeof(unsigned char), INBUFF, in);
		if(len <= 0)
			break;
		inc += len;

		state = mpg123_feed(m, buf, len);
		if(state == MPG123_ERR)
		{
			fprintf(stderr, "Error: %s", mpg123_strerror(m));
			return -1; 
		}
	}
	
	fseek(in, inoffset, SEEK_SET);
	
	while(1)
	{
		len = fread(buf, sizeof(unsigned char), INBUFF, in);
		if(len <= 0)
			break;
		inc += len;
		ret = mpg123_feed(m, buf, len);

		while(ret != MPG123_ERR && ret != MPG123_NEED_MORE)
		{
			ret = mpg123_decode_frame(m, &num, &audio, &bytes);
			if(ret == MPG123_NEW_FORMAT)
			{
				mpg123_getformat(m, &rate, &channels, &enc);
				initwavformat();
				initwav();
				fprintf(stderr, "New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
			}
			fwrite(audio, sizeof(unsigned char), bytes, out);
			outc += bytes;
		}

		if(ret == MPG123_ERR)
		{
			fprintf(stderr, "Error: %s", mpg123_strerror(m));
			break; 
		}
	}

	fprintf(stderr, "Finished read %lu, decoded %lu\n", (unsigned long)inc, (unsigned long)outc);

	closewav();
	fclose(out);
	fclose(in);
	mpg123_delete(m);
	mpg123_exit();
	return 0;
}
Beispiel #17
0
size_t
in_mp3_decode(plugin_obj *obj, uint8_t *in, size_t insz, uint8_t *out, size_t *outsz)
{
        int		r;
        size_t		done;

	done = 0;
//	r = mpg123_decode((mpg123_handle *)obj->data, in, insz, out, outsz, &done);

	/* feed the decoder */
	r = mpg123_feed((mpg123_handle *)obj->data, in, insz);

	if (r != MPG123_DONE)
		abort(); 	/* LULZ TODO XXX WTF */

	/* read decoded data from internal buffer */
	r = mpg123_read((mpg123_handle *)obj->data, out, *outsz, &done);

	/* increase buffer space if we need more space */
	if (done > *outsz) {
		unsigned char	*tmp;
		int		newsz;

		newsz = done;
		tmp = malloc(newsz);
		memcpy(tmp, out, *outsz);

		r = mpg123_read((mpg123_handle *)obj->data, (tmp + *outsz), (newsz - *outsz), &done);
		assert(done == (newsz - *outsz));

		assert(out != NULL);
		free(out);
		out = tmp;

		*outsz = newsz;
	}

	if (r == MPG123_NEW_FORMAT) {
		long rate;
		int chan, enc;

		mpg123_getformat((mpg123_handle *)obj->data, &rate, &chan, &enc);

		obj->channels = chan; /* XXX */
		obj->rate = rate;

		/* TODO reinit output */
	}

#if 0
	while(ret != MPG123_ERR && ret != MPG123_NEED_MORE) {
		/* Get all decoded audio that is available now before feeding more input. */
		ret = mpg123_decode(m,NULL,0,out,OUTBUFF,&size);

	}
#endif

	if (r == MPG123_ERR)
		return 0;

        return done;
}
static GstFlowReturn
gst_mpg123_audio_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
{
  GstMpg123AudioDec *mpg123_decoder;
  int decode_error;
  unsigned char *decoded_bytes;
  size_t num_decoded_bytes;

  if (G_UNLIKELY (!buffer))
    return GST_FLOW_OK;

  mpg123_decoder = GST_MPG123_AUDIO_DEC (dec);

  if (G_UNLIKELY (mpg123_decoder->handle == NULL)) {
    GstElement *element = GST_ELEMENT (dec);
    GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
        ("mpg123 handle is NULL"));
    return GST_FLOW_ERROR;
  }

  /* The actual decoding */
  {
    unsigned char const *inmemory;
    size_t inmemsize;
    GstMemory *memory;
    GstMapInfo info;

    memory = gst_buffer_get_all_memory (buffer);
    if (memory == NULL)
      return GST_FLOW_ERROR;

    if (!gst_memory_map (memory, &info, GST_MAP_READ)) {
      gst_memory_unref (memory);
      return GST_FLOW_ERROR;
    }

    inmemory = info.data;
    inmemsize = info.size;

    mpg123_feed (mpg123_decoder->handle, inmemory, inmemsize);
    decoded_bytes = NULL;
    num_decoded_bytes = 0;
    decode_error = mpg123_decode_frame (mpg123_decoder->handle,
        &mpg123_decoder->frame_offset, &decoded_bytes, &num_decoded_bytes);

    gst_memory_unmap (memory, &info);
    gst_memory_unref (memory);
  }

  switch (decode_error) {
    case MPG123_NEW_FORMAT:
      /*
         As mentioned in gst_mpg123_audio_dec_set_format(), the next audioinfo is not set immediately;
         instead, the code waits for mpg123 to take note of the new format, and then sets the audioinfo
         This fixes glitches with mp3s containing several format headers (for example, first half using 44.1kHz, second half 32 kHz)
       */

      GST_DEBUG_OBJECT (dec,
          "mpg123 reported a new format -> setting next srccaps");

      gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes,
          num_decoded_bytes);

      /*
         If there is a next audioinfo, use it, then set has_next_audioinfo to FALSE, to make sure
         gst_audio_decoder_set_output_format() isn't called again until set_format is called by the base class
       */
      if (mpg123_decoder->has_next_audioinfo) {
        if (!gst_audio_decoder_set_output_format (dec,
                &(mpg123_decoder->next_audioinfo))) {
          GstElement *element = GST_ELEMENT (dec);
          GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
              ("Unable to set output format"));
        }
        mpg123_decoder->has_next_audioinfo = FALSE;
      }

      break;

    case MPG123_NEED_MORE:
    case MPG123_OK:
      return gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder,
          decoded_bytes, num_decoded_bytes);

      /* If this happens, then the upstream parser somehow missed the ending of the bitstream */
    case MPG123_DONE:
      GST_DEBUG_OBJECT (dec, "mpg123 is done decoding");
      gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes,
          num_decoded_bytes);
      return GST_FLOW_EOS;

      /* Anything else is considered an error */
    default:
    {
      GstElement *element = GST_ELEMENT (dec);
      GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), ("Decoding error: %s",
              mpg123_plain_strerror (decode_error)));

      return GST_FLOW_ERROR;
    }
  }

  return GST_FLOW_OK;
}
Beispiel #19
0
void* player_thread(void* _mp3_info) 
{
  log_debug("player thread started");
  
  mp3_t* mp3_info = (mp3_t* ) _mp3_info;
  long current_position_in_ms = 0;
  long previous_position_in_ms = -1; 
  long guard_position_in_ms = -1;
  el_bool playing = el_false;
  pthread_t thread_id;
  int no_count = 0;
  
  post_event(mp3_info->client_notification, AUDIO_READY, current_position_in_ms);
 
  audio_event_t *event;
  event = audio_event_fifo_dequeue(mp3_info->player_control);
  while (event->state != INTERNAL_CMD_DESTROY) {
    
    if (event->state != INTERNAL_CMD_NONE) {
      log_debug4("event = %s, %ld, %s", audio_event_name(event->state), event->position_in_ms, mp3_info->file_or_url);
    }
    
    audio_state_t event_state = event->state;
    long event_position = event->position_in_ms;
    audio_event_destroy(event);
    
    switch (event_state) {
      case INTERNAL_CMD_LOAD_FILE: {
        playing = el_false;
        
        // Stop stream, if playing
        if (!mp3_info->is_file) {
          mp3_info->continue_streaming = el_false;
          psem_wait(mp3_info->stream_ready);
        }
        
        if (mp3_info->is_open) {
          mpg123_close(mp3_info->handle);
          aodev_close(mp3_info->ao_handle);
        }
        mpg123_open(mp3_info->handle, mp3_info->file_or_url);
        mpg123_getformat(mp3_info->handle, &mp3_info->rate, &mp3_info->channels, &mp3_info->encoding);
        mp3_info->buffer_size = mpg123_outblock(mp3_info->handle);
        mc_free(mp3_info->buffer);
        mp3_info->buffer = mc_malloc(mp3_info->buffer_size * sizeof(char) );
        int bytes_per_sample = get_encsize(mp3_info->encoding);
        aodev_set_format(mp3_info->ao_handle, bytes_per_sample * 8, mp3_info->rate, mp3_info->channels);
        aodev_open(mp3_info->ao_handle);
        mp3_info->is_open = el_true;
        mp3_info->is_file = el_true;
        mp3_info->can_seek = el_true;
        current_position_in_ms = 0;
        guard_position_in_ms = -1; 
        {
          off_t l = mpg123_length(mp3_info->handle);
          if (l == MPG123_ERR) {
            mp3_info->length = -1; 
          } else {
            mp3_info->length = (l * 1000) / mp3_info->rate;
          }
          psem_post(mp3_info->length_set);
        }
      }
      break;
      case INTERNAL_CMD_LOAD_URL: {
        playing = el_false;
        log_debug2("loading url %s", mp3_info->file_or_url);
        // Wait for feeding streams to end
        if (!mp3_info->is_file) {
          mp3_info->continue_streaming = el_false;
          psem_wait(mp3_info->stream_ready);
        }
        mp3_info->is_file = el_false;
        log_debug("current stream ended");
        
        if (mp3_info->is_open) {
          mpg123_close(mp3_info->handle);
          aodev_close(mp3_info->ao_handle);
          mp3_info->is_open = el_false;
        }
        log_debug("aodev closed");
        
        mpg123_open_feed(mp3_info->handle);
        log_debug("feed opened");
        
        pthread_create(&thread_id, NULL, stream_thread, mp3_info);
        log_debug("stream thread started");
        
        mp3_info->is_open = el_true;
        mp3_info->can_seek = el_false;
        current_position_in_ms = 0;
        guard_position_in_ms = -1;
        mp3_info->length = 0;
        mp3_info->continue_streaming = el_true;
        
        psem_post(mp3_info->length_set);
      }
      break;
      case INTERNAL_CMD_SEEK: {
        off_t pos = mpg123_timeframe(mp3_info->handle, (event_position / 1000.0));
        mpg123_seek_frame(mp3_info->handle, pos, SEEK_SET);
      }
      break;
      case INTERNAL_CMD_PLAY: {
        playing = el_true;
      }
      break;
      case INTERNAL_CMD_PAUSE: {
        playing = el_false;
      }
      break;
      case INTERNAL_CMD_GUARD: {
        guard_position_in_ms = event_position;
      }
      break;
      case INTERNAL_CMD_SET_VOLUME: {
        double volume = ((double) event_position) / 1000.0;
        mpg123_volume(mp3_info->handle, volume);
      }
      case INTERNAL_CMD_NONE:
      break;
      default:
      break;
    }
    
    //log_debug3("guard = %d, playing = %d", guard_position_in_ms, playing);
    if (guard_position_in_ms >= 0 && current_position_in_ms >= guard_position_in_ms) {

      guard_position_in_ms = -1;
      post_event(mp3_info->client_notification, AUDIO_GUARD_REACHED, current_position_in_ms);
      
    } else if (playing) {

      if (mp3_info->is_file) {  
        size_t bytes;
        int res = mpg123_read(mp3_info->handle, mp3_info->buffer, mp3_info->buffer_size, &bytes);
        if (res == MPG123_OK) {
          aodev_play_buffer(mp3_info->ao_handle, mp3_info->buffer, bytes);
          off_t frame = mpg123_tellframe(mp3_info->handle);
          double time_per_frame = (mpg123_tpf(mp3_info->handle)*1000.0);
          //static int prt = 1;
          //if (prt) { printf("tpf=%.6lf\n",time_per_frame);prt=0; }
          current_position_in_ms = (long) (frame * time_per_frame);    // 1 frame is about 26 milliseconds
          if (previous_position_in_ms == -1) previous_position_in_ms = current_position_in_ms;
          if ((current_position_in_ms - previous_position_in_ms) >= STATE_REPORT_THRESHOLD) {
            post_event(mp3_info->client_notification, AUDIO_PLAYING, current_position_in_ms);
          }
          previous_position_in_ms = current_position_in_ms;
        } else if (res == MPG123_DONE) {
          post_event(mp3_info->client_notification, AUDIO_EOS, current_position_in_ms);
          playing = el_false;
        } else {
          post_event(mp3_info->client_notification, AUDIO_STATE_ERROR, current_position_in_ms);
          playing = el_false;
        }
      } else { // Stream playing
        
        if (mp3_stream_fifo_peek(mp3_info->stream_fifo) != NULL) {
          el_bool go_on = el_true; 
          while (go_on && mp3_stream_fifo_peek(mp3_info->stream_fifo) != NULL) {
            memblock_t* blk = mp3_stream_fifo_dequeue(mp3_info->stream_fifo);
            
            mpg123_feed(mp3_info->handle, (const unsigned char*) memblock_as_str(blk), memblock_size(blk));
            memblock_destroy(blk);
            
            size_t done;
            int err;
            unsigned char *audio;
            off_t frame_offset;
            
            do {
              err = mpg123_decode_frame(mp3_info->handle, &frame_offset, &audio, &done);
              switch(err) {
                case MPG123_NEW_FORMAT:
                  mpg123_getformat(mp3_info->handle, &mp3_info->rate, &mp3_info->channels, &mp3_info->encoding);
                  if (aodev_is_open(mp3_info->ao_handle)) {
                    aodev_close(mp3_info->ao_handle);
                  }
                  aodev_set_format(mp3_info->ao_handle, get_encsize(mp3_info->encoding) * 8, mp3_info->rate, mp3_info->channels);
                  aodev_open(mp3_info->ao_handle);
                break;
                case MPG123_OK:
                  //log_debug2("playing buffer %d", done);
                  aodev_play_buffer(mp3_info->ao_handle, audio, done);
                  off_t frame = mpg123_tellframe(mp3_info->handle);
                  double time_per_frame = (mpg123_tpf(mp3_info->handle)*1000.0);
                  current_position_in_ms = (long) (frame * time_per_frame);    // 1 frame is about 26 milliseconds
                  if (previous_position_in_ms == -1) previous_position_in_ms = current_position_in_ms;
                  if ((current_position_in_ms - previous_position_in_ms) >= STATE_REPORT_THRESHOLD) {
                    post_event(mp3_info->client_notification, AUDIO_PLAYING, current_position_in_ms);
                  }
                  previous_position_in_ms = current_position_in_ms;
                  go_on = el_false;
                  break;
                case MPG123_NEED_MORE:
                  break;
                default:
                  break;
              }
            } while (done > 0);
          }
        } else {
          // no streaming data, prevent race conditions
          // sleep for a small time (50 ms);
          no_count += 1;
          if (no_count > 10) { 
            post_event(mp3_info->client_notification, AUDIO_BUFFERING, current_position_in_ms);
          }
          sleep_ms(50);
        }
      } 
    }
    
    if (playing) {
      if (audio_event_fifo_peek(mp3_info->player_control) != NULL) {
        event = audio_event_fifo_dequeue(mp3_info->player_control);
      } else {
        event = (audio_event_t*) mc_malloc(sizeof(audio_event_t));
        event->state = INTERNAL_CMD_NONE;
        event->position_in_ms = -1;
      }
    } else {
      //log_debug("waiting for next event");
      event = audio_event_fifo_dequeue(mp3_info->player_control);
    }
  }

  // destroy event received
  log_debug("destroy event received");
  
  // Kill playing streams
  if (mp3_info->streaming) {
    mp3_info->continue_streaming = el_false;
    psem_wait(mp3_info->stream_ready);
  }
  
  audio_event_destroy(event);

  // exit thread  
  return NULL;
}
Beispiel #20
0
/* This tries to extract a requested amount of decoded data.
 * Even when you request 0 bytes, it will feed enough input so that
 * the decoder _could_ have delivered something.
 * Returns byte count >= 0, -1 on error.
 *
 * Thoughts on exact pts keeping:
 * We have to assume that MPEG frames are cut in pieces by packet boundaries.
 * Also, it might be possible that the first packet does not contain enough
 * data to ensure initial stream sync... or re-sync on erroneous streams.
 * So we need something robust to relate the decoded byte count to the correct
 * time stamp. This is tricky, though. From the outside, you cannot tell if,
 * after having fed two packets until the first output arrives, one should
 * start counting from the first packet's pts or the second packet's.
 * So, let's just count from the last fed package's pts. If the packets are
 * exactly cut to MPEG frames, this will cause one frame mismatch in the
 * beginning (when mpg123 peeks ahead for the following header), but will
 * be corrected with the third frame already. One might add special code to
 * not increment the base pts past the first packet's after a resync before
 * the first decoded bytes arrived. */
static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count)
{
    int ret = MPG123_OK;
    int got = 0;
    struct ad_mpg123_context *con = sh->context;

    /* There will be one MPG123_NEW_FORMAT message on first open.
     * This will be handled in init(). */
    do {
        size_t got_now = 0;

        /* Feed the decoder. This will only fire from the second round on. */
        if (ret == MPG123_NEED_MORE) {
            int incount;
            double pts;
            unsigned char *inbuf;
            /* Feed more input data. */
            incount = ds_get_packet_pts(sh->ds, &inbuf, &pts);
            if (incount <= 0)
                break;          /* Apparently that's it. EOF. */

            /* Next bytes from that presentation time. */
            if (pts != MP_NOPTS_VALUE) {
                sh->pts       = pts;
                sh->pts_bytes = 0;
            }

#ifdef AD_MPG123_FRAMEWISE
            /* Have to use mpg123_feed() to avoid decoding here. */
            ret = mpg123_feed(con->handle, inbuf, incount);
#else
            /* Do not use mpg123_feed(), added in later libmpg123 versions. */
            ret = mpg123_decode(con->handle, inbuf, incount, NULL, 0, NULL);
#endif
            if (ret == MPG123_ERR)
                break;
        }
        /* Theoretically, mpg123 could return MPG123_DONE, so be prepared.
         * Should not happen in our usage, but it is a valid return code. */
        else if (ret == MPG123_ERR || ret == MPG123_DONE)
            break;

        /* Try to decode a bit. This is the return value that counts
         * for the loop condition. */
#ifdef AD_MPG123_FRAMEWISE
        if (!buf) { /* fake call just for feeding to get format */
            ret = mpg123_getformat(con->handle, NULL, NULL, NULL);
        } else { /* This is the decoding. One frame at a time. */
            ret = mpg123_replace_buffer(con->handle, buf, count);
            if (ret == MPG123_OK)
                ret = mpg123_decode_frame(con->handle, NULL, NULL, &got_now);
        }
#else
        ret = mpg123_decode(con->handle, NULL, 0, buf + got, count - got,
                            &got_now);
#endif

        got += got_now;
        sh->pts_bytes += got_now;

#ifdef AD_MPG123_FRAMEWISE
    } while (ret == MPG123_NEED_MORE || (got == 0 && count != 0));
#else
    } while (ret == MPG123_NEED_MORE || got < count);
Beispiel #21
0
int _tmain(int argc, _TCHAR* argv[])
{
    mpg123_handle *m;
    int i;
    if (argc < 3)
    {
        fprintf(stderr, "\nI will give you the estimated and exact sample lengths of MPEG audio files.\n");
        fprintf(stderr, "\nUsage: %s <mpeg audio file list>\n\n", argv[0]);
        return -1;
    }
    mpg123_init();
    m = mpg123_new(NULL, NULL);
    mpg123_param(m, MPG123_RESYNC_LIMIT, -1, 0); /* New in library version 0.0.1 . */

    off_t a, b;
    if (MPG123_OK != mpg123_open_feed(m)) {
        fprintf(stderr, "open feed failed");
        return -1;
    }

    FILE* file = _tfopen(argv[1], TEXT("rb"));
    if (!file) {
        fprintf(stderr, "open file failed");
        return -1;
    }

    _stat64i32 st = { 0 };
    _tstat(argv[1], &st);
    if (st.st_size <= 0) {
        fprintf(stderr, "file size is zero");
        return -1;
    }
    char* pDataBuf = new char[st.st_size];
    memset(pDataBuf, 0, st.st_size);
    if (st.st_size != fread(pDataBuf, 1, st.st_size, file)) {
        fprintf(stderr, "read file error");
        return -1;
    }
    if (MPG123_OK != mpg123_feed(m, (const unsigned char*)pDataBuf, st.st_size)) {
        fprintf(stderr, "feed failed");
        return -1;
    }

    // channels;
    bool bSaved = false;
    size_t nDone = 0;
    int res = mpg123_decode(m, NULL, 0, NULL, 0, &nDone);
    if (res == MPG123_NEW_FORMAT) {
        long rate = 0;
        int channels = 0;
        int enc = 0;
        mpg123_getformat(m, &rate, &channels, &enc);

        if (MPG123_ENC_SIGNED_16 == enc) {
            int nSamples = mpg123_length(m);
            int nBufCount = nSamples * channels;
            int nBufSize = nBufCount * sizeof(short);
            short* pBuf = new short[nBufCount];

            res = mpg123_decode(m, NULL, 0, (unsigned char*)pBuf, nBufSize, &nDone);
            if (res == MPG123_OK) {
                KWavFile file;
                file.Init(pBuf, nDone, rate, "");
                file.Save(CT2A(argv[2]));
                bSaved = true;
            }
            if (pBuf) {
                delete[] pBuf;
                pBuf = NULL;
            }
        }
    }


    mpg123_tclose(m);
    mpg123_delete(m);
    mpg123_exit();
    return 0;
}
Beispiel #22
0
static size_t stream_callback(void *ptr, size_t size, size_t nmemb, void *data)
{
	register unsigned int realsize = (unsigned int) (size * nmemb);
	shout_context_t *context = data;
	int decode_status = 0;
	size_t usedlen;
	uint32_t used, buf_size = 1024 * 128;	/* do not make this 64 or less, stutter will ensue after 
											   first 64k buffer is dry */

	if (context->prebuf) {
		buf_size = context->prebuf;
	}

	/* make sure we aren't over zealous by slowing down the stream when the buffer is too full */
	while (!context->err) {
		switch_mutex_lock(context->audio_mutex);
		used = switch_buffer_inuse(context->audio_buffer);
		switch_mutex_unlock(context->audio_mutex);

		if (used < buf_size) {
			/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Buffered %u/%u!\n", used, buf_size); */
			break;
		}

		switch_yield(500000);
	}

	if (mpg123_feed(context->mh, ptr, realsize) != MPG123_OK) {
		goto error;
	}

	do {
		usedlen = 0;

		decode_status = mpg123_read(context->mh, context->decode_buf, sizeof(context->decode_buf), &usedlen);

		if (decode_status == MPG123_NEW_FORMAT) {
			continue;
		} else if (decode_status == MPG123_OK || decode_status == MPG123_NEED_MORE) {
			;
		} else if (decode_status == MPG123_DONE) {
			context->eof++;
		} else if (decode_status == MPG123_ERR || decode_status > 0) {
			if (++context->mp3err >= 5) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decoder Error! %s\n", context->stream_url);
				context->eof++;
				goto error;
			}
			continue;
		}

		context->mp3err = 0;

		switch_mutex_lock(context->audio_mutex);
		switch_buffer_write(context->audio_buffer, context->decode_buf, usedlen);
		switch_mutex_unlock(context->audio_mutex);
	} while (!context->err && !context->eof && decode_status != MPG123_NEED_MORE);

	if (context->err) {
		goto error;
	}

	return realsize;

  error:
	switch_mutex_lock(context->audio_mutex);
	context->err++;
	switch_mutex_unlock(context->audio_mutex);
	return 0;
}
Beispiel #23
0
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************/
static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
{
    int i_err;
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_out = NULL;

    if( !p_sys->b_opened )
    {
        if( p_block )
            block_Release( p_block );
        return VLCDEC_ECRITICAL;
    }

    /* Feed input block */
    if( p_block != NULL )
    {
        if( !date_Get( &p_sys->end_date ) && p_block->i_pts <= VLC_TS_INVALID )
        {
            /* We've just started the stream, wait for the first PTS. */
            msg_Dbg( p_dec, "waiting for PTS" );
            goto end;
        }

        if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
        {
            Flush( p_dec );
            if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
                goto end;
        }

        /* Feed mpg123 with raw data */
        i_err = mpg123_feed( p_sys->p_handle, p_block->p_buffer,
                             p_block->i_buffer );

        if( i_err != MPG123_OK )
        {
            msg_Err( p_dec, "mpg123_feed failed: %s",
                     mpg123_plain_strerror( i_err ) );
            goto end;
        }
    }

    /* Fetch a new output block (if possible) */
    if( !p_sys->p_out
     || p_sys->p_out->i_buffer != mpg123_outblock( p_sys->p_handle ) )
    {
        if( p_sys->p_out )
            block_Release( p_sys->p_out );

        /* Keep the output buffer for next calls in case it's not used (in case
         * of MPG123_NEED_MORE status) */
        p_sys->p_out = block_Alloc( mpg123_outblock( p_sys->p_handle ) );

        if( unlikely( !p_sys->p_out ) )
            return VLCDEC_SUCCESS;
    }

    /* Do the actual decoding now */
    size_t i_bytes = 0;
    while( true )
    {
        /* Make mpg123 write directly into the VLC output buffer */
        i_err = mpg123_replace_buffer( p_sys->p_handle, p_sys->p_out->p_buffer,
                                       p_sys->p_out->i_buffer );
        if( i_err != MPG123_OK )
        {
            msg_Err( p_dec, "could not replace buffer: %s",
                     mpg123_plain_strerror( i_err ) );
            block_Release( p_sys->p_out );
            p_sys->p_out = NULL;
            return VLCDEC_SUCCESS;
        }

        i_err = mpg123_decode_frame( p_sys->p_handle, NULL, NULL, &i_bytes );
        if( i_err != MPG123_OK )
        {
            if( i_err == MPG123_NEW_FORMAT )
            {
                if( UpdateAudioFormat( p_dec ) != VLC_SUCCESS )
                    goto end;
                else
                    continue;
            }
            else if( i_err != MPG123_NEED_MORE )
                msg_Err( p_dec, "mpg123_decode_frame error: %s",
                         mpg123_plain_strerror( i_err ) );
        }
        else if( p_dec->fmt_out.audio.i_rate == 0 )
        {
            msg_Warn( p_dec, "mpg123_decode_frame returned valid frame without "
                             "updating the format" );
            if( UpdateAudioFormat( p_dec ) != VLC_SUCCESS )
                goto end;
        }
        break;
    }

    if( p_block && p_block->i_pts > VLC_TS_INVALID &&
        p_block->i_pts != date_Get( &p_sys->end_date ) )
        date_Set( &p_sys->end_date, p_block->i_pts );

    if( i_bytes == 0 )
        goto end;

    assert( p_dec->fmt_out.audio.i_rate != 0 );

    p_out = p_sys->p_out;
    p_sys->p_out = NULL;

    assert( p_out->i_buffer >= i_bytes );
    p_out->i_buffer = i_bytes;
    p_out->i_nb_samples = p_out->i_buffer * p_dec->fmt_out.audio.i_frame_length
                        / p_dec->fmt_out.audio.i_bytes_per_frame;

    /* Configure the buffer */
    p_out->i_dts = p_out->i_pts = date_Get( &p_sys->end_date );
    p_out->i_length = date_Increment( &p_sys->end_date, p_out->i_nb_samples )
        - p_out->i_pts;
end:
    if( p_block )
        block_Release( p_block );
    if( p_out != NULL )
        decoder_QueueAudio( p_dec, p_out );
    return VLCDEC_SUCCESS;
}