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;
}
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;
}