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.

269 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. avcodec_get_context_defaults(&st->codec);
  145. s1->streams[0] = st;
  146. s->img_number = 0;
  147. /* try to find the first image */
  148. for(i=0;i<5;i++) {
  149. if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
  150. goto fail;
  151. if (url_fopen(f, buf, URL_RDONLY) >= 0)
  152. break;
  153. s->img_number++;
  154. }
  155. if (i == 5)
  156. goto fail;
  157. url_fclose(f);
  158. st->codec.codec_type = CODEC_TYPE_VIDEO;
  159. st->codec.codec_id = CODEC_ID_MJPEG;
  160. if (!ap || !ap->frame_rate)
  161. st->codec.frame_rate = 25 * FRAME_RATE_BASE;
  162. else
  163. st->codec.frame_rate = ap->frame_rate;
  164. return 0;
  165. fail:
  166. av_free(s);
  167. return -EIO;
  168. }
  169. static int jpeg_read_packet(AVFormatContext *s1, AVPacket *pkt)
  170. {
  171. JpegContext *s = s1->priv_data;
  172. char filename[1024];
  173. int size;
  174. ByteIOContext f1, *f = &f1;
  175. if (get_frame_filename(filename, sizeof(filename),
  176. s->path, s->img_number) < 0)
  177. return -EIO;
  178. f = &f1;
  179. if (url_fopen(f, filename, URL_RDONLY) < 0)
  180. return -EIO;
  181. size = url_seek(url_fileno(f), 0, SEEK_END);
  182. url_seek(url_fileno(f), 0, SEEK_SET);
  183. av_new_packet(pkt, size);
  184. pkt->stream_index = 0;
  185. get_buffer(f, pkt->data, size);
  186. url_fclose(f);
  187. s->img_number++;
  188. return 0;
  189. }
  190. static int jpeg_read_close(AVFormatContext *s1)
  191. {
  192. return 0;
  193. }
  194. static AVInputFormat jpeg_iformat = {
  195. "jpeg",
  196. "JPEG image",
  197. sizeof(JpegContext),
  198. NULL,
  199. jpeg_read_header,
  200. jpeg_read_packet,
  201. jpeg_read_close,
  202. NULL,
  203. .flags = AVFMT_NOFILE | AVFMT_NEEDNUMBER,
  204. .extensions = "jpg,jpeg",
  205. };
  206. static AVOutputFormat jpeg_oformat = {
  207. "jpeg",
  208. "JPEG image",
  209. "image/jpeg",
  210. "jpg,jpeg",
  211. sizeof(JpegContext),
  212. CODEC_ID_NONE,
  213. CODEC_ID_MJPEG,
  214. jpeg_write_header,
  215. jpeg_write_packet,
  216. jpeg_write_trailer,
  217. .flags = AVFMT_NOFILE | AVFMT_NEEDNUMBER,
  218. };
  219. int jpeg_init(void)
  220. {
  221. av_register_output_format(&mpjpeg_format);
  222. av_register_output_format(&single_jpeg_format);
  223. av_register_input_format(&jpeg_iformat);
  224. av_register_output_format(&jpeg_oformat);
  225. return 0;
  226. }