[FFmpeg-devel,1/3] lavu/frame: add av_frame_realign().

Submitted by Nicolas George on May 7, 2017, 2:41 p.m.

Details

Message ID 20170507144111.GA1085904@phare.normalesup.org
State New
Headers show

Commit Message

Nicolas George May 7, 2017, 2:41 p.m.
L'octidi 18 floréal, an CCXXV, Marton Balint a écrit :
> I suggest to return 1 if an actual alignment (with deep copy) happened.

Actually, as Muhammad just pointed and as I noticed a few minutes ago,
we can not use the same function from lavfi and lavc, due to the
get_buffer issue.

I propose the attached patch to factor the alignment check (notice it is
slightly more complex than in Muhammad's patch, because it takes care of
all cases and not just the mp3lame crash). The realignment functions
will look like:

int ff_frame_realign(AVFrame *frame, unsigned align)
{
    if (ff_frame_check_align(frame, align))
	return 0;

    <copy-paste from av_frame_make_writable()>

    specific_get_buffer(frame);

    <copy-paste from av_frame_make_writable()>
}

If we were not so much in a rush, I would propose a solution to avoid
the copy-paste, but it can wait for later.

Regards,

Patch hide | download patch | download mbox

From 3dacd6fa2aa86b31b73edda83f995b841e1d57b5 Mon Sep 17 00:00:00 2001
From: Nicolas George <george@nsup.org>
Date: Sat, 6 May 2017 10:56:33 +0200
Subject: [PATCH 1/3] lavu/frame: add av_frame_check_align().

TODO APIchanges and minor bump.

Signed-off-by: Nicolas George <george@nsup.org>
---
 libavutil/frame.c | 18 ++++++++++++++++++
 libavutil/frame.h |  8 ++++++++
 2 files changed, 26 insertions(+)

diff --git a/libavutil/frame.c b/libavutil/frame.c
index dd12c5549c..cb6e334833 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -777,3 +777,21 @@  const char *av_frame_side_data_name(enum AVFrameSideDataType type)
     }
     return NULL;
 }
+
+int av_frame_check_align(AVFrame *frame, unsigned align)
+{
+    unsigned mask = (1 << align) - 1;
+    unsigned i;
+    int ret;
+
+    av_assert1(align < 16);
+    for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
+        if (((intptr_t)frame->data[i] & mask))
+            return 0;
+    if (!frame->extended_data || frame->extended_data == frame->data)
+        return 1;
+    for (i = AV_NUM_DATA_POINTERS; i < frame->channels; i++)
+        if (((intptr_t)frame->extended_data[i] & mask))
+            return 0;
+    return 1;
+}
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 4d8c1bed4f..f6ff807404 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -746,6 +746,14 @@  void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
 const char *av_frame_side_data_name(enum AVFrameSideDataType type);
 
 /**
+ * Check if the data pointers of a frame are aligned enough.
+ * Test if all frame data pointers have the alignment lower bits cleared,
+ * i.e. are a multiple of 1<<alignment.
+ * @return  >0 if aligned, 0 if not
+ */
+int av_frame_check_align(AVFrame *frame, unsigned align);
+
+/**
  * @}
  */
 
-- 
2.11.0