[004/200] avframe: switch to the new channel layout API

Message ID 20170517174712.8625-5-vittorio.giovara@gmail.com
State New
Headers show

Commit Message

Vittorio Giovara May 17, 2017, 5:46 p.m.
From: Anton Khirnov <anton@khirnov.net>

Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
---
 libavcodec/decode.c | 67 ++++++++++++++++++++++++++++------------
 libavcodec/encode.c |  9 ++++++
 libavutil/frame.c   | 88 +++++++++++++++++++++++++++++++++++++++++++++++------
 libavutil/frame.h   | 12 +++++++-
 4 files changed, 146 insertions(+), 30 deletions(-)

Comments

Luca Barbato May 23, 2017, 8:09 p.m. | #1
On 5/17/17 7:46 PM, Vittorio Giovara wrote:
> +    ret = av_channel_layout_copy(&frame->ch_layout, &avci->to_free->ch_layout);

Doesn't need to uninit first?
Vittorio Giovara May 26, 2017, 3:27 p.m. | #2
On Tue, May 23, 2017 at 4:09 PM, Luca Barbato <lu_zero@gentoo.org> wrote:
> On 5/17/17 7:46 PM, Vittorio Giovara wrote:
>> +    ret = av_channel_layout_copy(&frame->ch_layout, &avci->to_free->ch_layout);
>
> Doesn't need to uninit first?

I'll move uninit in _copy().
Ok otherwise?
Luca Barbato May 26, 2017, 4:36 p.m. | #3
On 5/26/17 5:27 PM, Vittorio Giovara wrote:
> On Tue, May 23, 2017 at 4:09 PM, Luca Barbato <lu_zero@gentoo.org> wrote:
>> On 5/17/17 7:46 PM, Vittorio Giovara wrote:
>>> +    ret = av_channel_layout_copy(&frame->ch_layout, &avci->to_free->ch_layout);
>>
>> Doesn't need to uninit first?
> 
> I'll move uninit in _copy().
> Ok otherwise?
> 
Yes

Patch

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 8ad5104d6b..8898caf1c0 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -132,7 +132,7 @@  static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
     memcpy(frame->data,     avci->to_free->data,     sizeof(frame->data));
     memcpy(frame->linesize, avci->to_free->linesize, sizeof(frame->linesize));
     if (avci->to_free->extended_data != avci->to_free->data) {
-        int planes = av_get_channel_layout_nb_channels(avci->to_free->channel_layout);
+        int planes = avci->to_free->ch_layout.nb_channels;
         int size   = planes * sizeof(*frame->extended_data);
 
         if (!size) {
@@ -153,9 +153,19 @@  static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
     frame->format         = avci->to_free->format;
     frame->width          = avci->to_free->width;
     frame->height         = avci->to_free->height;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
     frame->channel_layout = avci->to_free->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     frame->nb_samples     = avci->to_free->nb_samples;
 
+    ret = av_channel_layout_copy(&frame->ch_layout, &avci->to_free->ch_layout);
+    if (ret < 0) {
+        av_frame_unref(frame);
+        return ret;
+    }
+
     return 0;
 }
 
@@ -881,10 +891,20 @@  static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
         break;
         }
     case AVMEDIA_TYPE_AUDIO: {
-        int ch     = av_get_channel_layout_nb_channels(frame->channel_layout);
+        int ch     = frame->ch_layout.nb_channels;
         int planar = av_sample_fmt_is_planar(frame->format);
         int planes = planar ? ch : 1;
 
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (!ch && frame->channel_layout) {
+            av_channel_layout_from_mask(&frame->ch_layout, frame->channel_layout);
+            ch     = frame->ch_layout.nb_channels;
+            planes = planar ? ch : 1;
+        }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
         if (pool->format == frame->format && pool->planes == planes &&
             pool->channels == ch && frame->nb_samples == pool->samples)
             return 0;
@@ -1101,28 +1121,35 @@  int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
             frame->sample_rate    = avctx->sample_rate;
         if (frame->format < 0)
             frame->format         = avctx->sample_fmt;
+        if (!frame->ch_layout.nb_channels) {
+            if (avctx->channel_layout)
+                av_channel_layout_from_mask(&frame->ch_layout, avctx->channel_layout);
+            else
+                av_channel_layout_default(&frame->ch_layout, avctx->channels);
+        }
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        /* set the deprecated channel_layout field for callers
+         * that didn't update to the new API yet */
+        if (frame->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) {
+            av_log(avctx, AV_LOG_ERROR, "Too many channels.\n");
+            return AVERROR(EINVAL);
+        }
         if (!frame->channel_layout) {
-            if (avctx->channel_layout) {
-                 if (av_get_channel_layout_nb_channels(avctx->channel_layout) !=
-                     avctx->channels) {
-                     av_log(avctx, AV_LOG_ERROR, "Inconsistent channel "
-                            "configuration.\n");
-                     return AVERROR(EINVAL);
-                 }
-
-                frame->channel_layout = avctx->channel_layout;
-            } else {
-                if (avctx->channels > FF_SANE_NB_CHANNELS) {
-                    av_log(avctx, AV_LOG_ERROR, "Too many channels: %d.\n",
-                           avctx->channels);
-                    return AVERROR(ENOSYS);
-                }
-
-                frame->channel_layout = av_get_default_channel_layout(avctx->channels);
+            if (frame->ch_layout.order == AV_CHANNEL_ORDER_NATIVE)
+                frame->channel_layout = frame->ch_layout.u.mask;
+            else {
+                frame->channel_layout = av_get_default_channel_layout(frame->ch_layout.nb_channels);
                 if (!frame->channel_layout)
-                    frame->channel_layout = (1ULL << avctx->channels) - 1;
+                    frame->channel_layout = (1ULL << frame->ch_layout.nb_channels) - 1;
             }
         }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+        if (!av_channel_layout_check(&frame->ch_layout)) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid channel layout.\n");
+            return AVERROR_INVALIDDATA;
+        }
         break;
     default: return AVERROR(EINVAL);
     }
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 9bb7ae5bde..cf77fa7cff 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -60,8 +60,17 @@  static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src)
         return AVERROR(ENOMEM);
 
     frame->format         = src->format;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
     frame->channel_layout = src->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     frame->nb_samples     = s->frame_size;
