First of all, thanks for taking the time to discuss this. It has been too long, and the arguments need to be sharpened.
James Almer (2018-03-25): > Considering most are pretty small but not small enough to be dumped into > a header, no, I'm not joking. > Maybe avpriv_dnxhd_get_frame_size() should stay as is since it requires > a huge table and duplicating it would be a waste of space, but > avpriv_dca_convert_bitstream() seems simple enough that i don't see the > benefits from having it like this, when it could be in both avcodec and > avformat and weight maybe 1kb on each of them. The weight in code size is far from being the most important criterion. The case against code duplication is maintenance: when a bug is found, it requires fixing in all copies of the code. You can be sure it will not happen: only the copy where the bug was diagnosed will be fixed. The same goes for optimizations, evolutions, etc. This in turn causes another nightmare, when results are expected to be identical but are not because they come from two copies of the same code that evolved differently. > If they used distro packages then they wouldn't have any power over what > gets built or shipped. Distro packages are the "Enable everything" kind > of build, so I'm of course talking about projects shipping their own > builds of the libraries. I have nothing to add to that. But you only answered half the question. The other half was: do they use static or dynamic linking? I am not sure how familiar you are with the precise workings of both solutions, so let me summarize a bit. With static linking, libraries are just archives or object files (*.o), with an index of symbols. The linker will examine each archive in turn and select the object files that contains required symbols. With dynamic linking, the linker takes notes of all the libraries, checks that all symbols are resolved and registers as dependencies of the executable file. What is remarkable about static linking is that it only takes the object files that are necessary, nothing more. It does not matter whether there are one library, eight or two thousands (one for each object file in the project), the linker will take what it needs in all of that. Therefore, these project who insist on small libraries could achieve their goal with the simplest possible solution: they should be using static linking. It would work automatically, because linkers have been designed that way. It is possible that for some reason, they need a shared library. In that case, the best solution is to make their own: put all the functions that use lav* together somewhere (most projects will abstract the lav* APIs to suit their own design choices anyway), and link that statically with FFmpeg, making a shared library perfectly tailored to the needs of the project. And if you think about it, you will realize that what I propose has the consequence of making that simpler for them. > Steam, Foobar2000, Firefox, Chromium, only four examples of projects > where the av*.dll files they ship have long configure lines where they > manually disable all kinds of things beyond the standard > "--disable-everything --enable-decoder=foo" use case, including entire > libraries and frameworks, because they only need a handful of software > decoders. This is true, but misleading. First of all, I would like to emphasize that the framework code is very small compared to the code of the components. But most importantly, the granularity of the modules is not the correct one. Consider an application that needs to decode from a few files. It requires the lavc decoder framework and a few decoders, and the lavf demuxing framework and a few demuxers. All encoders and all muxers are disabled. Yet, it will include the encoding framework and the muxing framework. Now, you may say that it calls for more modularity, like you advocate below, and you would be right. But this is missing something, see below. > And Chromium as I said even goes the extra mile by manually striping > libavutil of virtually everything except the core modules, something our > build system currently doesn't support. And with my full proposal, our build system should actually support it. > Building a single monolithic library will force the presence of a lot of > public symbols that currently can be avoided by simply building ffmpeg > for one decoder and effectively require just avcodec and avutil. > The direction we should head towards is making the libraries even more > modular and independent, starting with libavutil. You are entirely right here, but it is actually not really related to the number of libraries. Modularity has a cost: tracking the dependencies between components. If you implement modularity with many libraries, you push that complexity into the build system. This is a waste, since the linker already has all the algorithms to track dependencies. As I have explained above, static linking already achieves maximum modularity automatically, and irregardless of whether there is one library or many. To achieve maximum modularity with dynamic linking, we should just try to imitate what happens with static linking. And this is easier with a single shared library, since we can rely on the linker to track the dependencies. For comparison, imagine what would be required with separate libraries. Frequently, you will find functions that are required by both a demuxer and a decoder. The function cannot be in lavc, since you may want to enable only the demuxer; for the same reason the function cannot be in lavf. But it cannot be in lavu either, because it would make it unconditional. With that logic, you would need a separate library for each individual avpriv function. It amounts to reinventing the job of the linker, and as always when reinventing the wheel, it would be square. > Not the core framework and public API for each library. Those are > unconditional and would remain so in a monolithic library, but with the > added drawback that instead of only needing those from avcodec/avutil in > a single decoder build, you'd be forced to also compile and ship those > from avfilter/swscale/swresample/avdevice. Whether we choose a single library or many, we can consider proposing build options to disable even public parts of the API. We just need to make sure to give a different SONAME to the library in that case. In short, my proposal would be a single libffmpeg with the following options: - For people who do not care about size, a default enable-everything library is perfect. - For people who care about size, static linking will achieve the optimum automatically. - For people who care about size and for some reason need dynamic linking, allow disabling large parts of the libraries, which would be named libffmpeg-custom.so maybe, or libffmpeg-custom-$sign.so, where $sign is a signature (hash) of the components that are enabled. This would achieve maximum modularity with minimum efforts. Regards, -- Nicolas George
signature.asc
Description: Digital signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel