History

avutil/frame: also align data pointers in av_frame_get_buffer()

This avoids unpleasant surprises to av_frame_get_buffer callers that explicitly specified 64-byte alignment and didn't get AVFrame.data pointers that are 64-byte aligned. For example, see https://github.com/sekrit-twc/zimg/issues/212 Although the zscale issue has already been resolved by other means it would still be prudent to improve the behavior of av_frame_get_buffer to fix any unknown and future instances of similar issues.

Pavel Koshevoy committed 1 year ago

Commit 46cb7b81 parent ea91d974 files · +25 −9Browse files

Unified · Split

4 files
  1. doc/APIchanges +4 −0
  2. libavutil/frame.c +16 −5
  3. libavutil/frame.h +4 −3
  4. libavutil/version.h +1 −1
doc/APIchanges+4−0
@@ -2,6 +2,10 @@ The last version increases of all libraries were on 2024-03-07 · 1 unmodified line
2 2
3API changes, most recent first:3API changes, most recent first:
4 4
52024-11-16 - xxxxxxxxxx - lavu 59.47.101 - frame.h
6 av_frame_get_buffer() now also aligns the data pointers according to
7 the requested alignment.
8
52024-11-13 - xxxxxxxxxx - lavu 59.47.100 - channel_layout.h92024-11-13 - xxxxxxxxxx - lavu 59.47.100 - channel_layout.h
6 Add AV_CHAN_BINAURAL_LEFT, AV_CHAN_BINAURAL_RIGHT10 Add AV_CHAN_BINAURAL_LEFT, AV_CHAN_BINAURAL_RIGHT
7 Add AV_CH_BINAURAL_LEFT, AV_CH_BINAURAL_RIGHT11 Add AV_CH_BINAURAL_LEFT, AV_CH_BINAURAL_RIGHT
libavutil/frame.c+16−5
@@ -210,7 +210,7 @@ static int get_video_buffer(AVFrame *frame, int align) · 209 unmodified lines
210 padded_height, linesizes)) < 0)210 padded_height, linesizes)) < 0)
211 return ret;211 return ret;
212 212
213 total_size = 4*plane_padding;213 total_size = 4 * plane_padding + 4 * align;
214 for (int i = 0; i < 4; i++) {214 for (int i = 0; i < 4; i++) {
215 if (sizes[i] > SIZE_MAX - total_size)215 if (sizes[i] > SIZE_MAX - total_size)
216 return AVERROR(EINVAL);216 return AVERROR(EINVAL);
@@ -230,6 +230,7 @@ static int get_video_buffer(AVFrame *frame, int align) · 13 unmodified lines
230 for (int i = 1; i < 4; i++) {230 for (int i = 1; i < 4; i++) {
231 if (frame->data[i])231 if (frame->data[i])
232 frame->data[i] += i * plane_padding;232 frame->data[i] += i * plane_padding;
233 frame->data[i] = (uint8_t *)FFALIGN((uintptr_t)frame->data[i], align);
233 }234 }
234 235
235 frame->extended_data = frame->data;236 frame->extended_data = frame->data;
@@ -244,6 +245,7 @@ static int get_audio_buffer(AVFrame *frame, int align) · 8 unmodified lines
244{245{
245 int planar = av_sample_fmt_is_planar(frame->format);246 int planar = av_sample_fmt_is_planar(frame->format);
246 int channels, planes;247 int channels, planes;
248 size_t size;
247 int ret;249 int ret;
248 250
249 channels = frame->ch_layout.nb_channels;251 channels = frame->ch_layout.nb_channels;
@@ -256,6 +258,9 @@ static int get_audio_buffer(AVFrame *frame, int align) · 6 unmodified lines
256 return ret;258 return ret;
257 }259 }
258 260
261 if (align <= 0)
262 align = ALIGN;
263
259 if (planes > AV_NUM_DATA_POINTERS) {264 if (planes > AV_NUM_DATA_POINTERS) {
260 frame->extended_data = av_calloc(planes,265 frame->extended_data = av_calloc(planes,
261 sizeof(*frame->extended_data));266 sizeof(*frame->extended_data));
@@ -270,21 +275,27 @@ static int get_audio_buffer(AVFrame *frame, int align) · 8 unmodified lines
270 } else275 } else
271 frame->extended_data = frame->data;276 frame->extended_data = frame->data;
272 277
278 if (frame->linesize[0] > SIZE_MAX - align)
279 return AVERROR(EINVAL);
280 size = frame->linesize[0] + (size_t)align;
281
273 for (int i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {282 for (int i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
274 frame->buf[i] = av_buffer_alloc(frame->linesize[0]);283 frame->buf[i] = av_buffer_alloc(size);
275 if (!frame->buf[i]) {284 if (!frame->buf[i]) {
276 av_frame_unref(frame);285 av_frame_unref(frame);
277 return AVERROR(ENOMEM);286 return AVERROR(ENOMEM);
278 }287 }
279 frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;288 frame->extended_data[i] = frame->data[i] =
289 (uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, align);
280 }290 }
281 for (int i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) {291 for (int i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) {
282 frame->extended_buf[i] = av_buffer_alloc(frame->linesize[0]);292 frame->extended_buf[i] = av_buffer_alloc(size);
283 if (!frame->extended_buf[i]) {293 if (!frame->extended_buf[i]) {
284 av_frame_unref(frame);294 av_frame_unref(frame);
285 return AVERROR(ENOMEM);295 return AVERROR(ENOMEM);
286 }296 }
287 frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data;297 frame->extended_data[i + AV_NUM_DATA_POINTERS] =
298 (uint8_t *)FFALIGN((uintptr_t)frame->extended_buf[i]->data, align);
288 }299 }
289 return 0;300 return 0;
290 301
libavutil/frame.h+4−3
@@ -887,9 +887,10 @@ void av_frame_move_ref(AVFrame *dst, AVFrame *src); · 886 unmodified lines
887 * cases.887 * cases.
888 *888 *
889 * @param frame frame in which to store the new buffers.889 * @param frame frame in which to store the new buffers.
890 * @param align Required buffer size alignment. If equal to 0, alignment will be890 * @param align Required buffer size and data pointer alignment. If equal to 0,
891 * chosen automatically for the current CPU. It is highly891 * alignment will be chosen automatically for the current CPU.
892 * recommended to pass 0 here unless you know what you are doing.892 * It is highly recommended to pass 0 here unless you know what
893 * you are doing.
893 *894 *
894 * @return 0 on success, a negative AVERROR on error.895 * @return 0 on success, a negative AVERROR on error.
895 */896 */
libavutil/version.h+1−1
@@ -80,7 +80,7 @@ · 79 unmodified lines
80 80
81#define LIBAVUTIL_VERSION_MAJOR 5981#define LIBAVUTIL_VERSION_MAJOR 59
82#define LIBAVUTIL_VERSION_MINOR 4782#define LIBAVUTIL_VERSION_MINOR 47
83#define LIBAVUTIL_VERSION_MICRO 10083#define LIBAVUTIL_VERSION_MICRO 101
84 84
85#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \85#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
86 LIBAVUTIL_VERSION_MINOR, \86 LIBAVUTIL_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t