Coverage Report

Created: 2026-02-05 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/test/src/input/decoder.c
Line
Count
Source
1
/*****************************************************************************
2
 * decoder.c
3
 *****************************************************************************
4
 * Copyright (C) 2017 VLC authors and VideoLAN
5
 *
6
 * Authors: Shaleen Jain <shaleen.jain95@gmail.com>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
23
#ifdef HAVE_CONFIG_H
24
# include "config.h"
25
#endif
26
27
#include <vlc_common.h>
28
#include <vlc_modules.h>
29
#include <vlc_codec.h>
30
#include <vlc_stream.h>
31
#include <vlc_access.h>
32
#include <vlc_meta.h>
33
#include <vlc_block.h>
34
#include <vlc_url.h>
35
36
#include <vlc/libvlc.h>
37
#include "../lib/libvlc_internal.h"
38
39
#include "common.h"
40
#include "decoder.h"
41
42
struct decoder_owner
43
{
44
    decoder_t dec;
45
    es_format_t fmt_in;
46
    decoder_t *packetizer;
47
};
48
49
static inline struct decoder_owner *dec_get_owner(decoder_t *dec)
50
64.0M
{
51
64.0M
    return container_of(dec, struct decoder_owner, dec);
52
64.0M
}
53
54
static subpicture_t *spu_new_buffer_decoder(decoder_t *dec,
55
                                            const subpicture_updater_t * p_subpic)
56
269k
{
57
269k
    (void) dec;
58
269k
    return subpicture_New (p_subpic);
59
269k
}
60
61
static vlc_decoder_device * get_no_device( decoder_t *dec )
62
0
{
63
0
    (void) dec;
64
    // no decoder device for this test
65
0
    return NULL;
66
0
}
67
68
static void queue_video(decoder_t *dec, picture_t *pic)
69
4.03k
{
70
4.03k
    (void) dec;
71
4.03k
    picture_Release(pic);
72
4.03k
}
73
74
static void queue_audio(decoder_t *dec, block_t *p_block)
75
0
{
76
0
    (void) dec;
77
0
    block_Release(p_block);
78
0
}
79
static void queue_cc(decoder_t *dec, block_t *p_block, const decoder_cc_desc_t *desc)
80
0
{
81
0
    (void) dec; (void) desc;
82
0
    block_Release(p_block);
83
0
}
84
static void queue_sub(decoder_t *dec, subpicture_t *p_subpic)
85
268k
{
86
268k
    (void) dec;
87
268k
    subpicture_Delete(p_subpic);
88
268k
}
89
90
static decoder_t *decoder_create(vlc_object_t *parent)
91
4.21M
{
92
4.21M
    struct decoder_owner *owner = vlc_object_create(parent, sizeof(*owner));
93
4.21M
    if (unlikely(owner == NULL))
94
0
        return NULL;
95
4.21M
    return &owner->dec;
96
4.21M
}
97
98
static int decoder_load(decoder_t *decoder, bool is_packetizer,
99
                         const es_format_t *restrict fmt)
100
4.22M
{
101
4.22M
    struct decoder_owner *owner = dec_get_owner(decoder);
102
103
4.22M
    decoder_Init( decoder, &owner->fmt_in, fmt );
104
105
4.22M
    decoder->b_frame_drop_allowed = true;
106
107
4.22M
    decoder_LoadModule(decoder, is_packetizer, false);
108
4.22M
    if (!decoder->p_module)
109
595k
    {
110
595k
        es_format_Clean( &owner->fmt_in );
111
595k
        decoder_Clean( decoder );
112
595k
        return VLC_EGENERIC;
113
595k
    }
114
3.62M
    return VLC_SUCCESS;
115
4.22M
}
116
117
static void decoder_destroy_clean(decoder_t *decoder)
118
4.21M
{
119
4.21M
    struct decoder_owner *owner = dec_get_owner(decoder);
120
4.21M
    es_format_Clean(&owner->fmt_in);
121
4.21M
    decoder_Destroy(decoder);
122
4.21M
}
123
124
void test_decoder_destroy(decoder_t *decoder)
125
1.51M
{
126
1.51M
    struct decoder_owner *owner = dec_get_owner(decoder);
127
1.51M
    decoder_destroy_clean(owner->packetizer);
128
1.51M
    decoder_destroy_clean(decoder);
129
1.51M
}
130
131
decoder_t *test_decoder_create(vlc_object_t *parent, const es_format_t *fmt)
132
2.10M
{
133
2.10M
    assert(parent && fmt);
134
2.10M
    decoder_t *packetizer = decoder_create(parent);
135
2.10M
    decoder_t *decoder = decoder_create(parent);
136
137
2.10M
    if (packetizer == NULL || decoder == NULL)
138
0
    {
139
0
        if (packetizer)
140
0
            decoder_destroy_clean(packetizer);
141
0
        return NULL;
142
0
    }
143
144
2.10M
    struct decoder_owner *owner = dec_get_owner(decoder);
145
2.10M
    owner->packetizer = packetizer;
146
147
2.10M
    static const struct decoder_owner_callbacks dec_video_cbs =
148
2.10M
    {
149
2.10M
        .video = {
150
2.10M
            .get_device = get_no_device,
151
2.10M
            .queue = queue_video,
152
2.10M
            .queue_cc = queue_cc,
153
2.10M
        },
154
2.10M
    };
155
2.10M
    static const struct decoder_owner_callbacks dec_audio_cbs =
156
2.10M
    {
157
2.10M
        .audio = {
158
2.10M
            .queue = queue_audio,
159
2.10M
        },
160
2.10M
    };
161
2.10M
    static const struct decoder_owner_callbacks dec_spu_cbs =
162
2.10M
    {
163
2.10M
        .spu = {
164
2.10M
            .buffer_new = spu_new_buffer_decoder,
165
2.10M
            .queue = queue_sub,
166
2.10M
        },
167
2.10M
    };
168
169
2.10M
    switch (fmt->i_cat)
170
2.10M
    {
171
51.6k
        case VIDEO_ES:
172
51.6k
            decoder->cbs = &dec_video_cbs;
173
51.6k
            break;
174
2.04M
        case AUDIO_ES:
175
2.04M
            decoder->cbs = &dec_audio_cbs;
176
2.04M
            break;
177
16.7k
        case SPU_ES:
178
16.7k
            decoder->cbs = &dec_spu_cbs;
179
16.7k
            break;
180
270
        default:
181
270
            decoder_destroy_clean(packetizer);
182
270
            decoder_destroy_clean(decoder);
183
270
            return NULL;
184
2.10M
    }
185
186
2.10M
    if (decoder_load(packetizer, true, fmt) != VLC_SUCCESS)
187
1.17k
    {
188
1.17k
        decoder_destroy_clean(packetizer);
189
1.17k
        decoder_destroy_clean(decoder);
190
1.17k
        return NULL;
191
1.17k
    }
192
193
2.10M
    if (decoder_load(decoder, false, &packetizer->fmt_out) != VLC_SUCCESS)
194
594k
    {
195
594k
        decoder_destroy_clean(packetizer);
196
594k
        decoder_destroy_clean(decoder);
197
594k
        return NULL;
198
594k
    }
199
200
1.51M
    return decoder;
201
2.10M
}
202
203
int test_decoder_process(decoder_t *decoder, block_t *p_block)
204
52.0M
{
205
52.0M
    struct decoder_owner *owner = dec_get_owner(decoder);
206
52.0M
    decoder_t *packetizer = owner->packetizer;
207
208
    /* This case can happen if a decoder reload failed */
