Merge pull request #27453 from MELSunny:4.x

Add Raspberry Pi 4 and 5 V4L2 Stateless HEVC Hardware Acceleration with FFmpeg #27453

This PR enables V4L2 stateless HEVC hardware acceleration for Raspberry Pi 5 within OpenCV's videoio module. It leverages FFmpeg's drm acceleration ([FFmpeg API changes](ee1f79b0fa/doc/APIchanges (L1529))), significantly improving HEVC decoding performance on RPi5 for robotics and embedded vision applications.

I have a working proof-of-concept with local benchmarks showing clear gains.

Checklist Status:

Ready: License, branch (4.x), FFmpeg reference, and (linked) related issue (#27452).
Seeking Guidance: Need help with formal C++ performance/accuracy tests, opencv_extra integration, and full documentation/examples.
As a Python developer, I welcome C++ best practice feedback and assistance with testing setup.

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Yan Wen 2025-07-18 09:19:58 +01:00 committed by GitHub
parent 4813d1cd32
commit f54286b672
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 25 additions and 0 deletions

View File

@ -268,6 +268,7 @@ enum VideoAccelerationType
VIDEO_ACCELERATION_D3D11 = 2, //!< DirectX 11 VIDEO_ACCELERATION_D3D11 = 2, //!< DirectX 11
VIDEO_ACCELERATION_VAAPI = 3, //!< VAAPI VIDEO_ACCELERATION_VAAPI = 3, //!< VAAPI
VIDEO_ACCELERATION_MFX = 4, //!< libmfx (Intel MediaSDK/oneVPL) VIDEO_ACCELERATION_MFX = 4, //!< libmfx (Intel MediaSDK/oneVPL)
VIDEO_ACCELERATION_DRM = 5, //!< Raspberry Pi V4
}; };
//! @} Hardware acceleration support //! @} Hardware acceleration support

View File

