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.

238 lines
7.5KB

  1. /*
  2. * Animated GIF muxer
  3. * Copyright (c) 2000 Fabrice Bellard
  4. *
  5. * first version by Francois Revol <revol@free.fr>
  6. *
  7. * This file is part of FFmpeg.
  8. *
  9. * FFmpeg is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * FFmpeg is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with FFmpeg; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * Features and limitations:
  25. * - currently no compression is performed,
  26. * in fact the size of the data is 9/8 the size of the image in 8bpp
  27. * - uses only a global standard palette
  28. * - tested with IE 5.0, Opera for BeOS, NetPositive (BeOS), and Mozilla (BeOS).
  29. *
  30. * Reference documents:
  31. * http://www.goice.co.jp/member/mo/formats/gif.html
  32. * http://astronomy.swin.edu.au/pbourke/dataformats/gif/
  33. * http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/GIF89a.txt
  34. *
  35. * this url claims to have an LZW algorithm not covered by Unisys patent:
  36. * http://www.msg.net/utility/whirlgif/gifencod.html
  37. * could help reduce the size of the files _a lot_...
  38. * some sites mentions an RLE type compression also.
  39. */
  40. #include "avformat.h"
  41. #include "libavutil/avassert.h"
  42. #include "libavutil/imgutils.h"
  43. #include "libavutil/log.h"
  44. #include "libavutil/opt.h"
  45. /* slows down the decoding (and some browsers don't like it) */
  46. /* update on the 'some browsers don't like it issue from above:
  47. * this was probably due to missing 'Data Sub-block Terminator'
  48. * (byte 19) in the app_header */
  49. #define GIF_ADD_APP_HEADER // required to enable looping of animated gif
  50. static int gif_image_write_header(AVIOContext *pb, int width, int height,
  51. int loop_count, uint32_t *palette)
  52. {
  53. int i;
  54. avio_write(pb, "GIF", 3);
  55. avio_write(pb, "89a", 3);
  56. avio_wl16(pb, width);
  57. avio_wl16(pb, height);
  58. if (palette) {
  59. avio_w8(pb, 0xf7); /* flags: global clut, 256 entries */
  60. avio_w8(pb, 0x1f); /* background color index */
  61. avio_w8(pb, 0); /* aspect ratio */
  62. for (i = 0; i < 256; i++) {
  63. const uint32_t v = palette[i];
  64. avio_wb24(pb, v);
  65. }
  66. } else {
  67. avio_w8(pb, 0); /* flags */
  68. avio_w8(pb, 0); /* background color index */
  69. avio_w8(pb, 0); /* aspect ratio */
  70. }
  71. /* update: this is the 'NETSCAPE EXTENSION' that allows for looped animated
  72. * GIF, see http://members.aol.com/royalef/gifabout.htm#net-extension
  73. *
  74. * byte 1 : 33 (hex 0x21) GIF Extension code
  75. * byte 2 : 255 (hex 0xFF) Application Extension Label
  76. * byte 3 : 11 (hex (0x0B) Length of Application Block
  77. * (eleven bytes of data to follow)
  78. * bytes 4 to 11 : "NETSCAPE"
  79. * bytes 12 to 14 : "2.0"
  80. * byte 15 : 3 (hex 0x03) Length of Data Sub-Block
  81. * (three bytes of data to follow)
  82. * byte 16 : 1 (hex 0x01)
  83. * bytes 17 to 18 : 0 to 65535, an unsigned integer in
  84. * lo-hi byte format. This indicate the
  85. * number of iterations the loop should
  86. * be executed.
  87. * bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator
  88. */
  89. /* application extension header */
  90. #ifdef GIF_ADD_APP_HEADER
  91. if (loop_count >= 0 && loop_count <= 65535) {
  92. avio_w8(pb, 0x21);
  93. avio_w8(pb, 0xff);
  94. avio_w8(pb, 0x0b);
  95. // bytes 4 to 14
  96. avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1);
  97. avio_w8(pb, 0x03); // byte 15
  98. avio_w8(pb, 0x01); // byte 16
  99. avio_wl16(pb, (uint16_t)loop_count);
  100. avio_w8(pb, 0x00); // byte 19
  101. }
  102. #endif
  103. return 0;
  104. }
  105. typedef struct {
  106. AVClass *class; /** Class for private options. */
  107. int64_t time, file_time;
  108. uint8_t buffer[100]; /* data chunks */
  109. int loop;
  110. } GIFContext;
  111. static int gif_write_header(AVFormatContext *s)
  112. {
  113. GIFContext *gif = s->priv_data;
  114. AVIOContext *pb = s->pb;
  115. AVCodecContext *enc, *video_enc;
  116. int i, width, height /*, rate*/;
  117. uint32_t palette[AVPALETTE_COUNT];
  118. /* XXX: do we reject audio streams or just ignore them ?
  119. * if (s->nb_streams > 1)
  120. * return -1;
  121. */
  122. gif->time = 0;
  123. gif->file_time = 0;
  124. video_enc = NULL;
  125. for (i = 0; i < s->nb_streams; i++) {
  126. enc = s->streams[i]->codec;
  127. if (enc->codec_type != AVMEDIA_TYPE_AUDIO)
  128. video_enc = enc;
  129. }
  130. if (!video_enc) {
  131. av_free(gif);
  132. return -1;
  133. } else {
  134. width = video_enc->width;
  135. height = video_enc->height;
  136. // rate = video_enc->time_base.den;
  137. }
  138. if (avpriv_set_systematic_pal2(palette, video_enc->pix_fmt) < 0) {
  139. av_assert0(video_enc->pix_fmt == AV_PIX_FMT_PAL8);
  140. gif_image_write_header(pb, width, height, gif->loop, NULL);
  141. } else {
  142. gif_image_write_header(pb, width, height, gif->loop, palette);
  143. }
  144. avio_flush(s->pb);
  145. return 0;
  146. }
  147. static int gif_write_video(AVFormatContext *s, AVCodecContext *enc,
  148. const uint8_t *buf, int size)
  149. {
  150. AVIOContext *pb = s->pb;
  151. int jiffies;
  152. /* graphic control extension block */
  153. avio_w8(pb, 0x21);
  154. avio_w8(pb, 0xf9);
  155. avio_w8(pb, 0x04); /* block size */
  156. avio_w8(pb, 0x04); /* flags */
  157. /* 1 jiffy is 1/70 s */
  158. /* the delay_time field indicates the number of jiffies - 1 */
  159. /* XXX: should use delay, in order to be more accurate */
  160. /* instead of using the same rounded value each time */
  161. /* XXX: don't even remember if I really use it for now */
  162. jiffies = (70 * enc->time_base.num / enc->time_base.den) - 1;
  163. avio_wl16(pb, jiffies);
  164. avio_w8(pb, 0x1f); /* transparent color index */
  165. avio_w8(pb, 0x00);
  166. avio_write(pb, buf, size);
  167. return 0;
  168. }
  169. static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
  170. {
  171. AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
  172. if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
  173. return 0; /* just ignore audio */
  174. else
  175. return gif_write_video(s, codec, pkt->data, pkt->size);
  176. }
  177. static int gif_write_trailer(AVFormatContext *s)
  178. {
  179. AVIOContext *pb = s->pb;
  180. avio_w8(pb, 0x3b);
  181. return 0;
  182. }
  183. #define OFFSET(x) offsetof(GIFContext, x)
  184. #define ENC AV_OPT_FLAG_ENCODING_PARAM
  185. static const AVOption options[] = {
  186. { "loop", "Number of times to loop the output.", OFFSET(loop),
  187. AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 65535, ENC },
  188. { NULL },
  189. };
  190. static const AVClass gif_muxer_class = {
  191. .class_name = "GIF muxer",
  192. .item_name = av_default_item_name,
  193. .version = LIBAVUTIL_VERSION_INT,
  194. .option = options,
  195. };
  196. AVOutputFormat ff_gif_muxer = {
  197. .name = "gif",
  198. .long_name = NULL_IF_CONFIG_SMALL("GIF Animation"),
  199. .mime_type = "image/gif",
  200. .extensions = "gif",
  201. .priv_data_size = sizeof(GIFContext),
  202. .audio_codec = AV_CODEC_ID_NONE,
  203. .video_codec = AV_CODEC_ID_GIF,
  204. .write_header = gif_write_header,
  205. .write_packet = gif_write_packet,
  206. .write_trailer = gif_write_trailer,
  207. .priv_class = &gif_muxer_class,
  208. };