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

249 lines
5.8 KiB
Markdown

# 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:
```bash
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:
```bash
docker build . -t intel-media-ffmpeg
```
## Verify hardware access
```bash
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
```bash
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:
```bash
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:
```bash
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:
```bash
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
```bash
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
```bash
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:
```bash
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:
```Dockerfile
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:
```bash
. 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
```