Skip to content

Commit

Permalink
avcodec/utils: Introduce avcodec_align_dimensions3, which returns a…
Browse files Browse the repository at this point in the history
… single linesize alignment value

`avcodec_align_dimensions2` returns an array of linesize alignment values even though all the values are the same. This API is less friendly to a custom `AVFrame` buffer allocator because some non-FFmpeg image libraries only accept a single linesize alignment value for all the planes (e.g. Core Video). Therefore, introduce `avcodec_align_dimensions3`, which returns a single linesize alignment value.
  • Loading branch information
Darren Mo committed Dec 1, 2019
1 parent aa69a3b commit ccb34cd
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 15 deletions.
16 changes: 10 additions & 6 deletions libavcodec/avcodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -2348,7 +2348,7 @@ typedef struct AVCodecContext {
* If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused
* (read and/or written to if it is writable) later by libavcodec.
*
* avcodec_align_dimensions2() should be used to find the required width and
* avcodec_align_dimensions3() should be used to find the required width and
* height, as they normally need to be rounded up to the next multiple of 16.
*
* Some decoders do not support linesizes changing between frames.
Expand All @@ -2357,7 +2357,7 @@ typedef struct AVCodecContext {
* this callback may be called from a different thread, but not from more
* than one at once. Does not need to be reentrant.
*
* @see avcodec_align_dimensions2()
* @see avcodec_align_dimensions3()
*
* Audio:
*
Expand Down Expand Up @@ -4685,21 +4685,25 @@ int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags);
* Modify width and height values so that they will result in a memory
* buffer that is acceptable for the codec if you do not use any horizontal
* padding.
*
* May only be used if a codec with AV_CODEC_CAP_DR1 has been opened.
*/
void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height);

/**
* Modify width and height values so that they will result in a memory
* buffer that is acceptable for the codec if you also ensure that all
* line sizes are a multiple of the respective linesize_align[i].
*
* May only be used if a codec with AV_CODEC_CAP_DR1 has been opened.
*/
void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
int linesize_align[AV_NUM_DATA_POINTERS]);

/**
* Modify width and height values so that they will result in a memory
* buffer that is acceptable for the codec if you also ensure that all
* line sizes are a multiple of linesize_align.
*/
void avcodec_align_dimensions3(AVCodecContext *s, int *width, int *height,
int *linesize_align);

/**
* Converts AVChromaLocation to swscale x/y chroma position.
*
Expand Down
4 changes: 2 additions & 2 deletions libavcodec/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,7 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
pool->width == frame->width && pool->height == frame->height)
return 0;

avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align);
avcodec_align_dimensions3(avctx, &w, &h, &pool->stride_align);

do {
// NOTE: do not align linesizes individually, this breaks e.g. assumptions
Expand All @@ -1555,7 +1555,7 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)

unaligned = 0;
for (i = 0; i < 4; i++)
unaligned |= linesize[i] % pool->stride_align[i];
unaligned |= linesize[i] % pool->stride_align;
} while (unaligned);

tmpsize = av_image_fill_pointers(data, avctx->pix_fmt, h,
Expand Down
2 changes: 1 addition & 1 deletion libavcodec/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ typedef struct FramePool {
*/
int format;
int width, height;
int stride_align[AV_NUM_DATA_POINTERS];
int stride_align;
int linesize[4];
int planes;
int channels;
Expand Down
19 changes: 14 additions & 5 deletions libavcodec/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,9 @@ int ff_side_data_update_matrix_encoding(AVFrame *frame,
return 0;
}

void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
int linesize_align[AV_NUM_DATA_POINTERS])
void avcodec_align_dimensions3(AVCodecContext *s, int *width, int *height,
int *linesize_align)
{
int i;
int w_align = 1;
int h_align = 1;
AVPixFmtDescriptor const *desc = av_pix_fmt_desc_get(s->pix_fmt);
Expand Down Expand Up @@ -331,8 +330,18 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
*width = FFMAX(*width, 32);
}

for (i = 0; i < 4; i++)
linesize_align[i] = STRIDE_ALIGN;
*linesize_align = STRIDE_ALIGN;
}

void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
int linesize_align[AV_NUM_DATA_POINTERS])
{
int i;

avcodec_align_dimensions3(s, width, height, linesize_align);

for (i = 1; i < 4; i++)
linesize_align[i] = linesize_align[0];
}

void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height)
Expand Down
2 changes: 1 addition & 1 deletion libavutil/frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ typedef struct AVFrame {
* This might be different from the first allocated byte
*
* Some decoders access areas outside 0,0 - width,height, please
* see avcodec_align_dimensions2(). Some filters and swscale can read
* see avcodec_align_dimensions3(). Some filters and swscale can read
* up to 16 bytes beyond the planes, if these filters are to be used,
* then 16 extra bytes must be allocated.
*
Expand Down

0 comments on commit ccb34cd

Please sign in to comment.