So 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…
Enjoy
Roy.