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.

220 lines
6.8KB

  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. #include "avformat.h"
  24. #include "libavutil/avassert.h"
  25. #include "libavutil/imgutils.h"
  26. #include "libavutil/log.h"
  27. #include "libavutil/opt.h"
  28. /* slows down the decoding (and some browsers don't like it) */
  29. /* update on the 'some browsers don't like it issue from above:
  30. * this was probably due to missing 'Data Sub-block Terminator'
  31. * (byte 19) in the app_header */
  32. #define GIF_ADD_APP_HEADER // required to enable looping of animated gif
  33. static int gif_image_write_header(AVIOContext *pb, int width, int height,
  34. int loop_count, uint32_t *palette)
  35. {
  36. int i;
  37. avio_write(pb, "GIF", 3);
  38. avio_write(pb, "89a", 3);
  39. avio_wl16(pb, width);
  40. avio_wl16(pb, height);
  41. if (palette) {
  42. avio_w8(pb, 0xf7); /* flags: global clut, 256 entries */
  43. avio_w8(pb, 0x1f); /* background color index */
  44. avio_w8(pb, 0); /* aspect ratio */
  45. for (i = 0; i < 256; i++) {
  46. const uint32_t v = palette[i] & 0xffffff;
  47. avio_wb24(pb, v);
  48. }
  49. } else {
  50. avio_w8(pb, 0); /* flags */
  51. avio_w8(pb, 0); /* background color index */
  52. avio_w8(pb, 0); /* aspect ratio */
  53. }
  54. /* update: this is the 'NETSCAPE EXTENSION' that allows for looped animated
  55. * GIF, see http://members.aol.com/royalef/gifabout.htm#net-extension
  56. *
  57. * byte 1 : 33 (hex 0x21) GIF Extension code
  58. * byte 2 : 255 (hex 0xFF) Application Extension Label
  59. * byte 3 : 11 (hex (0x0B) Length of Application Block
  60. * (eleven bytes of data to follow)
  61. * bytes 4 to 11 : "NETSCAPE"
  62. * bytes 12 to 14 : "2.0"
  63. * byte 15 : 3 (hex 0x03) Length of Data Sub-Block
  64. * (three bytes of data to follow)
  65. * byte 16 : 1 (hex 0x01)
  66. * bytes 17 to 18 : 0 to 65535, an unsigned integer in
  67. * lo-hi byte format. This indicate the
  68. * number of iterations the loop should
  69. * be executed.
  70. * bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator
  71. */
  72. /* application extension header */
  73. #ifdef GIF_ADD_APP_HEADER
  74. if (loop_count >= 0 && loop_count <= 65535) {
  75. avio_w8(pb, 0x21);
  76. avio_w8(pb, 0xff);
  77. avio_w8(pb, 0x0b);
  78. // bytes 4 to 14
  79. avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1);
  80. avio_w8(pb, 0x03); // byte 15
  81. avio_w8(pb, 0x01); // byte 16
  82. avio_wl16(pb, (uint16_t)loop_count);
  83. avio_w8(pb, 0x00); // byte 19
  84. }
  85. #endif
  86. return 0;
  87. }
  88. typedef struct {
  89. AVClass *class; /** Class for private options. */
  90. int64_t time, file_time;
  91. uint8_t buffer[100]; /* data chunks */
  92. int loop;
  93. } GIFContext;
  94. static int gif_write_header(AVFormatContext *s)
  95. {
  96. GIFContext *gif = s->priv_data;
  97. AVIOContext *pb = s->pb;
  98. AVCodecContext *enc, *video_enc;
  99. int i, width, height /*, rate*/;
  100. uint32_t palette[AVPALETTE_COUNT];
  101. /* XXX: do we reject audio streams or just ignore them ?
  102. * if (s->nb_streams > 1)
  103. * return -1;
  104. */
  105. gif->time = 0;
  106. gif->file_time = 0;
  107. video_enc = NULL;
  108. for (i = 0; i < s->nb_streams; i++) {
  109. enc = s->streams[i]->codec;
  110. if (enc->codec_type != AVMEDIA_TYPE_AUDIO)
  111. video_enc = enc;
  112. }
  113. if (!video_enc) {
  114. av_free(gif);
  115. return -1;
  116. } else {
  117. width = video_enc->width;
  118. height = video_enc->height;
  119. // rate = video_enc->time_base.den;
  120. }
  121. if (avpriv_set_systematic_pal2(palette, video_enc->pix_fmt) < 0) {
  122. av_assert0(video_enc->pix_fmt == AV_PIX_FMT_PAL8);
  123. gif_image_write_header(pb, width, height, gif->loop, NULL);
  124. } else {
  125. gif_image_write_header(pb, width, height, gif->loop, palette);
  126. }
  127. avio_flush(s->pb);
  128. return 0;
  129. }
  130. static int gif_write_video(AVFormatContext *s, AVCodecContext *enc,
  131. const uint8_t *buf, int size)
  132. {
  133. AVIOContext *pb = s->pb;
  134. int jiffies;
  135. /* graphic control extension block */
  136. avio_w8(pb, 0x21);
  137. avio_w8(pb, 0xf9);
  138. avio_w8(pb, 0x04); /* block size */
  139. avio_w8(pb, 0x04); /* flags */
  140. /* 1 jiffy is 1/70 s */
  141. /* the delay_time field indicates the number of jiffies - 1 */
  142. /* XXX: should use delay, in order to be more accurate */
  143. /* instead of using the same rounded value each time */
  144. /* XXX: don't even remember if I really use it for now */
  145. jiffies = (70 * enc->time_base.num / enc->time_base.den) - 1;
  146. avio_wl16(pb, jiffies);
  147. avio_w8(pb, 0x1f); /* transparent color index */
  148. avio_w8(pb, 0x00);
  149. avio_write(pb, buf, size);
  150. return 0;
  151. }
  152. static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
  153. {
  154. AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
  155. if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
  156. return 0; /* just ignore audio */
  157. else
  158. return gif_write_video(s, codec, pkt->data, pkt->size);
  159. }
  160. static int gif_write_trailer(AVFormatContext *s)
  161. {
  162. AVIOContext *pb = s->pb;
  163. avio_w8(pb, 0x3b);
  164. return 0;
  165. }
  166. #define OFFSET(x) offsetof(GIFContext, x)
  167. #define ENC AV_OPT_FLAG_ENCODING_PARAM
  168. static const AVOption options[] = {
  169. { "loop", "Number of times to loop the output.", OFFSET(loop),
  170. AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 65535, ENC },
  171. { NULL },
  172. };
  173. static const AVClass gif_muxer_class = {
  174. .class_name = "GIF muxer",
  175. .item_name = av_default_item_name,
  176. .version = LIBAVUTIL_VERSION_INT,
  177. .option = options,
  178. };
  179. AVOutputFormat ff_gif_muxer = {
  180. .name = "gif",
  181. .long_name = NULL_IF_CONFIG_SMALL("GIF Animation"),
  182. .mime_type = "image/gif",
  183. .extensions = "gif",
  184. .priv_data_size = sizeof(GIFContext),
  185. .audio_codec = AV_CODEC_ID_NONE,
  186. .video_codec = AV_CODEC_ID_GIF,
  187. .write_header = gif_write_header,
  188. .write_packet = gif_write_packet,
  189. .write_trailer = gif_write_trailer,
  190. .priv_class = &gif_muxer_class,
  191. };