Coverage Report

Created: 2025-08-28 07:12

/src/ffmpeg/libavutil/container_fifo.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * This file is part of FFmpeg.
3
 *
4
 * FFmpeg is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2.1 of the License, or (at your option) any later version.
8
 *
9
 * FFmpeg is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with FFmpeg; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
 */
18
19
#include "avassert.h"
20
#include "container_fifo.h"
21
#include "error.h"
22
#include "fifo.h"
23
#include "frame.h"
24
#include "mem.h"
25
#include "refstruct.h"
26
27
struct AVContainerFifo {
28
    AVFifo             *fifo;
29
    AVRefStructPool    *pool;
30
31
    void               *opaque;
32
    void*             (*container_alloc)(void *opaque);
33
    void              (*container_reset)(void *opaque, void *obj);
34
    void              (*container_free) (void *opaque, void *obj);
35
    int               (*fifo_transfer)  (void *opaque, void *dst, void *src, unsigned flags);
36
37
};
38
39
static int container_fifo_init_entry(AVRefStructOpaque opaque, void *obj)
40
9.71k
{
41
9.71k
    AVContainerFifo *cf = opaque.nc;
42
9.71k
    void **pobj = obj;
43
44
9.71k
    *pobj = cf->container_alloc(cf->opaque);
45
9.71k
    if (!*pobj)
46
0
        return AVERROR(ENOMEM);
47
48
9.71k
    return 0;
49
9.71k
}
50
51
static void container_fifo_reset_entry(AVRefStructOpaque opaque, void *obj)
52
44.7k
{
53
44.7k
    AVContainerFifo *cf = opaque.nc;
54
44.7k
    cf->container_reset(cf->opaque, *(void**)obj);
55
44.7k
}
56
57
static void container_fifo_free_entry(AVRefStructOpaque opaque, void *obj)
58
9.71k
{
59
9.71k
    AVContainerFifo *cf = opaque.nc;
60
9.71k
    cf->container_free(cf->opaque, *(void**)obj);
61
9.71k
}
62
63
AVContainerFifo*
64
av_container_fifo_alloc(void *opaque,
65
                        void* (*container_alloc)(void *opaque),
66
                        void  (*container_reset)(void *opaque, void *obj),
67
                        void  (*container_free) (void *opaque, void *obj),
68
                        int   (*fifo_transfer)  (void *opaque, void *dst, void *src, unsigned flags),
69
                        unsigned flags)
70
24.6k
{
71
24.6k
    AVContainerFifo *cf;
72
73
24.6k
    cf = av_mallocz(sizeof(*cf));
74
24.6k
    if (!cf)
75
0
        return NULL;
76
77
24.6k
    cf->opaque          = opaque;
78
24.6k
    cf->container_alloc = container_alloc;
79
24.6k
    cf->container_reset = container_reset;
80
24.6k
    cf->container_free  = container_free;
81
24.6k
    cf->fifo_transfer   = fifo_transfer;
82
83
24.6k
    cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW);
84
24.6k
    if (!cf->fifo)
85
0
        goto fail;
86
87
24.6k
    cf->pool = av_refstruct_pool_alloc_ext(sizeof(void*), 0, cf,
88
24.6k
                                           container_fifo_init_entry,
89
24.6k
                                           container_fifo_reset_entry,
90
24.6k
                                           container_fifo_free_entry,
91
24.6k
                                           NULL);
92
24.6k
    if (!cf->pool)
93
0
        goto fail;
94
95
24.6k
    return cf;
96
0
fail:
97
0
    av_container_fifo_free(&cf);
98
0
    return NULL;
