Coverage Report

Created: 2026-10-28 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/format.c
Line
Count
Source
1
/*
2
 * Format register and lookup
3
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include "config_components.h"
23
24
#include "libavutil/avstring.h"
25
#include "libavutil/mem.h"
26
#include "libavutil/opt.h"
27
28
#include "avio_internal.h"
29
#include "avformat.h"
30
#include "demux.h"
31
#include "id3v2.h"
32
#include "internal.h"
33
#include "url.h"
34
35
36
/**
37
 * @file
38
 * Format register and lookup
39
 */
40
41
int av_match_ext(const char *filename, const char *extensions)
42
0
{
43
0
    const char *ext;
44
45
0
    if (!filename)
46
0
        return 0;
47
48
0
    ext = strrchr(filename, '.');
49
0
    if (ext)
50
0
        return av_match_name(ext + 1, extensions);
51
0
    return 0;
52
0
}
53
54
int ff_match_url_ext(const char *url, const char *extensions)
55
0
{
56
0
    const char *ext;
57
0
    URLComponents uc;
58
0
    int ret;
59
0
    char scratchpad[128];
60
61
0
    if (!url)
62
0
        return 0;
63
64
0
    ret = ff_url_decompose(&uc, url, NULL);
65
0
    if (ret < 0 || !URL_COMPONENT_HAVE(uc, scheme))
66
0
        return ret;
67
0
    for (ext = uc.query; *ext != '.' && ext > uc.path; ext--)
68
0
        ;
69
70
0
    if (*ext != '.')
71
0
        return 0;
72
0
    if (uc.query - ext > sizeof(scratchpad))
73
0
        return AVERROR(ENOMEM); //not enough memory in our scratchpad
74
0
    av_strlcpy(scratchpad, ext + 1, uc.query - ext);
75
76
0
    return av_match_name(scratchpad, extensions);
77
0
}
78
79
const AVOutputFormat *av_guess_format(const char *short_name, const char *filename,
80
                                      const char *mime_type)
81
0
{
82
0
    const AVOutputFormat *fmt = NULL;
83
0
    const AVOutputFormat *fmt_found = NULL;
84
0
    void *i = 0;
85
0
    int score_max, score;
86
87
    /* specific test for image sequences */
88
#if CONFIG_IMAGE2_MUXER
89
    if (!short_name && filename &&
90
        av_filename_number_test(filename) &&
91
        ff_guess_image2_codec(filename) != AV_CODEC_ID_NONE) {
92
        return av_guess_format("image2", NULL, NULL);
93
    }
94
#endif
95
    /* Find the proper file type. */
96
0
    score_max = 0;
97
0
    while ((fmt = av_muxer_iterate(&i))) {
98
0
        if (fmt->flags & AVFMT_EXPERIMENTAL && !short_name)
99
0
            continue;
100
0
        score = 0;
101
0
        if (fmt->name && short_name && av_match_name(short_name, fmt->name))
102
0
            score += 100;
103
0
        if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
104
0
            score += 10;
105
0
        if (filename && fmt->extensions &&
106
0
            av_match_ext(filename, fmt->extensions)) {
107
0
            score += 5;
108
0
        }
109
0
        if (score > score_max) {
110
0
            score_max = score;
111
0
            fmt_found = fmt;
112
0
        }
113
0
    }
114
0
    return fmt_found;
115
0
}
116
117
enum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name,
118
                              const char *filename, const char *mime_type,
119
                              enum AVMediaType type)
120
0
{
121
0
    if (av_match_name("segment", fmt->name) || av_match_name("ssegment", fmt->name)) {
122
0
        const AVOutputFormat *fmt2 = av_guess_format(NULL, filename, NULL);
123
0
        if (fmt2)
124
0
            fmt = fmt2;
125
0
    }
126
127
0
    if (type == AVMEDIA_TYPE_VIDEO) {
128
0
        enum AVCodecID codec_id = AV_CODEC_ID_NONE;
129
130
#if CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER
131
        if (!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")) {
132
            codec_id = ff_guess_image2_codec(filename);
133
        }
134
#endif
135
0
        if (codec_id == AV_CODEC_ID_NONE)
136
0
            codec_id = fmt->video_codec;
137
0
        return codec_id;
138
0
    } else if (type == AVMEDIA_TYPE_AUDIO)
139
0
        return fmt->audio_codec;
140
0
    else if (type == AVMEDIA_TYPE_SUBTITLE)
141
0
        return fmt->subtitle_codec;
142
0
    else
143
0
        return AV_CODEC_ID_NONE;
144
0
}
145
146
const AVInputFormat *av_find_input_format(const char *short_name)
147
0
{
148
0
    const AVInputFormat *fmt = NULL;
149
0
    void *i = 0;
150
0
    while ((fmt = av_demuxer_iterate(&i)))
151
0
        if (av_match_name(short_name, fmt->name))
152
0
            return fmt;
153
0
    return NULL;
154
0
}
155
156
static const AVInputFormat *
157
probe_input_format_internal(const AVProbeData *pd, int is_opened,
158
                            int *score_ret, int *undecided)
