• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/bprint.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/thread.h"
28 
29 #include "avio_internal.h"
30 #include "avformat.h"
31 #include "id3v2.h"
32 #include "internal.h"
33 
34 
35 /**
36  * @file
37  * Format register and lookup
38  */
39 
av_match_ext(const char * filename,const char * extensions)40 int av_match_ext(const char *filename, const char *extensions)
41 {
42     const char *ext;
43 
44     if (!filename)
45         return 0;
46 
47     ext = strrchr(filename, '.');
48     if (ext)
49         return av_match_name(ext + 1, extensions);
50     return 0;
51 }
52 
av_guess_format(const char * short_name,const char * filename,const char * mime_type)53 const AVOutputFormat *av_guess_format(const char *short_name, const char *filename,
54                                       const char *mime_type)
55 {
56     const AVOutputFormat *fmt = NULL;
57     const AVOutputFormat *fmt_found = NULL;
58     void *i = 0;
59     int score_max, score;
60 
61     /* specific test for image sequences */
62 #if CONFIG_IMAGE2_MUXER
63     if (!short_name && filename &&
64         av_filename_number_test(filename) &&
65         ff_guess_image2_codec(filename) != AV_CODEC_ID_NONE) {
66         return av_guess_format("image2", NULL, NULL);
67     }
68 #endif
69     /* Find the proper file type. */
70     score_max = 0;
71     while ((fmt = av_muxer_iterate(&i))) {
72         score = 0;
73         if (fmt->name && short_name && av_match_name(short_name, fmt->name))
74             score += 100;
75         if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
76             score += 10;
77         if (filename && fmt->extensions &&
78             av_match_ext(filename, fmt->extensions)) {
79             score += 5;
80         }
81         if (score > score_max) {
82             score_max = score;
83             fmt_found = fmt;
84         }
85     }
86     return fmt_found;
87 }
88 
av_guess_codec(const AVOutputFormat * fmt,const char * short_name,const char * filename,const char * mime_type,enum AVMediaType type)89 enum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name,
90                               const char *filename, const char *mime_type,
91                               enum AVMediaType type)
92 {
93     if (av_match_name("segment", fmt->name) || av_match_name("ssegment", fmt->name)) {
94         const AVOutputFormat *fmt2 = av_guess_format(NULL, filename, NULL);
95         if (fmt2)
96             fmt = fmt2;
97     }
98 
99     if (type == AVMEDIA_TYPE_VIDEO) {
100         enum AVCodecID codec_id = AV_CODEC_ID_NONE;
101 
102 #if CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER
103         if (!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")) {
104             codec_id = ff_guess_image2_codec(filename);
105         }
106 #endif
107         if (codec_id == AV_CODEC_ID_NONE)
108             codec_id = fmt->video_codec;
109         return codec_id;
110     } else if (type == AVMEDIA_TYPE_AUDIO)
111         return fmt->audio_codec;
112     else if (type == AVMEDIA_TYPE_SUBTITLE)
113         return fmt->subtitle_codec;
114     else if (type == AVMEDIA_TYPE_DATA)
115         return fmt->data_codec;
116     else
117         return AV_CODEC_ID_NONE;
118 }
119 
av_find_input_format(const char * short_name)120 const AVInputFormat *av_find_input_format(const char *short_name)
121 {
122     const AVInputFormat *fmt = NULL;
123     void *i = 0;
124     while ((fmt = av_demuxer_iterate(&i)))
125         if (av_match_name(short_name, fmt->name))
126             return fmt;
127     return NULL;
128 }
129 
av_probe_input_format3(const AVProbeData * pd,int is_opened,int * score_ret)130 const AVInputFormat *av_probe_input_format3(const AVProbeData *pd,
131                                             int is_opened, int *score_ret)
132 {
133     AVProbeData lpd = *pd;
134     const AVInputFormat *fmt1 = NULL;
135     const AVInputFormat *fmt = NULL;
136     int score, score_max = 0;
137     void *i = 0;
138     const static uint8_t zerobuffer[AVPROBE_PADDING_SIZE];
139     enum nodat {
140         NO_ID3,
141         ID3_ALMOST_GREATER_PROBE,
142         ID3_GREATER_PROBE,
143         ID3_GREATER_MAX_PROBE,
144     } nodat = NO_ID3;
145 
146     if (!lpd.buf)
147         lpd.buf = (unsigned char *) zerobuffer;
148 
149     if (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) {
150         int id3len = ff_id3v2_tag_len(lpd.buf);
151         if (lpd.buf_size > id3len + 16) {
152             if (lpd.buf_size < 2LL*id3len + 16)
153                 nodat = ID3_ALMOST_GREATER_PROBE;
154             lpd.buf      += id3len;
155             lpd.buf_size -= id3len;
156         } else if (id3len >= PROBE_BUF_MAX) {
157             nodat = ID3_GREATER_MAX_PROBE;
158         } else
159             nodat = ID3_GREATER_PROBE;
160     }
161 
162     while ((fmt1 = av_demuxer_iterate(&i))) {
163         if (fmt1->flags & AVFMT_EXPERIMENTAL)
164             continue;
165         if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2"))
166             continue;
167         score = 0;
168         if (fmt1->read_probe) {
169             score = fmt1->read_probe(&lpd);
170             if (score)
171                 av_log(NULL, AV_LOG_TRACE, "Probing %s score:%d size:%d\n", fmt1->name, score, lpd.buf_size);
172             if (fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) {
173                 switch (nodat) {
174                 case NO_ID3:
175                     score = FFMAX(score, 1);
176                     break;
177                 case ID3_GREATER_PROBE:
178                 case ID3_ALMOST_GREATER_PROBE:
179                     score = FFMAX(score, AVPROBE_SCORE_EXTENSION / 2 - 1);
180                     break;
181                 case ID3_GREATER_MAX_PROBE:
182                     score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
183                     break;
184                 }
185             }
186         } else if (fmt1->extensions) {
187             if (av_match_ext(lpd.filename, fmt1->extensions))
188                 score = AVPROBE_SCORE_EXTENSION;
189         }
190         if (av_match_name(lpd.mime_type, fmt1->mime_type)) {
191             if (AVPROBE_SCORE_MIME > score) {
192                 av_log(NULL, AV_LOG_DEBUG, "Probing %s score:%d increased to %d due to MIME type\n", fmt1->name, score, AVPROBE_SCORE_MIME);
193                 score = AVPROBE_SCORE_MIME;
194             }
195         }
196         if (score > score_max) {
197             score_max = score;
198             fmt       = fmt1;
199         } else if (score == score_max)
200             fmt = NULL;
201     }
202     if (nodat == ID3_GREATER_PROBE)
203         score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max);
204     *score_ret = score_max;
205 
206     return fmt;
207 }
208 
av_probe_input_format2(const AVProbeData * pd,int is_opened,int * score_max)209 const AVInputFormat *av_probe_input_format2(const AVProbeData *pd,
210                                             int is_opened, int *score_max)
211 {
212     int score_ret;
213     const AVInputFormat *fmt = av_probe_input_format3(pd, is_opened, &score_ret);
214     if (score_ret > *score_max) {
215         *score_max = score_ret;
216         return fmt;
217     } else
218         return NULL;
219 }
220 
av_probe_input_format(const AVProbeData * pd,int is_opened)221 const AVInputFormat *av_probe_input_format(const AVProbeData *pd, int is_opened)
222 {
223     int score = 0;
224     return av_probe_input_format2(pd, is_opened, &score);
225 }
226 
av_probe_input_buffer2(AVIOContext * pb,const AVInputFormat ** fmt,const char * filename,void * logctx,unsigned int offset,unsigned int max_probe_size)227 int av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt,
228                            const char *filename, void *logctx,
229                            unsigned int offset, unsigned int max_probe_size)
230 {
231     AVProbeData pd = { filename ? filename : "" };
232     uint8_t *buf = NULL;
233     int ret = 0, probe_size, buf_offset = 0;
234     int score = 0;
235     int ret2;
236     int eof = 0;
237 
238     if (!max_probe_size)
239         max_probe_size = PROBE_BUF_MAX;
240     else if (max_probe_size < PROBE_BUF_MIN) {
241         av_log(logctx, AV_LOG_ERROR,
242                "Specified probe size value %u cannot be < %u\n", max_probe_size, PROBE_BUF_MIN);
243         return AVERROR(EINVAL);
244     }
245 
246     if (offset >= max_probe_size)
247         return AVERROR(EINVAL);
248 
249     if (pb->av_class) {
250         uint8_t *mime_type_opt = NULL;
251         char *semi;
252         av_opt_get(pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type_opt);
253         pd.mime_type = (const char *)mime_type_opt;
254         semi = pd.mime_type ? strchr(pd.mime_type, ';') : NULL;
255         if (semi) {
256             *semi = '\0';
257         }
258     }
259 
260     for (probe_size = PROBE_BUF_MIN; probe_size <= max_probe_size && !*fmt && !eof;
261          probe_size = FFMIN(probe_size << 1,
262                             FFMAX(max_probe_size, probe_size + 1))) {
263         score = probe_size < max_probe_size ? AVPROBE_SCORE_RETRY : 0;
264 
265         /* Read probe data. */
266         if ((ret = av_reallocp(&buf, probe_size + AVPROBE_PADDING_SIZE)) < 0)
267             goto fail;
268         if ((ret = avio_read(pb, buf + buf_offset,
269                              probe_size - buf_offset)) < 0) {
270             /* Fail if error was not end of file, otherwise, lower score. */
271             if (ret != AVERROR_EOF)
272                 goto fail;
273 
274             score = 0;
275             ret   = 0;          /* error was end of file, nothing read */
276             eof   = 1;
277         }
278         buf_offset += ret;
279         if (buf_offset < offset)
280             continue;
281         pd.buf_size = buf_offset - offset;
282         pd.buf = &buf[offset];
283 
284         memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE);
285 
286         /* Guess file format. */
287         *fmt = av_probe_input_format2(&pd, 1, &score);
288         if (*fmt) {
289             /* This can only be true in the last iteration. */
290             if (score <= AVPROBE_SCORE_RETRY) {
291                 av_log(logctx, AV_LOG_WARNING,
292                        "Format %s detected only with low score of %d, "
293                        "misdetection possible!\n", (*fmt)->name, score);
294             } else
295                 av_log(logctx, AV_LOG_DEBUG,
296                        "Format %s probed with size=%d and score=%d\n",
297                        (*fmt)->name, probe_size, score);
298 #if 0
299             FILE *f = fopen("probestat.tmp", "ab");
300             fprintf(f, "probe_size:%d format:%s score:%d filename:%s\n", probe_size, (*fmt)->name, score, filename);
301             fclose(f);
302 #endif
303         }
304     }
305 
306     if (!*fmt)
307         ret = AVERROR_INVALIDDATA;
308 
309 fail:
310     /* Rewind. Reuse probe buffer to avoid seeking. */
311     ret2 = ffio_rewind_with_probe_data(pb, &buf, buf_offset);
312     if (ret >= 0)
313         ret = ret2;
314 
315     av_freep(&pd.mime_type);
316     return ret < 0 ? ret : score;
317 }
318 
av_probe_input_buffer(AVIOContext * pb,const AVInputFormat ** fmt,const char * filename,void * logctx,unsigned int offset,unsigned int max_probe_size)319 int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt,
320                           const char *filename, void *logctx,
321                           unsigned int offset, unsigned int max_probe_size)
322 {
323     int ret = av_probe_input_buffer2(pb, fmt, filename, logctx, offset, max_probe_size);
324     return ret < 0 ? ret : 0;
325 }
326