Coverage Report

Created: 2026-10-28 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavutil/framepool.c
Line
Count
Source
1
/*
2
 * This file is part of FFmpeg.
3
 *
4
 * Copyright (c) 2015 Matthieu Bouron <matthieu.bouron stupeflix.com>
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 "framepool.h"
22
#include "avassert.h"
23
#include "avutil.h"
24
#include "buffer.h"
25
#include "frame.h"
26
#include "imgutils.h"
27
#include "imgutils_internal.h"
28
#include "mem.h"
29
#include "pixfmt.h"
30
31
static av_cold int frame_pool_video_init(int width, int height,
32
                                         enum AVPixelFormat format,
33
                                         int align, FFFramePool *pool)
34
0
{
35
0
    int ret;
36
37
0
    *pool = (FFFramePool) {
38
0
        .type = AVMEDIA_TYPE_VIDEO,
39
0
        .width = width,
40
0
        .height = height,
41
0
        .pix_fmt = format,
42
0
        .align = align,
43
0
    };
44
45
0
    if ((ret = av_image_check_size2(width, height, INT64_MAX, format, 0, NULL)) < 0)
46
0
        goto fail;
47
48
0
    ret = av_image_fill_linesizes(pool->linesize, pool->pix_fmt,
49
0
                                  FFALIGN(pool->width, align));
50
0
    if (ret < 0)
51
0
        goto fail;
52
53
0
    for (int i = 0; i < 4 && pool->linesize[i]; i++)
54
0
        pool->linesize[i] = FFALIGN(pool->linesize[i], pool->align);
55
56
0
    ptrdiff_t linesizes[4];
57
0
    for (int i = 0; i < 4; i++)
58
0
        linesizes[i] = pool->linesize[i];
59
60
0
    size_t sizes[4];
61
0
    ret = av_image_fill_plane_sizes(sizes, pool->pix_fmt,
62
0
                                    FFALIGN(pool->height, align),
63
0
                                    linesizes);
64
0
    if (ret < 0)
65
0
        goto fail;
66
67
0
    for (int i = 0; i < 4 && sizes[i]; i++) {
68
0
        if (sizes[i] > SIZE_MAX - align)
69
0
            goto fail;
70
0
        pool->pools[i] = av_buffer_pool_init(sizes[i] + align,
71
0
                                             CONFIG_MEMORY_POISONING
72
0
                                                 ? NULL
73
0
                                                 : av_buffer_allocz);
74
0
        if (!pool->pools[i]) {
75
0
            ret = AVERROR(ENOMEM);
76
0
            goto fail;
77
0
        }
78
0
    }
79
80
0
    return 0;
81
82
0
fail:
83
0
    ff_frame_pool_uninit(pool);
84
0
    return ret;
85
0
}
86
87
static av_cold int frame_pool_audio_init(int channels, int nb_samples,
88
                                         enum AVSampleFormat format,
89
                                         int align, FFFramePool *pool)
90
0
{
91
0
    int ret;
92
93
0
    int planar = av_sample_fmt_is_planar(format);
94
95
0
    *pool = (FFFramePool) {
96
0
        .type = AVMEDIA_TYPE_AUDIO,
97
0
        .planes = planar ? channels : 1,
98
0
        .channels = channels,
99
0
        .nb_samples = nb_samples,
100
0
        .sample_fmt = format,
101
0
        .align = align,
102
0
    };
103
104
0
    ret = av_samples_get_buffer_size(&pool->linesize[0], channels,
105
0
                                     nb_samples, format, 0);
106
0
    if (ret < 0)
107
0
        goto fail;
108
109
0
    if (pool->linesize[0] > SIZE_MAX - align) {
110
0
        ret = AVERROR(EINVAL);
111
0
        goto fail;
112
0
    }
113
114
0
    pool->pools[0] = av_buffer_pool_init(pool->linesize[0] + align,
115
0
                                         av_buffer_allocz);
116
0
    if (!pool->pools[0]) {
117
0
        ret = AVERROR(ENOMEM);
118
0
        goto fail;
119
0
    }
120
121
0
    return 0;
122
123
0
fail:
124
0
    ff_frame_pool_uninit(pool);
125
0
    return ret;
126
0
}
127
128
AVFrame *ff_frame_pool_get(FFFramePool *pool)
129
0
{
130
0
    const AVPixFmtDescriptor *desc;
131
132
0
    AVFrame *frame = av_frame_alloc();
133
0
    if (!frame)
134
0
        return NULL;
135
136
0
    switch(pool->type) {
137
0
    case AVMEDIA_TYPE_VIDEO:
138
0
        desc = av_pix_fmt_desc_get(pool->pix_fmt);
139
0
        if (!desc)
140
0
            goto fail;
141
142
0
        frame->width = pool->width;
143
0
        frame->height = pool->height;
144
0
        frame->format = pool->pix_fmt;
145
146
0
        for (int i = 0; i < 4; i++) {
147
0
            frame->linesize[i] = pool->linesize[i];
148
0
            if (!pool->pools[i])
149
0
                break;
150
151
0
            frame->buf[i] = av_buffer_pool_get(pool->pools[i]);
152
0
            if (!frame->buf[i])
153
0
                goto fail;
154
155
0
            frame->data[i] = (uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, pool->align);
156
0
        }
157
158
0
        if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
159
0
            enum AVPixelFormat format = pool->pix_fmt;
160
0
            if (format == AV_PIX_FMT_PAL8)
161
0
                format = AV_PIX_FMT_BGR8;
162
163
0
            av_assert0(frame->data[1] != NULL);
164
0
            if (avpriv_set_systematic_pal2((uint32_t *)frame->data[1], format) < 0)
165
0
                goto fail;
166
0
        }
167
168
0
        frame->extended_data = frame->data;
169
0
        break;
170
0
    case AVMEDIA_TYPE_AUDIO:
171
0
        frame->nb_samples = pool->nb_samples;
172
0
        frame->ch_layout.nb_channels = pool->channels;
173
0
        frame->format = pool->sample_fmt;
174
0
        frame->linesize[0] = pool->linesize[0];
175
176
0
        if (pool->planes > AV_NUM_DATA_POINTERS) {
177
0
            frame->extended_data = av_calloc(pool->planes,
178
0
                                             sizeof(*frame->extended_data));
179
0
            frame->nb_extended_buf = pool->planes - AV_NUM_DATA_POINTERS;
180
0
            frame->extended_buf  = av_calloc(frame->nb_extended_buf,
181
0
                                             sizeof(*frame->extended_buf));
182
0
            if (!frame->extended_data || !frame->extended_buf)
183
0
                goto fail;
184
0
        } else {
185
0
            frame->extended_data = frame->data;
186
0
            av_assert0(frame->nb_extended_buf == 0);
187
0
        }
188
189
0
        for (int i = 0; i < FFMIN(pool->planes, AV_NUM_DATA_POINTERS); i++) {
190
0
            frame->buf[i] = av_buffer_pool_get(pool->pools[0]);
191
0
            if (!frame->buf[i])
192
0
                goto fail;
193
0
            frame->extended_data[i] = frame->data[i] =
194
0
                (uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, pool->align);
195
0
        }
196
0
        for (int i = 0; i < frame->nb_extended_buf; i++) {
197
0
            frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]);
198
0
            if (!frame->extended_buf[i])
199
0
                goto fail;
200
0
            frame->extended_data[i + AV_NUM_DATA_POINTERS] =
201
0
                (uint8_t *)FFALIGN((uintptr_t)frame->extended_buf[i]->data, pool->align);
202
0
        }
203
204
0
        break;
205
0
    default:
206
0
        av_unreachable("only audio and video frame pools exist");
207
0
    }
208
209
0
    return frame;
210
0
fail:
211
0
    av_frame_free(&frame);
212
0
    return NULL;
213
0
}
214
215
av_cold void ff_frame_pool_uninit(FFFramePool *pool)
216
0
{
217
0
    for (int i = 0; i < 4; i++)
218
0
        av_buffer_pool_uninit(&pool->pools[i]);
219
220
0
    memset(pool, 0, sizeof(*pool));
221
0
}
222
223
int ff_frame_pool_video_reinit(FFFramePool *pool,
224
                               int width,
225
                               int height,
226
                               enum AVPixelFormat format,
227
                               int align)
228
0
{
229
0
    if (pool->type == AVMEDIA_TYPE_VIDEO &&
230
0
        pool->pix_fmt == format &&
231
0
        FFALIGN(pool->width,  pool->align) == FFALIGN(width,  align) &&
232
0
        FFALIGN(pool->height, pool->align) == FFALIGN(height, align) &&
233
0
        pool->align == align)
234
0
    {
235
0
        pool->width = width;
236
0
        pool->height = height;
237
0
        return 0;
238
0
    }
239
240
0
    ff_frame_pool_uninit(pool);
241
0
    return frame_pool_video_init(width, height, format, align, pool);
242
0
}
243
244
int ff_frame_pool_audio_reinit(FFFramePool *pool,
245
                               int channels,
246
                               int nb_samples,
247
                               enum AVSampleFormat format,
248
                               int align)
249
0
{
250
0
    if (pool->type == AVMEDIA_TYPE_AUDIO &&
251
0
        pool->sample_fmt == format &&
252
0
        pool->channels == channels &&
253
0
        pool->nb_samples == nb_samples &&
254
0
        pool->align == align)
255
0
    {
256
0
        return 0;
257
0
    }
258
259
0
    ff_frame_pool_uninit(pool);
260
0
    return frame_pool_audio_init(channels, nb_samples, format, align, pool);
261
0
}