159
1.43k
{
160
1.43k
    AVProbeData lpd = *pd;
161
1.43k
    const AVInputFormat *fmt1 = NULL;
162
1.43k
    const AVInputFormat *fmt = NULL;
163
1.43k
    int score, score_max = 0;
164
1.43k
    void *i = 0;
165
1.43k
    const static uint8_t zerobuffer[AVPROBE_PADDING_SIZE];
166
1.43k
    enum nodat {
167
1.43k
        NO_ID3,
168
1.43k
        ID3_ALMOST_GREATER_PROBE,
169
1.43k
        ID3_GREATER_PROBE,
170
1.43k
        ID3_GREATER_MAX_PROBE,
171
1.43k
    } nodat = NO_ID3;
172
173
1.43k
    if (!lpd.buf)
174
1.43k
        lpd.buf = (unsigned char *) zerobuffer;
175
176
1.43k
    while (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) {
177
0
        int id3len = ff_id3v2_tag_len(lpd.buf);
178
0
        if (lpd.buf_size > id3len + 16) {
179
0
            if (lpd.buf_size < 2LL*id3len + 16)
180
0
                nodat = ID3_ALMOST_GREATER_PROBE;
181
0
            lpd.buf      += id3len;
182
0
            lpd.buf_size -= id3len;
183
0
        } else if (id3len >= PROBE_BUF_MAX) {
184
0
            nodat = ID3_GREATER_MAX_PROBE;
185
0
            break;
186
0
        } else {
187
0
            nodat = ID3_GREATER_PROBE;
188
0
            break;
189
0
        }
190
0
    }
191
192
1.43k
    while ((fmt1 = av_demuxer_iterate(&i))) {
193
0
        if (fmt1->flags & AVFMT_EXPERIMENTAL)
194
0
            continue;
195
0
        if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2"))
196
0
            continue;
197
0
        score = 0;
198
0
        if (ffifmt(fmt1)->read_probe) {
199
0
            score = ffifmt(fmt1)->read_probe(&lpd);
200
0
            if (score == AVERROR(EAGAIN)) {
201
0
                av_log(NULL, AV_LOG_TRACE, "Probing %s score:undecided size:%d\n",
202
0
                       fmt1->name, lpd.buf_size);
203
0
                if (undecided)
204
0
                    *undecided = 1;
205
0
                score = 0;
206
0
            } else if (score)
207
0
                av_log(NULL, AV_LOG_TRACE, "Probing %s score:%d size:%d\n", fmt1->name, score, lpd.buf_size);
208
0
            if (fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) {
209
0
                switch (nodat) {
210
0
                case NO_ID3:
211
0
                    score = FFMAX(score, 1);
212
0
                    break;
213
0
                case ID3_GREATER_PROBE:
214
0
                case ID3_ALMOST_GREATER_PROBE:
215
0
                    score = FFMAX(score, AVPROBE_SCORE_EXTENSION / 2 - 1);
216
0
                    break;
217
0
                case ID3_GREATER_MAX_PROBE:
218
0
                    score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
219
0
                    break;
220
0
                }
221
0
            }
222
0
        } else if (fmt1->extensions) {
223
0
            if (av_match_ext(lpd.filename, fmt1->extensions))
224
0
                score = AVPROBE_SCORE_EXTENSION;
225
0
        }
226
0
        if (av_match_name(lpd.mime_type, fmt1->mime_type)) {
227
0
            int old_score = score;
228
0
            score += AVPROBE_SCORE_MIME_BONUS;
229
0
            if (score > AVPROBE_SCORE_MAX) score = AVPROBE_SCORE_MAX;
230
0
            av_log(NULL, AV_LOG_DEBUG, "Probing %s score:%d increased to %d due to MIME type\n", fmt1->name, old_score, score);
231
0
        }
232
0
        if (score > score_max) {
233
0
            score_max = score;
234
0
            fmt       = fmt1;
235
0
        } else if (score == score_max)
236
0
            fmt = NULL;
237
0
    }
238
1.43k
    if (nodat == ID3_GREATER_PROBE)
239
0
        score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max);
240
1.43k
    *score_ret = score_max;
241
242
1.43k
    return fmt;
243
1.43k
}
244
245
const AVInputFormat *av_probe_input_format3(const AVProbeData *pd,
246
                                            int is_opened, int *score_ret)
247
0
{
248
0
    return probe_input_format_internal(pd, is_opened, score_ret, NULL);
249
0
}
250
251
const AVInputFormat *av_probe_input_format2(const AVProbeData *pd,
252
                                            int is_opened, int *score_max)
253
1.43k
{
254
1.43k
    int score_ret;
255
1.43k
    const AVInputFormat *fmt;
256
1.43k
    fmt = probe_input_format_internal(pd, is_opened, &score_ret, NULL);
257
1.43k
    if (score_ret > *score_max) {
258
0
        *score_max = score_ret;
259
0
        return fmt;
260
0
    } else
261
1.43k
        return NULL;
262
1.43k
}
263
264
const AVInputFormat *av_probe_input_format(const AVProbeData *pd, int is_opened)
265
0
{
266
0
    int score = 0;
267
0
    return probe_input_format_internal(pd, is_opened, &score, NULL);
268
0
}
269
270
int av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt,
271
                           const char *filename, void *logctx,
