0

Context: I have a file called libffmpeg.so, that I took from the APK of an Android application that is using FFMPEG to encode and decode files between several Codecs. Thus, I take for grant that this is compiled with encoding options enable and that this .so file is containing all the codecs somewhere. This file is compiled for ARM (what we call ARMEABI profile on Android).

I also have a very complete class with interops to call API from ffmpeg. Whatever is the origin of this static library, all call responses are good and most endpoints exist. If not I add them or fix deprecated one.

When I want to create an ffmpeg Encoder, the returned encoder is correct.

var thisIsSuccessful = avcodec_find_encoder(myAVCodec.id);

Now, I have a problem with Codecs. The problem is that - let's say that out of curiosity - I iterate through the list of all the codecs to see which one I'm able to open with the avcodec_open call ...

        AVCodec codec;

        var res = FFmpeg.av_codec_next(&codec);
        while((res = FFmpeg.av_codec_next(res)) != null)
        {
            var name = res->longname;


            AVCodec* encoder = FFmpeg.avcodec_find_encoder(res->id);
            if (encoder != null) {
                AVCodecContext c = new AVCodecContext ();       

                /* put sample parameters */
                c.bit_rate = 64000;
                c.sample_rate = 22050;
                c.channels = 1;

                if (FFmpeg.avcodec_open (ref c, encoder) >= 0) {
                    System.Diagnostics.Debug.WriteLine ("[YES] - " + name);
                }
            } else {
                System.Diagnostics.Debug.WriteLine ("[NO ] - " + name);
            }
        }

... then only uncompressed codecs are working. (YUV, FFmpeg Video 1, etc)

My hypothesis are these one:

  • An option that was missing at the time of compiling to the .so file
  • The av_open_codec calls is acting depending on the properties of the AVCodecContext I've referenced in the call.

I'm really curious about why only a minimum set of uncompressed codecs are returned?

[EDIT]

@ronald-s-bultje answer led me to read AVCodecContext API description, and there are a lot of mendatory fileds with "MUST be set by user" when used on an encoder. Setting a value for these parameters on AVCodecContext made most of the nice codecs available:

c.time_base = new AVRational (); // Output framerate. Here, 30fps
c.time_base.num = 1;
c.time_base.den = 30;
c.me_method = 1; // Motion-estimation mode on compression -> 1 is none
c.width = 640; // Source width
c.height = 480; // Source height
c.gop_size = 30; // Used by h264. Just here for test purposes.
c.bit_rate = c.width * c.height * 4; // Randomly set to that...
c.pix_fmt = FFmpegSharp.Interop.Util.PixelFormat.PIX_FMT_YUV420P; // Source pixel format
Léon Pelletier
  • 2,701
  • 2
  • 40
  • 67
  • Maybe they omitted various codecs to get smaller binaries or to avoid licensing headaches. – Rhythmic Fistman May 25 '15 at 01:52
  • When looking at the application [screenshot](https://lh4.ggpht.com/8MsHM9MFSmMHBUyO9hCfP695scprxGYzeAOjAdzar-82IrRZxRPASPs1dJR5DS7mGg=h900-rw) on Google Play, it seems like there is at least 3GP as an OutputFormat, which is not the case when I'm listing codecs. – Léon Pelletier May 25 '15 at 01:57
  • @RhythmicFistman I'll add it as an hypothesis. I'll need to look at how the process to include/remove codecs from avcodec looks like. – Léon Pelletier May 25 '15 at 01:59

1 Answers1

1

The av_open_codec calls is acting depending on the properties of the AVCodecContext I've referenced in the call.

It's basically that. I mean, for the video encoders, you didn't even set width/height, so most encoders really can't be expected to do anything useful like this, and are right to error right out.

You can set default parameters using e.g. avcodec_get_context_defaults3(), which should help you a long way to getting some useful settings in the AVCodecContext. After that, set typical ones like width/height/pix_fmt to the ones describing your input format (if you want to do audio encoding - which is actually surprisingly unclear from your question, you'll need to set some different ones like sample_fmt/sample_rate/channels, but same idea). And then you should be relatively good to go.

Ronald S. Bultje
  • 10,828
  • 26
  • 47
  • As an expert in the area, do you know if one could use libx264 alone if the goal is just to encode YUV stuff and PCM sound to a working H264 movie contained in a .MP4 file? Sorry for the question, a short answer is accepted. :) – Léon Pelletier May 25 '15 at 02:54
  • 1
    You mean use libx264 directly instead of through ffmpeg? I think for video-only, you'll find it can do all of that, but when you want to start muxing in audio, I'd personally use ffmpeg already. You'll want to learn to use the private options API (av_opt_set_*()) to set values for options like "preset" and "x264_params"), and then it works very similar to the raw x264 API (see https://trac.ffmpeg.org/wiki/Encode/H.264). – Ronald S. Bultje May 25 '15 at 11:14
  • Last mini-question, I promise. (And this would be too specific to ask elsewhere.) I noticed that I need to write a lot of code to use ffmpeg API. Is ffmpeg.c the only code used by ffmpeg.exe for helpers and "autodetection" / presets handling? If so, I'd just use existing functions from ffmpeg.c instead of writing my encoding/decoding functions from scratch. – Léon Pelletier May 25 '15 at 15:15
  • Never mind. Exact question here: http://stackoverflow.com/questions/2401764/can-ffmpeg-be-used-as-a-library-instead-of-a-standalone-program – Léon Pelletier May 25 '15 at 15:47