mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
avauddec: Negotiate based on the AVFrame instead of just the AVCodecContext
This commit is contained in:
parent
523ddb5346
commit
0767bdda5f
1 changed files with 41 additions and 22 deletions
|
@ -27,6 +27,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ static GstFlowReturn gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder,
|
||||||
GstBuffer * inbuf);
|
GstBuffer * inbuf);
|
||||||
|
|
||||||
static gboolean gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec,
|
static gboolean gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec,
|
||||||
gboolean force);
|
AVCodecContext * context, AVFrame * frame, gboolean force);
|
||||||
|
|
||||||
static void gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec);
|
static void gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec);
|
||||||
|
|
||||||
|
@ -273,12 +274,17 @@ gst_ffmpegauddec_get_buffer (AVCodecContext * context, AVFrame * frame)
|
||||||
BufferInfo *buffer_info;
|
BufferInfo *buffer_info;
|
||||||
|
|
||||||
ffmpegdec = (GstFFMpegAudDec *) context->opaque;
|
ffmpegdec = (GstFFMpegAudDec *) context->opaque;
|
||||||
if (G_UNLIKELY (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE)))
|
|
||||||
|
if (ffmpegdec->info.finfo && settings_changed (ffmpegdec, context, frame))
|
||||||
|
goto fallback;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_ffmpegauddec_negotiate (ffmpegdec, context, frame,
|
||||||
|
FALSE)))
|
||||||
goto negotiate_failed;
|
goto negotiate_failed;
|
||||||
|
|
||||||
/* Always use the default allocator for planar audio formats because
|
/* Always use the default allocator for planar audio formats because
|
||||||
* we will have to copy and deinterleave later anyway */
|
* we will have to copy and deinterleave later anyway */
|
||||||
if (av_sample_fmt_is_planar (ffmpegdec->context->sample_fmt))
|
if (av_sample_fmt_is_planar (frame->format))
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
info = gst_audio_decoder_get_audio_info (GST_AUDIO_DECODER (ffmpegdec));
|
info = gst_audio_decoder_get_audio_info (GST_AUDIO_DECODER (ffmpegdec));
|
||||||
|
@ -372,45 +378,57 @@ open_failed:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, gboolean force)
|
settings_changed (GstFFMpegAudDec * ffmpegdec, AVFrame * frame)
|
||||||
|
{
|
||||||
|
GstAudioFormat format;
|
||||||
|
gint channels = av_get_channel_layout_nb_channels (frame->channel_layout);
|
||||||
|
|
||||||
|
format = gst_ffmpeg_smpfmt_to_audioformat (frame->format);
|
||||||
|
if (format == GST_AUDIO_FORMAT_UNKNOWN)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return !(ffmpegdec->info.rate ==
|
||||||
|
frame->sample_rate &&
|
||||||
|
ffmpegdec->info.channels == channels &&
|
||||||
|
ffmpegdec->info.finfo->format == format);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec,
|
||||||
|
AVCodecContext * context, AVFrame * frame, gboolean force)
|
||||||
{
|
{
|
||||||
GstFFMpegAudDecClass *oclass;
|
GstFFMpegAudDecClass *oclass;
|
||||||
gint depth;
|
|
||||||
GstAudioFormat format;
|
GstAudioFormat format;
|
||||||
|
gint channels;
|
||||||
GstAudioChannelPosition pos[64] = { 0, };
|
GstAudioChannelPosition pos[64] = { 0, };
|
||||||
|
|
||||||
oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
||||||
|
|
||||||
depth = av_smp_format_depth (ffmpegdec->context->sample_fmt) * 8;
|
format = gst_ffmpeg_smpfmt_to_audioformat (frame->format);
|
||||||
format = gst_ffmpeg_smpfmt_to_audioformat (ffmpegdec->context->sample_fmt);
|
|
||||||
if (format == GST_AUDIO_FORMAT_UNKNOWN)
|
if (format == GST_AUDIO_FORMAT_UNKNOWN)
|
||||||
goto no_caps;
|
goto no_caps;
|
||||||
|
channels = av_get_channel_layout_nb_channels (frame->channel_layout);
|
||||||
|
if (channels == 0)
|
||||||
|
goto no_caps;
|
||||||
|
|
||||||
if (!force && ffmpegdec->info.rate ==
|
if (!force && !settings_changed (ffmpegdec, frame))
|
||||||
ffmpegdec->context->sample_rate &&
|
|
||||||
ffmpegdec->info.channels == ffmpegdec->context->channels &&
|
|
||||||
ffmpegdec->info.finfo->depth == depth)
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec,
|
GST_DEBUG_OBJECT (ffmpegdec,
|
||||||
"Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)",
|
"Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)",
|
||||||
ffmpegdec->info.rate, ffmpegdec->info.channels,
|
ffmpegdec->info.rate, ffmpegdec->info.channels,
|
||||||
ffmpegdec->info.finfo->depth,
|
ffmpegdec->info.finfo->format, frame->sample_rate, channels, format);
|
||||||
ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth);
|
|
||||||
|
|
||||||
gst_ffmpeg_channel_layout_to_gst (ffmpegdec->context->channel_layout,
|
gst_ffmpeg_channel_layout_to_gst (frame->channel_layout, channels, pos);
|
||||||
ffmpegdec->context->channels, pos);
|
|
||||||
memcpy (ffmpegdec->ffmpeg_layout, pos,
|
memcpy (ffmpegdec->ffmpeg_layout, pos,
|
||||||
sizeof (GstAudioChannelPosition) * ffmpegdec->context->channels);
|
sizeof (GstAudioChannelPosition) * channels);
|
||||||
|
|
||||||
/* Get GStreamer channel layout */
|
/* Get GStreamer channel layout */
|
||||||
gst_audio_channel_positions_to_valid_order (pos,
|
gst_audio_channel_positions_to_valid_order (pos, channels);
|
||||||
ffmpegdec->context->channels);
|
|
||||||
ffmpegdec->needs_reorder =
|
ffmpegdec->needs_reorder =
|
||||||
memcmp (pos, ffmpegdec->ffmpeg_layout,
|
memcmp (pos, ffmpegdec->ffmpeg_layout, sizeof (pos[0]) * channels) != 0;
|
||||||
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);
|
frame->sample_rate, channels, pos);
|
||||||
|
|
||||||
if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (ffmpegdec),
|
if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (ffmpegdec),
|
||||||
&ffmpegdec->info))
|
&ffmpegdec->info))
|
||||||
|
@ -482,7 +500,8 @@ gst_ffmpegauddec_audio_frame (GstFFMpegAudDec * ffmpegdec,
|
||||||
gint nsamples, channels, byte_per_sample;
|
gint nsamples, channels, byte_per_sample;
|
||||||
gsize output_size;
|
gsize output_size;
|
||||||
|
|
||||||
if (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE)) {
|
if (!gst_ffmpegauddec_negotiate (ffmpegdec, ffmpegdec->context, &frame,
|
||||||
|
FALSE)) {
|
||||||
*outbuf = NULL;
|
*outbuf = NULL;
|
||||||
*ret = GST_FLOW_NOT_NEGOTIATED;
|
*ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
len = -1;
|
len = -1;
|
||||||
|
|
Loading…
Reference in a new issue