Categories
code ffmpeg graphics programming video

FFMPEG video writer – now with animated GIF support [w/ code]

simplifies FFMPEG video writer, now with animated GIF output

rect3825So animated gifs are awesome if you’re writing a software blog. It saves all this time working with YouTube embeddings and stuff, and your “videos” are stored locally. The simplified FFMPEG writer was before unable to output animated GIFs, but I’ve tweaked it and now it does. It’s also a nice piece of code to learn how to FFMPEG in C.

There’s not a lot to say technically because most of the code remained the same, except maybe a couple of things that have to do with the required formats that animated GIFs require (RGB24).
When getting the discovered codec from avformat_alloc_output_context (that examines the filename), we should set the pixel format to RGB24. The codec can give us a list of all supported pix formats:

        codec = avcodec_find_encoder(avcid);
        if (!codec) {
            fprintf(stderr, "codec not found: %s\n", avcodec_get_name(avcid));
            exit(1);
        } else {
            const AVPixelFormat* p = codec->pix_fmts;
            while (p != NULL && *p != AV_PIX_FMT_NONE) {
                printf("supported pix fmt: %s\n",av_get_pix_fmt_name(*p));
                supported_pix_fmt = *p;
                ++p;
            }
            // Codec doesn't have any pix formats?
            if (p == NULL || *p == AV_PIX_FMT_NONE) {
                if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
                    // Well if it's "rawvideo" we know it's GIF, and that needs RGB24
                    supported_pix_fmt = AV_PIX_FMT_RGB24;
                } else {
                    supported_pix_fmt = AV_PIX_FMT_YUV420P; /* default pix_fmt */
                }
            }
        }

The only other thing is when writing a frame, the rawvideo codec for GIFs doesn’t need encoding just streaming the pixels to the file:

    if (oc->oformat->flags & AVFMT_RAWPICTURE) {
        /* Raw video case - directly store the picture in the packet */
        AVPacket pkt;
        av_init_packet(&pkt);
        pkt.flags        |= AV_PKT_FLAG_KEY;
        pkt.stream_index  = video_st->index;
        pkt.data          = picture->data[0];
        pkt.size          = sizeof(AVPicture);
        ret = av_interleaved_write_frame(oc, &pkt);
    } else {
    ...

Code

Get the code: here

Compressing the GIFs

The outputs are usually huge, like 20Mb for 20 seconds, so ImageMagick helped a lot:

convert -quality 80% output.gif output-comp.gif

And here’s a sample…
output-comp
Enjoy
Roy.

Leave a Reply

Your email address will not be published. Required fields are marked *