Cap_ffmpeg_impl.hpp changes are not applied to opencv build

I am changed LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS value. However, I do not think it is being applied after I built opencv.

Is there a way to change the interrupt callback timeout for ffmpeg in windows build?

to my best knowledge, cap_ffmpeg_impl code is used for the opencv_videoio_ffmpeg.dll, which gets compiled on an external build server,
and downloaded from there via cmake.
it is not used when building the opencv libs locally

1 Like

Does this mean that there is a pre-built opencv_ffmpeg.dll somewhere (external)? and the changes to modules/videoio/src/cap_ffmpeg_impl.hpp does not matter because it is just a copy from the external source?

Yes that’s correct, the .dll is downloaded by cmake. I found the best way to change anything inside cap_ffmpeg_impl is to link against ffmpeg libraries directly but you have to modify the cmake scripts to do this.

1 Like

Thank you. This much is clear now.

Hello zadok,

Maybe you already found a solution for your problem. If it’s not the case, I share with you a tutorial I made to build the opencv_videoio_ffmpeg*.dll. It’s made to be use by anybody so don’t be mad if you found it too childish.

Tutorial to compil you own modified version of opencv_videoio_ffmpeg*.dll

Goal:
We will modify the library to change the pixel format used when writing raw video with the fourcc codec 0x00000000 which stand for BI_RGB label. There is no fourcc label to use this, you need to specify the hex code when creating the VideoWriter, example:

cv::VideoWriter outputVideo;
cv::Size S = cv::Size(800, 600);
outputVideo.open(
    "out.avi",  //output file
    0x00000000, //fourcc codec hex code [or use label VideoWriter::fourcc('I','4','2','0') = 0x30323449 in hex]
    24,         //framerate (must be greater than 6 for compatibility with most video player)
    S,          //the video size
    true        //boolean value to set if video is with color (which is the case here)
);

In the actual repository maintained by the developper of OpenCV, the 0x000000 codec use by default yuv420p pixel, which for me is a mistake (but who am I to judge).

Note: 0x000000 can be replace by 0, of course, but I prefer the hex form since it’s the one used by the fourcc web site. And if you want to change the 0x30323449? Uuhh!!! Yeah, me too.

Prerequisites:
Before the modification, you will need a few tools:

  1. A linux installation on you windows system : Ubuntu for example in the Microsoft Store.
  2. Docker desktop
    —Optional—
  3. GitHub Desktop

From Ubuntu, you need to configure git if it’s not already done with:

git config --global user.email "You@example.com"
git config --global user.name "Your Name"

Before starting to download the source code needed, you need to find the good one for your version of OpenCV. I use the 4.5.0 version released on 11th October 2020 (commit d5fd2f0). The date is important, because you need to download the good branch of opencv_3rdparty from github (at least the closer one in time).

opencv_3rdparty : GitHub - opencv/opencv_3rdparty at ffmpeg/master_20200908
opencv : GitHub - opencv/opencv at 4.5.0

For opencv_3rdparty you can download the zip archive of the branch. No need to clone the repository with git. Extract the zip archive somewhere. Inside the extracted directory (opencv_3rdparty-ffmpeg-master_20200908 or opencv_3rdparty for the remaining of this tuto), there is an empty opencv directory. We will clone opencv inside.
If you want to git clone opencv_3rdparty:

git clone https://github.com/opencv/opencv_3rdparty.git --single-branch --branch ffmpeg/master_20200908

For opencv you absolutly need to clone the repository and switch to the good branch.
So inside you opencv_3rdparty directory (not the empty opencv), do from the ubuntu command line (not the windows command line)

git clone https://github.com/opencv/opencv.git --single-branch --branch 4.5.0

this will clone to opencv_3rdparty/opencv and switch to the 4.5.0 branch

Using --single-branch can reduce the total size by two, mostly for opencv_3rdparty. Don’t try to build the dll with a different version of opencv than the targeted one, because it doesn’t work. Of course the compilation will be fine, but you will have problem when you use the dll. If you choose the wrong version of opencv_3rdparty, the compilation will probably failed.

Modification:
This part is up to you, you can modify opencv as you which but for opencv_videoio_ffmpeg*.dll, there is only three files inside opencv_3rdparty/opencv/modules/videoio/src

    cap_ffmpeg_impl.hpp
    cap_ffmpeg_legacy_api.hpp
    ffmpeg_codecs.hpp

