frame: add a convenience function for copying AVFrame data
authorAnton Khirnov <anton@khirnov.net>
Tue, 11 Feb 2014 13:15:20 +0000 (14:15 +0100)
committerAnton Khirnov <anton@khirnov.net>
Mon, 24 Feb 2014 06:25:07 +0000 (07:25 +0100)
doc/APIchanges
libavutil/frame.c
libavutil/frame.h
libavutil/version.h

index ec311a5..48b925b 100644 (file)
@@ -13,6 +13,9 @@ libavutil:     2013-12-xx
 
 API changes, most recent first:
 
+2014-xx-xx - xxxxxxx - lavu 53.05.0 - frame.h
+  Add av_frame_copy() for copying the frame data.
+
 2014-02-xx - xxxxxxx - lavr 1.2.0 - avresample.h
   Add avresample_is_open() for checking whether a resample context is open.
 
index 2529ae5..f81bbbd 100644 (file)
@@ -191,15 +191,11 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src)
         if (ret < 0)
             return ret;
 
-        if (src->nb_samples) {
-            int ch = av_get_channel_layout_nb_channels(src->channel_layout);
-            av_samples_copy(dst->extended_data, src->extended_data, 0, 0,
-                            dst->nb_samples, ch, dst->format);
-        } else {
-            av_image_copy(dst->data, dst->linesize, src->data, src->linesize,
-                          dst->format, dst->width, dst->height);
-        }
-        return 0;
+        ret = av_frame_copy(dst, src);
+        if (ret < 0)
+            av_frame_unref(dst);
+
+        return ret;
     }
 
     /* ref the buffers */
@@ -335,13 +331,10 @@ int av_frame_make_writable(AVFrame *frame)
     if (ret < 0)
         return ret;
 
-    if (tmp.nb_samples) {
-        int ch = av_get_channel_layout_nb_channels(tmp.channel_layout);
-        av_samples_copy(tmp.extended_data, frame->extended_data, 0, 0,
-                        frame->nb_samples, ch, frame->format);
-    } else {
-        av_image_copy(tmp.data, tmp.linesize, frame->data, frame->linesize,
-                      frame->format, frame->width, frame->height);
+    ret = av_frame_copy(&tmp, frame);
+    if (ret < 0) {
+        av_frame_unref(&tmp);
+        return ret;
     }
 
     ret = av_frame_copy_props(&tmp, frame);
@@ -477,3 +470,59 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
     }
     return NULL;
 }
+
+static int frame_copy_video(AVFrame *dst, const AVFrame *src)
+{
+    const uint8_t *src_data[4];
+    int i, planes;
+
+    if (dst->width  != src->width ||
+        dst->height != src->height)
+        return AVERROR(EINVAL);
+
+    planes = av_pix_fmt_count_planes(dst->format);
+    for (i = 0; i < planes; i++)
+        if (!dst->data[i] || !src->data[i])
+            return AVERROR(EINVAL);
+
+    memcpy(src_data, src->data, sizeof(src_data));
+    av_image_copy(dst->data, dst->linesize,
+                  src_data, src->linesize,
+                  dst->format, dst->width, dst->height);
+
+    return 0;
+}
+
+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 planes   = planar ? channels : 1;
+    int i;
+
+    if (dst->nb_samples     != src->nb_samples ||
+        dst->channel_layout != src->channel_layout)
+        return AVERROR(EINVAL);
+
+    for (i = 0; i < planes; i++)
+        if (!dst->extended_data[i] || !src->extended_data[i])
+            return AVERROR(EINVAL);
+
+    av_samples_copy(dst->extended_data, src->extended_data, 0, 0,
+                    dst->nb_samples, channels, dst->format);
+
+    return 0;
+}
+
+int av_frame_copy(AVFrame *dst, const AVFrame *src)
+{
+    if (dst->format != src->format || dst->format < 0)
+        return AVERROR(EINVAL);
+
+    if (dst->width > 0 && dst->height > 0)
+        return frame_copy_video(dst, src);
+    else if (dst->nb_samples > 0 && dst->channel_layout)
+        return frame_copy_audio(dst, src);
+
+    return AVERROR(EINVAL);
+}
index 2076642..30cc1e4 100644 (file)
@@ -506,6 +506,19 @@ int av_frame_is_writable(AVFrame *frame);
 int av_frame_make_writable(AVFrame *frame);
 
 /**
+ * Copy the frame data from src to dst.
+ *
+ * This function does not allocate anything, dst must be already initialized and
+ * allocated with the same parameters as src.
+ *
+ * This function only copies the frame data (i.e. the contents of the data /
+ * extended data arrays), not any other properties.
+ *
+ * @return >= 0 on success, a negative AVERROR on error.
+ */
+int av_frame_copy(AVFrame *dst, const AVFrame *src);
+
+/**
  * Copy only "metadata" fields from src to dst.
  *
  * Metadata for the purpose of this function are those fields that do not affect
index fd33bf5..cd0981c 100644 (file)
@@ -54,7 +54,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR 53
-#define LIBAVUTIL_VERSION_MINOR  4
+#define LIBAVUTIL_VERSION_MINOR  5
 #define LIBAVUTIL_VERSION_MICRO  0
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \