aviobuf.c
Go to the documentation of this file.
1 /*
2  * buffered I/O
3  * Copyright (c) 2000,2001 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/crc.h"
23 #include "libavutil/dict.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/log.h"
26 #include "libavutil/opt.h"
27 #include "avformat.h"
28 #include "avio.h"
29 #include "avio_internal.h"
30 #include "internal.h"
31 #include "url.h"
32 #include <stdarg.h>
33 
34 #define IO_BUFFER_SIZE 32768
35 
41 #define SHORT_SEEK_THRESHOLD 4096
42 
43 #if !FF_API_OLD_AVIO
44 static void *ffio_url_child_next(void *obj, void *prev)
45 {
46  AVIOContext *s = obj;
47  return prev ? NULL : s->opaque;
48 }
49 
50 static const AVClass *ffio_url_child_class_next(const AVClass *prev)
51 {
52  return prev ? NULL : &ffurl_context_class;
53 }
54 
55 static const AVOption ffio_url_options[] = {
56  { NULL },
57 };
58 
60  .class_name = "AVIOContext",
61  .item_name = av_default_item_name,
62  .version = LIBAVUTIL_VERSION_INT,
63  .option = ffio_url_options,
64  .child_next = ffio_url_child_next,
65  .child_class_next = ffio_url_child_class_next,
66 };
67 #endif
68 static void fill_buffer(AVIOContext *s);
69 static int url_resetbuf(AVIOContext *s, int flags);
70 
72  unsigned char *buffer,
73  int buffer_size,
74  int write_flag,
75  void *opaque,
76  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
77  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
78  int64_t (*seek)(void *opaque, int64_t offset, int whence))
79 {
80  s->buffer = buffer;
81  s->buffer_size = buffer_size;
82  s->buf_ptr = buffer;
83  s->opaque = opaque;
84  url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
87  s->seek = seek;
88  s->pos = 0;
89  s->must_flush = 0;
90  s->eof_reached = 0;
91  s->error = 0;
92 #if FF_API_OLD_AVIO
93  s->is_streamed = 0;
94 #endif
96  s->max_packet_size = 0;
98  if(!read_packet && !write_flag){
99  s->pos = buffer_size;
100  s->buf_end = s->buffer + buffer_size;
101  }
102  s->read_pause = NULL;
103  s->read_seek = NULL;
104  return 0;
105 }
106 
107 #if FF_API_OLD_AVIO
108 int init_put_byte(AVIOContext *s,
109  unsigned char *buffer,
110  int buffer_size,
111  int write_flag,
112  void *opaque,
113  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
114  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
115  int64_t (*seek)(void *opaque, int64_t offset, int whence))
116 {
117  return ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
118  read_packet, write_packet, seek);
119 }
120 AVIOContext *av_alloc_put_byte(
121  unsigned char *buffer,
122  int buffer_size,
123  int write_flag,
124  void *opaque,
125  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
126  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
127  int64_t (*seek)(void *opaque, int64_t offset, int whence))
128 {
129  return avio_alloc_context(buffer, buffer_size, write_flag, opaque,
130  read_packet, write_packet, seek);
131 }
132 #endif
133 
135  unsigned char *buffer,
136  int buffer_size,
137  int write_flag,
138  void *opaque,
139  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
140  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
141  int64_t (*seek)(void *opaque, int64_t offset, int whence))
142 {
143  AVIOContext *s = av_mallocz(sizeof(AVIOContext));
144  if (!s)
145  return NULL;
146  ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
147  read_packet, write_packet, seek);
148  return s;
149 }
150 
151 static void flush_buffer(AVIOContext *s)
152 {
153  if (s->buf_ptr > s->buffer) {
154  if (s->write_packet && !s->error){
155  int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
156  if(ret < 0){
157  s->error = ret;
158  }
159  }
160  if(s->update_checksum){
162  s->checksum_ptr= s->buffer;
163  }
164  s->pos += s->buf_ptr - s->buffer;
165  }
166  s->buf_ptr = s->buffer;
167 }
168 
169 void avio_w8(AVIOContext *s, int b)
170 {
171  *s->buf_ptr++ = b;
172  if (s->buf_ptr >= s->buf_end)
173  flush_buffer(s);
174 }
175 
176 void ffio_fill(AVIOContext *s, int b, int count)
177 {
178  while (count > 0) {
179  int len = FFMIN(s->buf_end - s->buf_ptr, count);
180  memset(s->buf_ptr, b, len);
181  s->buf_ptr += len;
182 
183  if (s->buf_ptr >= s->buf_end)
184  flush_buffer(s);
185 
186  count -= len;
187  }
188 }
189 
190 void avio_write(AVIOContext *s, const unsigned char *buf, int size)
191 {
192  while (size > 0) {
193  int len = FFMIN(s->buf_end - s->buf_ptr, size);
194  memcpy(s->buf_ptr, buf, len);
195  s->buf_ptr += len;
196 
197  if (s->buf_ptr >= s->buf_end)
198  flush_buffer(s);
199 
200  buf += len;
201  size -= len;
202  }
203 }
204 
206 {
207  flush_buffer(s);
208  s->must_flush = 0;
209 }
210 
211 int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
212 {
213  int64_t offset1;
214  int64_t pos;
215  int force = whence & AVSEEK_FORCE;
216  whence &= ~AVSEEK_FORCE;
217 
218  if(!s)
219  return AVERROR(EINVAL);
220 
221  pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
222 
223  if (whence != SEEK_CUR && whence != SEEK_SET)
224  return AVERROR(EINVAL);
225 
226  if (whence == SEEK_CUR) {
227  offset1 = pos + (s->buf_ptr - s->buffer);
228  if (offset == 0)
229  return offset1;
230  offset += offset1;
231  }
232  offset1 = offset - pos;
233  if (!s->must_flush &&
234  offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
235  /* can do the seek inside the buffer */
236  s->buf_ptr = s->buffer + offset1;
237  } else if ((!s->seekable ||
238  offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) &&
239  !s->write_flag && offset1 >= 0 &&
240  (whence != SEEK_END || force)) {
241  while(s->pos < offset && !s->eof_reached)
242  fill_buffer(s);
243  if (s->eof_reached)
244  return AVERROR_EOF;
245  s->buf_ptr = s->buf_end + offset - s->pos;
246  } else {
247  int64_t res;
248 
249 #if CONFIG_MUXERS || CONFIG_NETWORK
250  if (s->write_flag) {
251  flush_buffer(s);
252  s->must_flush = 1;
253  }
254 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */
255  if (!s->seek)
256  return AVERROR(EPIPE);
257  if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
258  return res;
259  if (!s->write_flag)
260  s->buf_end = s->buffer;
261  s->buf_ptr = s->buffer;
262  s->pos = offset;
263  }
264  s->eof_reached = 0;
265  return offset;
266 }
267 
268 #if FF_API_OLD_AVIO
269 int url_fskip(AVIOContext *s, int64_t offset)
270 {
271  int64_t ret = avio_seek(s, offset, SEEK_CUR);
272  return ret < 0 ? ret : 0;
273 }
274 
275 int64_t url_ftell(AVIOContext *s)
276 {
277  return avio_seek(s, 0, SEEK_CUR);
278 }
279 #endif
280 
282 {
283  int64_t size;
284 
285  if(!s)
286  return AVERROR(EINVAL);
287 
288  if (!s->seek)
289  return AVERROR(ENOSYS);
290  size = s->seek(s->opaque, 0, AVSEEK_SIZE);
291  if(size<0){
292  if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
293  return size;
294  size++;
295  s->seek(s->opaque, s->pos, SEEK_SET);
296  }
297  return size;
298 }
299 
300 #if FF_API_OLD_AVIO
301 int url_feof(AVIOContext *s)
302 {
303  if(!s)
304  return 0;
305  return s->eof_reached;
306 }
307 
308 int url_ferror(AVIOContext *s)
309 {
310  if(!s)
311  return 0;
312  return s->error;
313 }
314 #endif
315 
316 void avio_wl32(AVIOContext *s, unsigned int val)
317 {
318  avio_w8(s, val);
319  avio_w8(s, val >> 8);
320  avio_w8(s, val >> 16);
321  avio_w8(s, val >> 24);
322 }
323 
324 void avio_wb32(AVIOContext *s, unsigned int val)
325 {
326  avio_w8(s, val >> 24);
327  avio_w8(s, val >> 16);
328  avio_w8(s, val >> 8);
329  avio_w8(s, val);
330 }
331 
332 #if FF_API_OLD_AVIO
333 void put_strz(AVIOContext *s, const char *str)
334 {
335  avio_put_str(s, str);
336 }
337 
338 #define GET(name, type) \
339  type get_be ##name(AVIOContext *s) \
340 {\
341  return avio_rb ##name(s);\
342 }\
343  type get_le ##name(AVIOContext *s) \
344 {\
345  return avio_rl ##name(s);\
346 }
347 
348 GET(16, unsigned int)
349 GET(24, unsigned int)
350 GET(32, unsigned int)
351 GET(64, uint64_t)
352 
353 #undef GET
354 
355 #define PUT(name, type ) \
356  void put_le ##name(AVIOContext *s, type val)\
357 {\
358  avio_wl ##name(s, val);\
359 }\
360  void put_be ##name(AVIOContext *s, type val)\
361 {\
362  avio_wb ##name(s, val);\
363 }
364 
365 PUT(16, unsigned int)
366 PUT(24, unsigned int)
367 PUT(32, unsigned int)
368 PUT(64, uint64_t)
369 #undef PUT
370 
371 int get_byte(AVIOContext *s)
372 {
373  return avio_r8(s);
374 }
375 int get_buffer(AVIOContext *s, unsigned char *buf, int size)
376 {
377  return avio_read(s, buf, size);
378 }
379 int get_partial_buffer(AVIOContext *s, unsigned char *buf, int size)
380 {
381  return ffio_read_partial(s, buf, size);
382 }
383 void put_byte(AVIOContext *s, int val)
384 {
385  avio_w8(s, val);
386 }
387 void put_buffer(AVIOContext *s, const unsigned char *buf, int size)
388 {
389  avio_write(s, buf, size);
390 }
391 void put_nbyte(AVIOContext *s, int b, int count)
392 {
393  ffio_fill(s, b, count);
394 }
395 
396 int url_fopen(AVIOContext **s, const char *filename, int flags)
397 {
398  return avio_open(s, filename, flags);
399 }
400 int url_fclose(AVIOContext *s)
401 {
402  return avio_close(s);
403 }
404 int64_t url_fseek(AVIOContext *s, int64_t offset, int whence)
405 {
406  return avio_seek(s, offset, whence);
407 }
408 int64_t url_fsize(AVIOContext *s)
409 {
410  return avio_size(s);
411 }
412 int url_setbufsize(AVIOContext *s, int buf_size)
413 {
414  return ffio_set_buf_size(s, buf_size);
415 }
416 int url_fprintf(AVIOContext *s, const char *fmt, ...)
417 {
418  va_list ap;
419  char buf[4096];
420  int ret;
421 
422  va_start(ap, fmt);
423  ret = vsnprintf(buf, sizeof(buf), fmt, ap);
424  va_end(ap);
425  avio_write(s, buf, strlen(buf));
426  return ret;
427 }
428 void put_flush_packet(AVIOContext *s)
429 {
430  avio_flush(s);
431 }
432 int av_url_read_fpause(AVIOContext *s, int pause)
433 {
434  return avio_pause(s, pause);
435 }
436 int64_t av_url_read_fseek(AVIOContext *s, int stream_index,
437  int64_t timestamp, int flags)
438 {
439  return avio_seek_time(s, stream_index, timestamp, flags);
440 }
441 void init_checksum(AVIOContext *s,
442  unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
443  unsigned long checksum)
444 {
445  ffio_init_checksum(s, update_checksum, checksum);
446 }
447 unsigned long get_checksum(AVIOContext *s)
448 {
449  return ffio_get_checksum(s);
450 }
451 int url_open_dyn_buf(AVIOContext **s)
452 {
453  return avio_open_dyn_buf(s);
454 }
455 int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
456 {
457  return ffio_open_dyn_packet_buf(s, max_packet_size);
458 }
459 int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
460 {
461  return avio_close_dyn_buf(s, pbuffer);
462 }
463 int url_fdopen(AVIOContext **s, URLContext *h)
464 {
465  return ffio_fdopen(s, h);
466 }
467 #endif
468 
469 int avio_put_str(AVIOContext *s, const char *str)
470 {
471  int len = 1;
472  if (str) {
473  len += strlen(str);
474  avio_write(s, (const unsigned char *) str, len);
475  } else
476  avio_w8(s, 0);
477  return len;
478 }
479 
480 int avio_put_str16le(AVIOContext *s, const char *str)
481 {
482  const uint8_t *q = str;
483  int ret = 0;
484 
485  while (*q) {
486  uint32_t ch;
487  uint16_t tmp;
488 
489  GET_UTF8(ch, *q++, break;)
490  PUT_UTF16(ch, tmp, avio_wl16(s, tmp);ret += 2;)
491  }
492  avio_wl16(s, 0);
493  ret += 2;
494  return ret;
495 }
496 
497 int ff_get_v_length(uint64_t val){
498  int i=1;
499 
500  while(val>>=7)
501  i++;
502 
503  return i;
504 }
505 
506 void ff_put_v(AVIOContext *bc, uint64_t val){
507  int i= ff_get_v_length(val);
508 
509  while(--i>0)
510  avio_w8(bc, 128 | (val>>(7*i)));
511 
512  avio_w8(bc, val&127);
513 }
514 
515 void avio_wl64(AVIOContext *s, uint64_t val)
516 {
517  avio_wl32(s, (uint32_t)(val & 0xffffffff));
518  avio_wl32(s, (uint32_t)(val >> 32));
519 }
520 
521 void avio_wb64(AVIOContext *s, uint64_t val)
522 {
523  avio_wb32(s, (uint32_t)(val >> 32));
524  avio_wb32(s, (uint32_t)(val & 0xffffffff));
525 }
526 
527 void avio_wl16(AVIOContext *s, unsigned int val)
528 {
529  avio_w8(s, val);
530  avio_w8(s, val >> 8);
531 }
532 
533 void avio_wb16(AVIOContext *s, unsigned int val)
534 {
535  avio_w8(s, val >> 8);
536  avio_w8(s, val);
537 }
538 
539 void avio_wl24(AVIOContext *s, unsigned int val)
540 {
541  avio_wl16(s, val & 0xffff);
542  avio_w8(s, val >> 16);
543 }
544 
545 void avio_wb24(AVIOContext *s, unsigned int val)
546 {
547  avio_wb16(s, val >> 8);
548  avio_w8(s, val);
549 }
550 
551 #if FF_API_OLD_AVIO
552 void put_tag(AVIOContext *s, const char *tag)
553 {
554  while (*tag) {
555  avio_w8(s, *tag++);
556  }
557 }
558 #endif
559 
560 /* Input stream */
561 
562 static void fill_buffer(AVIOContext *s)
563 {
564  uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_end : s->buffer;
565  int len= s->buffer_size - (dst - s->buffer);
566  int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE;
567 
568  /* can't fill the buffer without read_packet, just set EOF if appropiate */
569  if (!s->read_packet && s->buf_ptr >= s->buf_end)
570  s->eof_reached = 1;
571 
572  /* no need to do anything if EOF already reached */
573  if (s->eof_reached)
574  return;
575 
576  if(s->update_checksum && dst == s->buffer){
577  if(s->buf_end > s->checksum_ptr)
579  s->checksum_ptr= s->buffer;
580  }
581 
582  /* make buffer smaller in case it ended up large after probing */
583  if (s->buffer_size > max_buffer_size) {
584  ffio_set_buf_size(s, max_buffer_size);
585 
586  s->checksum_ptr = dst = s->buffer;
587  len = s->buffer_size;
588  }
589 
590  if(s->read_packet)
591  len = s->read_packet(s->opaque, dst, len);
592  else
593  len = 0;
594  if (len <= 0) {
595  /* do not modify buffer if EOF reached so that a seek back can
596  be done without rereading data */
597  s->eof_reached = 1;
598  if(len<0)
599  s->error= len;
600  } else {
601  s->pos += len;
602  s->buf_ptr = dst;
603  s->buf_end = dst + len;
604  }
605 }
606 
607 unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
608  unsigned int len)
609 {
610  return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
611 }
612 
614 {
616  s->update_checksum= NULL;
617  return s->checksum;
618 }
619 
621  unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
622  unsigned long checksum)
623 {
624  s->update_checksum= update_checksum;
625  if(s->update_checksum){
626  s->checksum= checksum;
627  s->checksum_ptr= s->buf_ptr;
628  }
629 }
630 
631 /* XXX: put an inline version */
633 {
634  if (s->buf_ptr >= s->buf_end)
635  fill_buffer(s);
636  if (s->buf_ptr < s->buf_end)
637  return *s->buf_ptr++;
638  return 0;
639 }
640 
641 #if FF_API_OLD_AVIO
642 int url_fgetc(AVIOContext *s)
643 {
644  if (s->buf_ptr >= s->buf_end)
645  fill_buffer(s);
646  if (s->buf_ptr < s->buf_end)
647  return *s->buf_ptr++;
648  return URL_EOF;
649 }
650 #endif
651 
652 int avio_read(AVIOContext *s, unsigned char *buf, int size)
653 {
654  int len, size1;
655 
656  size1 = size;
657  while (size > 0) {
658  len = s->buf_end - s->buf_ptr;
659  if (len > size)
660  len = size;
661  if (len == 0) {
662  if(size > s->buffer_size && !s->update_checksum){
663  if(s->read_packet)
664  len = s->read_packet(s->opaque, buf, size);
665  if (len <= 0) {
666  /* do not modify buffer if EOF reached so that a seek back can
667  be done without rereading data */
668  s->eof_reached = 1;
669  if(len<0)
670  s->error= len;
671  break;
672  } else {
673  s->pos += len;
674  size -= len;
675  buf += len;
676  s->buf_ptr = s->buffer;
677  s->buf_end = s->buffer/* + len*/;
678  }
679  }else{
680  fill_buffer(s);
681  len = s->buf_end - s->buf_ptr;
682  if (len == 0)
683  break;
684  }
685  } else {
686  memcpy(buf, s->buf_ptr, len);
687  buf += len;
688  s->buf_ptr += len;
689  size -= len;
690  }
691  }
692  if (size1 == size) {
693  if (s->error) return s->error;
694  if (s->eof_reached) return AVERROR_EOF;
695  }
696  return size1 - size;
697 }
698 
699 int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size)
700 {
701  int len;
702 
703  if(size<0)
704  return -1;
705 
706  len = s->buf_end - s->buf_ptr;
707  if (len == 0) {
708  fill_buffer(s);
709  len = s->buf_end - s->buf_ptr;
710  }
711  if (len > size)
712  len = size;
713  memcpy(buf, s->buf_ptr, len);
714  s->buf_ptr += len;
715  if (!len) {
716  if (s->error) return s->error;
717  if (s->eof_reached) return AVERROR_EOF;
718  }
719  return len;
720 }
721 
722 unsigned int avio_rl16(AVIOContext *s)
723 {
724  unsigned int val;
725  val = avio_r8(s);
726  val |= avio_r8(s) << 8;
727  return val;
728 }
729 
730 unsigned int avio_rl24(AVIOContext *s)
731 {
732  unsigned int val;
733  val = avio_rl16(s);
734  val |= avio_r8(s) << 16;
735  return val;
736 }
737 
738 unsigned int avio_rl32(AVIOContext *s)
739 {
740  unsigned int val;
741  val = avio_rl16(s);
742  val |= avio_rl16(s) << 16;
743  return val;
744 }
745 
746 uint64_t avio_rl64(AVIOContext *s)
747 {
748  uint64_t val;
749  val = (uint64_t)avio_rl32(s);
750  val |= (uint64_t)avio_rl32(s) << 32;
751  return val;
752 }
753 
754 unsigned int avio_rb16(AVIOContext *s)
755 {
756  unsigned int val;
757  val = avio_r8(s) << 8;
758  val |= avio_r8(s);
759  return val;
760 }
761 
762 unsigned int avio_rb24(AVIOContext *s)
763 {
764  unsigned int val;
765  val = avio_rb16(s) << 8;
766  val |= avio_r8(s);
767  return val;
768 }
769 unsigned int avio_rb32(AVIOContext *s)
770 {
771  unsigned int val;
772  val = avio_rb16(s) << 16;
773  val |= avio_rb16(s);
774  return val;
775 }
776 
777 #if FF_API_OLD_AVIO
778 char *get_strz(AVIOContext *s, char *buf, int maxlen)
779 {
780  avio_get_str(s, INT_MAX, buf, maxlen);
781  return buf;
782 }
783 #endif
784 
785 int ff_get_line(AVIOContext *s, char *buf, int maxlen)
786 {
787  int i = 0;
788  char c;
789 
790  do {
791  c = avio_r8(s);
792  if (c && i < maxlen-1)
793  buf[i++] = c;
794  } while (c != '\n' && c);
795 
796  buf[i] = 0;
797  return i;
798 }
799 
800 int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen)
801 {
802  int i;
803 
804  if (buflen <= 0)
805  return AVERROR(EINVAL);
806  // reserve 1 byte for terminating 0
807  buflen = FFMIN(buflen - 1, maxlen);
808  for (i = 0; i < buflen; i++)
809  if (!(buf[i] = avio_r8(s)))
810  return i + 1;
811  buf[i] = 0;
812  for (; i < maxlen; i++)
813  if (!avio_r8(s))
814  return i + 1;
815  return maxlen;
816 }
817 
818 #define GET_STR16(type, read) \
819  int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
820 {\
821  char* q = buf;\
822  int ret = 0;\
823  if (buflen <= 0) \
824  return AVERROR(EINVAL); \
825  while (ret + 1 < maxlen) {\
826  uint8_t tmp;\
827  uint32_t ch;\
828  GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
829  if (!ch)\
830  break;\
831  PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
832  }\
833  *q = 0;\
834  return ret;\
835 }\
836 
838 GET_STR16(be, avio_rb16)
839 
840 #undef GET_STR16
841 
842 uint64_t avio_rb64(AVIOContext *s)
843 {
844  uint64_t val;
845  val = (uint64_t)avio_rb32(s) << 32;
846  val |= (uint64_t)avio_rb32(s);
847  return val;
848 }
849 
851  uint64_t val = 0;
852  int tmp;
853 
854  do{
855  tmp = avio_r8(bc);
856  val= (val<<7) + (tmp&127);
857  }while(tmp&128);
858  return val;
859 }
860 
862 {
863  uint8_t *buffer;
864  int buffer_size, max_packet_size;
865 
866  max_packet_size = h->max_packet_size;
867  if (max_packet_size) {
868  buffer_size = max_packet_size; /* no need to bufferize more than one packet */
869  } else {
870  buffer_size = IO_BUFFER_SIZE;
871  }
872  buffer = av_malloc(buffer_size);
873  if (!buffer)
874  return AVERROR(ENOMEM);
875 
876  *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h,
878  if (!*s) {
879  av_free(buffer);
880  return AVERROR(ENOMEM);
881  }
882 #if FF_API_OLD_AVIO
883  (*s)->is_streamed = h->is_streamed;
884 #endif
885  (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
886  (*s)->max_packet_size = max_packet_size;
887  if(h->prot) {
888  (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
889  (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
890  }
891 #if !FF_API_OLD_AVIO
892  (*s)->av_class = &ffio_url_class;
893 #endif
894  return 0;
895 }
896 
897 int ffio_set_buf_size(AVIOContext *s, int buf_size)
898 {
899  uint8_t *buffer;
900  buffer = av_malloc(buf_size);
901  if (!buffer)
902  return AVERROR(ENOMEM);
903 
904  av_free(s->buffer);
905  s->buffer = buffer;
906  s->buffer_size = buf_size;
907  s->buf_ptr = buffer;
909  return 0;
910 }
911 
912 static int url_resetbuf(AVIOContext *s, int flags)
913 {
914  assert(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ);
915 
916  if (flags & AVIO_FLAG_WRITE) {
917  s->buf_end = s->buffer + s->buffer_size;
918  s->write_flag = 1;
919  } else {
920  s->buf_end = s->buffer;
921  s->write_flag = 0;
922  }
923  return 0;
924 }
925 
926 int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size)
927 {
928  int64_t buffer_start;
929  int buffer_size;
930  int overlap, new_size, alloc_size;
931 
932  if (s->write_flag)
933  return AVERROR(EINVAL);
934 
935  buffer_size = s->buf_end - s->buffer;
936 
937  /* the buffers must touch or overlap */
938  if ((buffer_start = s->pos - buffer_size) > buf_size)
939  return AVERROR(EINVAL);
940 
941  overlap = buf_size - buffer_start;
942  new_size = buf_size + buffer_size - overlap;
943 
944  alloc_size = FFMAX(s->buffer_size, new_size);
945  if (alloc_size > buf_size)
946  if (!(buf = av_realloc(buf, alloc_size)))
947  return AVERROR(ENOMEM);
948 
949  if (new_size > buf_size) {
950  memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
951  buf_size = new_size;
952  }
953 
954  av_free(s->buffer);
955  s->buf_ptr = s->buffer = buf;
956  s->buffer_size = alloc_size;
957  s->pos = buf_size;
958  s->buf_end = s->buf_ptr + buf_size;
959  s->eof_reached = 0;
960  s->must_flush = 0;
961 
962  return 0;
963 }
964 
965 int avio_open(AVIOContext **s, const char *filename, int flags)
966 {
967  return avio_open2(s, filename, flags, NULL, NULL);
968 }
969 
970 int avio_open2(AVIOContext **s, const char *filename, int flags,
972 {
973  URLContext *h;
974  int err;
975 
976  err = ffurl_open(&h, filename, flags, int_cb, options);
977  if (err < 0)
978  return err;
979  err = ffio_fdopen(s, h);
980  if (err < 0) {
981  ffurl_close(h);
982  return err;
983  }
984  return 0;
985 }
986 
988 {
989  URLContext *h = s->opaque;
990 
991  av_free(s->buffer);
992  av_free(s);
993  return ffurl_close(h);
994 }
995 
996 #if FF_API_OLD_AVIO
997 URLContext *url_fileno(AVIOContext *s)
998 {
999  return s->opaque;
1000 }
1001 #endif
1002 
1003 int avio_printf(AVIOContext *s, const char *fmt, ...)
1004 {
1005  va_list ap;
1006  char buf[4096];
1007  int ret;
1008 
1009  va_start(ap, fmt);
1010  ret = vsnprintf(buf, sizeof(buf), fmt, ap);
1011  va_end(ap);
1012  avio_write(s, buf, strlen(buf));
1013  return ret;
1014 }
1015 
1016 #if FF_API_OLD_AVIO
1017 char *url_fgets(AVIOContext *s, char *buf, int buf_size)
1018 {
1019  int c;
1020  char *q;
1021 
1022  c = avio_r8(s);
1023  if (s->eof_reached)
1024  return NULL;
1025  q = buf;
1026  for(;;) {
1027  if (s->eof_reached || c == '\n')
1028  break;
1029  if ((q - buf) < buf_size - 1)
1030  *q++ = c;
1031  c = avio_r8(s);
1032  }
1033  if (buf_size > 0)
1034  *q = '\0';
1035  return buf;
1036 }
1037 
1038 int url_fget_max_packet_size(AVIOContext *s)
1039 {
1040  return s->max_packet_size;
1041 }
1042 #endif
1043 
1044 int avio_pause(AVIOContext *s, int pause)
1045 {
1046  if (!s->read_pause)
1047  return AVERROR(ENOSYS);
1048  return s->read_pause(s->opaque, pause);
1049 }
1050 
1051 int64_t avio_seek_time(AVIOContext *s, int stream_index,
1052  int64_t timestamp, int flags)
1053 {
1054  URLContext *h = s->opaque;
1055  int64_t ret;
1056  if (!s->read_seek)
1057  return AVERROR(ENOSYS);
1058  ret = s->read_seek(h, stream_index, timestamp, flags);
1059  if(ret >= 0) {
1060  int64_t pos;
1061  s->buf_ptr = s->buf_end; // Flush buffer
1062  pos = s->seek(h, 0, SEEK_CUR);
1063  if (pos >= 0)
1064  s->pos = pos;
1065  else if (pos != AVERROR(ENOSYS))
1066  ret = pos;
1067  }
1068  return ret;
1069 }
1070 
1071 /* buffer handling */
1072 #if FF_API_OLD_AVIO
1073 int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags)
1074 {
1075  int ret;
1076  *s = av_mallocz(sizeof(AVIOContext));
1077  if(!*s)
1078  return AVERROR(ENOMEM);
1079  ret = ffio_init_context(*s, buf, buf_size,
1080  flags & AVIO_FLAG_WRITE,
1081  NULL, NULL, NULL, NULL);
1082  if(ret != 0)
1083  av_freep(s);
1084  return ret;
1085 }
1086 
1087 int url_close_buf(AVIOContext *s)
1088 {
1089  avio_flush(s);
1090  return s->buf_ptr - s->buffer;
1091 }
1092 #endif
1093 
1094 /* output in a dynamic buffer */
1095 
1096 typedef struct DynBuffer {
1098  uint8_t *buffer;
1100  uint8_t io_buffer[1];
1101 } DynBuffer;
1102 
1103 static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
1104 {
1105  DynBuffer *d = opaque;
1106  unsigned new_size, new_allocated_size;
1107 
1108  /* reallocate buffer if needed */
1109  new_size = d->pos + buf_size;
1110  new_allocated_size = d->allocated_size;
1111  if(new_size < d->pos || new_size > INT_MAX/2)
1112  return -1;
1113  while (new_size > new_allocated_size) {
1114  if (!new_allocated_size)
1115  new_allocated_size = new_size;
1116  else
1117  new_allocated_size += new_allocated_size / 2 + 1;
1118  }
1119 
1120  if (new_allocated_size > d->allocated_size) {
1121  d->buffer = av_realloc(d->buffer, new_allocated_size);
1122  if(d->buffer == NULL)
1123  return AVERROR(ENOMEM);
1124  d->allocated_size = new_allocated_size;
1125  }
1126  memcpy(d->buffer + d->pos, buf, buf_size);
1127  d->pos = new_size;
1128  if (d->pos > d->size)
1129  d->size = d->pos;
1130  return buf_size;
1131 }
1132 
1133 static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
1134 {
1135  unsigned char buf1[4];
1136  int ret;
1137 
1138  /* packetized write: output the header */
1139  AV_WB32(buf1, buf_size);
1140  ret= dyn_buf_write(opaque, buf1, 4);
1141  if(ret < 0)
1142  return ret;
1143 
1144  /* then the data */
1145  return dyn_buf_write(opaque, buf, buf_size);
1146 }
1147 
1148 static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence)
1149 {
1150  DynBuffer *d = opaque;
1151 
1152  if (whence == SEEK_CUR)
1153  offset += d->pos;
1154  else if (whence == SEEK_END)
1155  offset += d->size;
1156  if (offset < 0 || offset > 0x7fffffffLL)
1157  return -1;
1158  d->pos = offset;
1159  return 0;
1160 }
1161 
1162 static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size)
1163 {
1164  DynBuffer *d;
1165  unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
1166 
1167  if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
1168  return -1;
1169  d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
1170  if (!d)
1171  return AVERROR(ENOMEM);
1172  d->io_buffer_size = io_buffer_size;
1173  *s = avio_alloc_context(d->io_buffer, d->io_buffer_size, 1, d, NULL,
1174  max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
1175  max_packet_size ? NULL : dyn_buf_seek);
1176  if(!*s) {
1177  av_free(d);
1178  return AVERROR(ENOMEM);
1179  }
1180  (*s)->max_packet_size = max_packet_size;
1181  return 0;
1182 }
1183 
1185 {
1186  return url_open_dyn_buf_internal(s, 0);
1187 }
1188 
1189 int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
1190 {
1191  if (max_packet_size <= 0)
1192  return -1;
1193  return url_open_dyn_buf_internal(s, max_packet_size);
1194 }
1195 
1196 int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
1197 {
1198  DynBuffer *d = s->opaque;
1199  int size;
1200  static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0};
1201  int padding = 0;
1202 
1203  /* don't attempt to pad fixed-size packet buffers */
1204  if (!s->max_packet_size) {
1205  avio_write(s, padbuf, sizeof(padbuf));
1206  padding = FF_INPUT_BUFFER_PADDING_SIZE;
1207  }
1208 
1209  avio_flush(s);
1210 
1211  *pbuffer = d->buffer;
1212  size = d->size;
1213  av_free(d);
1214  av_free(s);
1215  return size - padding;
1216 }