From cab519f37045ec405d4b6539d232dfaea13def80 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 5 Dec 2012 19:28:33 +0100 Subject: [PATCH] avaudenc: Add support for planar audio formats --- ext/libav/gstavaudenc.c | 80 ++++++++++++++++++++++++++++++++++++-- ext/libav/gstavcodecmap.c | 98 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 169 insertions(+), 9 deletions(-) diff --git a/ext/libav/gstavaudenc.c b/ext/libav/gstavaudenc.c index 6996da7..d3f58cc 100644 --- a/ext/libav/gstavaudenc.c +++ b/ext/libav/gstavaudenc.c @@ -367,6 +367,7 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc, GstAudioInfo *info; AVPacket pkt; AVFrame frame; + gboolean planar; enc = GST_AUDIO_ENCODER (ffmpegaudenc); @@ -378,11 +379,84 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc, memset (&frame, 0, sizeof (frame)); info = gst_audio_encoder_get_audio_info (enc); - frame.data[0] = audio_in; - frame.linesize[0] = in_size; - frame.nb_samples = in_size / info->bpf; + planar = av_sample_fmt_is_planar (ffmpegaudenc->context->sample_fmt); + + if (planar && info->channels > 1) { + gint channels, nsamples; + gint i, j; + + nsamples = frame.nb_samples = in_size / info->bpf; + channels = info->channels; + + frame.data[0] = g_malloc (in_size); + frame.linesize[0] = in_size / channels; + for (i = 1; i < channels; i++) { + frame.data[i] = frame.data[i - 1] + frame.linesize[0]; + frame.linesize[i] = frame.linesize[0]; + } + + switch (info->finfo->width) { + case 8:{ + const guint8 *idata = (const guint8 *) audio_in; + + for (i = 0; i < nsamples; i++) { + for (j = 0; j < channels; j++) { + ((guint8 *) frame.data[j])[i] = idata[j]; + } + idata += channels; + } + break; + } + case 16:{ + const guint16 *idata = (const guint16 *) audio_in; + + for (i = 0; i < nsamples; i++) { + for (j = 0; j < channels; j++) { + ((guint16 *) frame.data[j])[i] = idata[j]; + } + idata += channels; + } + break; + } + case 32:{ + const guint32 *idata = (const guint32 *) audio_in; + + for (i = 0; i < nsamples; i++) { + for (j = 0; j < channels; j++) { + ((guint32 *) frame.data[j])[i] = idata[j]; + } + idata += channels; + } + + break; + } + case 64:{ + const guint64 *idata = (const guint64 *) audio_in; + + for (i = 0; i < nsamples; i++) { + for (j = 0; j < channels; j++) { + ((guint64 *) frame.data[j])[i] = idata[j]; + } + idata += channels; + } + + break; + } + default: + g_assert_not_reached (); + break; + } + + } else { + frame.data[0] = audio_in; + frame.linesize[0] = in_size; + frame.nb_samples = in_size / info->bpf; + } res = avcodec_encode_audio2 (ctx, &pkt, &frame, have_data); + if (planar && info->channels > 1) + g_free (frame.data[0]); + if (res < 0) { char error_str[128] = { 0, }; diff --git a/ext/libav/gstavcodecmap.c b/ext/libav/gstavcodecmap.c index 7b30c93..75f3956 100644 --- a/ext/libav/gstavcodecmap.c +++ b/ext/libav/gstavcodecmap.c @@ -1747,19 +1747,25 @@ gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context, GstAudioFormat gst_ffmpeg_smpfmt_to_audioformat (enum AVSampleFormat sample_fmt) { - sample_fmt = av_get_packed_sample_fmt (sample_fmt); - switch (sample_fmt) { + case AV_SAMPLE_FMT_U8: + case AV_SAMPLE_FMT_U8P: + return GST_AUDIO_FORMAT_U8; + break; case AV_SAMPLE_FMT_S16: + case AV_SAMPLE_FMT_S16P: return GST_AUDIO_FORMAT_S16; break; case AV_SAMPLE_FMT_S32: + case AV_SAMPLE_FMT_S32P: return GST_AUDIO_FORMAT_S32; break; case AV_SAMPLE_FMT_FLT: + case AV_SAMPLE_FMT_FLTP: return GST_AUDIO_FORMAT_F32; break; case AV_SAMPLE_FMT_DBL: + case AV_SAMPLE_FMT_DBLP: return GST_AUDIO_FORMAT_F64; break; default: @@ -2201,25 +2207,105 @@ gst_ffmpeg_videoinfo_to_context (GstVideoInfo * info, AVCodecContext * context) void gst_ffmpeg_audioinfo_to_context (GstAudioInfo * info, AVCodecContext * context) { + const AVCodec *codec; + const enum AVSampleFormat *smpl_fmts; + enum AVSampleFormat smpl_fmt = -1; + context->channels = info->channels; context->sample_rate = info->rate; + codec = context->codec; + + smpl_fmts = codec->sample_fmts; + switch (info->finfo->format) { case GST_AUDIO_FORMAT_F32: - context->sample_fmt = AV_SAMPLE_FMT_FLT; + if (smpl_fmts) { + while (*smpl_fmts != -1) { + if (*smpl_fmts == AV_SAMPLE_FMT_FLT) { + smpl_fmt = *smpl_fmts; + break; + } else if (*smpl_fmts == AV_SAMPLE_FMT_FLTP) { + smpl_fmt = *smpl_fmts; + } + + smpl_fmts++; + } + } else { + smpl_fmt = AV_SAMPLE_FMT_FLT; + } break; case GST_AUDIO_FORMAT_F64: - context->sample_fmt = AV_SAMPLE_FMT_DBL; + if (smpl_fmts) { + while (*smpl_fmts != -1) { + if (*smpl_fmts == AV_SAMPLE_FMT_DBL) { + smpl_fmt = *smpl_fmts; + break; + } else if (*smpl_fmts == AV_SAMPLE_FMT_DBLP) { + smpl_fmt = *smpl_fmts; + } + + smpl_fmts++; + } + } else { + smpl_fmt = AV_SAMPLE_FMT_DBL; + } break; case GST_AUDIO_FORMAT_S32: - context->sample_fmt = AV_SAMPLE_FMT_S32; + if (smpl_fmts) { + while (*smpl_fmts != -1) { + if (*smpl_fmts == AV_SAMPLE_FMT_S32) { + smpl_fmt = *smpl_fmts; + break; + } else if (*smpl_fmts == AV_SAMPLE_FMT_S32P) { + smpl_fmt = *smpl_fmts; + } + + smpl_fmts++; + } + } else { + smpl_fmt = AV_SAMPLE_FMT_S32; + } break; case GST_AUDIO_FORMAT_S16: - context->sample_fmt = AV_SAMPLE_FMT_S16; + if (smpl_fmts) { + while (*smpl_fmts != -1) { + if (*smpl_fmts == AV_SAMPLE_FMT_S16) { + smpl_fmt = *smpl_fmts; + break; + } else if (*smpl_fmts == AV_SAMPLE_FMT_S16P) { + smpl_fmt = *smpl_fmts; + } + + smpl_fmts++; + } + } else { + smpl_fmt = AV_SAMPLE_FMT_S16; + } + break; + case GST_AUDIO_FORMAT_U8: + if (smpl_fmts) { + while (*smpl_fmts != -1) { + if (*smpl_fmts == AV_SAMPLE_FMT_U8) { + smpl_fmt = *smpl_fmts; + break; + } else if (*smpl_fmts == AV_SAMPLE_FMT_U8P) { + smpl_fmt = *smpl_fmts; + } + + smpl_fmts++; + } + } else { + smpl_fmt = AV_SAMPLE_FMT_U8; + } break; default: break; } + + g_assert (smpl_fmt != -1); + + context->sample_fmt = smpl_fmt; } /* Convert a GstCaps and a FFMPEG codec Type to a -- 2.7.4