mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-22 14:06:23 +00:00
avauddec: Port to non-deprecated avcodec_decode_audio4() API
Fixes bug #666435.
This commit is contained in:
parent
f4acd40767
commit
9456fb86c7
2 changed files with 90 additions and 19 deletions
|
@ -221,6 +221,69 @@ could_not_open:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
|
GstMapInfo map;
|
||||||
|
} BufferInfo;
|
||||||
|
|
||||||
|
/* called when ffmpeg wants us to allocate a buffer to write the decoded frame
|
||||||
|
* into. We try to give it memory from our pool */
|
||||||
|
static int
|
||||||
|
gst_ffmpegauddec_get_buffer (AVCodecContext * context, AVFrame * frame)
|
||||||
|
{
|
||||||
|
GstFFMpegAudDec *ffmpegdec;
|
||||||
|
GstAudioInfo *info;
|
||||||
|
BufferInfo *buffer_info = g_slice_new (BufferInfo);
|
||||||
|
|
||||||
|
ffmpegdec = (GstFFMpegAudDec *) context->opaque;
|
||||||
|
if (G_UNLIKELY (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE)))
|
||||||
|
goto negotiate_failed;
|
||||||
|
|
||||||
|
info = gst_audio_decoder_get_audio_info (GST_AUDIO_DECODER (ffmpegdec));
|
||||||
|
|
||||||
|
buffer_info->buffer =
|
||||||
|
gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (ffmpegdec),
|
||||||
|
frame->nb_samples * info->bpf);
|
||||||
|
gst_buffer_map (buffer_info->buffer, &buffer_info->map, GST_MAP_WRITE);
|
||||||
|
frame->opaque = buffer_info;
|
||||||
|
frame->data[0] = buffer_info->map.data;
|
||||||
|
frame->linesize[0] = buffer_info->map.size;
|
||||||
|
frame->type = FF_BUFFER_TYPE_USER;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
/* fallbacks */
|
||||||
|
negotiate_failed:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (ffmpegdec, "negotiate failed");
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
fallback:
|
||||||
|
{
|
||||||
|
return avcodec_default_get_buffer (context, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_ffmpegauddec_release_buffer (AVCodecContext * context, AVFrame * frame)
|
||||||
|
{
|
||||||
|
GstFFMpegAudDec *ffmpegdec;
|
||||||
|
BufferInfo *buffer_info;
|
||||||
|
|
||||||
|
ffmpegdec = (GstFFMpegAudDec *) context->opaque;
|
||||||
|
buffer_info = frame->opaque;
|
||||||
|
/* check if it was our buffer */
|
||||||
|
if (frame->type != FF_BUFFER_TYPE_USER) {
|
||||||
|
GST_DEBUG_OBJECT (ffmpegdec, "default release buffer");
|
||||||
|
avcodec_default_release_buffer (context, frame);
|
||||||
|
} else if (buffer_info) {
|
||||||
|
gst_buffer_unmap (buffer_info->buffer, &buffer_info->map);
|
||||||
|
gst_buffer_unref (buffer_info->buffer);
|
||||||
|
g_slice_free (BufferInfo, buffer_info);
|
||||||
|
}
|
||||||
|
frame->opaque = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ffmpegauddec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
|
gst_ffmpegauddec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -261,6 +324,11 @@ gst_ffmpegauddec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
|
||||||
ffmpegdec->context->workaround_bugs |= FF_BUG_AUTODETECT;
|
ffmpegdec->context->workaround_bugs |= FF_BUG_AUTODETECT;
|
||||||
ffmpegdec->context->error_recognition = 1;
|
ffmpegdec->context->error_recognition = 1;
|
||||||
|
|
||||||
|
ffmpegdec->context->opaque = ffmpegdec;
|
||||||
|
ffmpegdec->context->get_buffer = gst_ffmpegauddec_get_buffer;
|
||||||
|
ffmpegdec->context->reget_buffer = NULL;
|
||||||
|
ffmpegdec->context->release_buffer = gst_ffmpegauddec_release_buffer;
|
||||||
|
|
||||||
/* open codec - we don't select an output pix_fmt yet,
|
/* open codec - we don't select an output pix_fmt yet,
|
||||||
* simply because we don't know! We only get it
|
* simply because we don't know! We only get it
|
||||||
* during playback... */
|
* during playback... */
|
||||||
|
@ -315,6 +383,9 @@ gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, gboolean force)
|
||||||
/* Get GStreamer channel layout */
|
/* Get GStreamer channel layout */
|
||||||
gst_audio_channel_positions_to_valid_order (pos,
|
gst_audio_channel_positions_to_valid_order (pos,
|
||||||
ffmpegdec->context->channels);
|
ffmpegdec->context->channels);
|
||||||
|
ffmpegdec->needs_reorder =
|
||||||
|
memcmp (pos, ffmpegdec->ffmpeg_layout,
|
||||||
|
sizeof (pos[0]) * ffmpegdec->context->channels) != 0;
|
||||||
gst_audio_info_set_format (&ffmpegdec->info, format,
|
gst_audio_info_set_format (&ffmpegdec->info, format,
|
||||||
ffmpegdec->context->sample_rate, ffmpegdec->context->channels, pos);
|
ffmpegdec->context->sample_rate, ffmpegdec->context->channels, pos);
|
||||||
|
|
||||||
|
@ -370,31 +441,30 @@ gst_ffmpegauddec_audio_frame (GstFFMpegAudDec * ffmpegdec,
|
||||||
{
|
{
|
||||||
gint len = -1;
|
gint len = -1;
|
||||||
gint have_data = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
gint have_data = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||||
GstMapInfo map;
|
|
||||||
int16_t *odata;
|
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
|
AVFrame frame;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "size: %d", size);
|
GST_DEBUG_OBJECT (ffmpegdec, "size: %d", size);
|
||||||
|
|
||||||
*outbuf =
|
|
||||||
gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (ffmpegdec),
|
|
||||||
AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
|
||||||
|
|
||||||
gst_buffer_map (*outbuf, &map, GST_MAP_WRITE);
|
|
||||||
odata = (int16_t *) map.data;
|
|
||||||
|
|
||||||
gst_avpacket_init (&packet, data, size);
|
gst_avpacket_init (&packet, data, size);
|
||||||
len = avcodec_decode_audio3 (ffmpegdec->context, odata, &have_data, &packet);
|
memset (&frame, 0, sizeof (frame));
|
||||||
|
len = avcodec_decode_audio4 (ffmpegdec->context, &frame, &have_data, &packet);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec,
|
GST_DEBUG_OBJECT (ffmpegdec,
|
||||||
"Decode audio: len=%d, have_data=%d", len, have_data);
|
"Decode audio: len=%d, have_data=%d", len, have_data);
|
||||||
|
|
||||||
if (len >= 0 && have_data > 0) {
|
if (len >= 0 && have_data > 0) {
|
||||||
/* Buffer size */
|
BufferInfo *buffer_info = frame.opaque;
|
||||||
gst_buffer_unmap (*outbuf, &map);
|
|
||||||
gst_buffer_resize (*outbuf, 0, have_data);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "Creating output buffer");
|
GST_DEBUG_OBJECT (ffmpegdec, "Creating output buffer");
|
||||||
|
if (buffer_info) {
|
||||||
|
*outbuf = gst_buffer_ref (buffer_info->buffer);
|
||||||
|
} else {
|
||||||
|
*outbuf = gst_buffer_new_and_alloc (frame.linesize[0]);
|
||||||
|
gst_buffer_fill (*outbuf, 0, frame.data[0], frame.linesize[0]);
|
||||||
|
}
|
||||||
|
ffmpegdec->context->release_buffer (ffmpegdec->context, &frame);
|
||||||
|
|
||||||
if (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE)) {
|
if (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE)) {
|
||||||
gst_buffer_unref (*outbuf);
|
gst_buffer_unref (*outbuf);
|
||||||
*outbuf = NULL;
|
*outbuf = NULL;
|
||||||
|
@ -405,13 +475,13 @@ gst_ffmpegauddec_audio_frame (GstFFMpegAudDec * ffmpegdec,
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "Buffer created. Size: %d", have_data);
|
GST_DEBUG_OBJECT (ffmpegdec, "Buffer created. Size: %d", have_data);
|
||||||
|
|
||||||
/* Reorder channels to the GStreamer channel order */
|
/* Reorder channels to the GStreamer channel order */
|
||||||
/* Only the width really matters here... and it's stored as depth */
|
if (ffmpegdec->needs_reorder) {
|
||||||
|
*outbuf = gst_buffer_make_writable (*outbuf);
|
||||||
gst_audio_buffer_reorder_channels (*outbuf, ffmpegdec->info.finfo->format,
|
gst_audio_buffer_reorder_channels (*outbuf, ffmpegdec->info.finfo->format,
|
||||||
ffmpegdec->info.channels, ffmpegdec->ffmpeg_layout,
|
ffmpegdec->info.channels, ffmpegdec->ffmpeg_layout,
|
||||||
ffmpegdec->info.position);
|
ffmpegdec->info.position);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
gst_buffer_unmap (*outbuf, &map);
|
|
||||||
gst_buffer_unref (*outbuf);
|
|
||||||
*outbuf = NULL;
|
*outbuf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ struct _GstFFMpegAudDec
|
||||||
/* current output format */
|
/* current output format */
|
||||||
GstAudioInfo info;
|
GstAudioInfo info;
|
||||||
GstAudioChannelPosition ffmpeg_layout[64];
|
GstAudioChannelPosition ffmpeg_layout[64];
|
||||||
|
gboolean needs_reorder;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _GstFFMpegAudDecClass GstFFMpegAudDecClass;
|
typedef struct _GstFFMpegAudDecClass GstFFMpegAudDecClass;
|
||||||
|
|
Loading…
Reference in a new issue