libavformat/gif.c
Go to the documentation of this file.
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 #include "avformat.h"
25 #include "internal.h"
26 #include "libavutil/avassert.h"
27 #include "libavutil/imgutils.h"
28 #include "libavutil/log.h"
29 #include "libavutil/opt.h"
30 
32  int loop_count, uint32_t *palette)
33 {
34  int i;
35 
36  avio_write(pb, "GIF", 3);
37  avio_write(pb, "89a", 3);
38  avio_wl16(pb, width);
39  avio_wl16(pb, height);
40 
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 
55  /* "NETSCAPE EXTENSION" for looped animation GIF */
56  avio_w8(pb, 0x21); /* GIF Extension code */
57  avio_w8(pb, 0xff); /* Application Extension Label */
58  avio_w8(pb, 0x0b); /* Length of Application Block */
59  avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1);
60  avio_w8(pb, 0x03); /* Length of Data Sub-Block */
61  avio_w8(pb, 0x01);
62  avio_wl16(pb, (uint16_t)loop_count);
63  avio_w8(pb, 0x00); /* Data Sub-block Terminator */
64 
65  return 0;
66 }
67 
68 typedef struct {
69  AVClass *class; /** Class for private options. */
70  int loop;
73  int duration;
74 } GIFContext;
75 
77 {
78  GIFContext *gif = s->priv_data;
79  AVIOContext *pb = s->pb;
80  AVCodecContext *video_enc;
81  int width, height;
82  uint32_t palette[AVPALETTE_COUNT];
83 
84  if (s->nb_streams != 1 ||
88  "GIF muxer supports only a single video GIF stream.\n");
89  return AVERROR(EINVAL);
90  }
91 
92  video_enc = s->streams[0]->codec;
93  width = video_enc->width;
94  height = video_enc->height;
95 
96  avpriv_set_pts_info(s->streams[0], 64, 1, 100);
97  if (avpriv_set_systematic_pal2(palette, video_enc->pix_fmt) < 0) {
98  av_assert0(video_enc->pix_fmt == AV_PIX_FMT_PAL8);
99  gif_image_write_header(pb, width, height, gif->loop, NULL);
100  } else {
101  gif_image_write_header(pb, width, height, gif->loop, palette);
102  }
103 
104  avio_flush(s->pb);
105  return 0;
106 }
107 
109 {
110  GIFContext *gif = s->priv_data;
111  int size;
112  AVIOContext *pb = s->pb;
113  uint8_t flags = 0x4, transparent_color_index = 0x1f;
114  const uint32_t *palette;
115  AVPacket *pkt = gif->prev_pkt;
116 
117  if (!pkt)
118  return 0;
119 
120  /* Mark one colour as transparent if the input palette contains at least
121  * one colour that is more than 50% transparent. */
122  palette = (uint32_t*)av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size);
123  if (palette && size != AVPALETTE_SIZE) {
124  av_log(s, AV_LOG_ERROR, "Invalid palette extradata\n");
125  return AVERROR_INVALIDDATA;
126  }
127  if (palette) {
128  unsigned i, smallest_alpha = 0xff;
129 
130  for (i = 0; i < AVPALETTE_COUNT; i++) {
131  const uint32_t v = palette[i];
132  if (v >> 24 < smallest_alpha) {
133  smallest_alpha = v >> 24;
134  transparent_color_index = i;
135  }
136  }
137  if (smallest_alpha < 128)
138  flags |= 0x1; /* Transparent Color Flag */
139  }
140 
141  if (new && new->pts != AV_NOPTS_VALUE)
142  gif->duration = av_clip_uint16(new->pts - gif->prev_pkt->pts);
143  else if (!new && gif->last_delay >= 0)
144  gif->duration = gif->last_delay;
145 
146  /* graphic control extension block */
147  avio_w8(pb, 0x21);
148  avio_w8(pb, 0xf9);
149  avio_w8(pb, 0x04); /* block size */
150  avio_w8(pb, flags);
151  avio_wl16(pb, gif->duration);
152  avio_w8(pb, transparent_color_index);
153  avio_w8(pb, 0x00);
154 
155  avio_write(pb, pkt->data, pkt->size);
156 
157  av_free_packet(gif->prev_pkt);
158  if (new)
159  av_copy_packet(gif->prev_pkt, new);
160 
161  return 0;
162 }
163 
165 {
166  GIFContext *gif = s->priv_data;
167 
168  if (!gif->prev_pkt) {
169  gif->prev_pkt = av_malloc(sizeof(*gif->prev_pkt));
170  if (!gif->prev_pkt)
171  return AVERROR(ENOMEM);
172  return av_copy_packet(gif->prev_pkt, pkt);
173  }
174  return flush_packet(s, pkt);
175 }
176 
178 {
179  GIFContext *gif = s->priv_data;
180  AVIOContext *pb = s->pb;
181 
182  flush_packet(s, NULL);
183  av_freep(&gif->prev_pkt);
184  avio_w8(pb, 0x3b);
185 
186  return 0;
187 }
188 
189 #define OFFSET(x) offsetof(GIFContext, x)
190 #define ENC AV_OPT_FLAG_ENCODING_PARAM
191 static const AVOption options[] = {
192  { "loop", "Number of times to loop the output.", OFFSET(loop),
193  AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 65535, ENC },
194  { "final_delay", "Force delay (in ms) after the last frame", OFFSET(last_delay),
195  AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 65535, ENC },
196  { NULL },
197 };
198 
199 static const AVClass gif_muxer_class = {
200  .class_name = "GIF muxer",
201  .item_name = av_default_item_name,
202  .version = LIBAVUTIL_VERSION_INT,
203  .option = options,
204 };
205 
207  .name = "gif",
208  .long_name = NULL_IF_CONFIG_SMALL("GIF Animation"),
209  .mime_type = "image/gif",
210  .extensions = "gif",
211  .priv_data_size = sizeof(GIFContext),
212  .audio_codec = AV_CODEC_ID_NONE,
213  .video_codec = AV_CODEC_ID_GIF,
217  .priv_class = &gif_muxer_class,
219 };
void avio_wl16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:367
float v
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
AVOption.
Definition: opt.h:251
#define OFFSET(x)
av_default_item_name
misc image utilities
static int flush_packet(AVFormatContext *s, AVPacket *new)
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
static int write_packet(AVFormatContext *s, AVPacket *pkt)
int av_copy_packet(AVPacket *dst, AVPacket *src)
Copy packet, including contents.
Definition: avpacket.c:236
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
static int gif_write_header(AVFormatContext *s)
static const AVClass gif_muxer_class
#define ENC
AVOutputFormat ff_gif_muxer
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
Format I/O context.
Definition: avformat.h:944
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:55
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
uint8_t
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:79
AVOptions.
#define AVPALETTE_SIZE
Definition: pixfmt.h:33
static AVPacket pkt
Definition: demuxing.c:56
AVStream ** streams
Definition: avformat.h:992
uint8_t * data
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:173
static int gif_image_write_header(AVIOContext *pb, int width, int height, int loop_count, uint32_t *palette)
static int write_trailer(AVFormatContext *s)
int loop
Class for private options.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
simple assert() macros that are a bit more flexible than ISO C assert().
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt)
Definition: imgutils.c:150
int size
AVPacket * prev_pkt
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
unsigned int nb_streams
A list of all streams in the file.
Definition: avformat.h:991
int void avio_flush(AVIOContext *s)
Force flushing of buffered data to the output s.
Definition: aviobuf.c:193
int width
picture width / height.
void avio_wb24(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:385
const char * name
Definition: avformat.h:378
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
NULL
Definition: eval.c:55
static int gif_write_trailer(AVFormatContext *s)
static int width
Definition: tests/utils.c:158
enum AVMediaType codec_type
enum AVCodecID codec_id
AVIOContext * pb
I/O context.
Definition: avformat.h:977
static int loop
Definition: ffplay.c:305
static const AVOption options[]
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:151
main external API structure.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
BYTE int const BYTE int int int height
Definition: avisynth_c.h:713
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
Describe the class of an AVClass context structure.
Definition: log.h:50
synthesis window for stochastic i
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
#define AVPALETTE_COUNT
Definition: pixfmt.h:34
static int flags
Definition: cpu.c:23
int palette
Definition: v4l.c:61
Main libavformat public API header.
#define AVFMT_VARIABLE_FPS
Format allows variable fps.
Definition: avformat.h:355
void * priv_data
Format private data.
Definition: avformat.h:964
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:470
static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
uint8_t * av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:289
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:190