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.

271 lines
6.2KB

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