mad_ady wrote:Regular users on the forum might already know that memeka has managed to use the hardware video encoder on the XU4 by using a mainline kernel (4.8.x) . Here are the steps on how you can achieve the same thing:
Before you begin - this is a tutorial designed for medium/advanced users and if things go wrong you might have an unbootable system. It might be wise to make a backup before beginning:
http://forum.odroid.com/viewtopic.php?t=22930 (shameless plug)
1. Install a mainline kernel that supports the MFC encoder. The instructions here use @elatllat's branch (
https://github.com/Dmole/linux.git), but also mdrjr is working on a branch of his own (
https://github.com/mdrjr/linux) and so is memeka (
https://github.com/mihailescu2m/linux/c ... dxu3-4.9.y). You can use my kernel config (which tries to add all of HardKernel's modules), but you can modify it to fit your needs
http://pastebin.com/7YnakKmP, or you can use whatever defconfig comes with the kernel you chose.
*** NOTE: the kernel does not support HMP (big.LITTLE extensions) and treats all cores as equal. This is because HMP patches are unstable and can lock up the system. Consequently, overall system performance will be lower than when using Kernel 3.10 ***
*** NOTE2: Also, for XU4 sound over HDMI will no longer work with this kernel! ***
I have added the kernel compilation procedure here for convenience, but you should read/discuss the official kernel compilation thread here:
http://forum.odroid.com/viewtopic.php?f=95&t=23163 or this guide:
https://github.com/umiddelb/armhf/wiki/ ... ARM-device
a) Make a copy of your existing kernel, initrd, dtb and boot.ini:
Code: Select all
$ cd /media/boot
$ sudo -i
# cp zImage zImage-3
# cp uInitrd uInitrd-3
# cp exynos5422-odroidxu3.dtb exynos5422-odroidxu3-3.dtb
# cp boot.ini boot3.ini
Edit boot3.ini to point to the newly copied files by appending -3 to the name of the zImage, uInitrd and dtb. By replacing the stock boot.ini with this modified boot.ini you will be able to boot your old kernel in case of problems.
b) Download the new kernel
Code: Select all
$ sudo apt-get -y install bc curl gcc git libncurses5-dev lzop make u-boot-tools dos2unix
$ git clone --depth 1 -b odroidxu4-mihailescu2m-4.9 https://github.com/Dmole/linux.git linux
$ cd linux/
$ make odroidxu4_defconfig
Optionally get my config which supports most of the USB peripherals (TV tuners, sound cards, wifi cards) and a lot of networking modules (LXC support, VLANs, iptables).
Code: Select all
$ wget http://pastebin.com/raw/7YnakKmP -O .config
$ dos2unix .config
c) Next compile the kernel
Code: Select all
$ make menuconfig
$ make -j 8 zImage dtbs modules
$ kver=`make kernelrelease`
$ sudo cp arch/arm/boot/zImage arch/arm/boot/dts/exynos5422-odroidxu[34].dtb /media/boot
$ sudo cp .config /media/boot/config
$ sudo make INSTALL_MOD_STRIP=1 modules_install
$ sudo make firmware_install
$ sudo cp .config /boot/config-${kver}
$ cd /boot
$ sudo update-initramfs -c -k ${kver}
$ sudo mkimage -A arm -O linux -T ramdisk -a 0x0 -e 0x0 -n initrd.img-${kver} -d initrd.img-${kver} uInitrd-${kver}
$ sudo cp uInitrd-${kver} /media/boot/uInitrd
Next modify /media/boot/boot.ini and load exynos5422-odroidxu4.dtb instead of exynos5422-odroidxu3.dtb and save boot.ini.
d) Shut down and unplug HDMI and power. Without this step when you boot with the new kernel you will not have USB3 bus and onboard networking! This is needed only when switching between 3.x and 4.x kernels as far as I've seen.
Optionally - if you intend to run with a custom kernel from now on it's best to mark linux-image-xu3, linux-headers-xu3 and bootini as manual so that they won't be overwritten on subsequent package updates:
Code: Select all
sudo apt-mark hold linux-image-xu3 linux-headers-xu3 bootini
Using FFMPEG
2. Now that the kernel is ready, compile/install a custom ffmpeg which supports the hardware encoder
a) Compile your own ffmpeg
Code: Select all
#debian build tools
$ sudo apt-get install build-essential fakeroot devscripts libchromaprint-dev librubberband-dev libjs-bootstrap
#get the patched ffmpeg version
$ git clone -b v4l2_m2m-3.0.2 --depth=1 https://github.com/mihailescu2m/FFmpeg.git
# install ffmpeg's build dependencies (~190 packages)
$ sudo apt-get build-dep ffmpeg
#build ffmpeg as deb packages with no checks (some checks fail)
$ cd FFmpeg/
$ DEB_BUILD_OPTIONS="nocheck" debuild -b -uc -us
When building is done you should have 23 deb packages one level up (in the same directory as FFmpeg). You can download these packages pre-compiled from here:
http://www.mediafire.com/?l39zeyy4r172m
b) Install the packages:
This should replace any system-installed ffmpeg build with this ffmpeg which supports the hardware encoder.
If you plan on keeping using these packages you should mark them as manual so that they are not overwritten by future system updates:
Code: Select all
sudo apt-mark hold ffmpeg-doc ffmpeg libav-tools libavcodec-dev libavcodec-extra57 libavcodec-extra libavcodec57 libavdevice-dev libavdevice57 libavfilter-dev libavfilter6 libavformat-dev libavformat57 libavresample-dev libavresample3 libavutil-dev libavutil55 libpostproc-dev libpostproc54 libswresample-dev libswresample2 libswscale-dev libswscale4
3. Use the hardware encoder when transcoding (examples):
Note, depending on what you want to transform with ffmpeg you might get better or worse framerate. For example, changing the output fps of a video cuts off about 20-30fps from encoding time. The examples below do not change the fps.
Code: Select all
# encode video only, about 50fps (max)
$ ffmpeg -i big_buck_bunny_720p_h264.mov -acodec aac -vcodec h264 -b:v 2M -pix_fmt nv21 bbb.mp4
# encode video only, about 110fps (max)
$ ffmpeg -i big_buck_bunny_720p_h264.mov -codec:v copy -codec:a none -bsf:v h264_mp4toannexb -f rawvideo - | ffmpeg -r 24 -i - -an -vcodec h264 -b:v 2M -profile:v 10 -pix_fmt nv21 bbb.mp4
#encode video and audio, about 75fps (max)
$ ffmpeg -i big_buck_bunny_720p_h264.mov -codec:v copy -codec:a none -bsf:v h264_mp4toannexb -f rawvideo - | ffmpeg -r 24 -i - -i big_buck_bunny_720p_h264.mov -map 0:v:0 -vcodec h264 -b:v 2M -profile:v 10 -pix_fmt nv21 -map 1:a:0 -c:a:1 aac bbb.mp4
The encoder automatically selects h264_v4l2m2m which does the hardware encoding:
Code: Select all
Stream #0:0 -> #0:0 (h264 (native) -> h264 (h264_v4l2m2m))
Stream #0:1 -> #0:1 (ac3 (native) -> aac (native))
If you get the error:
Code: Select all
[h264_v4l2m2m @ 0xf3fa0] H264 codec detected, init annexb converter
[h264_v4l2m2m @ 0xf3fa0] Device path not set, probing /dev/video*
[h264_v4l2m2m @ 0xf3fa0] exynos-gsc.1:m2m is not the one we want
[h264_v4l2m2m @ 0xf3fa0] exynos-gsc.0:m2m is not the one we want
[h264_v4l2m2m @ 0xf3fa0] s5p-mfc-dec is not the one we want
[h264_v4l2m2m @ 0xf3fa0] Could not find a valid device
Make sure the user you are running ffmpeg with is part of the video group:
Code: Select all
odroid@odroid:~$ id
uid=1000(odroid) gid=1000(odroid) groups=1000(odroid),4(adm),20(dialout),24(cdrom),27(sudo),30(dip),44(video),46(plugdev),115(lpadmin),116(lightdm)
Sample output:
Code: Select all
adrianp@odroid:~> ffmpeg -i Sintel.2010.720p.mkv -acodec aac -vcodec h264 -b:v 2M -pix_fmt nv21 sintel-encoded.mp4
ffmpeg version 3.0.2-1ubuntu4 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 5.4.0 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.2) 20160609
configuration: --prefix=/usr --extra-version=1ubuntu4 --toolchain=hardened --libdir=/usr/lib/arm-linux-gnueabihf --incdir=/usr/include/arm-linux-gnueabihf --cc=cc --cxx=g++ --enable-gpl --enable-shared --d
isable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --
enable-libopus --enable-libpulse --enable-librubberband --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --
enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc139
4 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-chromaprint --enable-libx264
WARNING: library configuration mismatch
avcodec configuration: --prefix=/usr --extra-version=1ubuntu4 --toolchain=hardened --libdir=/usr/lib/arm-linux-gnueabihf --incdir=/usr/include/arm-linux-gnueabihf --cc=cc --cxx=g++ --enable-gpl --enabl
e-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-
libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-li
bopenjpeg --enable-libopus --enable-libpulse --enable-librubberband --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-
libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --ena
ble-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-chromaprint --enable-libx264 --enable-version3 --disable-doc --disable-programs --disable-avdevice --disable-avfilter --disable-avf
ormat --disable-avresample --disable-postproc --disable-swscale --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libvo_amrwbenc
libavutil 55. 17.103 / 55. 17.103
libavcodec 57. 24.102 / 57. 24.102
libavformat 57. 25.100 / 57. 25.100
libavdevice 57. 0.101 / 57. 0.101
libavfilter 6. 31.100 / 6. 31.100
libavresample 3. 0. 0 / 3. 0. 0
libswscale 4. 0.100 / 4. 0.100
libswresample 2. 0.101 / 2. 0.101
libpostproc 54. 0.100 / 54. 0.100
Input #0, matroska,webm, from 'Sintel.2010.720p.mkv':
Metadata:
encoder : libebml v1.0.0 + libmatroska v1.0.0
creation_time : 2011-04-24 17:20:33
Duration: 00:14:48.03, start: 0.000000, bitrate: 6071 kb/s
Chapter #0:0: start 0.000000, end 103.125000
Metadata:
title : Chapter 01
Chapter #0:1: start 103.125000, end 148.667000
Metadata:
title : Chapter 02
Chapter #0:2: start 148.667000, end 349.792000
Metadata:
title : Chapter 03
Chapter #0:3: start 349.792000, end 437.208000
Metadata:
title : Chapter 04
Chapter #0:4: start 437.208000, end 472.075000
Metadata:
title : Chapter 05
Chapter #0:5: start 472.075000, end 678.833000
Metadata:
title : Chapter 06
Chapter #0:6: start 678.833000, end 744.083000
Metadata:
title : Chapter 07
Chapter #0:7: start 744.083000, end 888.032000
Metadata:
title : Chapter 08
Stream #0:0(eng): Video: h264 (High), yuv420p(tv, bt709/unknown/unknown), 1280x544, SAR 1:1 DAR 40:17, 24 fps, 24 tbr, 1k tbn, 48 tbc
Stream #0:1(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 640 kb/s
Metadata:
title : AC3 5.1 @ 640 Kbps
Stream #0:2(ger): Subtitle: subrip
Stream #0:3(eng): Subtitle: subrip
Stream #0:4(spa): Subtitle: subrip
Stream #0:5(fre): Subtitle: subrip
Stream #0:6(ita): Subtitle: subrip
Stream #0:7(dut): Subtitle: subrip
Stream #0:8(pol): Subtitle: subrip
Stream #0:9(por): Subtitle: subrip
Stream #0:10(rus): Subtitle: subrip
Stream #0:11(vie): Subtitle: subrip
Codec AVOption preset (Configuration preset) specified for output file #0 (sintel-encoded.mp4) has not been used for any stream. The most likely reason is either wrong type (e.g. a video option with no video
streams) or that it is a private option of some encoder which was not actually used for any stream.
File 'sintel-encoded.mp4' already exists. Overwrite ? [y/N] y
[h264_v4l2m2m @ 0xf3fe0] H264 codec detected, init annexb converter
[h264_v4l2m2m @ 0xf3fe0] Device path not set, probing /dev/video*
[h264_v4l2m2m @ 0xf3fe0] exynos-gsc.1:m2m is not the one we want
[h264_v4l2m2m @ 0xf3fe0] exynos-gsc.0:m2m is not the one we want
[h264_v4l2m2m @ 0xf3fe0] Using device /dev/video1
Output #0, mp4, to 'sintel-encoded.mp4':
Metadata:
encoder : Lavf57.25.100
Chapter #0:0: start 0.000000, end 103.125000
Metadata:
title : Chapter 01
Chapter #0:1: start 103.125000, end 148.667000
Metadata:
title : Chapter 02
Chapter #0:2: start 148.667000, end 349.792000
Metadata:
title : Chapter 03
Chapter #0:3: start 349.792000, end 437.208000
Metadata:
title : Chapter 04
Chapter #0:4: start 437.208000, end 472.075000
Metadata:
title : Chapter 05
Chapter #0:5: start 472.075000, end 678.833000
Metadata:
title : Chapter 06
Chapter #0:6: start 678.833000, end 744.083000
Metadata:
title : Chapter 07
Chapter #0:7: start 744.083000, end 888.032000
Metadata:
title : Chapter 08
Stream #0:0(eng): Video: h264 (h264_v4l2m2m) ([33][0][0][0] / 0x0021), yuv420p, 1280x544 [SAR 1:1 DAR 40:17], q=2-31, 2000 kb/s, 24 fps, 12288 tbn, 24 tbc
Metadata:
encoder : Lavc57.24.102 h264_v4l2m2m
Stream #0:1(eng): Audio: aac (LC) ([64][0][0][0] / 0x0040), 48000 Hz, 5.1(side), fltp, 341 kb/s
Metadata:
title : AC3 5.1 @ 640 Kbps
encoder : Lavc57.24.102 aac
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (h264_v4l2m2m))
Stream #0:1 -> #0:1 (ac3 (native) -> aac (native))
Press [q] to stop, [?] for help
[h264_v4l2m2m @ 0xf3fe0] Performing useless memcpy() on output pool because buffers do not match
[h264_v4l2m2m @ 0xf3fe0] This could be avoided by using av_v4l_buffer_pool_get_buffer*() or av_v4l_buffer_pool_make_pipe()
[mp4 @ 0xb9c70] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
[mp4 @ 0xb9c70] Encoder did not produce proper pts, making some up.
[h264_v4l2m2m @ 0xf3fe0] No event occurred while waiting.01 bitrate=36881.3kbits/s speed=1.84x
frame= 2027 fps= 44 q=-0.0 Lsize= 383559kB time=00:01:25.20 bitrate=36877.0kbits/s speed=1.84x
video:379964kB audio:3551kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.011593%
Known issues:
* All known issues have been solved. Yay!
Using gstreamer
2. Compile gstreamer from memeka's branch
Code: Select all
$ apt-get install gstreamer1.0-plugins-bad
$ git clone https://github.com/mihailescu2m/gst-plugins-good
$ cd gst-plugins-good/
$ sudo apt-get install libgstreamer1.0-dev libgudev-1.0-dev libgstreamer-plugins-base1.0-dev dh-autoreconf automake autoconf libtool autopoint cdbs gtk-doc-tools libshout3-dev libaa1-dev libflac-dev libdv4-dev libdv-dev libgtk-3-dev libtag1-dev libsoup2.4-dev gstreamer1.0-doc gstreamer1.0-plugins-base-doc
$ dpkg-buildpackage -us -uc -b -j4
$ cd ../
$ sudo dpkg -i gstreamer*.deb
Alternatively you can get the pre-built deb packages from here:
https://www.mediafire.com/folder/5lz2po ... -odroidxu4
If you intend to keep these packages installed, mark them as manual so that they are not updated by apt:
Code: Select all
sudo apt-mark hold gstreamer1.0-plugins-good-dbg gstreamer1.0-plugins-good-doc gstreamer1.0-plugins-good gstreamer1.0-pulseaudio libgstreamer-plugins-good1.0-0 libgstreamer-plugins-good1.0-dev
To transcode something here's what you can try:
Identify which is the encoding and the decoding interfaces (they change after boot)
Code: Select all
$ decoder=`gst-inspect-1.0 | grep v4l2 | grep videodec | cut -d ":" -f 2`
$ encoder=`gst-inspect-1.0 | grep v4l2 | grep h264enc | cut -d ":" -f 2`
$ gst-launch-1.0 filesrc location=big_buck_bunny_720p_h264.mov ! qtdemux ! h264parse ! $decoder ! $encoder extra-controls="encode,h264_level=10,h264_profile=4,frame_level_rate_control_enable=1,video_bitrate=2097152" ! h264parse ! matroskamux ! filesink location=bbb.mkv