In my case, to modify the pixel format for 0x00000000 codec, the file is cap_ffmpeg_impl.hpp. The modification is:

[line 2295]
        case CV_CODEC(CODEC_ID_RAWVIDEO):
        // RGBA is the only RGB fourcc supported by AVI and MKV format
            if(fourcc == CV_FOURCC('R','G','B','A'))
            {
                codec_pix_fmt = AV_PIX_FMT_RGBA;
            }
+           else if(fourcc == 0x00000000)
+           {
+               codec_pix_fmt = AV_PIX_FMT_BGR24;
+           }
            else
            {
                switch(input_pix_fmt)
                {
                    case AV_PIX_FMT_GRAY8:
                    case AV_PIX_FMT_GRAY16LE:
                    case AV_PIX_FMT_GRAY16BE:
                        codec_pix_fmt = input_pix_fmt;
                        break;
                    default:
                        codec_pix_fmt = AV_PIX_FMT_YUV420P;
                        break;
                }
            }
[line 2314]

The four lines added (at position 2301 of the file) start with a ‘+’. As you can see, if the fourcc is not RGBA or the input is not GRAY, the pixel format used by default is AV_PIX_FMT_YUV420P. So I added AV_PIX_FMT_BGR24 for the 0x00000000.

Building:
Aaah, the most important part. First thing to do is to commit you change to the local repository of opencv. It’s realy important, if you not commit the changes, their will not apply to the build. The easiest way is to use GitHub Desktop. Or inside the opencv_3rdparty/opencv directory from ubuntu command line:

    git commit -am "modify cap_ffmpeg_impl.hpp for pix_fmt"
  1. Start Docker Desktop if it’s not already running or you will get the following error:

The command ‘docker’ could not be found in this WSL 2 distro.
We recommend to activate the WSL integration in Docker Desktop settings.

  1. From Ubuntu, inside the opencv_3rdparty directory :
    ffmpeg/build_via_docker.sh

That’s all :slight_smile:

The resulting dll can be found in opencv_3rdparty\ffmpeg, the previous one as been replaced.

Note : during the build, you will see that git package the three .hpp files above, at this stage you can check that inside this archive opencv_3rdparty\sources\opencv\opencv-videoio-ffmpeg.tar.xz, the files are actually modified. If it’s not the case it’s because you don’t commit you changes.

When you run ffmpeg/build_via_docker.sh, if you get ‘: wrong parameter’ or something like that, it’s because you probably clone the opencv_3rdparty from the windows console. And since it’s windows, the endline is CRLF, not LF. A solution is to run dos2unix on all the file inside opencv_3rdparty directory.

During the build you can see the below warnings:

/app/opencv_ffmpeg.rc:12: digit exceeds base
/app/opencv_ffmpeg.rc:13: digit exceeds base

It’s nothing you should care about.

I hope it will help.

Hi Tykyo, I read your guide above and thought I would give it a try. Unfortunately I have never used docker before and I have hit a problem. If I use

ffmpeg/build_via_docker.sh

I get the following error

=> ERROR [internal] load metadata for docker.io/library/ubuntu:18.04                                              3.5s
------
 > [internal] load metadata for docker.io/library/ubuntu:18.04:
------
failed to solve with frontend dockerfile.v0: failed to create LLB definition: rpc error: code = Unknown desc = open /home/b/.docker/.token_seed: permission denied

and if I use

sudo ffmpeg/build_via_docker.sh

I get

Running docker container:

groupadd: GID '0' already exists
useradd: group 'appgroup' does not exist
No passwd entry for user 'appuser'

Do you know what could be causing this?

Hi cudawarped,

For the sudo command, it’s normal since the script entry.sh (ffmpeg\docker\entry.sh) try to create a group (and a user) with the id=0 (the root group is 0) because you use sudo. If you don’t use sudo your id is 1000.

For the first part, I don’t know. Can you try to run the following command from the windows command line and from the ubuntu WSL command line?

docker run --rm --tty --interactive ubuntu:18.04

If it doesn’t work, you best option is to remove docker, restart the computer and make a new install https://docs.docker.com/docker-for-windows/install/

Are you on Windows 10 or Linux? If it’s Linux, you need to set permission for your user to use docker without using sudo https://docs.docker.com/engine/install/linux-postinstall/

1 Like

Excellent that worked perfectly for me, thank you.