Coverage Report

Created: 2026-02-14 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/mux_utils.c
Line
Count
Source
1
/*
2
 * Various muxing utility functions
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 "libavutil/dict.h"
23
#include "libavutil/internal.h"
24
#include "libavutil/log.h"
25
#include "libavutil/mem.h"
26
#include "libavutil/parseutils.h"
27
#include "avformat.h"
28
#include "avio.h"
29
#include "internal.h"
30
#include "mux.h"
31
32
int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
33
                         int std_compliance)
34
0
{
35
0
    if (ofmt) {
36
0
        unsigned int codec_tag;
37
0
        if (ffofmt(ofmt)->query_codec)
38
0
            return ffofmt(ofmt)->query_codec(codec_id, std_compliance);
39
0
        else if (ofmt->codec_tag)
40
0
            return !!av_codec_get_tag2(ofmt->codec_tag, codec_id, &codec_tag);
41
0
        else if (codec_id != AV_CODEC_ID_NONE &&
42
0
                 (codec_id == ofmt->video_codec ||
43
0
                  codec_id == ofmt->audio_codec ||
44
0
                  codec_id == ofmt->subtitle_codec))
45
0
            return 1;
46
0
        else if (ffofmt(ofmt)->flags_internal & FF_OFMT_FLAG_ONLY_DEFAULT_CODECS)
47
0
            return 0;
48
0
        else if (ffofmt(ofmt)->flags_internal & FF_OFMT_FLAG_MAX_ONE_OF_EACH) {
49
0
            enum AVMediaType type = avcodec_get_type(codec_id);
50
0
            switch (type) {
51
0
            case AVMEDIA_TYPE_AUDIO:
52
0
                if (ofmt->audio_codec == AV_CODEC_ID_NONE)
53
0
                    return 0;
54
0
                break;
55
0
            case AVMEDIA_TYPE_VIDEO:
56
0
                if (ofmt->video_codec == AV_CODEC_ID_NONE)
57
0
                    return 0;
58
0
                break;
59
0
            case AVMEDIA_TYPE_SUBTITLE:
60
0
                if (ofmt->subtitle_codec == AV_CODEC_ID_NONE)
61
0
                    return 0;
62
0
                break;
63
0
            default:
64
0
                return 0;
65
0
            }
66
0
        }
67
0
    }
68
0
    return AVERROR_PATCHWELCOME;
69
0
}
70
71
int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size)
72
0
{
73
0
    int ret;
74
0
    int64_t pos, pos_end;
75
0
    uint8_t *buf, *read_buf[2];
76
0
    int read_buf_id = 0;
77
0
    int read_size[2];
78
0
    AVIOContext *read_pb;
79
80
0
    buf = av_malloc_array(shift_size, 2);
81
0
    if (!buf)
82
0
        return AVERROR(ENOMEM);
83
0
    read_buf[0] = buf;
84
0
    read_buf[1] = buf + shift_size;
85
86
    /* Shift the data: the AVIO context of the output can only be used for
87
     * writing, so we re-open the same output, but for reading. It also avoids
88
     * a read/seek/write/seek back and forth. */
89
0
    avio_flush(s->pb);
90
0
    ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL);
91
0
    if (ret < 0) {
92
0
        av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for shifting data\n", s->url);
93
0
        goto end;
94
0
    }
95
96
    /* mark the end of the shift to up to the last data we wrote, and get ready
97
     * for writing */
98
0
    pos_end = avio_tell(s->pb);
99
0
    avio_seek(s->pb, read_start + shift_size, SEEK_SET);
100
101
0
    avio_seek(read_pb, read_start, SEEK_SET);
102
0
    pos = avio_tell(read_pb);
103
104
0
#define READ_BLOCK do {                                                             \
105
0
    read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], shift_size);  \
106
0
    read_buf_id ^= 1;                                                               \
107
0
} while (0)
108
109
    /* shift data by chunk of at most shift_size */
110
0
    READ_BLOCK;
111
0
    do {
112
0
        int n;
113
0
        READ_BLOCK;
114
0
        n = read_size[read_buf_id];
115
0
        if (n <= 0)
116
0
            break;
117
0
        avio_write(s->pb, read_buf[read_buf_id], n);
118
0
        pos += n;
119
0
    } while (pos < pos_end);
120
0
    ret = ff_format_io_close(s, &read_pb);
121
122
0
end:
123
0
    av_free(buf);
124
0
    return ret;
125
0
}
126
127
int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options)
128
0
{
129
0
    if (!s->oformat)
130
0
        return AVERROR(EINVAL);
131
132
0
    if (!(s->oformat->flags & AVFMT_NOFILE))
133
0
        return s->io_open(s, &s->pb, url, AVIO_FLAG_WRITE, options);
134
0
    return 0;
135
0
}
136
137
int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds)
138
0
{
139
0
    AVDictionaryEntry *entry;
140
0
    int64_t parsed_timestamp;
141
0
    int ret;
142
0
    if ((entry = av_dict_get(s->metadata, "creation_time", NULL, 0))) {
143
0
        if ((ret = av_parse_time(&parsed_timestamp, entry->value, 0)) >= 0) {
144
0
            *timestamp = return_seconds ? parsed_timestamp / 1000000 : parsed_timestamp;
145
0
            return 1;
146
0
        } else {
147
0
            av_log(s, AV_LOG_WARNING, "Failed to parse creation_time %s\n", entry->value);
148
0
            return ret;
149
0
        }
150
0
    }
151
0
    return 0;
152
0
}
153
154
int ff_standardize_creation_time(AVFormatContext *s)
155
0
{
156
0
    int64_t timestamp;
157
0
    int ret = ff_parse_creation_time_metadata(s, &timestamp, 0);
158
0
    if (ret == 1)
159
0
        return ff_dict_set_timestamp(&s->metadata, "creation_time", timestamp);
160
0
    return ret;
161
0
}