1
0
intel-media-ffmpeg/README.md
James Ketrenos 7748348f3f Removed deprecated MANIFEST creation information
Signed-off-by: James Ketrenos <james.p.ketrenos@intel.com>
2019-09-24 15:32:16 -07:00

5.8 KiB

Intel Media FFMPEG Transcode Container

This project hosts a container demonstrating the use of ffmpeg using GPU offload for transcode operations.

The Dockerfile itself is constructed from templates/* and Dockerfile.solution, and provides a multi-stage Docker container with the final container being a minimal run-time installation on top of the base OS.

Usage examples

Getting the container

You can pull the container from Harbor:

docker pull amr-registry.caas.intel.com/vtt-osgc/solutions/intel-media-ffmpeg
docker tag amr-registry.caas.intel.com/vtt-osgc/solutions/intel-media-ffmpeg intel-media-ffmpeg

or build it yourself:

docker build . -t intel-media-ffmpeg

Verify hardware access

docker run \
  --rm \
  --device=/dev/dri \
  -e QSV_DEVICE=${QSV_DEVICE:-/dev/dri/renderD128} \
  -it \
  intel-media-ffmpeg \
  info

The above will provide information about the software in the container, as well as the detected Intel graphics hardware.

If you are in a multicard environment, see Appendix A.

Test hardware accelerated FFMPEG media operations

scripts/test

The above will:

  1. Download a test content file from fate-suite.libav.org into $(pwd)/media
  2. Instantiate the 'intel-media-ffmpeg' container
  3. Perfom the following tests:
    1. decode AUD_MW_E.264 to AUD_MW.yuv
    2. encode AUD_MW.yuv to AUD_MW_E.h264
    3. transcode AUD_MW_E.264 to AUD_MW_E.hevc
    4. transcode AUD_MW_E.264 to two streams at once, AUD_1N-5M.h264 and AUD_1N-4M60FPS.h264

Once completed, you can check the contents of $(pwd)/media for the following files:

AUD_MW_E.264
AUD_MW.yuv
AUD_MW_E.h264
AUD_MW_E.hevc
AUD_1N-5M.h264
AUD_1N-4M60FPS.h264

Launch a shell in the container

The examples below are all assumed to be running in the container's environment:

docker run \
  --rm \
  --device=/dev/dri \
  -e QSV_DEVICE=${QSV_DEVICE:-/dev/dri/renderD128} \
  -it \
  intel-media-ffmpeg \
  shell

Decode

AVC (H.264) video decode and save as YUV 420P raw file:

IN_FILE=AUD_WM_E.264
OUT_FILE=AUD_MW.yuv
  ffmpeg \
    -hwaccel qsv \
    -qsv_device ${QSV_DEVICE:-/dev/dri/renderD128} \
    -c:v h264_qsv \
    -i /media/"${IN_FILE}" \
    -vf hwdownload,format=nv12 -pix_fmt yuv420p \
    -y \
    /media/"${OUT_FILE}"

Encode

Encode a 10 frames of 720p raw input as H264 with 5Mbps using VBR mode:

IN_FILE=AUD_MW.yuv
OUT_FILE=AUD_MW_E.h264
  ffmpeg \
    -loglevel debug \
    -init_hw_device vaapi=va:${QSV_DEVICE:-/dev/dri/renderD128} \
    -init_hw_device qsv=hw@va \
    -filter_hw_device hw \
    -f rawvideo \
    -pix_fmt yuv420p \
    -s:v 176x144 \
    -i /media/"${IN_FILE}" \
    -vf hwupload=extra_hw_frames=64,format=qsv \
    -c:v h264_qsv \
    -b:v 5M \
    -frames:v 10 \
    -y \
    /media/"${OUT_FILE}"

Transcode

AVC (H.264) => HEVC (H.265) with 5Mbps using VBR

IN_FILE=AUD_MW_E.264
OUT_FILE=AUD_MW_E.hevc
  ffmpeg \
    -loglevel debug \
    -hwaccel qsv \
    -qsv_device ${QSV_DEVICE:-/dev/dri/renderD128} \
    -c:v h264_qsv \
    -i /media/"${IN_FILE}" \
    -c:v hevc_qsv \
    -b:v 5M \
    -y \
    /media/"${OUT_FILE}"

1:N transcoding

IN_FILE=AUD_MW_E.264
OUT_FILE=AUD_1N_
  ffmpeg \
    -hwaccel qsv \
    -qsv_device ${QSV_DEVICE} \
    -c:v h264_qsv \
    -i /media/"${IN_FILE}" \
    -filter_complex "split=2[s1][s2]; \
                     [s1]scale_qsv=1280:720[o1]; \
                     [s2]vpp_qsv=framerate=60[o2]" \
    -map [o1] -c:v h264_qsv -b:v 5M /media/"${OUT_FILE}-5M.mp4" \
    -map [o2] -c:v h264_qsv -b:v 4M /media/"${OUT_FILE}-4M60FPS.h264"

Developing

The Dockerfile itself is constructed from re-usable snippets, located in the templates/ directory, and can be regenerated by running:

scripts/build-dockerfile

The above script uses environment substitution to stamp version information within the created Dockerfile. The files which declare the environment variables are in SOLUTION and MANIFEST.

After joining the template/* pieces together, the file Dockerfile.solution is then added to the Dockerfile with environment substitution.

SOLUTION

Solution specific definitions:

CONTAINER_IMAGE is used as the container tag name
OS_DISTRO       is used as the base OS distribution. Possible values: ubuntu
OS_RELEASE      is used as the OS version. Possible values: disco, eoan

MANIFEST

The version of MANIFEST is created by the set of Agama packages from the Agama repository and name-mangling them to be a VERSION declaration:

For example:

libgl1-mesa-glx_19.0.1-agama-109_amd64.deb

is changed to:

LIBGL1_MESA_GLX_VERSION=19.0.1-agama-109

This allows the Dockerfile templates version pin Agama packages:

  RUN apt-get install -y libgl1-mesa-glx=$LIBGL1_MESA_GLX_VERSION

The scripts/build-dockerfile loads MANIFEST, which defines LIBGL1_MESA_GLX_VERSION. That is then subsituted for the version in the above Dockerfile snippet when being placed into the main Dockerfile.

Tagging

If the build succeeds, we want to be able to tag the git project as well as corresponding Docker images with the appropriate Agama tag:

. MANIFEST ; git tag -f agama-${AGAMA_VERSION}

Appendix A: Multicard

Most of the filters and drivers for ffmpeg will default to connecting to /dev/dri/renderD128.

If you have multiple cards, the card you want to connect to might be exposed on a different render interface.

You can configure which interface is used by setting the QSV_DEVICE environment variable prior to running intel-docker (or by passing -e QSV_DEVICE to docker if you run it manually.)

You can find out the correct path for your Intel Graphics card by running:

ls -l /dev/dri/by-path/pci-*$(lspci | grep Intel.*Graphics | cut -d " " -f1)*

If the interface is on /dev/dri/renderD129, set QSV_DEVICE as follows:

export QSV_DEVICE=/dev/dri/renderD129