272
                           unsigned int offset, unsigned int max_probe_size)
273
0
{
274
0
    AVProbeData pd = { filename ? filename : "" };
275
0
    uint8_t *buf = NULL;
276
0
    int ret = 0, probe_size, buf_offset = 0;
277
0
    int score = 0;
278
0
    int ret2;
279
0
    int eof = 0;
280
281
0
    if (!max_probe_size)
282
0
        max_probe_size = PROBE_BUF_MAX;
283
0
    else if (max_probe_size < PROBE_BUF_MIN) {
284
0
        av_log(logctx, AV_LOG_ERROR,
285
0
               "Specified probe size value %u cannot be < %u\n", max_probe_size, PROBE_BUF_MIN);
286
0
        return AVERROR(EINVAL);
287
0
    }
288
289
0
    if (offset >= max_probe_size)
290
0
        return AVERROR(EINVAL);
291
292
0
    if (pb->av_class) {
293
0
        uint8_t *mime_type_opt = NULL;
294
0
        char *semi;
295
0
        av_opt_get(pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type_opt);
296
0
        pd.mime_type = (const char *)mime_type_opt;
297
0
        semi = pd.mime_type ? strchr(mime_type_opt, ';') : NULL;
298
0
        if (semi) {
299
0
            *semi = '\0';
300
0
        }
301
0
    }
302
303
0
    for (probe_size = PROBE_BUF_MIN; probe_size <= max_probe_size && !*fmt && !eof;
304
0
         probe_size = FFMIN(probe_size << 1,
305
0
                            FFMAX(max_probe_size, probe_size + 1))) {
306
0
        score = probe_size < max_probe_size ? AVPROBE_SCORE_RETRY : 0;
307
308
        /* Read probe data. */
309
0
        if ((ret = av_reallocp(&buf, probe_size + AVPROBE_PADDING_SIZE)) < 0)
310
0
            goto fail;
311
0
        if ((ret = avio_read(pb, buf + buf_offset,
312
0
                             probe_size - buf_offset)) < 0) {
313
            /* Fail if error was not end of file, otherwise, lower score. */
314
0
            if (ret != AVERROR_EOF)
315
0
                goto fail;
316
317
0
            score = 0;
318
0
            ret   = 0;          /* error was end of file, nothing read */
319
0
            eof   = 1;
320
0
        }
321
0
        buf_offset += ret;
322
0
        if (buf_offset < offset)
323
0
            continue;
324
0
        pd.buf_size = buf_offset - offset;
325
0
        pd.buf = &buf[offset];
326
327
0
        memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE);
328
329
        /* Guess file format. */
330
0
        int score_new, undecided = 0;
331
0
        const AVInputFormat *fmt_new;
332
0
        fmt_new = probe_input_format_internal(&pd, 1, &score_new, &undecided);
333
334
        /* Retry undecided formats as long as we have more data to feed */
335
0
        if (undecided && probe_size < max_probe_size && !eof) {
336
0
            continue;
337
0
        } else if (score_new > score) {
338
0
            score = score_new;
339
0
            *fmt  = fmt_new;
340
0
        }
341
342
0
        if (*fmt) {
343
            /* This can only be true in the last iteration. */
344
0
            if (score <= AVPROBE_SCORE_RETRY) {
345
0
                av_log(logctx, AV_LOG_WARNING,
346
0
                       "Format %s detected only with low score of %d, "
347
0
                       "misdetection possible!\n", (*fmt)->name, score);
348
0
            } else
349
0
                av_log(logctx, AV_LOG_DEBUG,
350
0
                       "Format %s probed with size=%d and score=%d\n",
351
0
                       (*fmt)->name, probe_size, score);
352
#if 0
353
            FILE *f = fopen("probestat.tmp", "ab");
354
            fprintf(f, "probe_size:%d format:%s score:%d filename:%s\n", probe_size, (*fmt)->name, score, filename);
355
            fclose(f);
356
#endif
357
0
        }
358
0
    }
359
360
0
    if (!*fmt)
361
0
        ret = AVERROR_INVALIDDATA;
362
363
0
fail:
364
    /* Rewind. Reuse probe buffer to avoid seeking. */
365
0
    ret2 = ffio_rewind_with_probe_data(pb, &buf, buf_offset);
366
0
    if (ret >= 0)
367
0
        ret = ret2;
368
369
0
    av_freep(&pd.mime_type);
370
0
    return ret < 0 ? ret : score;
371
0
}
372
373
int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt,
374
                          const char *filename, void *logctx,
375
                          unsigned int offset, unsigned int max_probe_size)
376
0
{
377
0
    int ret = av_probe_input_buffer2(pb, fmt, filename, logctx, offset, max_probe_size);
378
0
    return ret < 0 ? ret : 0;
379
0
}