@ -57,6 +57,9 @@ extern "C" {
#ifdef HAVE_MFX // dependency only on MFX header files, no linkage dependency #ifdef HAVE_MFX // dependency only on MFX header files, no linkage dependency
#include <libavutil/hwcontext_qsv.h> #include <libavutil/hwcontext_qsv.h>
#endif #endif
#ifdef HAVE_DRM
#include <libavutil/hwcontext_drm.h>
#endif
} }
#define HW_DEFAULT_POOL_SIZE 32 #define HW_DEFAULT_POOL_SIZE 32
@ -81,6 +84,7 @@ const char* getVideoAccelerationName(VideoAccelerationType va_type)
case VIDEO_ACCELERATION_D3D11: return "d3d11"; case VIDEO_ACCELERATION_D3D11: return "d3d11";
case VIDEO_ACCELERATION_VAAPI: return "vaapi"; case VIDEO_ACCELERATION_VAAPI: return "vaapi";
case VIDEO_ACCELERATION_MFX: return "mfx"; case VIDEO_ACCELERATION_MFX: return "mfx";
case VIDEO_ACCELERATION_DRM : return "drm";
} }
return "unknown"; return "unknown";
} }
@ -119,6 +123,7 @@ std::string getDecoderConfiguration(VideoAccelerationType va_type, AVDictionary
case VIDEO_ACCELERATION_D3D11: return ""; case VIDEO_ACCELERATION_D3D11: return "";
case VIDEO_ACCELERATION_VAAPI: return "vaapi.iHD"; case VIDEO_ACCELERATION_VAAPI: return "vaapi.iHD";
case VIDEO_ACCELERATION_MFX: return "qsv.iHD"; case VIDEO_ACCELERATION_MFX: return "qsv.iHD";
case VIDEO_ACCELERATION_DRM: return "drm";
} }
return ""; return "";
#endif #endif
@ -158,6 +163,8 @@ std::string getEncoderConfiguration(VideoAccelerationType va_type, AVDictionary
case VIDEO_ACCELERATION_D3D11: return ""; case VIDEO_ACCELERATION_D3D11: return "";
case VIDEO_ACCELERATION_VAAPI: return "vaapi.iHD"; case VIDEO_ACCELERATION_VAAPI: return "vaapi.iHD";
case VIDEO_ACCELERATION_MFX: return "qsv.iHD"; case VIDEO_ACCELERATION_MFX: return "qsv.iHD";
case VIDEO_ACCELERATION_DRM: return "";
// Raspberry Pi 5 has no encoders, so we don't support it
} }
return "unknown"; return "unknown";
#endif #endif
@ -236,6 +243,18 @@ bool hw_check_device(AVBufferRef* ctx, AVHWDeviceType hw_type, const std::string
dxgiDevice->Release(); dxgiDevice->Release();
} }
} }
#endif
#if defined(HAVE_DRM)
if (hw_device_ctx->type == AV_HWDEVICE_TYPE_DRM) {
AVDRMDeviceContext *drm_ctx = (AVDRMDeviceContext *)hw_device_ctx->hwctx;
if (drm_ctx->fd >= 0) {
drmVersionPtr drm_version = drmGetVersion(drm_ctx->fd);
if (drm_version) {
device_name = drm_version->name;
drmFreeVersion(drm_version);
}
}
}
#endif #endif
if (hw_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) { if (hw_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) {
#if defined(HAVE_VA) && (VA_MAJOR_VERSION >= 1) #if defined(HAVE_VA) && (VA_MAJOR_VERSION >= 1)
@ -908,6 +927,7 @@ VideoAccelerationType hw_type_to_va_type(AVHWDeviceType hw_type) {
{ AV_HWDEVICE_TYPE_VAAPI, VIDEO_ACCELERATION_VAAPI }, { AV_HWDEVICE_TYPE_VAAPI, VIDEO_ACCELERATION_VAAPI },
{ AV_HWDEVICE_TYPE_QSV, VIDEO_ACCELERATION_MFX }, { AV_HWDEVICE_TYPE_QSV, VIDEO_ACCELERATION_MFX },
{ AV_HWDEVICE_TYPE_CUDA, (VideoAccelerationType)(1 << 11) }, { AV_HWDEVICE_TYPE_CUDA, (VideoAccelerationType)(1 << 11) },
{ AV_HWDEVICE_TYPE_DRM, VIDEO_ACCELERATION_DRM }
}; };
for (const HWTypeFFMPEG& hw : known_hw_types) { for (const HWTypeFFMPEG& hw : known_hw_types) {
if (hw_type == hw.hw_type) if (hw_type == hw.hw_type)

View File

@ -417,6 +417,7 @@ std::ostream& operator<<(std::ostream& out, const VideoAccelerationType& va_type
case VIDEO_ACCELERATION_D3D11: out << "D3D11"; return out; case VIDEO_ACCELERATION_D3D11: out << "D3D11"; return out;
case VIDEO_ACCELERATION_VAAPI: out << "VAAPI"; return out; case VIDEO_ACCELERATION_VAAPI: out << "VAAPI"; return out;
case VIDEO_ACCELERATION_MFX: out << "MFX"; return out; case VIDEO_ACCELERATION_MFX: out << "MFX"; return out;
case VIDEO_ACCELERATION_DRM: out << "DRM"; return out;
} }
out << cv::format("UNKNOWN(0x%ux)", static_cast<unsigned int>(va_type)); out << cv::format("UNKNOWN(0x%ux)", static_cast<unsigned int>(va_type));
return out; return out;

View File

@ -35,6 +35,7 @@ std::ostream& operator<<(std::ostream& out, const VideoAccelerationType& va_type
{VIDEO_ACCELERATION_D3D11, "D3D11"}, {VIDEO_ACCELERATION_D3D11, "D3D11"},
{VIDEO_ACCELERATION_VAAPI, "VAAPI"}, {VIDEO_ACCELERATION_VAAPI, "VAAPI"},
{VIDEO_ACCELERATION_MFX, "MFX"}, {VIDEO_ACCELERATION_MFX, "MFX"},
{VIDEO_ACCELERATION_DRM, "DRM"},
}; };
for (const auto& va : va_types) { for (const auto& va : va_types) {
if (va_type == va.va_type) { if (va_type == va.va_type) {

View File

@ -871,6 +871,7 @@ static const VideoAccelerationType hw_types[] = {
VIDEO_ACCELERATION_D3D11, VIDEO_ACCELERATION_D3D11,
#else #else
VIDEO_ACCELERATION_VAAPI, VIDEO_ACCELERATION_VAAPI,
VIDEO_ACCELERATION_DRM,
#endif #endif
}; };

View File

@ -42,6 +42,7 @@ struct {
{ VIDEO_ACCELERATION_D3D11, "d3d11" }, { VIDEO_ACCELERATION_D3D11, "d3d11" },
{ VIDEO_ACCELERATION_VAAPI, "vaapi" }, { VIDEO_ACCELERATION_VAAPI, "vaapi" },
{ VIDEO_ACCELERATION_MFX, "mfx" }, { VIDEO_ACCELERATION_MFX, "mfx" },
{ VIDEO_ACCELERATION_DRM, "drm" },
}; };
class FPSCounter { class FPSCounter {