Coverage Report

Created: 2026-01-25 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavutil/container_fifo.c
Line
Count
Source
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
0
{
41
0
    AVContainerFifo *cf = opaque.nc;
42
0
    void **pobj = obj;
43
44
0
    *pobj = cf->container_alloc(cf->opaque);
45
0
    if (!*pobj)
46
0
        return AVERROR(ENOMEM);
47
48
0
    return 0;
49
0
}
50
51
static void container_fifo_reset_entry(AVRefStructOpaque opaque, void *obj)
52
0
{
53
0
    AVContainerFifo *cf = opaque.nc;
54
0
    cf->container_reset(cf->opaque, *(void**)obj);
55
0
}
56
57
static void container_fifo_free_entry(AVRefStructOpaque opaque, void *obj)
58
0
{
59
0
    AVContainerFifo *cf = opaque.nc;
60
0
    cf->container_free(cf->opaque, *(void**)obj);
61
0
}
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
0
{
71
0
    AVContainerFifo *cf;
72
73
0
    cf = av_mallocz(sizeof(*cf));
74
0
    if (!cf)
75
0
        return NULL;
76
77
0
    cf->opaque          = opaque;
78
0
    cf->container_alloc = container_alloc;
79
0
    cf->container_reset = container_reset;
80
0
    cf->container_free  = container_free;
81
0
    cf->fifo_transfer   = fifo_transfer;
82
83
0
    cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW);
84
0
    if (!cf->fifo)
85
0
        goto fail;
86
87
0
    cf->pool = av_refstruct_pool_alloc_ext(sizeof(void*), 0, cf,
88
0
                                           container_fifo_init_entry,
89
0
                                           container_fifo_reset_entry,
90
0
                                           container_fifo_free_entry,
91
0
                                           NULL);
92
0
    if (!cf->pool)
93
0
        goto fail;
94
95
0
    return cf;
96
0
fail:
97
0
    av_container_fifo_free(&cf);
98
0
    return NULL;
99
0
}
100
101
void av_container_fifo_free(AVContainerFifo **pcf)
102
0
{
103
0
    AVContainerFifo *cf;
104
105
0
    if (!*pcf)
106
0
        return;
107
108
0
    cf = *pcf;
109
110
0
    if (cf->fifo) {
111
0
        void *obj;
112
0
        while (av_fifo_read(cf->fifo, &obj, 1) >= 0)
113
0
            av_refstruct_unref(&obj);
114
0
        av_fifo_freep2(&cf->fifo);
115
0
    }
116
117
0
    av_refstruct_pool_uninit(&cf->pool);
118
119
0
    av_freep(pcf);
120
0
}
121
122
int av_container_fifo_read(AVContainerFifo *cf, void *obj, unsigned flags)
123
0
{
124
0
    void **psrc;
125
0
    int ret;
126
127
0
    ret = av_fifo_read(cf->fifo, &psrc, 1);
128
0
    if (ret < 0)
129
0
        return ret;
130
131
0
    ret = cf->fifo_transfer(cf->opaque, obj, *psrc, flags);
132
0
    av_refstruct_unref(&psrc);
133
134
0
    return ret;
135
0
}
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
0
{
164
0
    void **pdst;
165
0
    int ret;
166
167
0
    pdst = av_refstruct_pool_get(cf->pool);
168
0
    if (!pdst)
169
0
        return AVERROR(ENOMEM);
170
171
0
    ret = cf->fifo_transfer(cf->opaque, *pdst, obj, flags);
172
0
    if (ret < 0)
173
0
        goto fail;
174
175
0
    ret = av_fifo_write(cf->fifo, &pdst, 1);
176
0
    if (ret < 0)
177
0
        goto fail;
178
179
0
    return 0;
180
0
fail:
181
0
    av_refstruct_unref(&pdst);
182
0
    return ret;
183
0
}
184
185
size_t av_container_fifo_can_read(const AVContainerFifo *cf)
186
0
{
187
0
    return av_fifo_can_read(cf->fifo);
188
0
}
189
190
static void *frame_alloc(void *opaque)
191
0
{
192
0
    return av_frame_alloc();
193
0
}
194
195
static void frame_reset(void *opaque, void *obj)
196
0
{
197
0
    av_frame_unref(obj);
198
0
}
199
200
static void frame_free(void *opaque, void *obj)
201
0
{
202
0
    AVFrame *frame = obj;
203
0
    av_frame_free(&frame);
204
0
}
205
206
static int frame_transfer(void *opaque, void *dst, void *src, unsigned flags)
207
0
{
208
0
    if (flags & AV_CONTAINER_FIFO_FLAG_REF)
209
0
        return av_frame_ref(dst, src);
210
211
0
    av_frame_move_ref(dst, src);
212
0
    return 0;
213
0
}
214
215
AVContainerFifo *av_container_fifo_alloc_avframe(unsigned flags)
216
0
{
217
    return av_container_fifo_alloc(NULL, frame_alloc, frame_reset, frame_free,
218
0
                                   frame_transfer, 0);
219
0
}