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