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.

267 lines
6.2KB

  1. /*
  2. * JPEG based formats
  3. * Copyright (c) 2000, 2001 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. /* Multipart JPEG */
  21. #define BOUNDARY_TAG "ffserver"
  22. static int mpjpeg_write_header(AVFormatContext *s)
  23. {
  24. UINT8 buf1[256];
  25. snprintf(buf1, sizeof(buf1), "--%s\n", BOUNDARY_TAG);
  26. put_buffer(&s->pb, buf1, strlen(buf1));
  27. put_flush_packet(&s->pb);
  28. return 0;
  29. }
  30. static int mpjpeg_write_packet(AVFormatContext *s, int stream_index,
  31. UINT8 *buf, int size, int force_pts)
  32. {
  33. UINT8 buf1[256];
  34. snprintf(buf1, sizeof(buf1), "Content-type: image/jpeg\n\n");
  35. put_buffer(&s->pb, buf1, strlen(buf1));
  36. put_buffer(&s->pb, buf, size);
  37. snprintf(buf1, sizeof(buf1), "\n--%s\n", BOUNDARY_TAG);
  38. put_buffer(&s->pb, buf1, strlen(buf1));
  39. put_flush_packet(&s->pb);
  40. return 0;
  41. }
  42. static int mpjpeg_write_trailer(AVFormatContext *s)
  43. {
  44. return 0;
  45. }
  46. static AVOutputFormat mpjpeg_format = {
  47. "mpjpeg",
  48. "Mime multipart JPEG format",
  49. "multipart/x-mixed-replace;boundary=" BOUNDARY_TAG,
  50. "mjpg",
  51. 0,
  52. CODEC_ID_NONE,
  53. CODEC_ID_MJPEG,
  54. mpjpeg_write_header,
  55. mpjpeg_write_packet,
  56. mpjpeg_write_trailer,
  57. };
  58. /*************************************/
  59. /* single frame JPEG */
  60. static int single_jpeg_write_header(AVFormatContext *s)
  61. {
  62. return 0;
  63. }
  64. static int single_jpeg_write_packet(AVFormatContext *s, int stream_index,
  65. UINT8 *buf, int size, int force_pts)
  66. {
  67. put_buffer(&s->pb, buf, size);
  68. put_flush_packet(&s->pb);
  69. return 1; /* no more data can be sent */
  70. }
  71. static int single_jpeg_write_trailer(AVFormatContext *s)
  72. {
  73. return 0;
  74. }
  75. static AVOutputFormat single_jpeg_format = {
  76. "singlejpeg",
  77. "single JPEG image",
  78. "image/jpeg",
  79. NULL, /* note: no extension to favorize jpeg multiple images match */
  80. 0,
  81. CODEC_ID_NONE,
  82. CODEC_ID_MJPEG,
  83. single_jpeg_write_header,
  84. single_jpeg_write_packet,
  85. single_jpeg_write_trailer,
  86. };
  87. /*************************************/
  88. /* multiple jpeg images */
  89. typedef struct JpegContext {
  90. char path[1024];
  91. int img_number;
  92. } JpegContext;
  93. static int jpeg_write_header(AVFormatContext *s1)
  94. {
  95. JpegContext *s;
  96. s = av_mallocz(sizeof(JpegContext));
  97. if (!s)
  98. return -1;
  99. s1->priv_data = s;
  100. pstrcpy(s->path, sizeof(s->path), s1->filename);
  101. s->img_number = 1;
  102. return 0;
  103. }
  104. static int jpeg_write_packet(AVFormatContext *s1, int stream_index,
  105. UINT8 *buf, int size, int force_pts)
  106. {
  107. JpegContext *s = s1->priv_data;
  108. char filename[1024];
  109. ByteIOContext f1, *pb = &f1;
  110. if (get_frame_filename(filename, sizeof(filename),
  111. s->path, s->img_number) < 0)
  112. return -EIO;
  113. if (url_fopen(pb, filename, URL_WRONLY) < 0)
  114. return -EIO;
  115. put_buffer(pb, buf, size);
  116. put_flush_packet(pb);
  117. url_fclose(pb);
  118. s->img_number++;
  119. return 0;
  120. }
  121. static int jpeg_write_trailer(AVFormatContext *s1)
  122. {
  123. return 0;
  124. }
  125. /***/
  126. static int jpeg_read_header(AVFormatContext *s1, AVFormatParameters *ap)
  127. {
  128. JpegContext *s;
  129. int i;
  130. char buf[1024];
  131. ByteIOContext pb1, *f = &pb1;
  132. AVStream *st;
  133. s = av_mallocz(sizeof(JpegContext));
  134. if (!s)
  135. return -1;
  136. s1->priv_data = s;
  137. pstrcpy(s->path, sizeof(s->path), s1->filename);
  138. s1->nb_streams = 1;
  139. st = av_mallocz(sizeof(AVStream));
  140. if (!st) {
  141. av_free(s);
  142. return -ENOMEM;
  143. }
  144. s1->streams[0] = st;
  145. s->img_number = 0;
  146. /* try to find the first image */
  147. for(i=0;i<5;i++) {
  148. if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
  149. goto fail;
  150. if (url_fopen(f, buf, URL_RDONLY) >= 0)
  151. break;
  152. s->img_number++;
  153. }
  154. if (i == 5)
  155. goto fail;
  156. url_fclose(f);
  157. st->codec.codec_type = CODEC_TYPE_VIDEO;
  158. st->codec.codec_id = CODEC_ID_MJPEG;
  159. if (!ap || !ap->frame_rate)
  160. st->codec.frame_rate = 25 * FRAME_RATE_BASE;
  161. else
  162. st->codec.frame_rate = ap->frame_rate;
  163. return 0;
  164. fail:
  165. av_free(s);
  166. return -EIO;
  167. }
  168. static int jpeg_read_packet(AVFormatContext *s1, AVPacket *pkt)
  169. {
  170. JpegContext *s = s1->priv_data;
  171. char filename[1024];
  172. int size;
  173. ByteIOContext f1, *f = &f1;
  174. if (get_frame_filename(filename, sizeof(filename),
  175. s->path, s->img_number) < 0)
  176. return -EIO;
  177. f = &f1;
  178. if (url_fopen(f, filename, URL_RDONLY) < 0)
  179. return -EIO;
  180. size = url_seek(url_fileno(f), 0, SEEK_END);
  181. url_seek(url_fileno(f), 0, SEEK_SET);
  182. av_new_packet(pkt, size);
  183. pkt->stream_index = 0;
  184. get_buffer(f, pkt->data, size);
  185. url_fclose(f);
  186. s->img_number++;
  187. return 0;
  188. }
  189. static int jpeg_read_close(AVFormatContext *s1)
  190. {
  191. return 0;
  192. }
  193. static AVInputFormat jpeg_iformat = {
  194. "jpeg",
  195. "JPEG image",
  196. sizeof(JpegContext),
  197. NULL,
  198. jpeg_read_header,
  199. jpeg_read_packet,
  200. jpeg_read_close,
  201. NULL,
  202. .flags = AVFMT_NOFILE | AVFMT_NEEDNUMBER,
  203. .extensions = "jpg,jpeg",
  204. };
  205. static AVOutputFormat jpeg_oformat = {
  206. "jpeg",
  207. "JPEG image",
  208. "image/jpeg",
  209. "jpg,jpeg",
  210. sizeof(JpegContext),
  211. CODEC_ID_NONE,
  212. CODEC_ID_MJPEG,
  213. jpeg_write_header,
  214. jpeg_write_packet,
  215. jpeg_write_trailer,
  216. .flags = AVFMT_NOFILE | AVFMT_NEEDNUMBER,
  217. };
  218. int jpeg_init(void)
  219. {
  220. av_register_output_format(&mpjpeg_format);
  221. av_register_output_format(&single_jpeg_format);
  222. av_register_input_format(&jpeg_iformat);
  223. av_register_output_format(&jpeg_oformat);
  224. return 0;
  225. }