+
+    ret = av_channel_layout_copy(&frame->ch_layout, &src->ch_layout);
+    if (ret < 0)
+        goto fail;
+
     ret = av_frame_get_buffer(frame, 32);
     if (ret < 0)
         goto fail;
diff --git a/libavutil/frame.c b/libavutil/frame.c
index 9cd5f9ab37..ad1a5273f6 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -140,11 +140,20 @@  fail:
 
 static int get_audio_buffer(AVFrame *frame, int align)
 {
-    int channels = av_get_channel_layout_nb_channels(frame->channel_layout);
+    int channels = frame->ch_layout.nb_channels;
     int planar   = av_sample_fmt_is_planar(frame->format);
     int planes   = planar ? channels : 1;
     int ret, i;
 
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    if (!channels) {
+        av_channel_layout_from_mask(&frame->ch_layout, frame->channel_layout);
+        channels = frame->ch_layout.nb_channels;
+        planes   = planar ? channels : 1;
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     if (!frame->linesize[0]) {
         ret = av_samples_get_buffer_size(&frame->linesize[0], channels,
                                          frame->nb_samples, frame->format,
@@ -194,7 +203,14 @@  int av_frame_get_buffer(AVFrame *frame, int align)
 
     if (frame->width > 0 && frame->height > 0)
         return get_video_buffer(frame, align);
-    else if (frame->nb_samples > 0 && frame->channel_layout)
+    else if (frame->nb_samples > 0 &&
+             (av_channel_layout_check(&frame->ch_layout)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+              || frame->channel_layout
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+             ))
         return get_audio_buffer(frame, align);
 
     return AVERROR(EINVAL);
@@ -207,13 +223,26 @@  int av_frame_ref(AVFrame *dst, const AVFrame *src)
     dst->format         = src->format;
     dst->width          = src->width;
     dst->height         = src->height;
-    dst->channel_layout = src->channel_layout;
     dst->nb_samples     = src->nb_samples;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    dst->channel_layout = src->channel_layout;
+    if (!av_channel_layout_check(&src->ch_layout))
+        av_channel_layout_from_mask(&dst->ch_layout, src->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     ret = av_frame_copy_props(dst, src);
     if (ret < 0)
         return ret;
 
+    // this check is needed only until FF_API_OLD_CHANNEL_LAYOUT is out
+    if (av_channel_layout_check(&src->ch_layout)) {
+        ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
+        if (ret < 0)
+            goto fail;
+    }
+
     /* duplicate the frame data if it's not refcounted */
     if (!src->buf[0]) {
         ret = av_frame_get_buffer(dst, 32);
@@ -264,7 +293,7 @@  int av_frame_ref(AVFrame *dst, const AVFrame *src)
 
     /* duplicate extended data */
     if (src->extended_data != src->data) {
-        int ch = av_get_channel_layout_nb_channels(src->channel_layout);
+        int ch = dst->ch_layout.nb_channels;
 
         if (!ch) {
             ret = AVERROR(EINVAL);
@@ -319,6 +348,8 @@  void av_frame_unref(AVFrame *frame)
 
     av_buffer_unref(&frame->opaque_ref);
 
+    av_channel_layout_uninit(&frame->ch_layout);
+
     get_frame_defaults(frame);
 }
 
@@ -362,8 +393,18 @@  int av_frame_make_writable(AVFrame *frame)
     tmp.format         = frame->format;
     tmp.width          = frame->width;
     tmp.height         = frame->height;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
     tmp.channel_layout = frame->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     tmp.nb_samples     = frame->nb_samples;
+    ret = av_channel_layout_copy(&tmp.ch_layout, &frame->ch_layout);
+    if (ret < 0) {
+        av_frame_unref(&tmp);
+        return ret;
+    }
+
     ret = av_frame_get_buffer(&tmp, 32);
     if (ret < 0)
         return ret;
@@ -458,7 +499,14 @@  AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane)
     int planes, i;
 
     if (frame->nb_samples) {
-        int channels = av_get_channel_layout_nb_channels(frame->channel_layout);
+        int channels = frame->ch_layout.nb_channels;
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (!channels)
+            channels = av_get_channel_layout_nb_channels(frame->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
         if (!channels)
             return NULL;
         planes = av_sample_fmt_is_planar(frame->format) ? channels : 1;
@@ -552,12 +600,27 @@  static int frame_copy_video(AVFrame *dst, const AVFrame *src)
 static int frame_copy_audio(AVFrame *dst, const AVFrame *src)
 {
     int planar   = av_sample_fmt_is_planar(dst->format);
-    int channels = av_get_channel_layout_nb_channels(dst->channel_layout);
+    int channels = dst->ch_layout.nb_channels;
     int planes   = planar ? channels : 1;
     int i;
 
-    if (dst->nb_samples     != src->nb_samples ||
-        dst->channel_layout != src->channel_layout)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    if (!channels) {
+        channels = av_get_channel_layout_nb_channels(dst->channel_layout);
+        planes = planar ? channels : 1;
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    if (dst->nb_samples != src->nb_samples ||
+        av_channel_layout_compare(&dst->ch_layout, &src->ch_layout)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        || dst->channel_layout != src->channel_layout
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+        )
         return AVERROR(EINVAL);
 
     for (i = 0; i < planes; i++)
@@ -577,7 +640,14 @@  int av_frame_copy(AVFrame *dst, const AVFrame *src)
 
     if (dst->width > 0 && dst->height > 0)
         return frame_copy_video(dst, src);
-    else if (dst->nb_samples > 0 && dst->channel_layout)
+    else if (dst->nb_samples > 0 &&
+             (av_channel_layout_check(&dst->ch_layout)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+              || dst->channel_layout
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+            ))
         return frame_copy_audio(dst, src);
 
     return AVERROR(EINVAL);
diff --git a/libavutil/frame.h b/libavutil/frame.h
index f9ffb5bbbf..afa655026f 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -30,6 +30,7 @@ 
 
 #include "avutil.h"
 #include "buffer.h"
+#include "channel_layout.h"
 #include "dict.h"
 #include "rational.h"
 #include "samplefmt.h"
@@ -304,10 +305,14 @@  typedef struct AVFrame {
      */
     int sample_rate;
 
+#if FF_API_OLD_CHANNEL_LAYOUT
     /**
      * Channel layout of the audio data.
+     * @deprecated use ch_layout instead
      */
+    attribute_deprecated
     uint64_t channel_layout;
+#endif
 
     /**
      * AVBuffer references backing the data for this frame. If all elements of
@@ -406,6 +411,11 @@  typedef struct AVFrame {
      * purpose.
      */
     AVBufferRef *opaque_ref;
+
+    /**
+     * Channel layout of the audio data.
+     */
+    AVChannelLayout ch_layout;
 } AVFrame;
 
 /**
@@ -475,7 +485,7 @@  void av_frame_move_ref(AVFrame *dst, AVFrame *src);
  * The following fields must be set on frame before calling this function:
  * - format (pixel format for video, sample format for audio)
  * - width and height for video
- * - nb_samples and channel_layout for audio
+ * - nb_samples and ch_layout for audio
  *
  * This function will fill AVFrame.data and AVFrame.buf arrays and, if
  * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf.