FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/get_buffer.c
Date: 2024-04-19 17:50:32
Exec Total Coverage
Lines: 97 149 65.1%
Functions: 5 5 100.0%
Branches: 65 100 65.0%

Line Branch Exec Source
1 /*
2 * The default get_buffer2() implementation
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 <stdint.h>
22
23 #include "libavutil/avassert.h"
24 #include "libavutil/avutil.h"
25 #include "libavutil/buffer.h"
26 #include "libavutil/frame.h"
27 #include "libavutil/hwcontext.h"
28 #include "libavutil/imgutils.h"
29 #include "libavutil/mem.h"
30 #include "libavutil/samplefmt.h"
31 #include "libavutil/version.h"
32
33 #include "avcodec.h"
34 #include "internal.h"
35 #include "refstruct.h"
36
37 typedef struct FramePool {
38 /**
39 * Pools for each data plane. For audio all the planes have the same size,
40 * so only pools[0] is used.
41 */
42 AVBufferPool *pools[4];
43
44 /*
45 * Pool parameters
46 */
47 int format;
48 int width, height;
49 int stride_align[AV_NUM_DATA_POINTERS];
50 int linesize[4];
51 int planes;
52 int channels;
53 int samples;
54 } FramePool;
55
56 14929 static void frame_pool_free(FFRefStructOpaque unused, void *obj)
57 {
58 14929 FramePool *pool = obj;
59 int i;
60
61
2/2
✓ Branch 0 taken 59716 times.
✓ Branch 1 taken 14929 times.
74645 for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
62 59716 av_buffer_pool_uninit(&pool->pools[i]);
63 14929 }
64
65 378162 static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
66 {
67 378162 FramePool *pool = avctx->internal->pool;
68 int i, ret, ch, planes;
69
70
2/2
✓ Branch 0 taken 257084 times.
✓ Branch 1 taken 121078 times.
378162 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
71 257084 int planar = av_sample_fmt_is_planar(frame->format);
72 257084 ch = frame->ch_layout.nb_channels;
73
2/2
✓ Branch 0 taken 161202 times.
✓ Branch 1 taken 95882 times.
257084 planes = planar ? ch : 1;
74 }
75
76
4/4
✓ Branch 0 taken 370011 times.
✓ Branch 1 taken 8151 times.
✓ Branch 2 taken 369831 times.
✓ Branch 3 taken 180 times.
378162 if (pool && pool->format == frame->format) {
77
2/2
✓ Branch 0 taken 114647 times.
✓ Branch 1 taken 255184 times.
369831 if (avctx->codec_type == AVMEDIA_TYPE_VIDEO &&
78
4/4
✓ Branch 0 taken 114422 times.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 114409 times.
✓ Branch 3 taken 13 times.
114647 pool->width == frame->width && pool->height == frame->height)
79 114409 return 0;
80
4/4
✓ Branch 0 taken 255184 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 255171 times.
✓ Branch 3 taken 13 times.
255422 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && pool->planes == planes &&
81
3/4
✓ Branch 0 taken 255171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 248824 times.
✓ Branch 3 taken 6347 times.
255171 pool->channels == ch && frame->nb_samples == pool->samples)
82 248824 return 0;
83 }
84
85 14929 pool = ff_refstruct_alloc_ext(sizeof(*pool), 0, NULL, frame_pool_free);
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14929 times.
14929 if (!pool)
87 return AVERROR(ENOMEM);
88
89
2/3
✓ Branch 0 taken 6669 times.
✓ Branch 1 taken 8260 times.
✗ Branch 2 not taken.
14929 switch (avctx->codec_type) {
90 6669 case AVMEDIA_TYPE_VIDEO: {
91 int linesize[4];
92 6669 int w = frame->width;
93 6669 int h = frame->height;
94 int unaligned;
95 ptrdiff_t linesize1[4];
96 size_t size[4];
97
98 6669 avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align);
99
100 do {
101 // NOTE: do not align linesizes individually, this breaks e.g. assumptions
102 // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2
103 13305 ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w);
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13305 times.
13305 if (ret < 0)
105 goto fail;
106 // increase alignment of w for next try (rhs gives the lowest bit set in w)
107 13305 w += w & ~(w - 1);
108
109 13305 unaligned = 0;
110
2/2
✓ Branch 0 taken 53220 times.
✓ Branch 1 taken 13305 times.
66525 for (i = 0; i < 4; i++)
111 53220 unaligned |= linesize[i] % pool->stride_align[i];
112
2/2
✓ Branch 0 taken 6636 times.
✓ Branch 1 taken 6669 times.
13305 } while (unaligned);
113
114
2/2
✓ Branch 0 taken 26676 times.
✓ Branch 1 taken 6669 times.
33345 for (i = 0; i < 4; i++)
115 26676 linesize1[i] = linesize[i];
116 6669 ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1);
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6669 times.
6669 if (ret < 0)
118 goto fail;
119
120
2/2
✓ Branch 0 taken 26676 times.
✓ Branch 1 taken 6669 times.
33345 for (i = 0; i < 4; i++) {
121 26676 pool->linesize[i] = linesize[i];
122
2/2
✓ Branch 0 taken 18466 times.
✓ Branch 1 taken 8210 times.
26676 if (size[i]) {
123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18466 times.
18466 if (size[i] > INT_MAX - (16 + STRIDE_ALIGN - 1)) {
124 ret = AVERROR(EINVAL);
125 goto fail;
126 }
127 18466 pool->pools[i] = av_buffer_pool_init(size[i] + 16 + STRIDE_ALIGN - 1,
128 CONFIG_MEMORY_POISONING ?
129 NULL :
130 av_buffer_allocz);
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18466 times.
18466 if (!pool->pools[i]) {
132 ret = AVERROR(ENOMEM);
133 goto fail;
134 }
135 }
136 }
137 6669 pool->format = frame->format;
138 6669 pool->width = frame->width;
139 6669 pool->height = frame->height;
140
141 6669 break;
142 }
143 8260 case AVMEDIA_TYPE_AUDIO: {
144 8260 ret = av_samples_get_buffer_size(&pool->linesize[0], ch,
145 8260 frame->nb_samples, frame->format, 0);
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8260 times.
8260 if (ret < 0)
147 goto fail;
148
149 8260 pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL);
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8260 times.
8260 if (!pool->pools[0]) {
151 ret = AVERROR(ENOMEM);
152 goto fail;
153 }
154
155 8260 pool->format = frame->format;
156 8260 pool->planes = planes;
157 8260 pool->channels = ch;
158 8260 pool->samples = frame->nb_samples;
159 8260 break;
160 }
161 default: av_assert0(0);
162 }
163
164 14929 ff_refstruct_unref(&avctx->internal->pool);
165 14929 avctx->internal->pool = pool;
166
167 14929 return 0;
168 fail:
169 ff_refstruct_unref(&pool);
170 return ret;
171 }
172
173 257084 static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
174 {
175 257084 FramePool *pool = avctx->internal->pool;
176 257084 int planes = pool->planes;
177 int i;
178
179 257084 frame->linesize[0] = pool->linesize[0];
180
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 257084 times.
257084 if (planes > AV_NUM_DATA_POINTERS) {
182 frame->extended_data = av_calloc(planes, sizeof(*frame->extended_data));
183 frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
184 frame->extended_buf = av_calloc(frame->nb_extended_buf,
185 sizeof(*frame->extended_buf));
186 if (!frame->extended_data || !frame->extended_buf) {
187 av_freep(&frame->extended_data);
188 av_freep(&frame->extended_buf);
189 return AVERROR(ENOMEM);
190 }
191 } else {
192 257084 frame->extended_data = frame->data;
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 257084 times.
257084 av_assert0(frame->nb_extended_buf == 0);
194 }
195
196
2/2
✓ Branch 0 taken 400339 times.
✓ Branch 1 taken 257084 times.
657423 for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
197 400339 frame->buf[i] = av_buffer_pool_get(pool->pools[0]);
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 400339 times.
400339 if (!frame->buf[i])
199 goto fail;
200 400339 frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;
201 }
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 257084 times.
257084 for (i = 0; i < frame->nb_extended_buf; i++) {
203 frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]);
204 if (!frame->extended_buf[i])
205 goto fail;
206 frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data;
207 }
208
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 257084 times.
257084 if (avctx->debug & FF_DEBUG_BUFFERS)
210 av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame);
211
212 257084 return 0;
213 fail:
214 av_frame_unref(frame);
215 return AVERROR(ENOMEM);
216 }
217
218 121078 static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
219 {
220 121078 FramePool *pool = s->internal->pool;
221 int i;
222
223
4/8
✓ Branch 0 taken 121078 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121078 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121078 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 121078 times.
121078 if (pic->data[0] || pic->data[1] || pic->data[2] || pic->data[3]) {
224 av_log(s, AV_LOG_ERROR, "pic->data[*]!=NULL in avcodec_default_get_buffer\n");
225 return -1;
226 }
227
228 121078 memset(pic->data, 0, sizeof(pic->data));
229 121078 pic->extended_data = pic->data;
230
231
4/4
✓ Branch 0 taken 462136 times.
✓ Branch 1 taken 891 times.
✓ Branch 2 taken 341949 times.
✓ Branch 3 taken 120187 times.
463027 for (i = 0; i < 4 && pool->pools[i]; i++) {
232 341949 pic->linesize[i] = pool->linesize[i];
233
234 341949 pic->buf[i] = av_buffer_pool_get(pool->pools[i]);
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341949 times.
341949 if (!pic->buf[i])
236 goto fail;
237
238 341949 pic->data[i] = pic->buf[i]->data;
239 }
240
2/2
✓ Branch 0 taken 626675 times.
✓ Branch 1 taken 121078 times.
747753 for (; i < AV_NUM_DATA_POINTERS; i++) {
241 626675 pic->data[i] = NULL;
242 626675 pic->linesize[i] = 0;
243 }
244
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121078 times.
121078 if (s->debug & FF_DEBUG_BUFFERS)
246 av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic);
247
248 121078 return 0;
249 fail:
250 av_frame_unref(pic);
251 return AVERROR(ENOMEM);
252 }
253
254 378162 int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags)
255 {
256 int ret;
257
258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 378162 times.
378162 if (avctx->hw_frames_ctx) {
259 ret = av_hwframe_get_buffer(avctx->hw_frames_ctx, frame, 0);
260 if (ret == AVERROR(ENOMEM)) {
261 AVHWFramesContext *frames_ctx =
262 (AVHWFramesContext*)avctx->hw_frames_ctx->data;
263 if (frames_ctx->initial_pool_size > 0 &&
264 !avctx->internal->warned_on_failed_allocation_from_fixed_pool) {
265 av_log(avctx, AV_LOG_WARNING, "Failed to allocate a %s/%s "
266 "frame from a fixed pool of hardware frames.\n",
267 av_get_pix_fmt_name(frames_ctx->format),
268 av_get_pix_fmt_name(frames_ctx->sw_format));
269 av_log(avctx, AV_LOG_WARNING, "Consider setting "
270 "extra_hw_frames to a larger value "
271 "(currently set to %d, giving a pool size of %d).\n",
272 avctx->extra_hw_frames, frames_ctx->initial_pool_size);
273 avctx->internal->warned_on_failed_allocation_from_fixed_pool = 1;
274 }
275 }
276 frame->width = avctx->coded_width;
277 frame->height = avctx->coded_height;
278 return ret;
279 }
280
281
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 378162 times.
378162 if ((ret = update_frame_pool(avctx, frame)) < 0)
282 return ret;
283
284
2/3
✓ Branch 0 taken 121078 times.
✓ Branch 1 taken 257084 times.
✗ Branch 2 not taken.
378162 switch (avctx->codec_type) {
285 121078 case AVMEDIA_TYPE_VIDEO:
286 121078 return video_get_buffer(avctx, frame);
287 257084 case AVMEDIA_TYPE_AUDIO:
288 257084 return audio_get_buffer(avctx, frame);
289 default:
290 return -1;
291 }
292 }
293