History

avcodec/mpegpicture: Split ff_alloc_picture() into check and alloc part

ff_alloc_picture() currently does two things: It checks the consistency of the linesize (which should not be necessary, but is) and it allocates certain buffers. (It does not actually allocate the picture buffers, so its name is misleading.) This commit splits it into two separate functions. The rationale for this is that for the encoders, every picture needs its linesizes checked, but not every picture needs these extra buffers.

Andreas Rheinhardt committed 3 years ago

Commit 89ca63c1 parent 042117d4 files · +69 −81Browse files

Showing the changes to libavcodec (4 of 4 files). Show all

Unified · Split

4 files
  1. libavcodec/mpegpicture.c +25 −45
  2. libavcodec/mpegpicture.h +12 −3
  3. libavcodec/mpegvideo_dec.c +6 −2
  4. libavcodec/mpegvideo_enc.c +26 −31
libavcodec/mpegpicture.c+25−45
@@ -91,40 +91,27 @@ int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me, · 90 unmodified lines
9191 return 0;
9292 }
9393
94−/**
95− * Check the pic's linesize and allocate linesize dependent scratch buffers
96− */
97−static int handle_pic_linesizes(AVCodecContext *avctx, Picture *pic,
98− MotionEstContext *me, ScratchpadContext *sc,
99− int linesize, int uvlinesize)
94+int ff_mpv_pic_check_linesize(void *logctx, const AVFrame *f,
95+ ptrdiff_t *linesizep, ptrdiff_t *uvlinesizep)
10096 {
101− int ret;
102−
103− if ((linesize && linesize != pic->f->linesize[0]) ||
104− (uvlinesize && uvlinesize != pic->f->linesize[1])) {
105− av_log(avctx, AV_LOG_ERROR, "Stride change unsupported: "
106− "linesize=%d/%d uvlinesize=%d/%d)\n",
107− linesize, pic->f->linesize[0],
108− uvlinesize, pic->f->linesize[1]);
109− ff_mpeg_unref_picture(pic);
97+ ptrdiff_t linesize = *linesizep, uvlinesize = *uvlinesizep;
98+
99+ if ((linesize && linesize != f->linesize[0]) ||
100+ (uvlinesize && uvlinesize != f->linesize[1])) {
101+ av_log(logctx, AV_LOG_ERROR, "Stride change unsupported: "
102+ "linesize=%"PTRDIFF_SPECIFIER"/%d uvlinesize=%"PTRDIFF_SPECIFIER"/%d)\n",
103+ linesize, f->linesize[0],
104+ uvlinesize, f->linesize[1]);
110105 return AVERROR_PATCHWELCOME;
111106 }
112107
113− if (av_pix_fmt_count_planes(pic->f->format) > 2 &&
114− pic->f->linesize[1] != pic->f->linesize[2]) {
115− av_log(avctx, AV_LOG_ERROR, "uv stride mismatch unsupported\n");
116− ff_mpeg_unref_picture(pic);
108+ if (av_pix_fmt_count_planes(f->format) > 2 &&
109+ f->linesize[1] != f->linesize[2]) {
110+ av_log(logctx, AV_LOG_ERROR, "uv stride mismatch unsupported\n");
117111 return AVERROR_PATCHWELCOME;
118112 }
119−
120− ret = ff_mpeg_framesize_alloc(avctx, me, sc,
121− pic->f->linesize[0]);
122− if (ret < 0) {
123− av_log(avctx, AV_LOG_ERROR,
124− "get_buffer() failed to allocate context scratch buffers.\n");
125− ff_mpeg_unref_picture(pic);
126− return ret;
127− }
113+ *linesizep = f->linesize[0];
114+ *uvlinesizep = f->linesize[1];
128115
129116 return 0;
130117 }
@@ -156,28 +143,22 @@ static int alloc_picture_tables(BufferPoolContext *pools, Picture *pic, · 25 unmodified lines
156143 return 0;
157144 }
158145
159−/**
160− * Allocate a Picture.
161− * The pixels are allocated/set by calling get_buffer() if shared = 0
162− */
163−int ff_alloc_picture(AVCodecContext *avctx, Picture *pic, MotionEstContext *me,
164− ScratchpadContext *sc, BufferPoolContext *pools,
165− int mb_height, ptrdiff_t *linesize, ptrdiff_t *uvlinesize)
146+int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, Picture *pic,
147+ MotionEstContext *me, ScratchpadContext *sc,
148+ BufferPoolContext *pools, int mb_height)
166149 {
167150 int ret;
168151
169− if (handle_pic_linesizes(avctx, pic, me, sc,
170− *linesize, *uvlinesize) < 0)
171− return -1;
172−
173− *linesize = pic->f->linesize[0];
174− *uvlinesize = pic->f->linesize[1];
175−
176152 for (int i = 0; i < MPV_MAX_PLANES; i++) {
177153 pic->data[i] = pic->f->data[i];
178154 pic->linesize[i] = pic->f->linesize[i];
179155 }
180156
157+ ret = ff_mpeg_framesize_alloc(avctx, me, sc,
158+ pic->f->linesize[0]);
159+ if (ret < 0)
160+ goto fail;
161+
181162 ret = alloc_picture_tables(pools, pic, mb_height);
182163 if (ret < 0)
183164 goto fail;
@@ -192,9 +173,8 @@ int ff_alloc_picture(AVCodecContext *avctx, Picture *pic, MotionEstContext *me, · 8 unmodified lines
192173
193174 return 0;
194175 fail:
195− av_log(avctx, AV_LOG_ERROR, "Error allocating a picture.\n");
196− ff_mpeg_unref_picture(pic);
197− return AVERROR(ENOMEM);
176+ av_log(avctx, AV_LOG_ERROR, "Error allocating picture accessories.\n");
177+ return ret;
198178 }
199179
200180 /**
libavcodec/mpegpicture.h+12−3
@@ -96,9 +96,18 @@ typedef struct Picture { · 95 unmodified lines
9696 /**
9797 * Allocate a Picture's accessories, but not the AVFrame's buffer itself.
9898 */
99−int ff_alloc_picture(AVCodecContext *avctx, Picture *pic, MotionEstContext *me,
100− ScratchpadContext *sc, BufferPoolContext *pools,
101− int mb_height, ptrdiff_t *linesize, ptrdiff_t *uvlinesize);
99+int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, Picture *pic,
100+ MotionEstContext *me, ScratchpadContext *sc,
101+ BufferPoolContext *pools, int mb_height);
102+
103+/**
104+ * Check that the linesizes of an AVFrame are consistent with the requirements
105+ * of mpegvideo.
106+ * FIXME: There should be no need for this function. mpegvideo should be made
107+ * to work with changing linesizes.
108+ */
109+int ff_mpv_pic_check_linesize(void *logctx, const struct AVFrame *f,
110+ ptrdiff_t *linesizep, ptrdiff_t *uvlinesizep);
102111
103112 int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me,
104113 ScratchpadContext *sc, int linesize);
libavcodec/mpegvideo_dec.c+6−2
@@ -259,6 +259,10 @@ static int alloc_picture(MpegEncContext *s, Picture **picp, int reference) · 258 unmodified lines
259259 if (ret < 0)
260260 goto fail;
261261
262+ ret = ff_mpv_pic_check_linesize(avctx, pic->f, &s->linesize, &s->uvlinesize);
263+ if (ret < 0)
264+ goto fail;
265+
262266 ret = ff_hwaccel_frame_priv_alloc(avctx, &pic->hwaccel_picture_private);
263267 if (ret < 0)
264268 goto fail;
@@ -267,8 +271,8 @@ static int alloc_picture(MpegEncContext *s, Picture **picp, int reference) · 2 unmodified lines
267271 av_assert1(s->mb_height == s->buffer_pools.alloc_mb_height ||
268272 FFALIGN(s->mb_height, 2) == s->buffer_pools.alloc_mb_height);
269273 av_assert1(s->mb_stride == s->buffer_pools.alloc_mb_stride);
270− ret = ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, &s->buffer_pools,
271− s->mb_height, &s->linesize, &s->uvlinesize);
274+ ret = ff_mpv_alloc_pic_accessories(s->avctx, pic, &s->me, &s->sc,
275+ &s->buffer_pools, s->mb_height);
272276 if (ret < 0)
273277 goto fail;
274278 *picp = pic;
libavcodec/mpegvideo_enc.c+26−31
@@ -1103,6 +1103,10 @@ static int alloc_picture(MpegEncContext *s, Picture *pic) · 1102 unmodified lines
11031103 if (ret < 0)
11041104 return ret;
11051105
1106+ ret = ff_mpv_pic_check_linesize(avctx, pic->f, &s->linesize, &s->uvlinesize);
1107+ if (ret < 0)
1108+ return ret;
1109+
11061110 for (int i = 0; pic->f->data[i]; i++) {
11071111 int offset = (EDGE_WIDTH >> (i ? s->chroma_y_shift : 0)) *
11081112 pic->f->linesize[i] +
@@ -1112,11 +1116,7 @@ static int alloc_picture(MpegEncContext *s, Picture *pic) · 3 unmodified lines
11121116 pic->f->width = avctx->width;
11131117 pic->f->height = avctx->height;
11141118
1115− av_assert1(s->mb_width == s->buffer_pools.alloc_mb_width);
1116− av_assert1(s->mb_height == s->buffer_pools.alloc_mb_height);
1117− av_assert1(s->mb_stride == s->buffer_pools.alloc_mb_stride);
1118− return ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, &s->buffer_pools,
1119− s->mb_height, &s->linesize, &s->uvlinesize);
1119+ return 0;
11201120 }
11211121
11221122 static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg)
@@ -1188,7 +1188,7 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) · 65 unmodified lines
11881188 } else {
11891189 ret = alloc_picture(s, pic);
11901190 if (ret < 0)
1191− return ret;
1191+ goto fail;
11921192 ret = av_frame_copy_props(pic->f, pic_arg);
11931193 if (ret < 0) {
11941194 ff_mpeg_unref_picture(pic);
@@ -1258,6 +1258,9 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) · 63 unmodified lines
12581258 s->input_picture[encoding_delay] = pic;
12591259
12601260 return 0;
1261+fail:
1262+ ff_mpeg_unref_picture(pic);
1263+ return ret;
12611264 }
12621265
12631266 static int skip_check(MpegEncContext *s, const Picture *p, const Picture *ref)
@@ -1600,45 +1603,37 @@ no_output_pic: · 336 unmodified lines
16001603 s->reordered_input_picture[0]->f->pict_type !=
16011604 AV_PICTURE_TYPE_B ? 3 : 0;
16021605
1603− if ((ret = av_frame_ref(s->new_pic,
1604− s->reordered_input_picture[0]->f)))
1605− goto fail;
1606−
16071606 if (s->reordered_input_picture[0]->shared || s->avctx->rc_buffer_size) {
16081607 // input is a shared pix, so we can't modify it -> allocate a new
16091608 // one & ensure that the shared one is reuseable
1610−
1611− Picture *pic;
1612− int i = ff_find_unused_picture(s->avctx, s->picture, 0);
1613− if (i < 0)
1614− return i;
1615− pic = &s->picture[i];
1616−
1617− pic->reference = s->reordered_input_picture[0]->reference;
1618− ret = alloc_picture(s, pic);
1609+ av_frame_move_ref(s->new_pic, s->reordered_input_picture[0]->f);
1610+ ret = alloc_picture(s, s->reordered_input_picture[0]);
16191611 if (ret < 0)
16201612 goto fail;
16211613
1622− ret = av_frame_copy_props(pic->f, s->reordered_input_picture[0]->f);
1623− if (ret < 0) {
1624− ff_mpeg_unref_picture(pic);
1614+ ret = av_frame_copy_props(s->reordered_input_picture[0]->f, s->new_pic);
1615+ if (ret < 0)
16251616 goto fail;
1626− }
1627− pic->coded_picture_number = s->reordered_input_picture[0]->coded_picture_number;
1628− pic->display_picture_number = s->reordered_input_picture[0]->display_picture_number;
1629−
1630− /* mark us unused / free shared pic */
1631− ff_mpeg_unref_picture(s->reordered_input_picture[0]);
1632−
1633− s->cur_pic_ptr = pic;
16341617 } else {
16351618 // input is not a shared pix -> reuse buffer for current_pix
1636− s->cur_pic_ptr = s->reordered_input_picture[0];
1619+ ret = av_frame_ref(s->new_pic, s->reordered_input_picture[0]->f);
1620+ if (ret < 0)
1621+ goto fail;
16371622 for (int i = 0; i < MPV_MAX_PLANES; i++) {
16381623 if (s->new_pic->data[i])
16391624 s->new_pic->data[i] += INPLACE_OFFSET;
16401625 }
16411626 }
1627+ s->cur_pic_ptr = s->reordered_input_picture[0];
1628+ av_assert1(s->mb_width == s->buffer_pools.alloc_mb_width);
1629+ av_assert1(s->mb_height == s->buffer_pools.alloc_mb_height);
1630+ av_assert1(s->mb_stride == s->buffer_pools.alloc_mb_stride);
1631+ ret = ff_mpv_alloc_pic_accessories(s->avctx, s->cur_pic_ptr, &s->me,
1632+ &s->sc, &s->buffer_pools, s->mb_height);
1633+ if (ret < 0) {
1634+ ff_mpeg_unref_picture(s->cur_pic_ptr);
1635+ return ret;
1636+ }
16421637 s->picture_number = s->cur_pic_ptr->display_picture_number;
16431638
16441639 }

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