Mercurial > libavformat.hg
annotate utils.c @ 29:86a085c19c7f libavformat
video_device fixes
author | bellard |
---|---|
date | Thu, 23 Jan 2003 09:55:19 +0000 |
parents | 65433f1b2549 |
children | 90fd30dd68b3 |
rev | line source |
---|---|
0 | 1 /* |
2 * Various utilities for ffmpeg system | |
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard | |
4 * | |
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. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
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 | |
18 */ | |
19 #include "avformat.h" | |
20 #include <ctype.h> | |
22
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
21 #ifdef CONFIG_WIN32 |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
22 #define strcasecmp _stricmp |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
23 #include <sys/types.h> |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
24 #include <sys/timeb.h> |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
25 #elif defined(CONFIG_OS2) |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
26 #include <string.h> |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
27 #define strcasecmp stricmp |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
28 #include <sys/time.h> |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
29 #else |
0 | 30 #include <unistd.h> |
31 #include <fcntl.h> | |
32 #include <sys/time.h> | |
33 #endif | |
34 #include <time.h> | |
35 | |
36 #ifndef HAVE_STRPTIME | |
37 #include "strptime.h" | |
38 #endif | |
39 | |
40 AVInputFormat *first_iformat; | |
41 AVOutputFormat *first_oformat; | |
20 | 42 AVImageFormat *first_image_format; |
0 | 43 |
29 | 44 const char *video_device = "none"; |
45 | |
0 | 46 void av_register_input_format(AVInputFormat *format) |
47 { | |
48 AVInputFormat **p; | |
49 p = &first_iformat; | |
50 while (*p != NULL) p = &(*p)->next; | |
51 *p = format; | |
52 format->next = NULL; | |
53 } | |
54 | |
55 void av_register_output_format(AVOutputFormat *format) | |
56 { | |
57 AVOutputFormat **p; | |
58 p = &first_oformat; | |
59 while (*p != NULL) p = &(*p)->next; | |
60 *p = format; | |
61 format->next = NULL; | |
62 } | |
63 | |
64 int match_ext(const char *filename, const char *extensions) | |
65 { | |
66 const char *ext, *p; | |
67 char ext1[32], *q; | |
68 | |
69 ext = strrchr(filename, '.'); | |
70 if (ext) { | |
71 ext++; | |
72 p = extensions; | |
73 for(;;) { | |
74 q = ext1; | |
75 while (*p != '\0' && *p != ',') | |
76 *q++ = *p++; | |
77 *q = '\0'; | |
78 if (!strcasecmp(ext1, ext)) | |
79 return 1; | |
80 if (*p == '\0') | |
81 break; | |
82 p++; | |
83 } | |
84 } | |
85 return 0; | |
86 } | |
87 | |
88 AVOutputFormat *guess_format(const char *short_name, const char *filename, | |
89 const char *mime_type) | |
90 { | |
91 AVOutputFormat *fmt, *fmt_found; | |
92 int score_max, score; | |
93 | |
20 | 94 /* specific test for image sequences */ |
21 | 95 if (!short_name && filename && |
96 filename_number_test(filename) >= 0 && | |
97 guess_image_format(filename)) { | |
20 | 98 return guess_format("image", NULL, NULL); |
99 } | |
100 | |
0 | 101 /* find the proper file type */ |
102 fmt_found = NULL; | |
103 score_max = 0; | |
104 fmt = first_oformat; | |
105 while (fmt != NULL) { | |
106 score = 0; | |
107 if (fmt->name && short_name && !strcmp(fmt->name, short_name)) | |
108 score += 100; | |
109 if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type)) | |
110 score += 10; | |
111 if (filename && fmt->extensions && | |
112 match_ext(filename, fmt->extensions)) { | |
113 score += 5; | |
114 } | |
115 if (score > score_max) { | |
116 score_max = score; | |
117 fmt_found = fmt; | |
118 } | |
119 fmt = fmt->next; | |
120 } | |
121 return fmt_found; | |
122 } | |
123 | |
124 AVOutputFormat *guess_stream_format(const char *short_name, const char *filename, | |
125 const char *mime_type) | |
126 { | |
127 AVOutputFormat *fmt = guess_format(short_name, filename, mime_type); | |
128 | |
129 if (fmt) { | |
130 AVOutputFormat *stream_fmt; | |
131 char stream_format_name[64]; | |
132 | |
133 snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name); | |
134 stream_fmt = guess_format(stream_format_name, NULL, NULL); | |
135 | |
136 if (stream_fmt) | |
137 fmt = stream_fmt; | |
138 } | |
139 | |
140 return fmt; | |
141 } | |
142 | |
143 AVInputFormat *av_find_input_format(const char *short_name) | |
144 { | |
145 AVInputFormat *fmt; | |
146 for(fmt = first_iformat; fmt != NULL; fmt = fmt->next) { | |
147 if (!strcmp(fmt->name, short_name)) | |
148 return fmt; | |
149 } | |
150 return NULL; | |
151 } | |
152 | |
153 /* memory handling */ | |
154 | |
155 /** | |
156 * Allocate the payload of a packet and intialized its fields to default values. | |
157 * | |
158 * @param pkt packet | |
159 * @param size wanted payload size | |
160 * @return 0 if OK. AVERROR_xxx otherwise. | |
161 */ | |
162 int av_new_packet(AVPacket *pkt, int size) | |
163 { | |
164 int i; | |
165 pkt->data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); | |
166 if (!pkt->data) | |
167 return AVERROR_NOMEM; | |
168 pkt->size = size; | |
169 /* sane state */ | |
170 pkt->pts = AV_NOPTS_VALUE; | |
171 pkt->stream_index = 0; | |
172 pkt->flags = 0; | |
173 | |
174 for(i=0; i<FF_INPUT_BUFFER_PADDING_SIZE; i++) | |
175 pkt->data[size+i]= 0; | |
176 | |
177 return 0; | |
178 } | |
179 | |
180 /** | |
181 * Free a packet | |
182 * | |
183 * @param pkt packet to free | |
184 */ | |
185 void av_free_packet(AVPacket *pkt) | |
186 { | |
187 av_freep(&pkt->data); | |
188 /* fail safe */ | |
189 pkt->size = 0; | |
190 } | |
191 | |
192 /* fifo handling */ | |
193 | |
194 int fifo_init(FifoBuffer *f, int size) | |
195 { | |
196 f->buffer = av_malloc(size); | |
197 if (!f->buffer) | |
198 return -1; | |
199 f->end = f->buffer + size; | |
200 f->wptr = f->rptr = f->buffer; | |
201 return 0; | |
202 } | |
203 | |
204 void fifo_free(FifoBuffer *f) | |
205 { | |
206 av_free(f->buffer); | |
207 } | |
208 | |
209 int fifo_size(FifoBuffer *f, UINT8 *rptr) | |
210 { | |
211 int size; | |
212 | |
213 if (f->wptr >= rptr) { | |
214 size = f->wptr - rptr; | |
215 } else { | |
216 size = (f->end - rptr) + (f->wptr - f->buffer); | |
217 } | |
218 return size; | |
219 } | |
220 | |
221 /* get data from the fifo (return -1 if not enough data) */ | |
222 int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr) | |
223 { | |
224 UINT8 *rptr = *rptr_ptr; | |
225 int size, len; | |
226 | |
227 if (f->wptr >= rptr) { | |
228 size = f->wptr - rptr; | |
229 } else { | |
230 size = (f->end - rptr) + (f->wptr - f->buffer); | |
231 } | |
232 | |
233 if (size < buf_size) | |
234 return -1; | |
235 while (buf_size > 0) { | |
236 len = f->end - rptr; | |
237 if (len > buf_size) | |
238 len = buf_size; | |
239 memcpy(buf, rptr, len); | |
240 buf += len; | |
241 rptr += len; | |
242 if (rptr >= f->end) | |
243 rptr = f->buffer; | |
244 buf_size -= len; | |
245 } | |
246 *rptr_ptr = rptr; | |
247 return 0; | |
248 } | |
249 | |
250 void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr) | |
251 { | |
252 int len; | |
253 UINT8 *wptr; | |
254 wptr = *wptr_ptr; | |
255 while (size > 0) { | |
256 len = f->end - wptr; | |
257 if (len > size) | |
258 len = size; | |
259 memcpy(wptr, buf, len); | |
260 wptr += len; | |
261 if (wptr >= f->end) | |
262 wptr = f->buffer; | |
263 buf += len; | |
264 size -= len; | |
265 } | |
266 *wptr_ptr = wptr; | |
267 } | |
268 | |
269 int filename_number_test(const char *filename) | |
270 { | |
271 char buf[1024]; | |
272 return get_frame_filename(buf, sizeof(buf), filename, 1); | |
273 } | |
274 | |
275 /* guess file format */ | |
276 AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened) | |
277 { | |
278 AVInputFormat *fmt1, *fmt; | |
279 int score, score_max; | |
280 | |
281 fmt = NULL; | |
282 score_max = 0; | |
283 for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) { | |
284 if (!is_opened && !(fmt1->flags & AVFMT_NOFILE)) | |
285 continue; | |
286 score = 0; | |
287 if (fmt1->read_probe) { | |
288 score = fmt1->read_probe(pd); | |
289 } else if (fmt1->extensions) { | |
290 if (match_ext(pd->filename, fmt1->extensions)) { | |
291 score = 50; | |
292 } | |
293 } | |
294 if (score > score_max) { | |
295 score_max = score; | |
296 fmt = fmt1; | |
297 } | |
298 } | |
299 return fmt; | |
300 } | |
301 | |
302 /************************************************************/ | |
303 /* input media file */ | |
304 | |
305 #define PROBE_BUF_SIZE 2048 | |
306 | |
307 /** | |
308 * Open a media file as input. The codec are not opened. Only the file | |
309 * header (if present) is read. | |
310 * | |
311 * @param ic_ptr the opened media file handle is put here | |
312 * @param filename filename to open. | |
313 * @param fmt if non NULL, force the file format to use | |
314 * @param buf_size optional buffer size (zero if default is OK) | |
315 * @param ap additionnal parameters needed when opening the file (NULL if default) | |
316 * @return 0 if OK. AVERROR_xxx otherwise. | |
317 */ | |
318 int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, | |
319 AVInputFormat *fmt, | |
320 int buf_size, | |
321 AVFormatParameters *ap) | |
322 { | |
323 AVFormatContext *ic = NULL; | |
324 int err; | |
325 char buf[PROBE_BUF_SIZE]; | |
326 AVProbeData probe_data, *pd = &probe_data; | |
327 | |
328 ic = av_mallocz(sizeof(AVFormatContext)); | |
329 if (!ic) { | |
330 err = AVERROR_NOMEM; | |
331 goto fail; | |
332 } | |
333 pstrcpy(ic->filename, sizeof(ic->filename), filename); | |
334 pd->filename = ic->filename; | |
335 pd->buf = buf; | |
336 pd->buf_size = 0; | |
337 | |
338 if (!fmt) { | |
339 /* guess format if no file can be opened */ | |
340 fmt = av_probe_input_format(pd, 0); | |
341 } | |
342 | |
343 if (!fmt || !(fmt->flags & AVFMT_NOFILE)) { | |
20 | 344 /* if no file needed do not try to open one */ |
0 | 345 if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0) { |
346 err = AVERROR_IO; | |
347 goto fail; | |
348 } | |
349 if (buf_size > 0) { | |
350 url_setbufsize(&ic->pb, buf_size); | |
351 } | |
352 if (!fmt) { | |
353 /* read probe data */ | |
354 pd->buf_size = get_buffer(&ic->pb, buf, PROBE_BUF_SIZE); | |
355 url_fseek(&ic->pb, 0, SEEK_SET); | |
356 } | |
357 } | |
358 | |
359 /* guess file format */ | |
360 if (!fmt) { | |
361 fmt = av_probe_input_format(pd, 1); | |
362 } | |
363 | |
364 /* if still no format found, error */ | |
365 if (!fmt) { | |
366 err = AVERROR_NOFMT; | |
367 goto fail; | |
368 } | |
369 | |
370 /* XXX: suppress this hack for redirectors */ | |
22
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
371 #ifdef CONFIG_NETWORK |
0 | 372 if (fmt == &redir_demux) { |
373 err = redir_open(ic_ptr, &ic->pb); | |
374 url_fclose(&ic->pb); | |
375 av_free(ic); | |
376 return err; | |
377 } | |
11
932b59c66c60
mingw patch by (Bill Eldridge <bill at rfa dot org>)
michaelni
parents:
9
diff
changeset
|
378 #endif |
0 | 379 |
380 ic->iformat = fmt; | |
381 | |
20 | 382 /* check filename in case of an image number is expected */ |
383 if (ic->iformat->flags & AVFMT_NEEDNUMBER) { | |
384 if (filename_number_test(ic->filename) < 0) { | |
385 err = AVERROR_NUMEXPECTED; | |
386 goto fail1; | |
387 } | |
388 } | |
389 | |
0 | 390 /* allocate private data */ |
391 ic->priv_data = av_mallocz(fmt->priv_data_size); | |
392 if (!ic->priv_data) { | |
393 err = AVERROR_NOMEM; | |
394 goto fail; | |
395 } | |
396 | |
397 /* default pts settings is MPEG like */ | |
398 av_set_pts_info(ic, 33, 1, 90000); | |
399 | |
400 err = ic->iformat->read_header(ic, ap); | |
401 if (err < 0) | |
402 goto fail1; | |
403 *ic_ptr = ic; | |
404 return 0; | |
405 fail1: | |
406 if (!(fmt->flags & AVFMT_NOFILE)) { | |
407 url_fclose(&ic->pb); | |
408 } | |
409 fail: | |
410 if (ic) { | |
411 av_freep(&ic->priv_data); | |
412 } | |
413 av_free(ic); | |
414 *ic_ptr = NULL; | |
415 return err; | |
416 } | |
417 | |
418 /** | |
419 * Read a packet from a media file | |
420 * @param s media file handle | |
421 * @param pkt is filled | |
422 * @return 0 if OK. AVERROR_xxx if error. | |
423 */ | |
424 int av_read_packet(AVFormatContext *s, AVPacket *pkt) | |
425 { | |
426 AVPacketList *pktl; | |
427 | |
428 pktl = s->packet_buffer; | |
429 if (pktl) { | |
430 /* read packet from packet buffer, if there is data */ | |
431 *pkt = pktl->pkt; | |
432 s->packet_buffer = pktl->next; | |
433 av_free(pktl); | |
434 return 0; | |
435 } else { | |
436 return s->iformat->read_packet(s, pkt); | |
437 } | |
438 } | |
439 | |
440 /* state for codec information */ | |
441 #define CSTATE_NOTFOUND 0 | |
442 #define CSTATE_DECODING 1 | |
443 #define CSTATE_FOUND 2 | |
444 | |
445 static int has_codec_parameters(AVCodecContext *enc) | |
446 { | |
447 int val; | |
448 switch(enc->codec_type) { | |
449 case CODEC_TYPE_AUDIO: | |
450 val = enc->sample_rate; | |
451 break; | |
452 case CODEC_TYPE_VIDEO: | |
453 val = enc->width; | |
454 break; | |
455 default: | |
456 val = 1; | |
457 break; | |
458 } | |
459 return (val != 0); | |
460 } | |
461 | |
462 /** | |
463 * Read the beginning of a media file to get stream information. This | |
464 * is useful for file formats with no headers such as MPEG. This | |
465 * function also compute the real frame rate in case of mpeg2 repeat | |
466 * frame mode. | |
467 * | |
468 * @param ic media file handle | |
469 * @return >=0 if OK. AVERROR_xxx if error. | |
470 */ | |
471 int av_find_stream_info(AVFormatContext *ic) | |
472 { | |
473 int i, count, ret, got_picture, size, read_size; | |
474 AVCodec *codec; | |
475 AVStream *st; | |
476 AVPacket *pkt; | |
7 | 477 AVFrame picture; |
0 | 478 AVPacketList *pktl=NULL, **ppktl; |
479 short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2]; | |
480 UINT8 *ptr; | |
481 int min_read_size, max_read_size; | |
482 | |
483 /* typical mpeg ts rate is 40 Mbits. DVD rate is about 10 | |
484 Mbits. We read at most 0.1 second of file to find all streams */ | |
485 | |
486 /* XXX: base it on stream bitrate when possible */ | |
487 if (ic->iformat == &mpegts_demux) { | |
488 /* maximum number of bytes we accept to read to find all the streams | |
489 in a file */ | |
490 min_read_size = 3000000; | |
491 } else { | |
492 min_read_size = 125000; | |
493 } | |
494 /* max read size is 2 seconds of video max */ | |
495 max_read_size = min_read_size * 20; | |
496 | |
497 /* set initial codec state */ | |
498 for(i=0;i<ic->nb_streams;i++) { | |
499 st = ic->streams[i]; | |
500 if (has_codec_parameters(&st->codec)) | |
501 st->codec_info_state = CSTATE_FOUND; | |
502 else | |
503 st->codec_info_state = CSTATE_NOTFOUND; | |
504 st->codec_info_nb_repeat_frames = 0; | |
505 st->codec_info_nb_real_frames = 0; | |
506 } | |
507 | |
508 count = 0; | |
509 read_size = 0; | |
510 ppktl = &ic->packet_buffer; | |
511 for(;;) { | |
512 /* check if one codec still needs to be handled */ | |
513 for(i=0;i<ic->nb_streams;i++) { | |
514 st = ic->streams[i]; | |
515 if (st->codec_info_state != CSTATE_FOUND) | |
516 break; | |
517 } | |
518 if (i == ic->nb_streams) { | |
519 /* NOTE: if the format has no header, then we need to read | |
520 some packets to get most of the streams, so we cannot | |
521 stop here */ | |
522 if (!(ic->iformat->flags & AVFMT_NOHEADER) || | |
523 read_size >= min_read_size) { | |
524 /* if we found the info for all the codecs, we can stop */ | |
525 ret = count; | |
526 break; | |
527 } | |
528 } else { | |
529 /* we did not get all the codec info, but we read too much data */ | |
530 if (read_size >= max_read_size) { | |
531 ret = count; | |
532 break; | |
533 } | |
534 } | |
535 | |
536 pktl = av_mallocz(sizeof(AVPacketList)); | |
537 if (!pktl) { | |
538 ret = AVERROR_NOMEM; | |
539 break; | |
540 } | |
541 | |
542 /* add the packet in the buffered packet list */ | |
543 *ppktl = pktl; | |
544 ppktl = &pktl->next; | |
545 | |
546 /* NOTE: a new stream can be added there if no header in file | |
547 (AVFMT_NOHEADER) */ | |
548 pkt = &pktl->pkt; | |
549 if (ic->iformat->read_packet(ic, pkt) < 0) { | |
550 /* EOF or error */ | |
551 ret = -1; /* we could not have all the codec parameters before EOF */ | |
552 if ((ic->iformat->flags & AVFMT_NOHEADER) && | |
553 i == ic->nb_streams) | |
554 ret = 0; | |
555 break; | |
556 } | |
557 read_size += pkt->size; | |
558 | |
559 /* open new codecs */ | |
560 for(i=0;i<ic->nb_streams;i++) { | |
561 st = ic->streams[i]; | |
562 if (st->codec_info_state == CSTATE_NOTFOUND) { | |
563 /* set to found in case of error */ | |
564 st->codec_info_state = CSTATE_FOUND; | |
565 codec = avcodec_find_decoder(st->codec.codec_id); | |
566 if (codec) { | |
567 if(codec->capabilities & CODEC_CAP_TRUNCATED) | |
568 st->codec.flags |= CODEC_FLAG_TRUNCATED; | |
569 | |
570 ret = avcodec_open(&st->codec, codec); | |
571 if (ret >= 0) | |
572 st->codec_info_state = CSTATE_DECODING; | |
573 } | |
574 } | |
575 } | |
576 | |
577 st = ic->streams[pkt->stream_index]; | |
578 if (st->codec_info_state == CSTATE_DECODING) { | |
579 /* decode the data and update codec parameters */ | |
580 ptr = pkt->data; | |
581 size = pkt->size; | |
582 while (size > 0) { | |
583 switch(st->codec.codec_type) { | |
584 case CODEC_TYPE_VIDEO: | |
585 ret = avcodec_decode_video(&st->codec, &picture, | |
586 &got_picture, ptr, size); | |
587 break; | |
588 case CODEC_TYPE_AUDIO: | |
589 ret = avcodec_decode_audio(&st->codec, samples, | |
590 &got_picture, ptr, size); | |
591 break; | |
592 default: | |
593 ret = -1; | |
594 break; | |
595 } | |
596 if (ret < 0) { | |
597 /* if error, simply ignore because another packet | |
598 may be OK */ | |
599 break; | |
600 } | |
601 if (got_picture) { | |
602 /* we got the parameters - now we can stop | |
603 examining this stream */ | |
604 /* XXX: add a codec info so that we can decide if | |
605 the codec can repeat frames */ | |
606 if (st->codec.codec_id == CODEC_ID_MPEG1VIDEO && | |
607 ic->iformat != &mpegts_demux && | |
608 st->codec.sub_id == 2) { | |
609 /* for mpeg2 video, we want to know the real | |
610 frame rate, so we decode 40 frames. In mpeg | |
611 TS case we do not do it because it would be | |
612 too long */ | |
613 st->codec_info_nb_real_frames++; | |
614 st->codec_info_nb_repeat_frames += st->codec.repeat_pict; | |
615 #if 0 | |
616 /* XXX: testing */ | |
617 if ((st->codec_info_nb_real_frames % 24) == 23) { | |
618 st->codec_info_nb_repeat_frames += 2; | |
619 } | |
620 #endif | |
621 /* stop after 40 frames */ | |
622 if (st->codec_info_nb_real_frames >= 40) { | |
623 st->r_frame_rate = (st->codec.frame_rate * | |
624 st->codec_info_nb_real_frames) / | |
625 (st->codec_info_nb_real_frames + | |
626 (st->codec_info_nb_repeat_frames >> 1)); | |
627 goto close_codec; | |
628 } | |
629 } else { | |
630 close_codec: | |
631 st->codec_info_state = CSTATE_FOUND; | |
632 avcodec_close(&st->codec); | |
633 break; | |
634 } | |
635 } | |
636 ptr += ret; | |
637 size -= ret; | |
638 } | |
639 } | |
640 count++; | |
641 } | |
642 | |
643 /* close each codec if there are opened */ | |
644 for(i=0;i<ic->nb_streams;i++) { | |
645 st = ic->streams[i]; | |
646 if (st->codec_info_state == CSTATE_DECODING) | |
647 avcodec_close(&st->codec); | |
648 } | |
649 | |
650 /* set real frame rate info */ | |
651 for(i=0;i<ic->nb_streams;i++) { | |
652 st = ic->streams[i]; | |
653 if (st->codec.codec_type == CODEC_TYPE_VIDEO) { | |
654 if (!st->r_frame_rate) | |
655 st->r_frame_rate = st->codec.frame_rate; | |
656 } | |
657 } | |
658 | |
659 return ret; | |
660 } | |
661 | |
662 /** | |
663 * Close a media file (but not its codecs) | |
664 * | |
665 * @param s media file handle | |
666 */ | |
667 void av_close_input_file(AVFormatContext *s) | |
668 { | |
669 int i; | |
670 | |
671 if (s->iformat->read_close) | |
672 s->iformat->read_close(s); | |
673 for(i=0;i<s->nb_streams;i++) { | |
674 av_free(s->streams[i]); | |
675 } | |
676 if (s->packet_buffer) { | |
677 AVPacketList *p, *p1; | |
678 p = s->packet_buffer; | |
679 while (p != NULL) { | |
680 p1 = p->next; | |
681 av_free_packet(&p->pkt); | |
682 av_free(p); | |
683 p = p1; | |
684 } | |
685 s->packet_buffer = NULL; | |
686 } | |
687 if (!(s->iformat->flags & AVFMT_NOFILE)) { | |
688 url_fclose(&s->pb); | |
689 } | |
690 av_freep(&s->priv_data); | |
691 av_free(s); | |
692 } | |
693 | |
694 /** | |
695 * Add a new stream to a media file. Can only be called in the | |
696 * read_header function. If the flag AVFMT_NOHEADER is in the format | |
697 * description, then new streams can be added in read_packet too. | |
698 * | |
699 * | |
700 * @param s media file handle | |
701 * @param id file format dependent stream id | |
702 */ | |
703 AVStream *av_new_stream(AVFormatContext *s, int id) | |
704 { | |
705 AVStream *st; | |
706 | |
707 if (s->nb_streams >= MAX_STREAMS) | |
708 return NULL; | |
709 | |
710 st = av_mallocz(sizeof(AVStream)); | |
711 if (!st) | |
712 return NULL; | |
5 | 713 avcodec_get_context_defaults(&st->codec); |
714 | |
0 | 715 st->index = s->nb_streams; |
716 st->id = id; | |
717 s->streams[s->nb_streams++] = st; | |
718 return st; | |
719 } | |
720 | |
721 /************************************************************/ | |
722 /* output media file */ | |
723 | |
20 | 724 int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap) |
725 { | |
726 int ret; | |
727 | |
728 s->priv_data = av_mallocz(s->oformat->priv_data_size); | |
729 if (!s->priv_data) | |
730 return AVERROR_NOMEM; | |
731 if (s->oformat->set_parameters) { | |
732 ret = s->oformat->set_parameters(s, ap); | |
733 if (ret < 0) | |
734 return ret; | |
735 } | |
736 return 0; | |
737 } | |
738 | |
0 | 739 /** |
740 * allocate the stream private data and write the stream header to an | |
741 * output media file | |
742 * | |
743 * @param s media file handle | |
744 * @return 0 if OK. AVERROR_xxx if error. | |
745 */ | |
746 int av_write_header(AVFormatContext *s) | |
747 { | |
748 int ret, i; | |
749 AVStream *st; | |
750 | |
751 /* default pts settings is MPEG like */ | |
752 av_set_pts_info(s, 33, 1, 90000); | |
753 ret = s->oformat->write_header(s); | |
754 if (ret < 0) | |
755 return ret; | |
756 | |
757 /* init PTS generation */ | |
758 for(i=0;i<s->nb_streams;i++) { | |
759 st = s->streams[i]; | |
760 | |
761 switch (st->codec.codec_type) { | |
762 case CODEC_TYPE_AUDIO: | |
763 av_frac_init(&st->pts, 0, 0, | |
764 (INT64)s->pts_num * st->codec.sample_rate); | |
765 break; | |
766 case CODEC_TYPE_VIDEO: | |
767 av_frac_init(&st->pts, 0, 0, | |
768 (INT64)s->pts_num * st->codec.frame_rate); | |
769 break; | |
770 default: | |
771 break; | |
772 } | |
773 } | |
774 return 0; | |
775 } | |
776 | |
777 /** | |
778 * Write a packet to an output media file. The packet shall contain | |
779 * one audio or video frame. | |
780 * | |
781 * @param s media file handle | |
782 * @param stream_index stream index | |
783 * @param buf buffer containing the frame data | |
784 * @param size size of buffer | |
785 * @return < 0 if error, = 0 if OK, 1 if end of stream wanted. | |
786 */ | |
787 int av_write_frame(AVFormatContext *s, int stream_index, const uint8_t *buf, | |
788 int size) | |
789 { | |
790 AVStream *st; | |
791 INT64 pts_mask; | |
792 int ret, frame_size; | |
793 | |
794 st = s->streams[stream_index]; | |
795 pts_mask = (1LL << s->pts_wrap_bits) - 1; | |
796 ret = s->oformat->write_packet(s, stream_index, (uint8_t *)buf, size, | |
797 st->pts.val & pts_mask); | |
798 if (ret < 0) | |
799 return ret; | |
800 | |
801 /* update pts */ | |
802 switch (st->codec.codec_type) { | |
803 case CODEC_TYPE_AUDIO: | |
804 if (st->codec.frame_size <= 1) { | |
805 frame_size = size / st->codec.channels; | |
806 /* specific hack for pcm codecs because no frame size is provided */ | |
807 switch(st->codec.codec_id) { | |
808 case CODEC_ID_PCM_S16LE: | |
809 case CODEC_ID_PCM_S16BE: | |
810 case CODEC_ID_PCM_U16LE: | |
811 case CODEC_ID_PCM_U16BE: | |
812 frame_size >>= 1; | |
813 break; | |
814 default: | |
815 break; | |
816 } | |
817 } else { | |
818 frame_size = st->codec.frame_size; | |
819 } | |
820 av_frac_add(&st->pts, | |
821 (INT64)s->pts_den * frame_size); | |
822 break; | |
823 case CODEC_TYPE_VIDEO: | |
824 av_frac_add(&st->pts, | |
825 (INT64)s->pts_den * FRAME_RATE_BASE); | |
826 break; | |
827 default: | |
828 break; | |
829 } | |
830 return ret; | |
831 } | |
832 | |
833 /** | |
834 * write the stream trailer to an output media file and and free the | |
835 * file private data. | |
836 * | |
837 * @param s media file handle | |
838 * @return 0 if OK. AVERROR_xxx if error. */ | |
839 int av_write_trailer(AVFormatContext *s) | |
840 { | |
841 int ret; | |
842 ret = s->oformat->write_trailer(s); | |
843 av_freep(&s->priv_data); | |
844 return ret; | |
845 } | |
846 | |
847 /* "user interface" functions */ | |
848 | |
849 void dump_format(AVFormatContext *ic, | |
850 int index, | |
851 const char *url, | |
852 int is_output) | |
853 { | |
854 int i, flags; | |
855 char buf[256]; | |
856 | |
857 fprintf(stderr, "%s #%d, %s, %s '%s':\n", | |
858 is_output ? "Output" : "Input", | |
859 index, | |
860 is_output ? ic->oformat->name : ic->iformat->name, | |
861 is_output ? "to" : "from", url); | |
862 for(i=0;i<ic->nb_streams;i++) { | |
863 AVStream *st = ic->streams[i]; | |
864 avcodec_string(buf, sizeof(buf), &st->codec, is_output); | |
865 fprintf(stderr, " Stream #%d.%d", index, i); | |
866 /* the pid is an important information, so we display it */ | |
867 /* XXX: add a generic system */ | |
868 if (is_output) | |
869 flags = ic->oformat->flags; | |
870 else | |
871 flags = ic->iformat->flags; | |
872 if (flags & AVFMT_SHOW_IDS) { | |
873 fprintf(stderr, "[0x%x]", st->id); | |
874 } | |
875 fprintf(stderr, ": %s\n", buf); | |
876 } | |
877 } | |
878 | |
879 typedef struct { | |
880 const char *str; | |
881 int width, height; | |
882 } SizeEntry; | |
883 | |
884 static SizeEntry sizes[] = { | |
885 { "sqcif", 128, 96 }, | |
886 { "qcif", 176, 144 }, | |
887 { "cif", 352, 288 }, | |
888 { "4cif", 704, 576 }, | |
889 }; | |
890 | |
891 int parse_image_size(int *width_ptr, int *height_ptr, const char *str) | |
892 { | |
893 int i; | |
894 int n = sizeof(sizes) / sizeof(SizeEntry); | |
895 const char *p; | |
896 int frame_width = 0, frame_height = 0; | |
897 | |
898 for(i=0;i<n;i++) { | |
899 if (!strcmp(sizes[i].str, str)) { | |
900 frame_width = sizes[i].width; | |
901 frame_height = sizes[i].height; | |
902 break; | |
903 } | |
904 } | |
905 if (i == n) { | |
906 p = str; | |
907 frame_width = strtol(p, (char **)&p, 10); | |
908 if (*p) | |
909 p++; | |
910 frame_height = strtol(p, (char **)&p, 10); | |
911 } | |
912 if (frame_width <= 0 || frame_height <= 0) | |
913 return -1; | |
914 *width_ptr = frame_width; | |
915 *height_ptr = frame_height; | |
916 return 0; | |
917 } | |
918 | |
919 INT64 av_gettime(void) | |
920 { | |
921 #ifdef CONFIG_WIN32 | |
922 struct _timeb tb; | |
923 _ftime(&tb); | |
924 return ((INT64)tb.time * INT64_C(1000) + (INT64)tb.millitm) * INT64_C(1000); | |
925 #else | |
926 struct timeval tv; | |
927 gettimeofday(&tv,NULL); | |
928 return (INT64)tv.tv_sec * 1000000 + tv.tv_usec; | |
929 #endif | |
930 } | |
931 | |
932 static time_t mktimegm(struct tm *tm) | |
933 { | |
934 time_t t; | |
935 | |
936 int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday; | |
937 | |
938 if (m < 3) { | |
939 m += 12; | |
940 y--; | |
941 } | |
942 | |
943 t = 86400 * | |
944 (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469); | |
945 | |
946 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec; | |
947 | |
948 return t; | |
949 } | |
950 | |
951 /* Syntax: | |
952 * - If not a duration: | |
953 * [{YYYY-MM-DD|YYYYMMDD}]{T| }{HH[:MM[:SS[.m...]]][Z]|HH[MM[SS[.m...]]][Z]} | |
954 * Time is localtime unless Z is suffixed to the end. In this case GMT | |
955 * Return the date in micro seconds since 1970 | |
956 * - If duration: | |
957 * HH[:MM[:SS[.m...]]] | |
958 * S+[.m...] | |
959 */ | |
960 INT64 parse_date(const char *datestr, int duration) | |
961 { | |
962 const char *p; | |
963 INT64 t; | |
964 struct tm dt; | |
965 int i; | |
966 static const char *date_fmt[] = { | |
967 "%Y-%m-%d", | |
968 "%Y%m%d", | |
969 }; | |
970 static const char *time_fmt[] = { | |
971 "%H:%M:%S", | |
972 "%H%M%S", | |
973 }; | |
974 const char *q; | |
975 int is_utc, len; | |
976 char lastch; | |
977 time_t now = time(0); | |
978 | |
979 len = strlen(datestr); | |
980 if (len > 0) | |
981 lastch = datestr[len - 1]; | |
982 else | |
983 lastch = '\0'; | |
984 is_utc = (lastch == 'z' || lastch == 'Z'); | |
985 | |
986 memset(&dt, 0, sizeof(dt)); | |
987 | |
988 p = datestr; | |
989 q = NULL; | |
990 if (!duration) { | |
991 for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) { | |
992 q = strptime(p, date_fmt[i], &dt); | |
993 if (q) { | |
994 break; | |
995 } | |
996 } | |
997 | |
998 if (!q) { | |
999 if (is_utc) { | |
1000 dt = *gmtime(&now); | |
1001 } else { | |
1002 dt = *localtime(&now); | |
1003 } | |
1004 dt.tm_hour = dt.tm_min = dt.tm_sec = 0; | |
1005 } else { | |
1006 p = q; | |
1007 } | |
1008 | |
1009 if (*p == 'T' || *p == 't' || *p == ' ') | |
1010 p++; | |
1011 | |
1012 for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) { | |
1013 q = strptime(p, time_fmt[i], &dt); | |
1014 if (q) { | |
1015 break; | |
1016 } | |
1017 } | |
1018 } else { | |
1019 q = strptime(p, time_fmt[0], &dt); | |
1020 if (!q) { | |
1021 dt.tm_sec = strtol(p, (char **)&q, 10); | |
1022 dt.tm_min = 0; | |
1023 dt.tm_hour = 0; | |
1024 } | |
1025 } | |
1026 | |
1027 /* Now we have all the fields that we can get */ | |
1028 if (!q) { | |
1029 if (duration) | |
1030 return 0; | |
1031 else | |
1032 return now * INT64_C(1000000); | |
1033 } | |
1034 | |
1035 if (duration) { | |
1036 t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec; | |
1037 } else { | |
1038 dt.tm_isdst = -1; /* unknown */ | |
1039 if (is_utc) { | |
1040 t = mktimegm(&dt); | |
1041 } else { | |
1042 t = mktime(&dt); | |
1043 } | |
1044 } | |
1045 | |
1046 t *= 1000000; | |
1047 | |
1048 if (*q == '.') { | |
1049 int val, n; | |
1050 q++; | |
1051 for (val = 0, n = 100000; n >= 1; n /= 10, q++) { | |
1052 if (!isdigit(*q)) | |
1053 break; | |
1054 val += n * (*q - '0'); | |
1055 } | |
1056 t += val; | |
1057 } | |
1058 return t; | |
1059 } | |
1060 | |
1061 /* syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done. Return | |
1062 1 if found */ | |
1063 int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info) | |
1064 { | |
1065 const char *p; | |
1066 char tag[128], *q; | |
1067 | |
1068 p = info; | |
1069 if (*p == '?') | |
1070 p++; | |
1071 for(;;) { | |
1072 q = tag; | |
1073 while (*p != '\0' && *p != '=' && *p != '&') { | |
1074 if ((q - tag) < sizeof(tag) - 1) | |
1075 *q++ = *p; | |
1076 p++; | |
1077 } | |
1078 *q = '\0'; | |
1079 q = arg; | |
1080 if (*p == '=') { | |
1081 p++; | |
1082 while (*p != '&' && *p != '\0') { | |
1083 if ((q - arg) < arg_size - 1) { | |
1084 if (*p == '+') | |
1085 *q++ = ' '; | |
1086 else | |
1087 *q++ = *p; | |
1088 } | |
1089 p++; | |
1090 } | |
1091 *q = '\0'; | |
1092 } | |
1093 if (!strcmp(tag, tag1)) | |
1094 return 1; | |
1095 if (*p != '&') | |
1096 break; | |
1097 p++; | |
1098 } | |
1099 return 0; | |
1100 } | |
1101 | |
1102 /* Return in 'buf' the path with '%d' replaced by number. Also handles | |
1103 the '%0nd' format where 'n' is the total number of digits and | |
1104 '%%'. Return 0 if OK, and -1 if format error */ | |
1105 int get_frame_filename(char *buf, int buf_size, | |
1106 const char *path, int number) | |
1107 { | |
1108 const char *p; | |
1109 char *q, buf1[20]; | |
1110 int nd, len, c, percentd_found; | |
1111 | |
1112 q = buf; | |
1113 p = path; | |
1114 percentd_found = 0; | |
1115 for(;;) { | |
1116 c = *p++; | |
1117 if (c == '\0') | |
1118 break; | |
1119 if (c == '%') { | |
9
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1120 do { |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1121 nd = 0; |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1122 while (isdigit(*p)) { |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1123 nd = nd * 10 + *p++ - '0'; |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1124 } |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1125 c = *p++; |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1126 if (c == '*' && nd > 0) { |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1127 // The nd field is actually the modulus |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1128 number = number % nd; |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1129 c = *p++; |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1130 nd = 0; |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1131 } |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1132 } while (isdigit(c)); |
97e61383cb81
* Extend the syntax of a filename for the img reader to allow looping. Thus
philipjsg
parents:
7
diff
changeset
|
1133 |
0 | 1134 switch(c) { |
1135 case '%': | |
1136 goto addchar; | |
1137 case 'd': | |
1138 if (percentd_found) | |
1139 goto fail; | |
1140 percentd_found = 1; | |
1141 snprintf(buf1, sizeof(buf1), "%0*d", nd, number); | |
1142 len = strlen(buf1); | |
1143 if ((q - buf + len) > buf_size - 1) | |
1144 goto fail; | |
1145 memcpy(q, buf1, len); | |
1146 q += len; | |
1147 break; | |
1148 default: | |
1149 goto fail; | |
1150 } | |
1151 } else { | |
1152 addchar: | |
1153 if ((q - buf) < buf_size - 1) | |
1154 *q++ = c; | |
1155 } | |
1156 } | |
1157 if (!percentd_found) | |
1158 goto fail; | |
1159 *q = '\0'; | |
1160 return 0; | |
1161 fail: | |
1162 *q = '\0'; | |
1163 return -1; | |
1164 } | |
1165 | |
1166 /** | |
1167 * | |
1168 * Print on stdout a nice hexa dump of a buffer | |
1169 * @param buf buffer | |
1170 * @param size buffer size | |
1171 */ | |
1172 void av_hex_dump(UINT8 *buf, int size) | |
1173 { | |
1174 int len, i, j, c; | |
1175 | |
1176 for(i=0;i<size;i+=16) { | |
1177 len = size - i; | |
1178 if (len > 16) | |
1179 len = 16; | |
1180 printf("%08x ", i); | |
1181 for(j=0;j<16;j++) { | |
1182 if (j < len) | |
1183 printf(" %02x", buf[i+j]); | |
1184 else | |
1185 printf(" "); | |
1186 } | |
1187 printf(" "); | |
1188 for(j=0;j<len;j++) { | |
1189 c = buf[i+j]; | |
1190 if (c < ' ' || c > '~') | |
1191 c = '.'; | |
1192 printf("%c", c); | |
1193 } | |
1194 printf("\n"); | |
1195 } | |
1196 } | |
1197 | |
1198 void url_split(char *proto, int proto_size, | |
1199 char *hostname, int hostname_size, | |
1200 int *port_ptr, | |
1201 char *path, int path_size, | |
1202 const char *url) | |
1203 { | |
1204 const char *p; | |
1205 char *q; | |
1206 int port; | |
1207 | |
1208 port = -1; | |
1209 | |
1210 p = url; | |
1211 q = proto; | |
1212 while (*p != ':' && *p != '\0') { | |
1213 if ((q - proto) < proto_size - 1) | |
1214 *q++ = *p; | |
1215 p++; | |
1216 } | |
1217 if (proto_size > 0) | |
1218 *q = '\0'; | |
1219 if (*p == '\0') { | |
1220 if (proto_size > 0) | |
1221 proto[0] = '\0'; | |
1222 if (hostname_size > 0) | |
1223 hostname[0] = '\0'; | |
1224 p = url; | |
1225 } else { | |
1226 p++; | |
1227 if (*p == '/') | |
1228 p++; | |
1229 if (*p == '/') | |
1230 p++; | |
1231 q = hostname; | |
1232 while (*p != ':' && *p != '/' && *p != '?' && *p != '\0') { | |
1233 if ((q - hostname) < hostname_size - 1) | |
1234 *q++ = *p; | |
1235 p++; | |
1236 } | |
1237 if (hostname_size > 0) | |
1238 *q = '\0'; | |
1239 if (*p == ':') { | |
1240 p++; | |
1241 port = strtoul(p, (char **)&p, 10); | |
1242 } | |
1243 } | |
1244 if (port_ptr) | |
1245 *port_ptr = port; | |
1246 pstrcpy(path, path_size, p); | |
1247 } | |
1248 | |
1249 /** | |
1250 * Set the pts for a given stream | |
1251 * @param s stream | |
1252 * @param pts_wrap_bits number of bits effectively used by the pts | |
1253 * (used for wrap control, 33 is the value for MPEG) | |
1254 * @param pts_num numerator to convert to seconds (MPEG: 1) | |
1255 * @param pts_den denominator to convert to seconds (MPEG: 90000) | |
1256 */ | |
1257 void av_set_pts_info(AVFormatContext *s, int pts_wrap_bits, | |
1258 int pts_num, int pts_den) | |
1259 { | |
1260 s->pts_wrap_bits = pts_wrap_bits; | |
1261 s->pts_num = pts_num; | |
1262 s->pts_den = pts_den; | |
1263 } | |
1264 | |
1265 /* fraction handling */ | |
1266 | |
1267 /** | |
1268 * f = val + (num / den) + 0.5. 'num' is normalized so that it is such | |
1269 * as 0 <= num < den. | |
1270 * | |
1271 * @param f fractional number | |
1272 * @param val integer value | |
1273 * @param num must be >= 0 | |
1274 * @param den must be >= 1 | |
1275 */ | |
1276 void av_frac_init(AVFrac *f, INT64 val, INT64 num, INT64 den) | |
1277 { | |
1278 num += (den >> 1); | |
1279 if (num >= den) { | |
1280 val += num / den; | |
1281 num = num % den; | |
1282 } | |
1283 f->val = val; | |
1284 f->num = num; | |
1285 f->den = den; | |
1286 } | |
1287 | |
1288 /* set f to (val + 0.5) */ | |
1289 void av_frac_set(AVFrac *f, INT64 val) | |
1290 { | |
1291 f->val = val; | |
1292 f->num = f->den >> 1; | |
1293 } | |
1294 | |
1295 /** | |
1296 * Fractionnal addition to f: f = f + (incr / f->den) | |
1297 * | |
1298 * @param f fractional number | |
1299 * @param incr increment, can be positive or negative | |
1300 */ | |
1301 void av_frac_add(AVFrac *f, INT64 incr) | |
1302 { | |
1303 INT64 num, den; | |
1304 | |
1305 num = f->num + incr; | |
1306 den = f->den; | |
1307 if (num < 0) { | |
1308 f->val += num / den; | |
1309 num = num % den; | |
1310 if (num < 0) { | |
1311 num += den; | |
1312 f->val--; | |
1313 } | |
1314 } else if (num >= den) { | |
1315 f->val += num / den; | |
1316 num = num % den; | |
1317 } | |
1318 f->num = num; | |
1319 } | |
20 | 1320 |
1321 /** | |
1322 * register a new image format | |
1323 * @param img_fmt Image format descriptor | |
1324 */ | |
1325 void av_register_image_format(AVImageFormat *img_fmt) | |
1326 { | |
1327 AVImageFormat **p; | |
1328 | |
1329 p = &first_image_format; | |
1330 while (*p != NULL) p = &(*p)->next; | |
1331 *p = img_fmt; | |
1332 img_fmt->next = NULL; | |
1333 } | |
1334 | |
1335 /* guess image format */ | |
1336 AVImageFormat *av_probe_image_format(AVProbeData *pd) | |
1337 { | |
1338 AVImageFormat *fmt1, *fmt; | |
1339 int score, score_max; | |
1340 | |
1341 fmt = NULL; | |
1342 score_max = 0; | |
1343 for(fmt1 = first_image_format; fmt1 != NULL; fmt1 = fmt1->next) { | |
1344 if (fmt1->img_probe) { | |
1345 score = fmt1->img_probe(pd); | |
1346 if (score > score_max) { | |
1347 score_max = score; | |
1348 fmt = fmt1; | |
1349 } | |
1350 } | |
1351 } | |
1352 return fmt; | |
1353 } | |
1354 | |
1355 AVImageFormat *guess_image_format(const char *filename) | |
1356 { | |
1357 AVImageFormat *fmt1; | |
1358 | |
1359 for(fmt1 = first_image_format; fmt1 != NULL; fmt1 = fmt1->next) { | |
1360 if (fmt1->extensions && match_ext(filename, fmt1->extensions)) | |
1361 return fmt1; | |
1362 } | |
1363 return NULL; | |
1364 } | |
1365 | |
1366 /** | |
1367 * Read an image from a stream. | |
1368 * @param gb byte stream containing the image | |
1369 * @param fmt image format, NULL if probing is required | |
1370 */ | |
1371 int av_read_image(ByteIOContext *pb, const char *filename, | |
1372 AVImageFormat *fmt, | |
1373 int (*alloc_cb)(void *, AVImageInfo *info), void *opaque) | |
1374 { | |
1375 char buf[PROBE_BUF_SIZE]; | |
1376 AVProbeData probe_data, *pd = &probe_data; | |
1377 offset_t pos; | |
1378 int ret; | |
1379 | |
1380 if (!fmt) { | |
1381 pd->filename = (char *)filename; | |
1382 pd->buf = buf; | |
1383 pos = url_ftell(pb); | |
1384 pd->buf_size = get_buffer(pb, buf, PROBE_BUF_SIZE); | |
1385 url_fseek(pb, pos, SEEK_SET); | |
1386 fmt = av_probe_image_format(pd); | |
1387 } | |
1388 if (!fmt) | |
1389 return AVERROR_NOFMT; | |
1390 ret = fmt->img_read(pb, alloc_cb, opaque); | |
1391 return ret; | |
1392 } | |
1393 | |
1394 /** | |
1395 * Write an image to a stream. | |
1396 * @param pb byte stream for the image output | |
1397 * @param fmt image format | |
1398 * @param img image data and informations | |
1399 */ | |
1400 int av_write_image(ByteIOContext *pb, AVImageFormat *fmt, AVImageInfo *img) | |
1401 { | |
1402 return fmt->img_write(pb, img); | |
1403 } | |
1404 |