Skip to content
This repository has been archived by the owner on Jun 10, 2024. It is now read-only.

VPF Tegra support (HW enc acceleration missing) #515

Closed
wants to merge 0 commits into from

Conversation

RomanArzumanyan
Copy link
Contributor

@RomanArzumanyan RomanArzumanyan commented Aug 10, 2023

Hello world,

This PR adds MVP Tegra support for VPF.

What's new:

  • PyNvDecoder and PyNvEncoder classes aren't compiled and exported to PyNvCodec module for Tegra. It happens because Tegra doesn't support Video Codec SDK and relies on V4L2 instead.
  • HW decoding acceleration is supported through PyFfmpegDecoder class.

How to build:
I did it on Tegra board itself, it takes couple minutes

  • Use FFmpeg build for Tegra supplied by NVIDIA: apt install ffmpeg. It has some limitations like the lack of MP4 containers support. Please be aware of that.
  • Export TEGRA_BUILD env. variable: export TEGRA_BUILD. It's required because to my best knowledge there's no reliable way to auto-detect Tegra platform. Please correct me if I'm wrong, I'll be happy to get rid of this extra step.
  • Run usual installation script: python3 -m pip install .

How to run:

To use HW decoding acceleration, use PyFfmpegDecoder and choose appropriate codec:

# VP9 file for example.For H.264 it will be h264_nvv4l2dec corresp.
nvDec = nvc.PyFfmpegDecoder("/path/to/video/i/have/used/vp9.webm, {"c:v": "vp9_nvv4l2dec"})

That's the only difference, rest is the same.
There's more feature-reach Tegra FFmpeg build with decoding and encoding support: https://github.com/jocover/jetson-ffmpeg
But for some reason my build segfaults on Xavier NX board I've used for development.

Future directions:
Feature parity with Video Codec SDK builds.
Fix https://github.com/jocover/jetson-ffmpeg segfaults, then add HW acceleration for encoding.

P. S.
For those who like to build FFmpeg from source, here's how you can substitute apt install ffmpeg step:

# This will download NVIDIA FFmpeg build package sources.
apt source ffmpeg
cd ffmpeg-4.2.7  
mkdir -p build_release_shared

./configure \
  --prefix=$(pwd)/build_release_shared \
  --enable-nvv4l2dec \
  --enable-libv4l2 \
  --disable-doc \
  --disable-static \
  --enable-shared \
  --enable-pic \
  --extra-cflags="-I/usr/src/jetson_multimedia_api/include" \
  --extra-libs="-L/usr/lib/aarch64-linux-gnu/tegra -lnvbuf_utils -lv4l2"

make -j6 -s && make install

cd  ./build_release_shared
export LD_LIBRARY_PATH=$(pwd)/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$(pwd)/lib/pkgconfig 

Copy link
Collaborator

@gedoensmax gedoensmax left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave it a quick review @rarzumanyan if you think this does not brake anything etc I am fine merging this. As I have no HW to test this and we are not committed to this I'll make it your decision to have this in master or not.

Comment on lines 50 to 60
src/PyBufferUploader.cpp
src/PyCudaBufferDownloader.cpp
src/PyFFMpegDecoder.cpp
src/PyFFMpegDemuxer.cpp
src/PyFrameUploader.cpp
src/PyNvCodec.cpp
src/PySurface.cpp
src/PySurfaceConverter.cpp
src/PySurfaceDownloader.cpp
src/PySurfaceRemaper.cpp
src/PySurfaceResizer.cpp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be nicer using a CMake variable outside the if as you would have to change 2 locations in the future otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're probably right, it can be substituted with list(APPEND ...)
Could you please do it when merging PR?

Comment on lines 199 to 224
bool SaveGRAY12LE(AVFrame* pframe) {
size_t size = frame->width * frame->height * 2;

if (!dec_frame) {
dec_frame = Buffer::MakeOwnMem(size);
} else if (size != dec_frame->GetRawMemSize()) {
delete dec_frame;
dec_frame = Buffer::MakeOwnMem(size);
}

auto plane = 0U;
auto* dst = dec_frame->GetDataAs<uint8_t>();

auto* src = frame->data[plane];
auto width = frame->width;
auto height = frame->height;

for (int i = 0; i < height; i++) {
memcpy(dst, src, 2*width);
dst += 2*width;
src += frame->linesize[plane];
}

return true;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for removing this ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That probably happened because I created PR, then #502 was merged, and only then I submitted #515
So the answer is no, this is unintentional.

src/TC/src/FfmpegDecoder.cpp Outdated Show resolved Hide resolved
@RomanArzumanyan
Copy link
Contributor Author

RomanArzumanyan commented Aug 15, 2023

As I have no HW to test this and we are not committed to this I'll make it your decision to have this in master or not.

I totally understand, NP.
This was a popular request some time ago (Tegra support) so I hope it will be useful for community.
I'm planning to use it on Tegra in production so at least for the time being it will be tested and supported.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants