Unified · Split
| @@ -19,9 +19,12 @@ · 18 unmodified lines | ||
| 19 | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 | 20 | */ |
| 21 | 21 | |
| 22 | +#include "libavutil/avstring.h" | |
| 23 | + | |
| 24 | +#include "avio_internal.h" | |
| 22 | 25 | #include "avformat.h" |
| 26 | +#include "id3v2.h" | |
| 23 | 27 | #include "internal.h" |
| 24 | −#include "libavutil/avstring.h" | |
| 25 | 28 | |
| 26 | 29 | /** |
| 27 | 30 | * @file |
| @@ -181,3 +184,137 @@ AVInputFormat *av_find_input_format(const char *short_name) · 153 unmodified lines | ||
| 181 | 184 | return fmt; |
| 182 | 185 | return NULL; |
| 183 | 186 | } |
| 187 | + | |
| 188 | +AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, | |
| 189 | + int *score_max) | |
| 190 | +{ | |
| 191 | + AVProbeData lpd = *pd; | |
| 192 | + AVInputFormat *fmt1 = NULL, *fmt; | |
| 193 | + int score, id3 = 0; | |
| 194 | + | |
| 195 | + if (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) { | |
| 196 | + int id3len = ff_id3v2_tag_len(lpd.buf); | |
| 197 | + if (lpd.buf_size > id3len + 16) { | |
| 198 | + lpd.buf += id3len; | |
| 199 | + lpd.buf_size -= id3len; | |
| 200 | + } | |
| 201 | + id3 = 1; | |
| 202 | + } | |
| 203 | + | |
| 204 | + fmt = NULL; | |
| 205 | + while ((fmt1 = av_iformat_next(fmt1))) { | |
| 206 | + if (!is_opened == !(fmt1->flags & AVFMT_NOFILE)) | |
| 207 | + continue; | |
| 208 | + score = 0; | |
| 209 | + if (fmt1->read_probe) { | |
| 210 | + score = fmt1->read_probe(&lpd); | |
| 211 | + } else if (fmt1->extensions) { | |
| 212 | + if (av_match_ext(lpd.filename, fmt1->extensions)) | |
| 213 | + score = AVPROBE_SCORE_EXTENSION; | |
| 214 | + } | |
| 215 | + if (score > *score_max) { | |
| 216 | + *score_max = score; | |
| 217 | + fmt = fmt1; | |
| 218 | + } else if (score == *score_max) | |
| 219 | + fmt = NULL; | |
| 220 | + } | |
| 221 | + | |
| 222 | + // A hack for files with huge id3v2 tags -- try to guess by file extension. | |
| 223 | + if (!fmt && is_opened && *score_max < AVPROBE_SCORE_EXTENSION / 2) { | |
| 224 | + while ((fmt = av_iformat_next(fmt))) | |
| 225 | + if (fmt->extensions && | |
| 226 | + av_match_ext(lpd.filename, fmt->extensions)) { | |
| 227 | + *score_max = AVPROBE_SCORE_EXTENSION / 2; | |
| 228 | + break; | |
| 229 | + } | |
| 230 | + } | |
| 231 | + | |
| 232 | + if (!fmt && id3 && *score_max < AVPROBE_SCORE_EXTENSION / 2 - 1) { | |
| 233 | + while ((fmt = av_iformat_next(fmt))) | |
| 234 | + if (fmt->extensions && av_match_ext("mp3", fmt->extensions)) { | |
| 235 | + *score_max = AVPROBE_SCORE_EXTENSION / 2 - 1; | |
| 236 | + break; | |
| 237 | + } | |
| 238 | + } | |
| 239 | + | |
| 240 | + return fmt; | |
| 241 | +} | |
| 242 | + | |
| 243 | +AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened) | |
| 244 | +{ | |
| 245 | + int score = 0; | |
| 246 | + return av_probe_input_format2(pd, is_opened, &score); | |
| 247 | +} | |
| 248 | + | |
| 249 | +/* size of probe buffer, for guessing file type from file contents */ | |
| 250 | +#define PROBE_BUF_MIN 2048 | |
| 251 | +#define PROBE_BUF_MAX (1 << 20) | |
| 252 | + | |
| 253 | +int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, | |
| 254 | + const char *filename, void *logctx, | |
| 255 | + unsigned int offset, unsigned int max_probe_size) | |
| 256 | +{ | |
| 257 | + AVProbeData pd = { filename ? filename : "" }; | |
| 258 | + uint8_t *buf = NULL; | |
| 259 | + int ret = 0, probe_size; | |
| 260 | + | |
| 261 | + if (!max_probe_size) | |
| 262 | + max_probe_size = PROBE_BUF_MAX; | |
| 263 | + else if (max_probe_size > PROBE_BUF_MAX) | |
| 264 | + max_probe_size = PROBE_BUF_MAX; | |
| 265 | + else if (max_probe_size < PROBE_BUF_MIN) | |
| 266 | + return AVERROR(EINVAL); | |
| 267 | + | |
| 268 | + if (offset >= max_probe_size) | |
| 269 | + return AVERROR(EINVAL); | |
| 270 | + avio_skip(pb, offset); | |
| 271 | + max_probe_size -= offset; | |
| 272 | + | |
| 273 | + for (probe_size = PROBE_BUF_MIN; probe_size <= max_probe_size && !*fmt; | |
| 274 | + probe_size = FFMIN(probe_size << 1, | |
| 275 | + FFMAX(max_probe_size, probe_size + 1))) { | |
| 276 | + int score = probe_size < max_probe_size ? AVPROBE_SCORE_MAX / 4 : 0; | |
| 277 | + | |
| 278 | + /* Read probe data. */ | |
| 279 | + if ((ret = av_reallocp(&buf, probe_size + AVPROBE_PADDING_SIZE)) < 0) | |
| 280 | + return ret; | |
| 281 | + if ((ret = avio_read(pb, buf + pd.buf_size, | |
| 282 | + probe_size - pd.buf_size)) < 0) { | |
| 283 | + /* Fail if error was not end of file, otherwise, lower score. */ | |
| 284 | + if (ret != AVERROR_EOF) { | |
| 285 | + av_free(buf); | |
| 286 | + return ret; | |
| 287 | + } | |
| 288 | + score = 0; | |
| 289 | + ret = 0; /* error was end of file, nothing read */ | |
| 290 | + } | |
| 291 | + pd.buf_size += ret; | |
| 292 | + pd.buf = buf; | |
| 293 | + | |
| 294 | + memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE); | |
| 295 | + | |
| 296 | + /* Guess file format. */ | |
| 297 | + *fmt = av_probe_input_format2(&pd, 1, &score); | |
| 298 | + if (*fmt) { | |
| 299 | + /* This can only be true in the last iteration. */ | |
| 300 | + if (score <= AVPROBE_SCORE_MAX / 4) { | |
| 301 | + av_log(logctx, AV_LOG_WARNING, | |
| 302 | + "Format detected only with low score of %d, " | |
| 303 | + "misdetection possible!\n", score); | |
| 304 | + } else | |
| 305 | + av_log(logctx, AV_LOG_DEBUG, | |
| 306 | + "Probed with size=%d and score=%d\n", probe_size, score); | |
| 307 | + } | |
| 308 | + } | |
| 309 | + | |
| 310 | + if (!*fmt) { | |
| 311 | + av_free(buf); | |
| 312 | + return AVERROR_INVALIDDATA; | |
| 313 | + } | |
| 314 | + | |
| 315 | + /* Rewind. Reuse probe buffer to avoid seeking. */ | |
| 316 | + if ((ret = ffio_rewind_with_probe_data(pb, buf, pd.buf_size)) < 0) | |
| 317 | + av_free(buf); | |
| 318 | + | |
| 319 | + return ret; | |
| 320 | +} | |
| @@ -41,7 +41,6 @@ · 40 unmodified lines | ||
| 41 | 41 | |
| 42 | 42 | #include "audiointerleave.h" |
| 43 | 43 | #include "avformat.h" |
| 44 | −#include "avio_internal.h" | |
| 45 | 44 | #include "id3v2.h" |
| 46 | 45 | #include "internal.h" |
| 47 | 46 | #include "metadata.h" |
| @@ -139,67 +138,6 @@ int av_filename_number_test(const char *filename) · 91 unmodified lines | ||
| 139 | 138 | (av_get_frame_filename(buf, sizeof(buf), filename, 1) >= 0); |
| 140 | 139 | } |
| 141 | 140 | |
| 142 | −AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, | |
| 143 | − int *score_max) | |
| 144 | −{ | |
| 145 | − AVProbeData lpd = *pd; | |
| 146 | − AVInputFormat *fmt1 = NULL, *fmt; | |
| 147 | − int score, id3 = 0; | |
| 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 | − lpd.buf += id3len; | |
| 153 | − lpd.buf_size -= id3len; | |
| 154 | − } | |
| 155 | − id3 = 1; | |
| 156 | − } | |
| 157 | − | |
| 158 | − fmt = NULL; | |
| 159 | − while ((fmt1 = av_iformat_next(fmt1))) { | |
| 160 | − if (!is_opened == !(fmt1->flags & AVFMT_NOFILE)) | |
| 161 | − continue; | |
| 162 | − score = 0; | |
| 163 | − if (fmt1->read_probe) { | |
| 164 | − score = fmt1->read_probe(&lpd); | |
| 165 | − } else if (fmt1->extensions) { | |
| 166 | − if (av_match_ext(lpd.filename, fmt1->extensions)) | |
| 167 | − score = AVPROBE_SCORE_EXTENSION; | |
| 168 | − } | |
| 169 | − if (score > *score_max) { | |
| 170 | − *score_max = score; | |
| 171 | − fmt = fmt1; | |
| 172 | − } else if (score == *score_max) | |
| 173 | − fmt = NULL; | |
| 174 | − } | |
| 175 | − | |
| 176 | − // A hack for files with huge id3v2 tags -- try to guess by file extension. | |
| 177 | − if (!fmt && is_opened && *score_max < AVPROBE_SCORE_EXTENSION / 2) { | |
| 178 | − while ((fmt = av_iformat_next(fmt))) | |
| 179 | − if (fmt->extensions && | |
| 180 | − av_match_ext(lpd.filename, fmt->extensions)) { | |
| 181 | − *score_max = AVPROBE_SCORE_EXTENSION / 2; | |
| 182 | − break; | |
| 183 | − } | |
| 184 | − } | |
| 185 | − | |
| 186 | − if (!fmt && id3 && *score_max < AVPROBE_SCORE_EXTENSION / 2 - 1) { | |
| 187 | − while ((fmt = av_iformat_next(fmt))) | |
| 188 | − if (fmt->extensions && av_match_ext("mp3", fmt->extensions)) { | |
| 189 | − *score_max = AVPROBE_SCORE_EXTENSION / 2 - 1; | |
| 190 | − break; | |
| 191 | − } | |
| 192 | − } | |
| 193 | − | |
| 194 | − return fmt; | |
| 195 | −} | |
| 196 | − | |
| 197 | −AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened) | |
| 198 | −{ | |
| 199 | − int score = 0; | |
| 200 | − return av_probe_input_format2(pd, is_opened, &score); | |
| 201 | −} | |
| 202 | − | |
| 203 | 141 | static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, |
| 204 | 142 | AVProbeData *pd, int score) |
| 205 | 143 | { |
| @@ -241,79 +179,6 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, · 35 unmodified lines | ||
| 241 | 179 | /************************************************************/ |
| 242 | 180 | /* input media file */ |
| 243 | 181 | |
| 244 | −/** size of probe buffer, for guessing file type from file contents */ | |
| 245 | −#define PROBE_BUF_MIN 2048 | |
| 246 | −#define PROBE_BUF_MAX (1 << 20) | |
| 247 | − | |
| 248 | −int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, | |
| 249 | − const char *filename, void *logctx, | |
| 250 | − unsigned int offset, unsigned int max_probe_size) | |
| 251 | −{ | |
| 252 | − AVProbeData pd = { filename ? filename : "" }; | |
| 253 | − uint8_t *buf = NULL; | |
| 254 | − int ret = 0, probe_size; | |
| 255 | − | |
| 256 | − if (!max_probe_size) | |
| 257 | − max_probe_size = PROBE_BUF_MAX; | |
| 258 | − else if (max_probe_size > PROBE_BUF_MAX) | |
| 259 | − max_probe_size = PROBE_BUF_MAX; | |
| 260 | − else if (max_probe_size < PROBE_BUF_MIN) | |
| 261 | − return AVERROR(EINVAL); | |
| 262 | − | |
| 263 | − if (offset >= max_probe_size) | |
| 264 | − return AVERROR(EINVAL); | |
| 265 | − avio_skip(pb, offset); | |
| 266 | − max_probe_size -= offset; | |
| 267 | − | |
| 268 | − for (probe_size = PROBE_BUF_MIN; probe_size <= max_probe_size && !*fmt; | |
| 269 | − probe_size = FFMIN(probe_size << 1, | |
| 270 | − FFMAX(max_probe_size, probe_size + 1))) { | |
| 271 | − int score = probe_size < max_probe_size ? AVPROBE_SCORE_MAX / 4 : 0; | |
| 272 | − | |
| 273 | − /* Read probe data. */ | |
| 274 | − if ((ret = av_reallocp(&buf, probe_size + AVPROBE_PADDING_SIZE)) < 0) | |
| 275 | − return ret; | |
| 276 | − if ((ret = avio_read(pb, buf + pd.buf_size, | |
| 277 | − probe_size - pd.buf_size)) < 0) { | |
| 278 | − /* Fail if error was not end of file, otherwise, lower score. */ | |
| 279 | − if (ret != AVERROR_EOF) { | |
| 280 | − av_free(buf); | |
| 281 | − return ret; | |
| 282 | − } | |
| 283 | − score = 0; | |
| 284 | − ret = 0; /* error was end of file, nothing read */ | |
| 285 | − } | |
| 286 | − pd.buf_size += ret; | |
| 287 | − pd.buf = buf; | |
| 288 | − | |
| 289 | − memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE); | |
| 290 | − | |
| 291 | − /* Guess file format. */ | |
| 292 | − *fmt = av_probe_input_format2(&pd, 1, &score); | |
| 293 | − if (*fmt) { | |
| 294 | − /* This can only be true in the last iteration. */ | |
| 295 | − if (score <= AVPROBE_SCORE_MAX / 4) { | |
| 296 | − av_log(logctx, AV_LOG_WARNING, | |
| 297 | − "Format detected only with low score of %d, " | |
| 298 | − "misdetection possible!\n", score); | |
| 299 | − } else | |
| 300 | − av_log(logctx, AV_LOG_DEBUG, | |
| 301 | − "Probed with size=%d and score=%d\n", probe_size, score); | |
| 302 | − } | |
| 303 | − } | |
| 304 | − | |
| 305 | − if (!*fmt) { | |
| 306 | − av_free(buf); | |
| 307 | − return AVERROR_INVALIDDATA; | |
| 308 | − } | |
| 309 | − | |
| 310 | − /* Rewind. Reuse probe buffer to avoid seeking. */ | |
| 311 | − if ((ret = ffio_rewind_with_probe_data(pb, buf, pd.buf_size)) < 0) | |
| 312 | − av_free(buf); | |
| 313 | − | |
| 314 | − return ret; | |
| 315 | −} | |
| 316 | − | |
| 317 | 182 | /* Open input file and probe the format if necessary. */ |
| 318 | 183 | static int init_input(AVFormatContext *s, const char *filename, |
| 319 | 184 | AVDictionary **options) |