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
av_stream_get_end_pts(const AVStream * st)32 int64_t av_stream_get_end_pts(const AVStream *st)
33 {
34 if (cffstream(st)->priv_pts) {
35 return cffstream(st)->priv_pts->val;
36 } else
37 return AV_NOPTS_VALUE;
38 }
39
avformat_query_codec(const AVOutputFormat * ofmt,enum AVCodecID codec_id,int std_compliance)40 int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
41 int std_compliance)
42 {
43 if (ofmt) {
44 unsigned int codec_tag;
45 if (ofmt->query_codec)
46 return ofmt->query_codec(codec_id, std_compliance);
47 else if (ofmt->codec_tag)
48 return !!av_codec_get_tag2(ofmt->codec_tag, codec_id, &codec_tag);
49 else if (codec_id == ofmt->video_codec ||
50 codec_id == ofmt->audio_codec ||
51 codec_id == ofmt->subtitle_codec ||
52 codec_id == ofmt->data_codec)
53 return 1;
54 }
55 return AVERROR_PATCHWELCOME;
56 }
57
ff_format_shift_data(AVFormatContext * s,int64_t read_start,int shift_size)58 int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size)
59 {
60 int ret;
61 int64_t pos, pos_end;
62 uint8_t *buf, *read_buf[2];
63 int read_buf_id = 0;
64 int read_size[2];
65 AVIOContext *read_pb;
66
67 buf = av_malloc_array(shift_size, 2);
68 if (!buf)
69 return AVERROR(ENOMEM);
70 read_buf[0] = buf;
71 read_buf[1] = buf + shift_size;
72
73 /* Shift the data: the AVIO context of the output can only be used for
74 * writing, so we re-open the same output, but for reading. It also avoids
75 * a read/seek/write/seek back and forth. */
76 avio_flush(s->pb);
77 ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL);
78 if (ret < 0) {
79 av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for shifting data\n", s->url);
80 goto end;
81 }
82
83 /* mark the end of the shift to up to the last data we wrote, and get ready
84 * for writing */
85 pos_end = avio_tell(s->pb);
86 avio_seek(s->pb, read_start + shift_size, SEEK_SET);
87
88 avio_seek(read_pb, read_start, SEEK_SET);
89 pos = avio_tell(read_pb);
90
91 #define READ_BLOCK do { \
92 read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], shift_size); \
93 read_buf_id ^= 1; \
94 } while (0)
95
96 /* shift data by chunk of at most shift_size */
97 READ_BLOCK;
98 do {
99 int n;
100 READ_BLOCK;
101 n = read_size[read_buf_id];
102 if (n <= 0)
103 break;
104 avio_write(s->pb, read_buf[read_buf_id], n);
105 pos += n;
106 } while (pos < pos_end);
107 ret = ff_format_io_close(s, &read_pb);
108
109 end:
110 av_free(buf);
111 return ret;
112 }
113
ff_format_output_open(AVFormatContext * s,const char * url,AVDictionary ** options)114 int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options)
115 {
116 if (!s->oformat)
117 return AVERROR(EINVAL);
118
119 if (!(s->oformat->flags & AVFMT_NOFILE))
120 return s->io_open(s, &s->pb, url, AVIO_FLAG_WRITE, options);
121 return 0;
122 }
123
ff_stream_encode_params_copy(AVStream * dst,const AVStream * src)124 int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src)
125 {
126 int ret;
127
128 dst->id = src->id;
129 dst->time_base = src->time_base;
130 dst->nb_frames = src->nb_frames;
131 dst->disposition = src->disposition;
132 dst->sample_aspect_ratio = src->sample_aspect_ratio;
133 dst->avg_frame_rate = src->avg_frame_rate;
134 dst->r_frame_rate = src->r_frame_rate;
135
136 av_dict_free(&dst->metadata);
137 ret = av_dict_copy(&dst->metadata, src->metadata, 0);
138 if (ret < 0)
139 return ret;
140
141 ret = avcodec_parameters_copy(dst->codecpar, src->codecpar);
142 if (ret < 0)
143 return ret;
144
145 ret = ff_stream_side_data_copy(dst, src);
146 if (ret < 0)
147 return ret;
148
149 return 0;
150 }
151
ff_parse_creation_time_metadata(AVFormatContext * s,int64_t * timestamp,int return_seconds)152 int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds)
153 {
154 AVDictionaryEntry *entry;
155 int64_t parsed_timestamp;
156 int ret;
157 if ((entry = av_dict_get(s->metadata, "creation_time", NULL, 0))) {
158 if ((ret = av_parse_time(&parsed_timestamp, entry->value, 0)) >= 0) {
159 *timestamp = return_seconds ? parsed_timestamp / 1000000 : parsed_timestamp;
160 return 1;
161 } else {
162 av_log(s, AV_LOG_WARNING, "Failed to parse creation_time %s\n", entry->value);
163 return ret;
164 }
165 }
166 return 0;
167 }
168
ff_standardize_creation_time(AVFormatContext * s)169 int ff_standardize_creation_time(AVFormatContext *s)
170 {
171 int64_t timestamp;
172 int ret = ff_parse_creation_time_metadata(s, ×tamp, 0);
173 if (ret == 1)
174 return avpriv_dict_set_timestamp(&s->metadata, "creation_time", timestamp);
175 return ret;
176 }
177