99
24.6k
}
100
101
void av_container_fifo_free(AVContainerFifo **pcf)
102
24.6k
{
103
24.6k
    AVContainerFifo *cf;
104
105
24.6k
    if (!*pcf)
106
0
        return;
107
108
24.6k
    cf = *pcf;
109
110
24.6k
    if (cf->fifo) {
111
24.6k
        void *obj;
112
24.7k
        while (av_fifo_read(cf->fifo, &obj, 1) >= 0)
113
16
            av_refstruct_unref(&obj);
114
24.6k
        av_fifo_freep2(&cf->fifo);
115
24.6k
    }
116
117
24.6k
    av_refstruct_pool_uninit(&cf->pool);
118
119
24.6k
    av_freep(pcf);
120
24.6k
}
121
122
int av_container_fifo_read(AVContainerFifo *cf, void *obj, unsigned flags)
123
215k
{
124
215k
    void **psrc;
125
215k
    int ret;
126
127
215k
    ret = av_fifo_read(cf->fifo, &psrc, 1);
128
215k
    if (ret < 0)
129
170k
        return ret;
130
131
44.7k
    ret = cf->fifo_transfer(cf->opaque, obj, *psrc, flags);
132
44.7k
    av_refstruct_unref(&psrc);
133
134
44.7k
    return ret;
135
215k
}
136
137
int av_container_fifo_peek(AVContainerFifo *cf, void **pdst, size_t offset)
138
0
{
139
0
    void **pobj;
140
0
    int ret;
141
142
0
    ret = av_fifo_peek(cf->fifo, &pobj, 1, offset);
143
0
    if (ret < 0)
144
0
        return ret;
145
146
0
    *pdst = *pobj;
147
148
0
    return 0;
149
0
}
150
151
void av_container_fifo_drain(AVContainerFifo *cf, size_t nb_elems)
152
0
{
153
0
    av_assert0(nb_elems <= av_fifo_can_read(cf->fifo));
154
0
    while (nb_elems--) {
155
0
        void **pobj;
156
0
        int ret = av_fifo_read(cf->fifo, &pobj, 1);
157
0
        av_assert0(ret >= 0);
158
0
        av_refstruct_unref(&pobj);
159
0
    }
160
0
}
161
162
int av_container_fifo_write(AVContainerFifo *cf, void *obj, unsigned flags)
163
44.7k
{
164
44.7k
    void **pdst;
165
44.7k
    int ret;
166
167
44.7k
    pdst = av_refstruct_pool_get(cf->pool);
168
44.7k
    if (!pdst)
169
0
        return AVERROR(ENOMEM);
170
171
44.7k
    ret = cf->fifo_transfer(cf->opaque, *pdst, obj, flags);
172
44.7k
    if (ret < 0)
173
0
        goto fail;
174
175
44.7k
    ret = av_fifo_write(cf->fifo, &pdst, 1);
176
44.7k
    if (ret < 0)
177
0
        goto fail;
178
179
44.7k
    return 0;
180
0
fail:
181
0
    av_refstruct_unref(&pdst);
182
0
    return ret;
183
44.7k
}
184
185
size_t av_container_fifo_can_read(const AVContainerFifo *cf)
186
458k
{
187
458k
    return av_fifo_can_read(cf->fifo);
188
458k
}
189
190
static void *frame_alloc(void *opaque)
191
9.71k
{
192
9.71k
    return av_frame_alloc();
193
9.71k
}
194
195
static void frame_reset(void *opaque, void *obj)
196
44.7k
{
197
44.7k
    av_frame_unref(obj);
198
44.7k
}
199
200
static void frame_free(void *opaque, void *obj)
201
9.71k
{
202
9.71k
    AVFrame *frame = obj;
203
9.71k
    av_frame_free(&frame);
204
9.71k
}
205
206
static int frame_transfer(void *opaque, void *dst, void *src, unsigned flags)
207
89.5k
{
208
89.5k
    if (flags & AV_CONTAINER_FIFO_FLAG_REF)
209
44.7k
        return av_frame_ref(dst, src);
210
211
44.7k
    av_frame_move_ref(dst, src);
212
44.7k
    return 0;
213
89.5k
}
214
215
AVContainerFifo *av_container_fifo_alloc_avframe(unsigned flags)
216
24.6k
{
217
24.6k
    return av_container_fifo_alloc(NULL, frame_alloc, frame_reset, frame_free,
218
24.6k
                                   frame_transfer, 0);
219
24.6k
}