/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, ×tamp, 0); |
158 | 0 | if (ret == 1) |
159 | 0 | return ff_dict_set_timestamp(&s->metadata, "creation_time", timestamp); |
160 | 0 | return ret; |
161 | 0 | } |