FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/mpegpicture.c
Date: 2024-11-20 23:03:26
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 "refstruct.h"
30
31 21557 static void mpv_pic_reset(FFRefStructOpaque unused, void *obj)
32 {
33 21557 MPVPicture *pic = obj;
34
35 21557 av_frame_unref(pic->f);
36 21557 ff_thread_progress_reset(&pic->progress);
37
38 21557 ff_refstruct_unref(&pic->hwaccel_picture_private);
39
40 21557 ff_refstruct_unref(&pic->mbskip_table);
41 21557 ff_refstruct_unref(&pic->qscale_table_base);
42 21557 ff_refstruct_unref(&pic->mb_type_base);
43
44
2/2
✓ Branch 0 taken 43114 times.
✓ Branch 1 taken 21557 times.
64671 for (int i = 0; i < 2; i++) {
45 43114 ff_refstruct_unref(&pic->motion_val_base[i]);
46 43114 ff_refstruct_unref(&pic->ref_index[i]);
47
48 43114 pic->motion_val[i] = NULL;
49 }
50
51 21557 pic->mb_type = NULL;
52 21557 pic->qscale_table = NULL;
53
54 21557 pic->mb_stride =
55 21557 pic->mb_width =
56 21557 pic->mb_height = 0;
57
58 21557 pic->dummy = 0;
59 21557 pic->field_picture = 0;
60 21557 pic->b_frame_score = 0;
61 21557 pic->reference = 0;
62 21557 pic->shared = 0;
63 21557 pic->display_picture_number = 0;
64 21557 pic->coded_picture_number = 0;
65 21557 }
66
67 1388 static int av_cold mpv_pic_init(FFRefStructOpaque 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(FFRefStructOpaque 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 FFRefStructPool *ff_mpv_alloc_pic_pool(int init_progress)
91 {
92 1664 return ff_refstruct_pool_alloc_ext(sizeof(MPVPicture),
93 FF_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 39891 void ff_mpv_unref_picture(MPVWorkPicture *pic)
99 {
100 39891 ff_refstruct_unref(&pic->ptr);
101 39891 memset(pic, 0, sizeof(*pic));
102 39891 }
103
104 38385 static void set_workpic_from_pic(MPVWorkPicture *wpic, const MPVPicture *pic)
105 {
106
2/2
✓ Branch 0 taken 115155 times.
✓ Branch 1 taken 38385 times.
153540 for (int i = 0; i < MPV_MAX_PLANES; i++) {
107 115155 wpic->data[i] = pic->f->data[i];
108 115155 wpic->linesize[i] = pic->f->linesize[i];
109 }
110 38385 wpic->qscale_table = pic->qscale_table;
111 38385 wpic->mb_type = pic->mb_type;
112 38385 wpic->mbskip_table = pic->mbskip_table;
113
114
2/2
✓ Branch 0 taken 76770 times.
✓ Branch 1 taken 38385 times.
115155 for (int i = 0; i < 2; i++) {
115 76770 wpic->motion_val[i] = pic->motion_val[i];
116 76770 wpic->ref_index[i] = pic->ref_index[i];
117 }
118 38385 wpic->reference = pic->reference;
119 38385 }
120
121 17950 void ff_mpv_replace_picture(MPVWorkPicture *dst, const MPVWorkPicture *src)
122 {
123 av_assert1(dst != src);
124 17950 ff_refstruct_replace(&dst->ptr, src->ptr);
125 17950 memcpy(dst, src, sizeof(*dst));
126 17950 }
127
128 17148 void ff_mpv_workpic_from_pic(MPVWorkPicture *wpic, MPVPicture *pic)
129 {
130 17148 ff_refstruct_replace(&wpic->ptr, pic);
131
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 16828 times.
17148 if (!pic) {
132 320 memset(wpic, 0, sizeof(*wpic));
133 320 return;
134 }
135 16828 set_workpic_from_pic(wpic, pic);
136 }
137
138 29173 int ff_mpv_framesize_alloc(AVCodecContext *avctx,
139 ScratchpadContext *sc, int linesize)
140 {
141 # define EMU_EDGE_HEIGHT (4 * 70)
142 29173 int linesizeabs = FFABS(linesize);
143 29173 int alloc_size = FFALIGN(linesizeabs + 64, 32);
144
145
2/2
✓ Branch 0 taken 28737 times.
✓ Branch 1 taken 436 times.
29173 if (linesizeabs <= sc->linesize)
146 28737 return 0;
147
148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 436 times.
436 if (avctx->hwaccel)
149 return 0;
150
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 436 times.
436 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 436 times.
436 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 436 av_freep(&sc->edge_emu_buffer);
160 436 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 436 times.
✗ Branch 2 not taken.
436 if (!FF_ALLOCZ_TYPED_ARRAY(sc->edge_emu_buffer, alloc_size * EMU_EDGE_HEIGHT) ||
169
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 436 times.
436 !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 436 sc->linesize = linesizeabs;
175
176 436 sc->obmc_scratchpad = sc->scratchpad_buf + 16;
177
178 436 return 0;
179 }
180
181 21607 int ff_mpv_pic_check_linesize(void *logctx, const AVFrame *f,
182 ptrdiff_t *linesizep, ptrdiff_t *uvlinesizep)
183 {
184 21607 ptrdiff_t linesize = *linesizep, uvlinesize = *uvlinesizep;
185
186
5/6
✓ Branch 0 taken 21163 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 21163 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21163 times.
✓ Branch 5 taken 444 times.
21607 if ((linesize && linesize != f->linesize[0]) ||
187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21163 times.
21163 (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 21607 times.
✗ Branch 2 not taken.
21607 if (av_pix_fmt_count_planes(f->format) > 2 &&
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21607 times.
21607 f->linesize[1] != f->linesize[2]) {
197 av_log(logctx, AV_LOG_ERROR, "uv stride mismatch unsupported\n");
198 return AVERROR_PATCHWELCOME;
199 }
200 21607 *linesizep = f->linesize[0];
201 21607 *uvlinesizep = f->linesize[1];
202
203 21607 return 0;
204 }
205
206 21557 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 = ff_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 21557 times.
21557 GET_BUFFER(qscale_table, _base,);
215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21557 times.
21557 GET_BUFFER(mb_type, _base,);
216
2/2
✓ Branch 0 taken 17328 times.
✓ Branch 1 taken 4229 times.
21557 if (pools->motion_val_pool) {
217
2/2
✓ Branch 0 taken 6052 times.
✓ Branch 1 taken 11276 times.
17328 if (pools->mbskip_table_pool)
218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6052 times.
6052 GET_BUFFER(mbskip_table,,);
219
2/2
✓ Branch 0 taken 34656 times.
✓ Branch 1 taken 17328 times.
51984 for (int i = 0; i < 2; i++) {
220
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 34656 times.
34656 GET_BUFFER(ref_index,, [i]);
221
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 34656 times.
34656 GET_BUFFER(motion_val, _base, [i]);
222 34656 pic->motion_val[i] = pic->motion_val_base[i] + 4;
223 }
224 }
225 #undef GET_BUFFER
226
227 21557 pic->mb_width = pools->alloc_mb_width;
228 21557 pic->mb_height = mb_height;
229 21557 pic->mb_stride = pools->alloc_mb_stride;
230
231 21557 pic->qscale_table = pic->qscale_table_base + 2 * pic->mb_stride + 1;
232 21557 pic->mb_type = pic->mb_type_base + 2 * pic->mb_stride + 1;
233
234 21557 return 0;
235 }
236
237 21557 int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, MPVWorkPicture *wpic,
238 ScratchpadContext *sc,
239 BufferPoolContext *pools, int mb_height)
240 {
241 21557 MPVPicture *pic = wpic->ptr;
242 int ret;
243
244 21557 ret = ff_mpv_framesize_alloc(avctx, sc, pic->f->linesize[0]);
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21557 times.
21557 if (ret < 0)
246 goto fail;
247
248 21557 ret = alloc_picture_tables(pools, pic, mb_height);
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21557 times.
21557 if (ret < 0)
250 goto fail;
251
252 21557 set_workpic_from_pic(wpic, pic);
253
254 21557 return 0;
255 fail:
256 av_log(avctx, AV_LOG_ERROR, "Error allocating picture accessories.\n");
257 return ret;
258 }
259