Commit | Line | Data |
---|---|---|
de6d9b64 FB |
1 | /* |
2 | * Various utilities for ffmpeg system | |
19720f15 | 3 | * Copyright (c) 2000, 2001, 2002 Fabrice Bellard |
de6d9b64 | 4 | * |
19720f15 FB |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2 of the License, or (at your option) any later version. | |
de6d9b64 | 9 | * |
19720f15 | 10 | * This library is distributed in the hope that it will be useful, |
de6d9b64 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19720f15 FB |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. | |
de6d9b64 | 14 | * |
19720f15 FB |
15 | * You should have received a copy of the GNU Lesser General Public |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
de6d9b64 | 18 | */ |
8be1c656 | 19 | #include "avformat.h" |
af469427 | 20 | #include "tick.h" |
8be1c656 | 21 | #ifndef CONFIG_WIN32 |
de6d9b64 FB |
22 | #include <unistd.h> |
23 | #include <fcntl.h> | |
de6d9b64 | 24 | #include <sys/time.h> |
8be1c656 FB |
25 | #else |
26 | #define strcasecmp _stricmp | |
27 | #include <sys/types.h> | |
28 | #include <sys/timeb.h> | |
29 | #endif | |
9235088f | 30 | #include <time.h> |
de6d9b64 | 31 | |
b9a281db FB |
32 | AVInputFormat *first_iformat; |
33 | AVOutputFormat *first_oformat; | |
de6d9b64 | 34 | |
b9a281db | 35 | void av_register_input_format(AVInputFormat *format) |
de6d9b64 | 36 | { |
b9a281db FB |
37 | AVInputFormat **p; |
38 | p = &first_iformat; | |
39 | while (*p != NULL) p = &(*p)->next; | |
40 | *p = format; | |
41 | format->next = NULL; | |
42 | } | |
43 | ||
44 | void av_register_output_format(AVOutputFormat *format) | |
45 | { | |
46 | AVOutputFormat **p; | |
47 | p = &first_oformat; | |
de6d9b64 FB |
48 | while (*p != NULL) p = &(*p)->next; |
49 | *p = format; | |
50 | format->next = NULL; | |
51 | } | |
52 | ||
53 | int match_ext(const char *filename, const char *extensions) | |
54 | { | |
55 | const char *ext, *p; | |
56 | char ext1[32], *q; | |
57 | ||
58 | ext = strrchr(filename, '.'); | |
59 | if (ext) { | |
60 | ext++; | |
61 | p = extensions; | |
62 | for(;;) { | |
63 | q = ext1; | |
64 | while (*p != '\0' && *p != ',') | |
65 | *q++ = *p++; | |
66 | *q = '\0'; | |
67 | if (!strcasecmp(ext1, ext)) | |
68 | return 1; | |
69 | if (*p == '\0') | |
70 | break; | |
71 | p++; | |
72 | } | |
73 | } | |
74 | return 0; | |
75 | } | |
76 | ||
b9a281db FB |
77 | AVOutputFormat *guess_format(const char *short_name, const char *filename, |
78 | const char *mime_type) | |
de6d9b64 | 79 | { |
b9a281db | 80 | AVOutputFormat *fmt, *fmt_found; |
de6d9b64 FB |
81 | int score_max, score; |
82 | ||
83 | /* find the proper file type */ | |
84 | fmt_found = NULL; | |
85 | score_max = 0; | |
b9a281db | 86 | fmt = first_oformat; |
de6d9b64 FB |
87 | while (fmt != NULL) { |
88 | score = 0; | |
89 | if (fmt->name && short_name && !strcmp(fmt->name, short_name)) | |
90 | score += 100; | |
91 | if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type)) | |
92 | score += 10; | |
93 | if (filename && fmt->extensions && | |
94 | match_ext(filename, fmt->extensions)) { | |
95 | score += 5; | |
96 | } | |
97 | if (score > score_max) { | |
98 | score_max = score; | |
99 | fmt_found = fmt; | |
100 | } | |
101 | fmt = fmt->next; | |
102 | } | |
103 | return fmt_found; | |
104 | } | |
105 | ||
b9a281db FB |
106 | AVInputFormat *av_find_input_format(const char *short_name) |
107 | { | |
108 | AVInputFormat *fmt; | |
109 | for(fmt = first_iformat; fmt != NULL; fmt = fmt->next) { | |
110 | if (!strcmp(fmt->name, short_name)) | |
111 | return fmt; | |
112 | } | |
113 | return NULL; | |
114 | } | |
115 | ||
116 | ||
117 | /** | |
118 | * Return TRUE if val is a prefix of str. If it returns TRUE, ptr is | |
119 | * set to the next character in 'str' after the prefix. | |
120 | * | |
121 | * @param str input string | |
122 | * @param val prefix to test | |
123 | * @param ptr updated after the prefix in str in there is a match | |
124 | * @return TRUE if there is a match | |
125 | */ | |
de6d9b64 FB |
126 | int strstart(const char *str, const char *val, const char **ptr) |
127 | { | |
128 | const char *p, *q; | |
129 | p = str; | |
130 | q = val; | |
131 | while (*q != '\0') { | |
132 | if (*p != *q) | |
133 | return 0; | |
134 | p++; | |
135 | q++; | |
136 | } | |
137 | if (ptr) | |
138 | *ptr = p; | |
139 | return 1; | |
140 | } | |
141 | ||
b9a281db FB |
142 | /** |
143 | * Copy the string str to buf. If str length is bigger than buf_size - | |
144 | * 1 then it is clamped to buf_size - 1. | |
145 | * NOTE: this function does what strncpy should have done to be | |
146 | * useful. NEVER use strncpy. | |
147 | * | |
148 | * @param buf destination buffer | |
149 | * @param buf_size size of destination buffer | |
150 | * @param str source string | |
151 | */ | |
152 | void pstrcpy(char *buf, int buf_size, const char *str) | |
de6d9b64 FB |
153 | { |
154 | int c; | |
155 | char *q = buf; | |
156 | ||
157 | for(;;) { | |
158 | c = *str++; | |
159 | if (c == 0 || q >= buf + buf_size - 1) | |
160 | break; | |
161 | *q++ = c; | |
162 | } | |
163 | *q = '\0'; | |
164 | } | |
165 | ||
166 | void register_all(void) | |
167 | { | |
168 | avcodec_init(); | |
169 | avcodec_register_all(); | |
de6d9b64 | 170 | |
b9a281db FB |
171 | mpegps_init(); |
172 | mpegts_init(); | |
173 | crc_init(); | |
174 | img_init(); | |
175 | raw_init(); | |
176 | rm_init(); | |
177 | asf_init(); | |
178 | avienc_init(); | |
179 | avidec_init(); | |
180 | wav_init(); | |
181 | swf_init(); | |
182 | au_init(); | |
183 | gif_init(); | |
184 | mov_init(); | |
185 | jpeg_init(); | |
186 | ||
8be1c656 | 187 | #ifndef CONFIG_WIN32 |
b9a281db | 188 | ffm_init(); |
8be1c656 | 189 | #endif |
19720f15 | 190 | #ifdef CONFIG_VIDEO4LINUX |
b9a281db | 191 | video_grab_init(); |
19720f15 FB |
192 | #endif |
193 | #ifdef CONFIG_AUDIO_OSS | |
b9a281db | 194 | audio_init(); |
96baaa6a | 195 | #endif |
96baaa6a | 196 | /* file protocols */ |
de6d9b64 FB |
197 | register_protocol(&file_protocol); |
198 | register_protocol(&pipe_protocol); | |
19720f15 | 199 | #ifdef CONFIG_NETWORK |
de6d9b64 FB |
200 | register_protocol(&udp_protocol); |
201 | register_protocol(&http_protocol); | |
8be1c656 | 202 | #endif |
de6d9b64 FB |
203 | } |
204 | ||
205 | /* memory handling */ | |
206 | ||
b9a281db FB |
207 | /** |
208 | * Allocate the payload of a packet and intialized its fields to default values. | |
209 | * | |
210 | * @param pkt packet | |
211 | * @param size wanted payload size | |
212 | * @return 0 if OK. AVERROR_xxx otherwise. | |
213 | */ | |
de6d9b64 FB |
214 | int av_new_packet(AVPacket *pkt, int size) |
215 | { | |
1ea4f593 | 216 | pkt->data = av_malloc(size); |
de6d9b64 | 217 | if (!pkt->data) |
b9a281db | 218 | return AVERROR_NOMEM; |
de6d9b64 FB |
219 | pkt->size = size; |
220 | /* sane state */ | |
221 | pkt->pts = 0; | |
222 | pkt->stream_index = 0; | |
223 | pkt->flags = 0; | |
224 | return 0; | |
225 | } | |
226 | ||
b9a281db FB |
227 | /** |
228 | * Free a packet | |
229 | * | |
230 | * @param pkt packet to free | |
231 | */ | |
de6d9b64 FB |
232 | void av_free_packet(AVPacket *pkt) |
233 | { | |
1ea4f593 | 234 | av_freep(&pkt->data); |
de6d9b64 | 235 | /* fail safe */ |
de6d9b64 FB |
236 | pkt->size = 0; |
237 | } | |
238 | ||
239 | /* fifo handling */ | |
240 | ||
241 | int fifo_init(FifoBuffer *f, int size) | |
242 | { | |
1ea4f593 | 243 | f->buffer = av_malloc(size); |
de6d9b64 FB |
244 | if (!f->buffer) |
245 | return -1; | |
246 | f->end = f->buffer + size; | |
247 | f->wptr = f->rptr = f->buffer; | |
248 | return 0; | |
249 | } | |
250 | ||
251 | void fifo_free(FifoBuffer *f) | |
252 | { | |
1ea4f593 | 253 | av_free(f->buffer); |
de6d9b64 FB |
254 | } |
255 | ||
256 | int fifo_size(FifoBuffer *f, UINT8 *rptr) | |
257 | { | |
258 | int size; | |
259 | ||
260 | if (f->wptr >= rptr) { | |
261 | size = f->wptr - rptr; | |
262 | } else { | |
263 | size = (f->end - rptr) + (f->wptr - f->buffer); | |
264 | } | |
265 | return size; | |
266 | } | |
267 | ||
268 | /* get data from the fifo (return -1 if not enough data) */ | |
269 | int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr) | |
270 | { | |
271 | UINT8 *rptr = *rptr_ptr; | |
272 | int size, len; | |
273 | ||
274 | if (f->wptr >= rptr) { | |
275 | size = f->wptr - rptr; | |
276 | } else { | |
277 | size = (f->end - rptr) + (f->wptr - f->buffer); | |
278 | } | |
279 | ||
280 | if (size < buf_size) | |
281 | return -1; | |
282 | while (buf_size > 0) { | |
283 | len = f->end - rptr; | |
284 | if (len > buf_size) | |
285 | len = buf_size; | |
286 | memcpy(buf, rptr, len); | |
287 | buf += len; | |
288 | rptr += len; | |
289 | if (rptr >= f->end) | |
290 | rptr = f->buffer; | |
291 | buf_size -= len; | |
292 | } | |
293 | *rptr_ptr = rptr; | |
294 | return 0; | |
295 | } | |
296 | ||
297 | void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr) | |
298 | { | |
299 | int len; | |
300 | UINT8 *wptr; | |
301 | wptr = *wptr_ptr; | |
302 | while (size > 0) { | |
303 | len = f->end - wptr; | |
304 | if (len > size) | |
305 | len = size; | |
306 | memcpy(wptr, buf, len); | |
307 | wptr += len; | |
308 | if (wptr >= f->end) | |
309 | wptr = f->buffer; | |
310 | buf += len; | |
311 | size -= len; | |
312 | } | |
313 | *wptr_ptr = wptr; | |
314 | } | |
315 | ||
b9a281db FB |
316 | int filename_number_test(const char *filename) |
317 | { | |
318 | char buf[1024]; | |
319 | return get_frame_filename(buf, sizeof(buf), filename, 1); | |
320 | } | |
321 | ||
322 | /* guess file format */ | |
323 | static AVInputFormat *probe_input_format(AVProbeData *pd, int is_opened) | |
324 | { | |
325 | AVInputFormat *fmt1, *fmt; | |
326 | int score, score_max; | |
327 | ||
328 | fmt = NULL; | |
329 | score_max = 0; | |
330 | for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) { | |
331 | if (!is_opened && !(fmt1->flags & AVFMT_NOFILE)) | |
332 | continue; | |
333 | score = 0; | |
a8dbe951 PG |
334 | if (fmt1->read_probe) { |
335 | score = fmt1->read_probe(pd); | |
336 | } else if (fmt1->extensions) { | |
b9a281db FB |
337 | if (match_ext(pd->filename, fmt1->extensions)) { |
338 | score = 50; | |
339 | } | |
a8dbe951 | 340 | } |
b9a281db FB |
341 | if (score > score_max) { |
342 | score_max = score; | |
343 | fmt = fmt1; | |
344 | } | |
345 | } | |
346 | return fmt; | |
347 | } | |
348 | ||
349 | /************************************************************/ | |
350 | /* input media file */ | |
96baaa6a | 351 | |
b9a281db FB |
352 | #define PROBE_BUF_SIZE 2048 |
353 | ||
354 | /** | |
355 | * Open a media file as input. The codec are not opened. Only the file | |
356 | * header (if present) is read. | |
357 | * | |
358 | * @param ic_ptr the opened media file handle is put here | |
359 | * @param filename filename to open. | |
360 | * @param fmt if non NULL, force the file format to use | |
361 | * @param buf_size optional buffer size (zero if default is OK) | |
362 | * @param ap additionnal parameters needed when opening the file (NULL if default) | |
363 | * @return 0 if OK. AVERROR_xxx otherwise. | |
364 | */ | |
365 | int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, | |
366 | AVInputFormat *fmt, | |
367 | int buf_size, | |
368 | AVFormatParameters *ap) | |
de6d9b64 | 369 | { |
de6d9b64 | 370 | AVFormatContext *ic = NULL; |
de6d9b64 | 371 | int err; |
b9a281db FB |
372 | char buf[PROBE_BUF_SIZE]; |
373 | AVProbeData probe_data, *pd = &probe_data; | |
de6d9b64 FB |
374 | |
375 | ic = av_mallocz(sizeof(AVFormatContext)); | |
b9a281db FB |
376 | if (!ic) { |
377 | err = AVERROR_NOMEM; | |
de6d9b64 | 378 | goto fail; |
de6d9b64 | 379 | } |
b9a281db FB |
380 | pstrcpy(ic->filename, sizeof(ic->filename), filename); |
381 | pd->filename = ic->filename; | |
382 | pd->buf = buf; | |
383 | pd->buf_size = 0; | |
384 | ||
385 | if (!fmt) { | |
386 | /* guess format if no file can be opened */ | |
387 | fmt = probe_input_format(pd, 0); | |
de6d9b64 | 388 | } |
de6d9b64 | 389 | |
96baaa6a | 390 | /* if no file needed do not try to open one */ |
b9a281db FB |
391 | if (!fmt || !(fmt->flags & AVFMT_NOFILE)) { |
392 | if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0) { | |
393 | err = AVERROR_IO; | |
96baaa6a | 394 | goto fail; |
b9a281db | 395 | } |
96baaa6a FB |
396 | if (buf_size > 0) { |
397 | url_setbufsize(&ic->pb, buf_size); | |
398 | } | |
b9a281db FB |
399 | /* read probe data */ |
400 | pd->buf_size = get_buffer(&ic->pb, buf, PROBE_BUF_SIZE); | |
401 | url_fseek(&ic->pb, 0, SEEK_SET); | |
96baaa6a FB |
402 | } |
403 | ||
b9a281db FB |
404 | /* guess file format */ |
405 | if (!fmt) { | |
406 | fmt = probe_input_format(pd, 1); | |
407 | } | |
408 | ||
409 | /* if still no format found, error */ | |
410 | if (!fmt) { | |
411 | err = AVERROR_NOFMT; | |
de6d9b64 FB |
412 | goto fail; |
413 | } | |
b9a281db FB |
414 | |
415 | ic->iformat = fmt; | |
de6d9b64 | 416 | |
b9a281db FB |
417 | /* allocate private data */ |
418 | ic->priv_data = av_mallocz(fmt->priv_data_size); | |
419 | if (!ic->priv_data) { | |
420 | err = AVERROR_NOMEM; | |
421 | goto fail; | |
422 | } | |
423 | ||
424 | /* check filename in case of an image number is expected */ | |
425 | if (ic->iformat->flags & AVFMT_NEEDNUMBER) { | |
426 | if (filename_number_test(ic->filename) < 0) { | |
427 | err = AVERROR_NUMEXPECTED; | |
428 | goto fail1; | |
429 | } | |
430 | } | |
431 | ||
432 | err = ic->iformat->read_header(ic, ap); | |
433 | if (err < 0) | |
434 | goto fail1; | |
435 | *ic_ptr = ic; | |
436 | return 0; | |
437 | fail1: | |
438 | if (!(fmt->flags & AVFMT_NOFILE)) { | |
439 | url_fclose(&ic->pb); | |
440 | } | |
de6d9b64 | 441 | fail: |
b9a281db | 442 | if (ic) { |
a8dbe951 | 443 | av_freep(&ic->priv_data); |
b9a281db | 444 | } |
1ea4f593 | 445 | av_free(ic); |
b9a281db FB |
446 | *ic_ptr = NULL; |
447 | return err; | |
de6d9b64 FB |
448 | } |
449 | ||
b9a281db FB |
450 | /** |
451 | * Read a packet from a media file | |
452 | * @param s media file handle | |
453 | * @param pkt is filled | |
454 | * @return 0 if OK. AVERROR_xxx if error. | |
455 | */ | |
de6d9b64 FB |
456 | int av_read_packet(AVFormatContext *s, AVPacket *pkt) |
457 | { | |
458 | AVPacketList *pktl; | |
459 | ||
460 | pktl = s->packet_buffer; | |
461 | if (pktl) { | |
462 | /* read packet from packet buffer, if there is data */ | |
463 | *pkt = pktl->pkt; | |
464 | s->packet_buffer = pktl->next; | |
1ea4f593 | 465 | av_free(pktl); |
de6d9b64 FB |
466 | return 0; |
467 | } else { | |
b9a281db FB |
468 | return s->iformat->read_packet(s, pkt); |
469 | } | |
470 | } | |
471 | ||
472 | /* state for codec information */ | |
473 | #define CSTATE_NOTFOUND 0 | |
474 | #define CSTATE_DECODING 1 | |
475 | #define CSTATE_FOUND 2 | |
476 | ||
477 | static int has_codec_parameters(AVCodecContext *enc) | |
478 | { | |
479 | int val; | |
480 | switch(enc->codec_type) { | |
481 | case CODEC_TYPE_AUDIO: | |
482 | val = enc->sample_rate; | |
483 | break; | |
484 | case CODEC_TYPE_VIDEO: | |
485 | val = enc->width; | |
486 | break; | |
487 | default: | |
488 | val = 1; | |
489 | break; | |
490 | } | |
491 | return (val != 0); | |
492 | } | |
493 | ||
494 | /** | |
495 | * Read the beginning of a media file to get stream information. This | |
496 | * is useful for file formats with no headers such as MPEG. This | |
497 | * function also compute the real frame rate in case of mpeg2 repeat | |
498 | * frame mode. | |
499 | * | |
500 | * @param ic media file handle | |
501 | * @return >=0 if OK. AVERROR_xxx if error. | |
502 | */ | |
503 | int av_find_stream_info(AVFormatContext *ic) | |
504 | { | |
505 | int i, count, ret, got_picture, size, read_size; | |
506 | AVCodec *codec; | |
507 | AVStream *st; | |
508 | AVPacket *pkt; | |
509 | AVPicture picture; | |
510 | AVPacketList *pktl=NULL, **ppktl; | |
511 | short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2]; | |
512 | UINT8 *ptr; | |
513 | int min_read_size, max_read_size; | |
514 | ||
515 | /* typical mpeg ts rate is 40 Mbits. DVD rate is about 10 | |
516 | Mbits. We read at most 0.1 second of file to find all streams */ | |
517 | ||
518 | /* XXX: base it on stream bitrate when possible */ | |
519 | if (ic->iformat == &mpegts_demux) { | |
520 | /* maximum number of bytes we accept to read to find all the streams | |
521 | in a file */ | |
522 | min_read_size = 3000000; | |
523 | } else { | |
524 | min_read_size = 125000; | |
525 | } | |
526 | /* max read size is 2 seconds of video max */ | |
527 | max_read_size = min_read_size * 20; | |
528 | ||
529 | /* set initial codec state */ | |
530 | for(i=0;i<ic->nb_streams;i++) { | |
531 | st = ic->streams[i]; | |
532 | if (has_codec_parameters(&st->codec)) | |
533 | st->codec_info_state = CSTATE_FOUND; | |
534 | else | |
535 | st->codec_info_state = CSTATE_NOTFOUND; | |
536 | st->codec_info_nb_repeat_frames = 0; | |
537 | st->codec_info_nb_real_frames = 0; | |
538 | } | |
539 | ||
540 | count = 0; | |
541 | read_size = 0; | |
542 | ppktl = &ic->packet_buffer; | |
543 | for(;;) { | |
544 | /* check if one codec still needs to be handled */ | |
545 | for(i=0;i<ic->nb_streams;i++) { | |
546 | st = ic->streams[i]; | |
547 | if (st->codec_info_state != CSTATE_FOUND) | |
548 | break; | |
549 | } | |
550 | if (i == ic->nb_streams) { | |
551 | /* NOTE: if the format has no header, then we need to read | |
552 | some packets to get most of the streams, so we cannot | |
553 | stop here */ | |
554 | if (!(ic->iformat->flags & AVFMT_NOHEADER) || | |
555 | read_size >= min_read_size) { | |
556 | /* if we found the info for all the codecs, we can stop */ | |
557 | ret = count; | |
558 | break; | |
559 | } | |
560 | } else { | |
561 | /* we did not get all the codec info, but we read too much data */ | |
562 | if (read_size >= max_read_size) { | |
563 | ret = count; | |
564 | break; | |
565 | } | |
566 | } | |
567 | ||
568 | pktl = av_mallocz(sizeof(AVPacketList)); | |
569 | if (!pktl) { | |
570 | ret = AVERROR_NOMEM; | |
571 | break; | |
572 | } | |
573 | ||
574 | /* add the packet in the buffered packet list */ | |
575 | *ppktl = pktl; | |
576 | ppktl = &pktl->next; | |
577 | ||
578 | /* NOTE: a new stream can be added there if no header in file | |
579 | (AVFMT_NOHEADER) */ | |
580 | pkt = &pktl->pkt; | |
581 | if (ic->iformat->read_packet(ic, pkt) < 0) { | |
582 | /* EOF or error */ | |
583 | ret = -1; /* we could not have all the codec parameters before EOF */ | |
584 | if ((ic->iformat->flags & AVFMT_NOHEADER) && | |
585 | i == ic->nb_streams) | |
586 | ret = 0; | |
587 | break; | |
588 | } | |
589 | read_size += pkt->size; | |
590 | ||
591 | /* open new codecs */ | |
592 | for(i=0;i<ic->nb_streams;i++) { | |
593 | st = ic->streams[i]; | |
594 | if (st->codec_info_state == CSTATE_NOTFOUND) { | |
595 | /* set to found in case of error */ | |
596 | st->codec_info_state = CSTATE_FOUND; | |
597 | codec = avcodec_find_decoder(st->codec.codec_id); | |
598 | if (codec) { | |
599 | ret = avcodec_open(&st->codec, codec); | |
600 | if (ret >= 0) | |
601 | st->codec_info_state = CSTATE_DECODING; | |
602 | } | |
603 | } | |
604 | } | |
605 | ||
606 | st = ic->streams[pkt->stream_index]; | |
607 | if (st->codec_info_state == CSTATE_DECODING) { | |
608 | /* decode the data and update codec parameters */ | |
609 | ptr = pkt->data; | |
610 | size = pkt->size; | |
611 | while (size > 0) { | |
612 | switch(st->codec.codec_type) { | |
613 | case CODEC_TYPE_VIDEO: | |
614 | ret = avcodec_decode_video(&st->codec, &picture, | |
615 | &got_picture, ptr, size); | |
616 | break; | |
617 | case CODEC_TYPE_AUDIO: | |
618 | ret = avcodec_decode_audio(&st->codec, samples, | |
619 | &got_picture, ptr, size); | |
620 | break; | |
621 | default: | |
622 | ret = -1; | |
623 | break; | |
624 | } | |
625 | if (ret < 0) { | |
626 | /* if error, simply ignore because another packet | |
627 | may be OK */ | |
628 | break; | |
629 | } | |
630 | if (got_picture) { | |
631 | /* we got the parameters - now we can stop | |
632 | examining this stream */ | |
633 | /* XXX: add a codec info so that we can decide if | |
634 | the codec can repeat frames */ | |
635 | if (st->codec.codec_id == CODEC_ID_MPEG1VIDEO && | |
636 | ic->iformat != &mpegts_demux && | |
637 | st->codec.sub_id == 2) { | |
638 | /* for mpeg2 video, we want to know the real | |
639 | frame rate, so we decode 40 frames. In mpeg | |
640 | TS case we do not do it because it would be | |
641 | too long */ | |
642 | st->codec_info_nb_real_frames++; | |
643 | st->codec_info_nb_repeat_frames += st->codec.repeat_pict; | |
644 | #if 0 | |
645 | /* XXX: testing */ | |
646 | if ((st->codec_info_nb_real_frames % 24) == 23) { | |
647 | st->codec_info_nb_repeat_frames += 2; | |
648 | } | |
649 | #endif | |
650 | /* stop after 40 frames */ | |
651 | if (st->codec_info_nb_real_frames >= 40) { | |
652 | st->r_frame_rate = (st->codec.frame_rate * | |
653 | st->codec_info_nb_real_frames) / | |
654 | (st->codec_info_nb_real_frames + | |
655 | (st->codec_info_nb_repeat_frames >> 1)); | |
656 | goto close_codec; | |
657 | } | |
658 | } else { | |
659 | close_codec: | |
660 | st->codec_info_state = CSTATE_FOUND; | |
661 | avcodec_close(&st->codec); | |
24f9709b | 662 | break; |
b9a281db | 663 | } |
b9a281db FB |
664 | } |
665 | ptr += ret; | |
666 | size -= ret; | |
667 | } | |
668 | } | |
669 | count++; | |
670 | } | |
671 | ||
672 | /* close each codec if there are opened */ | |
673 | for(i=0;i<ic->nb_streams;i++) { | |
674 | st = ic->streams[i]; | |
675 | if (st->codec_info_state == CSTATE_DECODING) | |
676 | avcodec_close(&st->codec); | |
677 | } | |
678 | ||
679 | /* set real frame rate info */ | |
680 | for(i=0;i<ic->nb_streams;i++) { | |
681 | st = ic->streams[i]; | |
682 | if (st->codec.codec_type == CODEC_TYPE_VIDEO) { | |
683 | if (!st->r_frame_rate) | |
684 | st->r_frame_rate = st->codec.frame_rate; | |
685 | } | |
de6d9b64 | 686 | } |
b9a281db FB |
687 | |
688 | return ret; | |
de6d9b64 FB |
689 | } |
690 | ||
b9a281db FB |
691 | /** |
692 | * Close a media file (but not its codecs) | |
693 | * | |
694 | * @param s media file handle | |
695 | */ | |
de6d9b64 FB |
696 | void av_close_input_file(AVFormatContext *s) |
697 | { | |
698 | int i; | |
699 | ||
b9a281db FB |
700 | if (s->iformat->read_close) |
701 | s->iformat->read_close(s); | |
de6d9b64 | 702 | for(i=0;i<s->nb_streams;i++) { |
1ea4f593 | 703 | av_free(s->streams[i]); |
de6d9b64 FB |
704 | } |
705 | if (s->packet_buffer) { | |
706 | AVPacketList *p, *p1; | |
707 | p = s->packet_buffer; | |
708 | while (p != NULL) { | |
709 | p1 = p->next; | |
710 | av_free_packet(&p->pkt); | |
1ea4f593 | 711 | av_free(p); |
de6d9b64 FB |
712 | p = p1; |
713 | } | |
714 | s->packet_buffer = NULL; | |
715 | } | |
b9a281db | 716 | if (!(s->iformat->flags & AVFMT_NOFILE)) { |
96baaa6a FB |
717 | url_fclose(&s->pb); |
718 | } | |
a8dbe951 | 719 | av_freep(&s->priv_data); |
1ea4f593 | 720 | av_free(s); |
de6d9b64 FB |
721 | } |
722 | ||
b9a281db FB |
723 | /** |
724 | * Add a new stream to a media file. Can only be called in the | |
725 | * read_header function. If the flag AVFMT_NOHEADER is in the format | |
726 | * description, then new streams can be added in read_packet too. | |
727 | * | |
728 | * | |
729 | * @param s media file handle | |
730 | * @param id file format dependent stream id | |
731 | */ | |
732 | AVStream *av_new_stream(AVFormatContext *s, int id) | |
733 | { | |
734 | AVStream *st; | |
735 | ||
736 | if (s->nb_streams >= MAX_STREAMS) | |
737 | return NULL; | |
738 | ||
739 | st = av_mallocz(sizeof(AVStream)); | |
740 | if (!st) | |
741 | return NULL; | |
742 | st->index = s->nb_streams; | |
743 | st->id = id; | |
744 | s->streams[s->nb_streams++] = st; | |
745 | return st; | |
746 | } | |
747 | ||
748 | /************************************************************/ | |
749 | /* output media file */ | |
de6d9b64 | 750 | |
b9a281db FB |
751 | /** |
752 | * allocate the stream private data and write the stream header to an | |
753 | * output media file | |
754 | * | |
755 | * @param s media file handle | |
756 | * @return 0 if OK. AVERROR_xxx if error. | |
757 | */ | |
758 | int av_write_header(AVFormatContext *s) | |
759 | { | |
760 | s->priv_data = av_mallocz(s->oformat->priv_data_size); | |
761 | if (!s->priv_data) | |
762 | return AVERROR_NOMEM; | |
763 | return s->oformat->write_header(s); | |
764 | } | |
765 | ||
766 | /** | |
767 | * write a packet to an output media file | |
768 | * | |
769 | * @param s media file handle | |
770 | * @param pkt packet to write | |
771 | * @param force_pts XXX: need to suppress that | |
772 | */ | |
10bb7023 | 773 | int av_write_packet(AVFormatContext *s, AVPacket *pkt, int force_pts) |
de6d9b64 FB |
774 | { |
775 | /* XXX: currently, an emulation because internal API must change */ | |
b9a281db FB |
776 | return s->oformat->write_packet(s, pkt->stream_index, pkt->data, pkt->size, force_pts); |
777 | } | |
778 | ||
779 | /** | |
780 | * write the stream trailer to an output media file and and free the | |
781 | * file private data. | |
782 | * | |
783 | * @param s media file handle | |
784 | * @return 0 if OK. AVERROR_xxx if error. */ | |
785 | int av_write_trailer(AVFormatContext *s) | |
786 | { | |
787 | int ret; | |
788 | ret = s->oformat->write_trailer(s); | |
789 | av_freep(&s->priv_data); | |
790 | return ret; | |
de6d9b64 FB |
791 | } |
792 | ||
793 | /* "user interface" functions */ | |
794 | ||
795 | void dump_format(AVFormatContext *ic, | |
796 | int index, | |
797 | const char *url, | |
798 | int is_output) | |
799 | { | |
b9a281db | 800 | int i, flags; |
de6d9b64 FB |
801 | char buf[256]; |
802 | ||
803 | fprintf(stderr, "%s #%d, %s, %s '%s':\n", | |
804 | is_output ? "Output" : "Input", | |
b9a281db FB |
805 | index, |
806 | is_output ? ic->oformat->name : ic->iformat->name, | |
de6d9b64 FB |
807 | is_output ? "to" : "from", url); |
808 | for(i=0;i<ic->nb_streams;i++) { | |
809 | AVStream *st = ic->streams[i]; | |
810 | avcodec_string(buf, sizeof(buf), &st->codec, is_output); | |
b9a281db FB |
811 | fprintf(stderr, " Stream #%d.%d", index, i); |
812 | /* the pid is an important information, so we display it */ | |
813 | /* XXX: add a generic system */ | |
814 | if (is_output) | |
815 | flags = ic->oformat->flags; | |
816 | else | |
817 | flags = ic->iformat->flags; | |
818 | if (flags & AVFMT_SHOW_IDS) { | |
819 | fprintf(stderr, "[0x%x]", st->id); | |
820 | } | |
821 | fprintf(stderr, ": %s\n", buf); | |
de6d9b64 FB |
822 | } |
823 | } | |
824 | ||
825 | typedef struct { | |
826 | const char *str; | |
827 | int width, height; | |
828 | } SizeEntry; | |
829 | ||
830 | static SizeEntry sizes[] = { | |
831 | { "sqcif", 128, 96 }, | |
832 | { "qcif", 176, 144 }, | |
833 | { "cif", 352, 288 }, | |
834 | { "4cif", 704, 576 }, | |
835 | }; | |
836 | ||
837 | int parse_image_size(int *width_ptr, int *height_ptr, const char *str) | |
838 | { | |
839 | int i; | |
840 | int n = sizeof(sizes) / sizeof(SizeEntry); | |
841 | const char *p; | |
842 | int frame_width = 0, frame_height = 0; | |
843 | ||
844 | for(i=0;i<n;i++) { | |
845 | if (!strcmp(sizes[i].str, str)) { | |
846 | frame_width = sizes[i].width; | |
847 | frame_height = sizes[i].height; | |
848 | break; | |
849 | } | |
850 | } | |
851 | if (i == n) { | |
852 | p = str; | |
853 | frame_width = strtol(p, (char **)&p, 10); | |
854 | if (*p) | |
855 | p++; | |
856 | frame_height = strtol(p, (char **)&p, 10); | |
857 | } | |
858 | if (frame_width <= 0 || frame_height <= 0) | |
859 | return -1; | |
860 | *width_ptr = frame_width; | |
861 | *height_ptr = frame_height; | |
862 | return 0; | |
863 | } | |
864 | ||
865 | INT64 gettime(void) | |
866 | { | |
8be1c656 FB |
867 | #ifdef CONFIG_WIN32 |
868 | struct _timeb tb; | |
869 | _ftime(&tb); | |
870 | return ((INT64)tb.time * INT64_C(1000) + (INT64)tb.millitm) * INT64_C(1000); | |
871 | #else | |
de6d9b64 FB |
872 | struct timeval tv; |
873 | gettimeofday(&tv,NULL); | |
874 | return (INT64)tv.tv_sec * 1000000 + tv.tv_usec; | |
8be1c656 | 875 | #endif |
de6d9b64 FB |
876 | } |
877 | ||
878 | /* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */ | |
879 | INT64 parse_date(const char *datestr, int duration) | |
880 | { | |
881 | const char *p; | |
882 | INT64 t; | |
2dbceb9f PG |
883 | struct tm dt; |
884 | ||
885 | memset(&dt, 0, sizeof(dt)); | |
de6d9b64 FB |
886 | |
887 | p = datestr; | |
888 | if (!duration) { | |
de6d9b64 | 889 | if (strlen(p) >= 5 && p[4] == '-') { |
2dbceb9f | 890 | dt.tm_year = strtol(p, (char **)&p, 10); |
de6d9b64 FB |
891 | if (*p) |
892 | p++; | |
2dbceb9f | 893 | dt.tm_mon = strtol(p, (char **)&p, 10) - 1; |
de6d9b64 FB |
894 | if (*p) |
895 | p++; | |
2dbceb9f | 896 | dt.tm_mday = strtol(p, (char **)&p, 10) - 1; |
de6d9b64 FB |
897 | if (*p) |
898 | p++; | |
de6d9b64 | 899 | } else { |
2dbceb9f PG |
900 | time_t now = time(0); |
901 | dt = *localtime(&now); | |
902 | dt.tm_hour = 0; | |
903 | dt.tm_min = 0; | |
904 | dt.tm_sec = 0; | |
de6d9b64 | 905 | } |
de6d9b64 FB |
906 | } |
907 | ||
2dbceb9f PG |
908 | dt.tm_hour = strtol(p, (char **)&p, 10); |
909 | if (*p) | |
910 | p++; | |
911 | dt.tm_min = strtol(p, (char **)&p, 10); | |
912 | if (*p) | |
de6d9b64 | 913 | p++; |
2dbceb9f PG |
914 | dt.tm_sec = strtol(p, (char **)&p, 10); |
915 | ||
916 | if (duration) { | |
917 | t = (INT64) 1000000 * (dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec); | |
918 | } else { | |
919 | t = (INT64) 1000000 * mktime(&dt); | |
de6d9b64 | 920 | } |
2dbceb9f | 921 | |
de6d9b64 FB |
922 | if (*p == '.') { |
923 | int val, n; | |
924 | p++; | |
925 | n = strlen(p); | |
926 | if (n > 6) | |
927 | n = 6; | |
928 | val = strtol(p, NULL, 10); | |
929 | while (n < 6) { | |
930 | val = val * 10; | |
931 | n++; | |
932 | } | |
933 | t += val; | |
934 | } | |
935 | return t; | |
936 | } | |
937 | ||
2dbceb9f | 938 | /* syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done. Return |
de6d9b64 FB |
939 | 1 if found */ |
940 | int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info) | |
941 | { | |
942 | const char *p; | |
943 | char tag[128], *q; | |
944 | ||
945 | p = info; | |
946 | if (*p == '?') | |
947 | p++; | |
948 | for(;;) { | |
949 | q = tag; | |
950 | while (*p != '\0' && *p != '=' && *p != '&') { | |
951 | if ((q - tag) < sizeof(tag) - 1) | |
952 | *q++ = *p; | |
953 | p++; | |
954 | } | |
955 | *q = '\0'; | |
956 | q = arg; | |
957 | if (*p == '=') { | |
958 | p++; | |
959 | while (*p != '&' && *p != '\0') { | |
2dbceb9f PG |
960 | if ((q - arg) < arg_size - 1) { |
961 | if (*p == '+') | |
962 | *q++ = ' '; | |
963 | else | |
964 | *q++ = *p; | |
965 | } | |
de6d9b64 FB |
966 | p++; |
967 | } | |
968 | *q = '\0'; | |
969 | } | |
970 | if (!strcmp(tag, tag1)) | |
971 | return 1; | |
972 | if (*p != '&') | |
973 | break; | |
8d1335ea | 974 | p++; |
de6d9b64 FB |
975 | } |
976 | return 0; | |
977 | } | |
978 | ||
9150f42e FB |
979 | /* Return in 'buf' the path with '%d' replaced by number. Also handles |
980 | the '%0nd' format where 'n' is the total number of digits and | |
981 | '%%'. Return 0 if OK, and -1 if format error */ | |
982 | int get_frame_filename(char *buf, int buf_size, | |
983 | const char *path, int number) | |
984 | { | |
985 | const char *p; | |
986 | char *q, buf1[20]; | |
987 | int nd, len, c, percentd_found; | |
988 | ||
989 | q = buf; | |
990 | p = path; | |
991 | percentd_found = 0; | |
992 | for(;;) { | |
993 | c = *p++; | |
994 | if (c == '\0') | |
995 | break; | |
996 | if (c == '%') { | |
997 | nd = 0; | |
998 | while (*p >= '0' && *p <= '9') { | |
999 | nd = nd * 10 + *p++ - '0'; | |
1000 | } | |
1001 | c = *p++; | |
1002 | switch(c) { | |
1003 | case '%': | |
1004 | goto addchar; | |
1005 | case 'd': | |
1006 | if (percentd_found) | |
1007 | goto fail; | |
1008 | percentd_found = 1; | |
1009 | snprintf(buf1, sizeof(buf1), "%0*d", nd, number); | |
1010 | len = strlen(buf1); | |
1011 | if ((q - buf + len) > buf_size - 1) | |
1012 | goto fail; | |
1013 | memcpy(q, buf1, len); | |
1014 | q += len; | |
1015 | break; | |
1016 | default: | |
1017 | goto fail; | |
1018 | } | |
1019 | } else { | |
1020 | addchar: | |
1021 | if ((q - buf) < buf_size - 1) | |
1022 | *q++ = c; | |
1023 | } | |
1024 | } | |
1025 | if (!percentd_found) | |
1026 | goto fail; | |
1027 | *q = '\0'; | |
1028 | return 0; | |
1029 | fail: | |
1030 | *q = '\0'; | |
1031 | return -1; | |
1032 | } | |
1033 | ||
af469427 J |
1034 | static int gcd(INT64 a, INT64 b) |
1035 | { | |
1036 | INT64 c; | |
1037 | ||
1038 | while (1) { | |
1039 | c = a % b; | |
1040 | if (c == 0) | |
1041 | return b; | |
1042 | a = b; | |
1043 | b = c; | |
1044 | } | |
1045 | } | |
1046 | ||
1047 | void ticker_init(Ticker *tick, INT64 inrate, INT64 outrate) | |
1048 | { | |
1049 | int g; | |
1050 | ||
1051 | g = gcd(inrate, outrate); | |
1052 | inrate /= g; | |
1053 | outrate /= g; | |
9150f42e | 1054 | |
af469427 J |
1055 | tick->value = -outrate/2; |
1056 | ||
1057 | tick->inrate = inrate; | |
1058 | tick->outrate = outrate; | |
1059 | tick->div = tick->outrate / tick->inrate; | |
1060 | tick->mod = tick->outrate % tick->inrate; | |
1061 | } | |
b9a281db FB |
1062 | |
1063 | /** | |
1064 | * | |
1065 | * Print on stdout a nice hexa dump of a buffer | |
1066 | * @param buf buffer | |
1067 | * @param size buffer size | |
1068 | */ | |
1069 | void av_hex_dump(UINT8 *buf, int size) | |
1070 | { | |
1071 | int len, i, j, c; | |
1072 | ||
1073 | for(i=0;i<size;i+=16) { | |
1074 | len = size - i; | |
1075 | if (len > 16) | |
1076 | len = 16; | |
1077 | printf("%08x ", i); | |
1078 | for(j=0;j<16;j++) { | |
1079 | if (j < len) | |
1080 | printf(" %02x", buf[i+j]); | |
1081 | else | |
1082 | printf(" "); | |
1083 | } | |
1084 | printf(" "); | |
1085 | for(j=0;j<len;j++) { | |
1086 | c = buf[i+j]; | |
1087 | if (c < ' ' || c > '~') | |
1088 | c = '.'; | |
1089 | printf("%c", c); | |
1090 | } | |
1091 | printf("\n"); | |
1092 | } | |
1093 | } | |
1094 | ||
a9a721da FB |
1095 | void url_split(char *proto, int proto_size, |
1096 | char *hostname, int hostname_size, | |
1097 | int *port_ptr, | |
1098 | char *path, int path_size, | |
1099 | const char *url) | |
1100 | { | |
1101 | const char *p; | |
1102 | char *q; | |
1103 | int port; | |
1104 | ||
1105 | port = -1; | |
1106 | ||
1107 | p = url; | |
1108 | q = proto; | |
1109 | while (*p != ':' && *p != '\0') { | |
1110 | if ((q - proto) < proto_size - 1) | |
1111 | *q++ = *p; | |
1112 | p++; | |
1113 | } | |
1114 | if (proto_size > 0) | |
1115 | *q = '\0'; | |
1116 | if (*p == '\0') { | |
1117 | if (proto_size > 0) | |
1118 | proto[0] = '\0'; | |
1119 | if (hostname_size > 0) | |
1120 | hostname[0] = '\0'; | |
1121 | p = url; | |
1122 | } else { | |
1123 | p++; | |
1124 | if (*p == '/') | |
1125 | p++; | |
1126 | if (*p == '/') | |
1127 | p++; | |
1128 | q = hostname; | |
1129 | while (*p != ':' && *p != '/' && *p != '?' && *p != '\0') { | |
1130 | if ((q - hostname) < hostname_size - 1) | |
1131 | *q++ = *p; | |
1132 | p++; | |
1133 | } | |
1134 | if (hostname_size > 0) | |
1135 | *q = '\0'; | |
1136 | if (*p == ':') { | |
1137 | p++; | |
1138 | port = strtoul(p, (char **)&p, 10); | |
1139 | } | |
1140 | } | |
1141 | if (port_ptr) | |
1142 | *port_ptr = port; | |
1143 | pstrcpy(path, path_size, p); | |
1144 | } | |
1145 |