209
52.0M
    if (decoder->p_module == NULL)
210
0
    {
211
0
        if (p_block != NULL)
212
0
            block_Release(p_block);
213
0
        return VLC_EGENERIC;
214
0
    }
215
216
52.0M
    block_t **pp_block = p_block ? &p_block : NULL;
217
52.0M
    block_t *p_packetized_block;
218
83.4M
    while ((p_packetized_block =
219
83.4M
                packetizer->pf_packetize(packetizer, pp_block)))
220
31.4M
    {
221
222
31.4M
        if (!es_format_IsSimilar(decoder->fmt_in, &packetizer->fmt_out))
223
5.26k
        {
224
5.26k
            debug("restarting module due to input format change\n");
225
226
            /* Drain the decoder module */
227
5.26k
            decoder->pf_decode(decoder, NULL);
228
229
            /* Reload decoder */
230
5.26k
            es_format_Clean( &owner->fmt_in );
231
5.26k
            decoder_Clean(decoder);
232
5.26k
            if (decoder_load(decoder, false, &packetizer->fmt_out) != VLC_SUCCESS)
233
0
            {
234
0
                block_ChainRelease(p_packetized_block);
235
0
                return VLC_EGENERIC;
236
0
            }
237
5.26k
        }
238
239
31.4M
        if (packetizer->pf_get_cc)
240
0
        {
241
0
            decoder_cc_desc_t desc;
242
0
            block_t *p_cc = packetizer->pf_get_cc(packetizer, &desc);
243
0
            if (p_cc)
244
0
                block_Release(p_cc);
245
0
        }
246
247
62.8M
        while (p_packetized_block != NULL)
248
31.4M
        {
249
250
31.4M
            block_t *p_next = p_packetized_block->p_next;
251
31.4M
            p_packetized_block->p_next = NULL;
252
253
31.4M
            int ret = decoder->pf_decode(decoder, p_packetized_block);
254
255
31.4M
            if (ret == VLCDEC_ECRITICAL)
256
0
            {
257
0
                block_ChainRelease(p_next);
258
0
                return VLC_EGENERIC;
259
0
            }
260
261
31.4M
            p_packetized_block = p_next;
262
31.4M
        }
263
31.4M
    }
264
52.0M
    if (p_block == NULL) /* Drain */
265
52.0M
        decoder->pf_decode(decoder, NULL);
266
52.0M
    return VLC_SUCCESS;
267
52.0M
}