• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &timestamp, 0);
173     if (ret == 1)
174         return avpriv_dict_set_timestamp(&s->metadata, "creation_time", timestamp);
175     return ret;
176 }
177