Scott Lamb
Scott Lamb

Reputation: 2216

How can I detect ffmpeg vs libav in CMake?

My project uses libavformat to connect to rtsp:// URLs. It's important that it set a socket timeout and reconnect on error. Unfortunately, the stimeout open option for this only exists in ffmpeg (and in particular, its libavformat versions >= 55.1.100), not the competing project libav (any version). And some systems I'd like to support (such as Raspbian Jessie) are still bundled with libav.

So, I think my best option is to detect whether I have a suitable version using cmake, and install ffmpeg in-tree if not. I think I should be able to do this via something like:

pkg_check_modules(FFMPEG libavutil libavcodec libavformat)

if(not FFMPEG_FOUND or FFMPEG_VERSION VERSION_LESS 55.1.101)
  ExternalProject_Add(
    FfmpegProject
    URL "http://ffmpeg.org/releases/ffmpeg-2.8.3.tar.xz"
    URL_HASH "SHA1=a6f39efe1bea9a9b271c903d3c1dcb940a510c87"
    INSTALL_COMMAND "")
  ...set up flags and such to use this in-tree version...
endif()

except that I don't know how to detect libav vs ffmpeg. I don't see anything in the pkgconfig stuff or libavformat/version.h to distinguish them. The version numbers they use seem to overlap. It's not obvious to me at all how to tell the difference programmatically, much less do so with a not-weird cmake rule. Any ideas?

Upvotes: 1

Views: 989

Answers (1)

Ronald S. Bultje
Ronald S. Bultje

Reputation: 11184

To specifically answer your question, use this code:

#include <stdio.h>
#include "libavutil/opt.h"
#include "libavformat/avformat.h"

int main(int argc, char *argv[]) {
    av_register_all();
    AVInputFormat *input = av_find_input_format("rtsp");
    const AVClass *klass = input->priv_class;
    const AVOption *opt = av_opt_find2(&klass, argv[1], NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL);
    printf("%p\n", opt);
    return 0;
}

This can do runtime detection, and here's how it works:

bash-3.2$ /tmp/test hi
0x0
bash-3.2$ /tmp/test stimeout
0x103420100

For your other question, detecting Libav vs. FFmpeg can be done by looking at the library micro version. For FFmpeg, they all start at 100 (e.g. libavformat 55.1.100), whereas for Libav, they start at 0. So if micro < 100, it's Libav, else it's FFmpeg. To get libavformat micro version at runtime, use avformat_version() & 0xff, or LIBAVFORMAT_VERSION_MICRO at compile time.

Upvotes: 5

Related Questions