FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/mpegpicture.c
Date: 2025-03-08 20:38:41
Exec Total Coverage
Lines: 115 135 85.2%
Functions: 12 12 100.0%
Branches: 38 56 67.9%

Line Branch Exec Source
1 /*
2 * Mpeg video formats-related picture management functions
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "libavutil/avassert.h"
22 #include "libavutil/common.h"
23 #include "libavutil/mem.h"
24 #include "libavutil/pixdesc.h"
25 #include "libavutil/imgutils.h"
26
27 #include "avcodec.h"
28 #include "mpegpicture.h"
29 #include "libavutil/refstruct.h"
30
31 21554 static void mpv_pic_reset(AVRefStructOpaque unused, void *obj)
32 {
33 21554 MPVPicture *pic = obj;
34
35 21554 av_frame_unref(pic->f);
36 21554 ff_thread_progress_reset(&pic->progress);
37
38 21554 av_refstruct_unref(&pic->hwaccel_picture_private);
39
40 21554 av_refstruct_unref(&pic->mbskip_table);
41 21554 av_refstruct_unref(&pic->qscale_table_base);
42 21554 av_refstruct_unref(&pic->mb_type_base);
43
44
2/2
✓ Branch 0 taken 43108 times.
✓ Branch 1 taken 21554 times.
64662 for (int i = 0; i < 2; i++) {
45 43108 av_refstruct_unref(&pic->motion_val_base[i]);
46 43108 av_refstruct_unref(&pic->ref_index[i]);
47
48 43108 pic->motion_val[i] = NULL;
49 }
50
51 21554 pic->mb_type = NULL;
52 21554 pic->qscale_table = NULL;
53
54 21554 pic->mb_stride =
55 21554 pic->mb_width =
56 21554 pic->mb_height = 0;
57
58 21554 pic->dummy = 0;
59 21554 pic->field_picture = 0;
60 21554 pic->b_frame_score = 0;
61 21554 pic->reference = 0;
62 21554 pic->shared = 0;
63 21554 pic->display_picture_number = 0;
64 21554 pic->coded_picture_number = 0;
65 21554 }
66
67 1388 static int av_cold mpv_pic_init(AVRefStructOpaque opaque, void *obj)
68 {
69 1388 MPVPicture *pic = obj;
70 1388 int ret, init_progress = (uintptr_t)opaque.nc;
71
72 1388 ret = ff_thread_progress_init(&pic->progress, init_progress);
73
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1388 times.
1388 if (ret < 0)
74 return ret;
75
76 1388 pic->f = av_frame_alloc();
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1388 times.
1388 if (!pic->f)
78 return AVERROR(ENOMEM);
79 1388 return 0;
80 }
81
82 1388 static void av_cold mpv_pic_free(AVRefStructOpaque unused, void *obj)
83 {
84 1388 MPVPicture *pic = obj;
85
86 1388 ff_thread_progress_destroy(&pic->progress);
87 1388 av_frame_free(&pic->f);
88 1388 }
89
90 832 av_cold AVRefStructPool *ff_mpv_alloc_pic_pool(int init_progress)
91 {
92 1664 return av_refstruct_pool_alloc_ext(sizeof(MPVPicture),
93 AV_REFSTRUCT_POOL_FLAG_FREE_ON_INIT_ERROR,
94 832 (void*)(uintptr_t)init_progress,
95 mpv_pic_init, mpv_pic_reset, mpv_pic_free, NULL);
96 }
97
98 39879 void ff_mpv_unref_picture(MPVWorkPicture *pic)
99 {
100 39879 av_refstruct_unref(&pic->ptr);
101 39879 memset(pic, 0, sizeof(*pic));
102 39879 }
103
104 38368 static void set_workpic_from_pic(MPVWorkPicture *wpic, const MPVPicture *pic)
105 {
106
2/2
✓ Branch 0 taken 115104 times.
✓ Branch 1 taken 38368 times.
153472 for (int i = 0; i < MPV_MAX_PLANES; i++) {
107 115104 wpic->data[i] = pic->f->data[i];
108 115104 wpic->linesize[i] = pic->f->linesize[i];
109 }
110 38368 wpic->qscale_table = pic->qscale_table;
111 38368 wpic->mb_type = pic->mb_type;
112 38368 wpic->mbskip_table = pic->mbskip_table;
113
114
2/2
✓ Branch 0 taken 76736 times.
✓ Branch 1 taken 38368 times.
115104 for (int i = 0; i < 2; i++) {
115 76736 wpic->motion_val[i] = pic->motion_val[i];
116 76736 wpic->ref_index[i] = pic->ref_index[i];
117 }
118 38368 wpic->reference = pic->reference;
119 38368 }
120
121 17950 void ff_mpv_replace_picture(MPVWorkPicture *dst, const MPVWorkPicture *src)
122 {
123 av_assert1(dst != src);
124 17950 av_refstruct_replace(&dst->ptr, src->ptr);
125 17950 memcpy(dst, src, sizeof(*dst));
126 17950 }
127
128 17134 void ff_mpv_workpic_from_pic(MPVWorkPicture *wpic, MPVPicture *pic)
129 {
130 17134 av_refstruct_replace(&wpic->ptr, pic);
131
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 16814 times.
17134 if (!pic) {
132 320 memset(wpic, 0, sizeof(*wpic));
133 320 return;
134 }
135 16814 set_workpic_from_pic(wpic, pic);
136 }
137
138 29170 int ff_mpv_framesize_alloc(AVCodecContext *avctx,
139 ScratchpadContext *sc, int linesize)
140 {
141 # define EMU_EDGE_HEIGHT (4 * 70)
142 29170 int linesizeabs = FFABS(linesize);
143 29170 int alloc_size = FFALIGN(linesizeabs + 64, 32);
144
145
2/2
✓ Branch 0 taken 28774 times.
✓ Branch 1 taken 396 times.
29170 if (linesizeabs <= sc->linesize)
146 28774 return 0;
147
148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 396 times.
396 if (avctx->hwaccel)
149 return 0;
150
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 396 times.
396 if (linesizeabs < 24) {
152 av_log(avctx, AV_LOG_ERROR, "Image too small, temporary buffers cannot function\n");
153 return AVERROR_PATCHWELCOME;
154 }
155
156
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 396 times.
396 if (av_image_check_size2(alloc_size, EMU_EDGE_HEIGHT, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0)
157 return AVERROR(ENOMEM);
158
159 396 av_freep(&sc->edge_emu_buffer);
160 396 av_freep(&sc->scratchpad_buf);
161
162 // edge emu needs blocksize + filter length - 1
163 // (= 17x17 for halfpel / 21x21 for H.264)
164 // VC-1 computes luma and chroma simultaneously and needs 19X19 + 9x9
165 // at uvlinesize. It supports only YUV420 so 24x24 is enough
166 // linesize * interlaced * MBsize
167 // we also use this buffer for encoding in encode_mb_internal() needig an additional 32 lines
168
1/2
✓ Branch 1 taken 396 times.
✗ Branch 2 not taken.
396 if (!FF_ALLOCZ_TYPED_ARRAY(sc->edge_emu_buffer, alloc_size * EMU_EDGE_HEIGHT) ||
169
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 396 times.
396 !FF_ALLOCZ_TYPED_ARRAY(sc->scratchpad_buf, alloc_size * 4 * 16 * 2)) {
170 sc->linesize = 0;
171 av_freep(&sc->edge_emu_buffer);
172 return AVERROR(ENOMEM);
173 }
174 396 sc->linesize = linesizeabs;
175
176 396 sc->obmc_scratchpad = sc->scratchpad_buf + 16;
177
178 396 return 0;
179 }
180
181 21604 int ff_mpv_pic_check_linesize(void *logctx, const AVFrame *f,
182 ptrdiff_t *linesizep, ptrdiff_t *uvlinesizep)
183 {
184 21604 ptrdiff_t linesize = *linesizep, uvlinesize = *uvlinesizep;
185
186
5/6
✓ Branch 0 taken 21160 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 21160 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21160 times.
✓ Branch 5 taken 444 times.
21604 if ((linesize && linesize != f->linesize[0]) ||
187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21160 times.
21160 (uvlinesize && uvlinesize != f->linesize[1])) {
188 av_log(logctx, AV_LOG_ERROR, "Stride change unsupported: "
189 "linesize=%"PTRDIFF_SPECIFIER"/%d uvlinesize=%"PTRDIFF_SPECIFIER"/%d)\n",
190 linesize, f->linesize[0],
191 uvlinesize, f->linesize[1]);
192 return AVERROR_PATCHWELCOME;
193 }
194
195
1/2
✓ Branch 1 taken 21604 times.
✗ Branch 2 not taken.
21604 if (av_pix_fmt_count_planes(f->format) > 2 &&
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21604 times.
21604 f->linesize[1] != f->linesize[2]) {
197 av_log(logctx, AV_LOG_ERROR, "uv stride mismatch unsupported\n");
198 return AVERROR_PATCHWELCOME;
199 }
200 21604 *linesizep = f->linesize[0];
201 21604 *uvlinesizep = f->linesize[1];
202
203 21604 return 0;
204 }
205
206 21554 static int alloc_picture_tables(BufferPoolContext *pools, MPVPicture *pic,
207 int mb_height)
208 {
209 #define GET_BUFFER(name, buf_suffix, idx_suffix) do { \
210 pic->name ## buf_suffix idx_suffix = av_refstruct_pool_get(pools->name ## _pool); \
211 if (!pic->name ## buf_suffix idx_suffix) \
212 return AVERROR(ENOMEM); \
213 } while (0)
214
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21554 times.
21554 GET_BUFFER(qscale_table, _base,);
215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21554 times.
21554 GET_BUFFER(mb_type, _base,);
216
2/2
✓ Branch 0 taken 17334 times.
✓ Branch 1 taken 4220 times.
21554 if (pools->motion_val_pool) {
217
2/2
✓ Branch 0 taken 6058 times.
✓ Branch 1 taken 11276 times.
17334 if (pools->mbskip_table_pool)
218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6058 times.
6058 GET_BUFFER(mbskip_table,,);
219
2/2
✓ Branch 0 taken 34668 times.
✓ Branch 1 taken 17334 times.
52002 for (int i = 0; i < 2; i++) {
220
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 34668 times.
34668 GET_BUFFER(ref_index,, [i]);
221
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 34668 times.
34668 GET_BUFFER(motion_val, _base, [i]);
222 34668 pic->motion_val[i] = pic->motion_val_base[i] + 4;
223 }
224 }
225 #undef GET_BUFFER
226
227 21554 pic->mb_width = pools->alloc_mb_width;
228 21554 pic->mb_height = mb_height;
229 21554 pic->mb_stride = pools->alloc_mb_stride;
230
231 21554 pic->qscale_table = pic->qscale_table_base + 2 * pic->mb_stride + 1;
232 21554 pic->mb_type = pic->mb_type_base + 2 * pic->mb_stride + 1;
233
234 21554 return 0;
235 }
236
237 21554 int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, MPVWorkPicture *wpic,
238 ScratchpadContext *sc,
239 BufferPoolContext *pools, int mb_height)
240 {
241 21554 MPVPicture *pic = wpic->ptr;
242 int ret;
243
244 21554 ret = ff_mpv_framesize_alloc(avctx, sc, pic->f->linesize[0]);
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21554 times.
21554 if (ret < 0)
246 goto fail;
247
248 21554 ret = alloc_picture_tables(pools, pic, mb_height);
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21554 times.
21554 if (ret < 0)
250 goto fail;
251
252 21554 set_workpic_from_pic(wpic, pic);
253
254 21554 return 0;
255 fail:
256 av_log(avctx, AV_LOG_ERROR, "Error allocating picture accessories.\n");
257 return ret;
258 }
259