~ubuntu-branches/ubuntu/trusty/libav/trusty-proposed

« back to all changes in this revision

Viewing changes to libavformat/gif.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2013-10-22 23:24:08 UTC
  • mfrom: (1.3.36 sid)
  • Revision ID: package-import@ubuntu.com-20131022232408-b8tvvn4pyzri9mi3
Tags: 6:9.10-1ubuntu1
* Build all -extra flavors from this source package, as libav got demoted
  from main to universe, cf LP: #1243235
* Simplify debian/rules to follow exactly the code that debian executes
* New upstream (LP: #1180288) fixes lots of security issues (LP: #1242802)
* Merge from unstable, remaining changes:
  - build-depend on libtiff5-dev rather than libtiff4-dev,
    avoids FTBFS caused by imlib
  - follow the regular debian codepaths

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
#define GIF_CHUNKS 100
54
54
 
55
55
/* slows down the decoding (and some browsers don't like it) */
56
 
/* update on the 'some browsers don't like it issue from above: this was probably due to missing 'Data Sub-block Terminator' (byte 19) in the app_header */
 
56
/* update on the 'some browsers don't like it issue from above:
 
57
 * this was probably due to missing 'Data Sub-block Terminator'
 
58
 * (byte 19) in the app_header */
57
59
#define GIF_ADD_APP_HEADER // required to enable looping of animated gif
58
60
 
59
61
typedef struct {
65
67
/* we use the standard 216 color palette */
66
68
 
67
69
/* this script was used to create the palette:
68
 
 * for r in 00 33 66 99 cc ff; do for g in 00 33 66 99 cc ff; do echo -n "    "; for b in 00 33 66 99 cc ff; do
69
 
 *   echo -n "{ 0x$r, 0x$g, 0x$b }, "; done; echo ""; done; done
 
70
 * for r in 00 33 66 99 cc ff; do
 
71
 *     for g in 00 33 66 99 cc ff; do
 
72
 *         echo -n "    "
 
73
 *         for b in 00 33 66 99 cc ff; do
 
74
 *             echo -n "{ 0x$r, 0x$g, 0x$b }, "
 
75
 *         done
 
76
 *         echo ""
 
77
 *     done
 
78
 * done
70
79
 */
71
80
 
72
81
static const rgb_triplet gif_clut[216] = {
109
118
};
110
119
 
111
120
/* GIF header */
112
 
static int gif_image_write_header(AVIOContext *pb,
113
 
                                  int width, int height, int loop_count,
114
 
                                  uint32_t *palette)
 
121
static int gif_image_write_header(AVIOContext *pb, int width, int height,
 
122
                                  int loop_count, uint32_t *palette)
115
123
{
116
124
    int i;
117
125
    unsigned int v;
127
135
 
128
136
    /* the global palette */
129
137
    if (!palette) {
130
 
        avio_write(pb, (const unsigned char *)gif_clut, 216*3);
131
 
        for(i=0;i<((256-216)*3);i++)
 
138
        avio_write(pb, (const unsigned char *)gif_clut, 216 * 3);
 
139
        for (i = 0; i < ((256 - 216) * 3); i++)
132
140
            avio_w8(pb, 0);
133
141
    } else {
134
 
        for(i=0;i<256;i++) {
 
142
        for (i = 0; i < 256; i++) {
135
143
            v = palette[i];
136
144
            avio_w8(pb, (v >> 16) & 0xff);
137
 
            avio_w8(pb, (v >> 8) & 0xff);
138
 
            avio_w8(pb, (v) & 0xff);
 
145
            avio_w8(pb, (v >>  8) & 0xff);
 
146
            avio_w8(pb, (v)       & 0xff);
139
147
        }
140
148
    }
141
149
 
142
 
        /*        update: this is the 'NETSCAPE EXTENSION' that allows for looped animated gif
143
 
                see http://members.aol.com/royalef/gifabout.htm#net-extension
144
 
 
145
 
                byte   1       : 33 (hex 0x21) GIF Extension code
146
 
                byte   2       : 255 (hex 0xFF) Application Extension Label
147
 
                byte   3       : 11 (hex (0x0B) Length of Application Block
148
 
                                         (eleven bytes of data to follow)
149
 
                bytes  4 to 11 : "NETSCAPE"
150
 
                bytes 12 to 14 : "2.0"
151
 
                byte  15       : 3 (hex 0x03) Length of Data Sub-Block
152
 
                                         (three bytes of data to follow)
153
 
                byte  16       : 1 (hex 0x01)
154
 
                bytes 17 to 18 : 0 to 65535, an unsigned integer in
155
 
                                         lo-hi byte format. This indicate the
156
 
                                         number of iterations the loop should
157
 
                                         be executed.
158
 
                bytes 19       : 0 (hex 0x00) a Data Sub-block Terminator
159
 
        */
 
150
    /* update: this is the 'NETSCAPE EXTENSION' that allows for looped animated
 
151
     * GIF, see http://members.aol.com/royalef/gifabout.htm#net-extension
 
152
     *
 
153
     * byte   1       : 33 (hex 0x21) GIF Extension code
 
154
     * byte   2       : 255 (hex 0xFF) Application Extension Label
 
155
     * byte   3       : 11 (hex (0x0B) Length of Application Block
 
156
     *                          (eleven bytes of data to follow)
 
157
     * bytes  4 to 11 : "NETSCAPE"
 
158
     * bytes 12 to 14 : "2.0"
 
159
     * byte  15       : 3 (hex 0x03) Length of Data Sub-Block
 
160
     *                          (three bytes of data to follow)
 
161
     * byte  16       : 1 (hex 0x01)
 
162
     * bytes 17 to 18 : 0 to 65535, an unsigned integer in
 
163
     *                          lo-hi byte format. This indicate the
 
164
     *                          number of iterations the loop should
 
165
     *                          be executed.
 
166
     * bytes 19       : 0 (hex 0x00) a Data Sub-block Terminator
 
167
     */
160
168
 
161
169
    /* application extension header */
162
170
#ifdef GIF_ADD_APP_HEADER
163
171
    if (loop_count >= 0 && loop_count <= 65535) {
164
 
    avio_w8(pb, 0x21);
165
 
    avio_w8(pb, 0xff);
166
 
    avio_w8(pb, 0x0b);
167
 
        avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1);  // bytes 4 to 14
 
172
        avio_w8(pb, 0x21);
 
173
        avio_w8(pb, 0xff);
 
174
        avio_w8(pb, 0x0b);
 
175
        // bytes 4 to 14
 
176
        avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1);
168
177
        avio_w8(pb, 0x03); // byte 15
169
178
        avio_w8(pb, 0x01); // byte 16
170
179
        avio_wl16(pb, (uint16_t)loop_count);
180
189
    return (((r) / 47) % 6) * 6 * 6 + (((g) / 47) % 6) * 6 + (((b) / 47) % 6);
181
190
}
182
191
 
183
 
 
184
192
static int gif_image_write_image(AVIOContext *pb,
185
193
                                 int x1, int y1, int width, int height,
186
194
                                 const uint8_t *buf, int linesize, int pix_fmt)
201
209
 
202
210
    avio_w8(pb, 0x08);
203
211
 
204
 
    left= width * height;
 
212
    left = width * height;
205
213
 
206
214
    init_put_bits(&p, buffer, 130);
207
215
 
208
216
/*
209
 
 * the thing here is the bitstream is written as little packets, with a size byte before
210
 
 * but it's still the same bitstream between packets (no flush !)
 
217
 * the thing here is the bitstream is written as little packets, with a size
 
218
 * byte before but it's still the same bitstream between packets (no flush !)
211
219
 */
212
220
    ptr = buf;
213
 
    w = width;
214
 
    while(left>0) {
215
 
 
 
221
    w   = width;
 
222
    while (left > 0) {
216
223
        put_bits(&p, 9, 0x0100); /* clear code */
217
224
 
218
 
        for(i=(left<GIF_CHUNKS)?left:GIF_CHUNKS;i;i--) {
219
 
            if (pix_fmt == PIX_FMT_RGB24) {
220
 
                v = gif_clut_index(ptr[0], ptr[1], ptr[2]);
221
 
                ptr+=3;
 
225
        for (i = (left < GIF_CHUNKS) ? left : GIF_CHUNKS; i; i--) {
 
226
            if (pix_fmt == AV_PIX_FMT_RGB24) {
 
227
                v    = gif_clut_index(ptr[0], ptr[1], ptr[2]);
 
228
                ptr += 3;
222
229
            } else {
223
230
                v = *ptr++;
224
231
            }
225
232
            put_bits(&p, 9, v);
226
233
            if (--w == 0) {
227
 
                w = width;
 
234
                w    = width;
228
235
                buf += linesize;
229
 
                ptr = buf;
 
236
                ptr  = buf;
230
237
            }
231
238
        }
232
239
 
233
 
        if(left<=GIF_CHUNKS) {
 
240
        if (left <= GIF_CHUNKS) {
234
241
            put_bits(&p, 9, 0x101); /* end of stream */
235
242
            flush_put_bits(&p);
236
243
        }
237
 
        if(put_bits_ptr(&p) - p.buf > 0) {
 
244
        if (put_bits_ptr(&p) - p.buf > 0) {
238
245
            avio_w8(pb, put_bits_ptr(&p) - p.buf); /* byte count of the packet */
239
246
            avio_write(pb, p.buf, put_bits_ptr(&p) - p.buf); /* the actual buffer */
240
247
            p.buf_ptr = p.buf; /* dequeue the bytes off the bitstream */
241
248
        }
242
 
        left-=GIF_CHUNKS;
 
249
        left -= GIF_CHUNKS;
243
250
    }
244
251
    avio_w8(pb, 0x00); /* end of image block */
245
252
 
261
268
    int i, width, height /*, rate*/;
262
269
 
263
270
/* XXX: do we reject audio streams or just ignore them ?
264
 
    if(s->nb_streams > 1)
265
 
        return -1;
266
 
*/
267
 
    gif->time = 0;
 
271
 *  if (s->nb_streams > 1)
 
272
 *      return -1;
 
273
 */
 
274
    gif->time      = 0;
268
275
    gif->file_time = 0;
269
276
 
270
277
    video_enc = NULL;
271
 
    for(i=0;i<s->nb_streams;i++) {
 
278
    for (i = 0; i < s->nb_streams; i++) {
272
279
        enc = s->streams[i]->codec;
273
280
        if (enc->codec_type != AVMEDIA_TYPE_AUDIO)
274
281
            video_enc = enc;
278
285
        av_free(gif);
279
286
        return -1;
280
287
    } else {
281
 
        width = video_enc->width;
 
288
        width  = video_enc->width;
282
289
        height = video_enc->height;
283
290
//        rate = video_enc->time_base.den;
284
291
    }
285
292
 
286
 
    if (video_enc->pix_fmt != PIX_FMT_RGB24) {
287
 
        av_log(s, AV_LOG_ERROR, "ERROR: gif only handles the rgb24 pixel format. Use -pix_fmt rgb24.\n");
 
293
    if (video_enc->pix_fmt != AV_PIX_FMT_RGB24) {
 
294
        av_log(s, AV_LOG_ERROR,
 
295
               "ERROR: gif only handles the rgb24 pixel format. Use -pix_fmt rgb24.\n");
288
296
        return AVERROR(EIO);
289
297
    }
290
298
 
291
 
#if FF_API_LOOP_OUTPUT
292
 
    if (s->loop_output)
293
 
        gif->loop = s->loop_output;
294
 
#endif
295
 
 
296
299
    gif_image_write_header(pb, width, height, gif->loop, NULL);
297
300
 
298
301
    avio_flush(s->pb);
299
302
    return 0;
300
303
}
301
304
 
302
 
static int gif_write_video(AVFormatContext *s,
303
 
                           AVCodecContext *enc, const uint8_t *buf, int size)
 
305
static int gif_write_video(AVFormatContext *s, AVCodecContext *enc,
 
306
                           const uint8_t *buf, int size)
304
307
{
305
308
    AVIOContext *pb = s->pb;
306
309
    int jiffies;
316
319
    /* XXX: should use delay, in order to be more accurate */
317
320
    /* instead of using the same rounded value each time */
318
321
    /* XXX: don't even remember if I really use it for now */
319
 
    jiffies = (70*enc->time_base.num/enc->time_base.den) - 1;
 
322
    jiffies = (70 * enc->time_base.num / enc->time_base.den) - 1;
320
323
 
321
324
    avio_wl16(pb, jiffies);
322
325
 
324
327
    avio_w8(pb, 0x00);
325
328
 
326
329
    gif_image_write_image(pb, 0, 0, enc->width, enc->height,
327
 
                          buf, enc->width * 3, PIX_FMT_RGB24);
 
330
                          buf, enc->width * 3, AV_PIX_FMT_RGB24);
328
331
 
329
332
    avio_flush(s->pb);
330
333
    return 0;
344
347
    AVIOContext *pb = s->pb;
345
348
 
346
349
    avio_w8(pb, 0x3b);
347
 
    avio_flush(s->pb);
 
350
 
348
351
    return 0;
349
352
}
350
353
 
351
354
#define OFFSET(x) offsetof(GIFContext, x)
352
355
#define ENC AV_OPT_FLAG_ENCODING_PARAM
353
356
static const AVOption options[] = {
354
 
    { "loop", "Number of times to loop the output.", OFFSET(loop), AV_OPT_TYPE_INT, {0}, 0, 65535, ENC },
 
357
    { "loop", "Number of times to loop the output.", OFFSET(loop),
 
358
      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 65535, ENC },
355
359
    { NULL },
356
360
};
357
361
 
363
367
};
364
368
 
365
369
AVOutputFormat ff_gif_muxer = {
366
 
    .name              = "gif",
367
 
    .long_name         = NULL_IF_CONFIG_SMALL("GIF Animation"),
368
 
    .mime_type         = "image/gif",
369
 
    .extensions        = "gif",
370
 
    .priv_data_size    = sizeof(GIFContext),
371
 
    .audio_codec       = CODEC_ID_NONE,
372
 
    .video_codec       = CODEC_ID_RAWVIDEO,
373
 
    .write_header      = gif_write_header,
374
 
    .write_packet      = gif_write_packet,
375
 
    .write_trailer     = gif_write_trailer,
376
 
    .priv_class = &gif_muxer_class,
 
370
    .name           = "gif",
 
371
    .long_name      = NULL_IF_CONFIG_SMALL("GIF Animation"),
 
372
    .mime_type      = "image/gif",
 
373
    .extensions     = "gif",
 
374
    .priv_data_size = sizeof(GIFContext),
 
375
    .audio_codec    = AV_CODEC_ID_NONE,
 
376
    .video_codec    = AV_CODEC_ID_RAWVIDEO,
 
377
    .write_header   = gif_write_header,
 
378
    .write_packet   = gif_write_packet,
 
379
    .write_trailer  = gif_write_trailer,
 
380
    .priv_class     = &gif_muxer_class,
377
381
};