You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

416 lines
9.4KB

  1. /*
  2. * Buffered I/O for ffmpeg system
  3. * Copyright (c) 2000,2001 Gerard Lantau
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program 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
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include "avformat.h"
  20. #define IO_BUFFER_SIZE 32768
  21. int init_put_byte(ByteIOContext *s,
  22. unsigned char *buffer,
  23. int buffer_size,
  24. int write_flag,
  25. void *opaque,
  26. int (*read_packet)(void *opaque, UINT8 *buf, int buf_size),
  27. void (*write_packet)(void *opaque, UINT8 *buf, int buf_size),
  28. int (*seek)(void *opaque, offset_t offset, int whence))
  29. {
  30. s->buffer = buffer;
  31. s->buffer_size = buffer_size;
  32. s->buf_ptr = buffer;
  33. s->write_flag = write_flag;
  34. if (!s->write_flag)
  35. s->buf_end = buffer;
  36. else
  37. s->buf_end = buffer + buffer_size;
  38. s->opaque = opaque;
  39. s->write_packet = write_packet;
  40. s->read_packet = read_packet;
  41. s->seek = seek;
  42. s->pos = 0;
  43. s->must_flush = 0;
  44. s->eof_reached = 0;
  45. s->is_streamed = 0;
  46. s->packet_size = 1;
  47. return 0;
  48. }
  49. static void flush_buffer(ByteIOContext *s)
  50. {
  51. if (s->buf_ptr > s->buffer) {
  52. if (s->write_packet)
  53. s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
  54. s->pos += s->buf_ptr - s->buffer;
  55. }
  56. s->buf_ptr = s->buffer;
  57. }
  58. void put_byte(ByteIOContext *s, int b)
  59. {
  60. *(s->buf_ptr)++ = b;
  61. if (s->buf_ptr >= s->buf_end)
  62. flush_buffer(s);
  63. }
  64. void put_buffer(ByteIOContext *s, unsigned char *buf, int size)
  65. {
  66. int len;
  67. while (size > 0) {
  68. len = (s->buf_end - s->buf_ptr);
  69. if (len > size)
  70. len = size;
  71. memcpy(s->buf_ptr, buf, len);
  72. s->buf_ptr += len;
  73. if (s->buf_ptr >= s->buf_end)
  74. flush_buffer(s);
  75. buf += len;
  76. size -= len;
  77. }
  78. }
  79. void put_flush_packet(ByteIOContext *s)
  80. {
  81. flush_buffer(s);
  82. s->must_flush = 0;
  83. }
  84. offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence)
  85. {
  86. offset_t offset1;
  87. if (whence != SEEK_CUR && whence != SEEK_SET)
  88. return -EINVAL;
  89. if (s->write_flag) {
  90. if (whence == SEEK_CUR) {
  91. offset1 = s->pos + (s->buf_ptr - s->buffer);
  92. if (offset == 0)
  93. return offset1;
  94. offset += offset1;
  95. }
  96. offset1 = offset - s->pos;
  97. if (!s->must_flush &&
  98. offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) {
  99. /* can do the seek inside the buffer */
  100. s->buf_ptr = s->buffer + offset1;
  101. } else {
  102. if (!s->seek)
  103. return -EPIPE;
  104. flush_buffer(s);
  105. s->must_flush = 1;
  106. s->buf_ptr = s->buffer;
  107. s->seek(s->opaque, offset, SEEK_SET);
  108. s->pos = offset;
  109. }
  110. } else {
  111. if (whence == SEEK_CUR) {
  112. offset1 = s->pos - (s->buf_end - s->buffer) + (s->buf_ptr - s->buffer);
  113. if (offset == 0)
  114. return offset1;
  115. offset += offset1;
  116. }
  117. offset1 = offset - (s->pos - (s->buf_end - s->buffer));
  118. if (offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
  119. /* can do the seek inside the buffer */
  120. s->buf_ptr = s->buffer + offset1;
  121. } else {
  122. if (!s->seek)
  123. return -EPIPE;
  124. s->buf_ptr = s->buffer;
  125. s->buf_end = s->buffer;
  126. s->eof_reached = 0;
  127. s->seek(s->opaque, offset, SEEK_SET);
  128. s->pos = offset;
  129. }
  130. }
  131. return offset;
  132. }
  133. void url_fskip(ByteIOContext *s, offset_t offset)
  134. {
  135. url_fseek(s, offset, SEEK_CUR);
  136. }
  137. offset_t url_ftell(ByteIOContext *s)
  138. {
  139. return url_fseek(s, 0, SEEK_CUR);
  140. }
  141. int url_feof(ByteIOContext *s)
  142. {
  143. return s->eof_reached;
  144. }
  145. void put_le32(ByteIOContext *s, unsigned int val)
  146. {
  147. put_byte(s, val);
  148. put_byte(s, val >> 8);
  149. put_byte(s, val >> 16);
  150. put_byte(s, val >> 24);
  151. }
  152. void put_be32(ByteIOContext *s, unsigned int val)
  153. {
  154. put_byte(s, val >> 24);
  155. put_byte(s, val >> 16);
  156. put_byte(s, val >> 8);
  157. put_byte(s, val);
  158. }
  159. void put_le64(ByteIOContext *s, UINT64 val)
  160. {
  161. put_le32(s, (UINT32)(val & 0xffffffff));
  162. put_le32(s, (UINT32)(val >> 32));
  163. }
  164. void put_be64(ByteIOContext *s, UINT64 val)
  165. {
  166. put_be32(s, (UINT32)(val >> 32));
  167. put_be32(s, (UINT32)(val & 0xffffffff));
  168. }
  169. void put_le16(ByteIOContext *s, unsigned int val)
  170. {
  171. put_byte(s, val);
  172. put_byte(s, val >> 8);
  173. }
  174. void put_be16(ByteIOContext *s, unsigned int val)
  175. {
  176. put_byte(s, val >> 8);
  177. put_byte(s, val);
  178. }
  179. void put_tag(ByteIOContext *s, char *tag)
  180. {
  181. while (*tag) {
  182. put_byte(s, *tag++);
  183. }
  184. }
  185. /* Input stream */
  186. static void fill_buffer(ByteIOContext *s)
  187. {
  188. int len;
  189. len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
  190. s->pos += len;
  191. s->buf_ptr = s->buffer;
  192. s->buf_end = s->buffer + len;
  193. if (len == 0) {
  194. s->eof_reached = 1;
  195. }
  196. }
  197. int get_byte(ByteIOContext *s)
  198. {
  199. if (s->buf_ptr < s->buf_end) {
  200. return *s->buf_ptr++;
  201. } else {
  202. fill_buffer(s);
  203. if (s->buf_ptr < s->buf_end)
  204. return *s->buf_ptr++;
  205. else
  206. return 0;
  207. }
  208. }
  209. int get_buffer(ByteIOContext *s, unsigned char *buf, int size)
  210. {
  211. int len, size1;
  212. size1 = size;
  213. while (size > 0) {
  214. len = s->buf_end - s->buf_ptr;
  215. if (len > size)
  216. len = size;
  217. if (len == 0) {
  218. fill_buffer(s);
  219. len = s->buf_end - s->buf_ptr;
  220. if (len == 0)
  221. break;
  222. } else {
  223. memcpy(buf, s->buf_ptr, len);
  224. buf += len;
  225. s->buf_ptr += len;
  226. size -= len;
  227. }
  228. }
  229. return size1 - size;
  230. }
  231. unsigned int get_le16(ByteIOContext *s)
  232. {
  233. unsigned int val;
  234. val = get_byte(s);
  235. val |= get_byte(s) << 8;
  236. return val;
  237. }
  238. unsigned int get_le32(ByteIOContext *s)
  239. {
  240. unsigned int val;
  241. val = get_byte(s);
  242. val |= get_byte(s) << 8;
  243. val |= get_byte(s) << 16;
  244. val |= get_byte(s) << 24;
  245. return val;
  246. }
  247. UINT64 get_le64(ByteIOContext *s)
  248. {
  249. UINT64 val;
  250. val = (UINT64)get_le32(s);
  251. val |= (UINT64)get_le32(s) << 32;
  252. return val;
  253. }
  254. unsigned int get_be16(ByteIOContext *s)
  255. {
  256. unsigned int val;
  257. val = get_byte(s) << 8;
  258. val |= get_byte(s);
  259. return val;
  260. }
  261. unsigned int get_be32(ByteIOContext *s)
  262. {
  263. unsigned int val;
  264. val = get_byte(s) << 24;
  265. val |= get_byte(s) << 16;
  266. val |= get_byte(s) << 8;
  267. val |= get_byte(s);
  268. return val;
  269. }
  270. UINT64 get_be64(ByteIOContext *s)
  271. {
  272. UINT64 val;
  273. val = (UINT64)get_be32(s) << 32;
  274. val |= (UINT64)get_be32(s);
  275. return val;
  276. }
  277. /* link with avio functions */
  278. void url_write_packet(void *opaque, UINT8 *buf, int buf_size)
  279. {
  280. URLContext *h = opaque;
  281. url_write(h, buf, buf_size);
  282. }
  283. int url_read_packet(void *opaque, UINT8 *buf, int buf_size)
  284. {
  285. URLContext *h = opaque;
  286. return url_read(h, buf, buf_size);
  287. }
  288. int url_seek_packet(void *opaque, INT64 offset, int whence)
  289. {
  290. URLContext *h = opaque;
  291. url_seek(h, offset, whence);
  292. return 0;
  293. }
  294. int url_fdopen(ByteIOContext *s, URLContext *h)
  295. {
  296. UINT8 *buffer;
  297. int buffer_size;
  298. buffer_size = (IO_BUFFER_SIZE / h->packet_size) * h->packet_size;
  299. buffer = av_malloc(buffer_size);
  300. if (!buffer)
  301. return -ENOMEM;
  302. if (init_put_byte(s, buffer, buffer_size,
  303. (h->flags & URL_WRONLY) != 0, h,
  304. url_read_packet, url_write_packet, url_seek_packet) < 0) {
  305. av_free(buffer);
  306. return -EIO;
  307. }
  308. s->is_streamed = h->is_streamed;
  309. s->packet_size = h->packet_size;
  310. return 0;
  311. }
  312. /* XXX: must be called before any I/O */
  313. int url_setbufsize(ByteIOContext *s, int buf_size)
  314. {
  315. UINT8 *buffer;
  316. buffer = av_malloc(buf_size);
  317. if (!buffer)
  318. return -ENOMEM;
  319. av_free(s->buffer);
  320. s->buffer = buffer;
  321. s->buffer_size = buf_size;
  322. s->buf_ptr = buffer;
  323. if (!s->write_flag)
  324. s->buf_end = buffer;
  325. else
  326. s->buf_end = buffer + buf_size;
  327. return 0;
  328. }
  329. int url_fopen(ByteIOContext *s, const char *filename, int flags)
  330. {
  331. URLContext *h;
  332. int err;
  333. err = url_open(&h, filename, flags);
  334. if (err < 0)
  335. return err;
  336. err = url_fdopen(s, h);
  337. if (err < 0) {
  338. url_close(h);
  339. return err;
  340. }
  341. return 0;
  342. }
  343. int url_fclose(ByteIOContext *s)
  344. {
  345. URLContext *h = s->opaque;
  346. av_free(s->buffer);
  347. memset(s, 0, sizeof(ByteIOContext));
  348. return url_close(h);
  349. }
  350. URLContext *url_fileno(ByteIOContext *s)
  351. {
  352. return s->opaque;
  353. }
  354. /* buffer handling */
  355. int url_open_buf(ByteIOContext *s, UINT8 *buf, int buf_size, int flags)
  356. {
  357. return init_put_byte(s, buf, buf_size,
  358. (flags & URL_WRONLY) != 0, NULL, NULL, NULL, NULL);
  359. }
  360. /* return the written or read size */
  361. int url_close_buf(ByteIOContext *s)
  362. {
  363. return s->buf_ptr - s->buffer;
  364. }