Reintroduce support for FFmpeg 4

Some SBCs still depend on patched FFmpeg 4.x builds for hardware acceleration.
This commit is contained in:
Cameron Gutman 2024-08-24 16:50:27 -05:00
parent 9186feca80
commit 76fd502262
3 changed files with 30 additions and 1 deletions

View file

@ -52,7 +52,7 @@ Hosting for Moonlight's Debian and L4T package repositories is graciously provid
### Linux/Unix Build Requirements ### Linux/Unix Build Requirements
* Qt 6 is recommended, but Qt 5.9 or later is also supported (replace `qmake6` with `qmake` when using Qt 5). * Qt 6 is recommended, but Qt 5.9 or later is also supported (replace `qmake6` with `qmake` when using Qt 5).
* GCC or Clang * GCC or Clang
* FFmpeg 5.0 or later * FFmpeg 4.0 or later
* Install the required packages: * Install the required packages:
* Debian/Ubuntu: * Debian/Ubuntu:
* Base Requirements: `libegl1-mesa-dev libgl1-mesa-dev libopus-dev libsdl2-dev libsdl2-ttf-dev libssl-dev libavcodec-dev libavformat-dev libswscale-dev libva-dev libvdpau-dev libxkbcommon-dev wayland-protocols libdrm-dev` * Base Requirements: `libegl1-mesa-dev libgl1-mesa-dev libopus-dev libsdl2-dev libsdl2-ttf-dev libssl-dev libavcodec-dev libavformat-dev libswscale-dev libva-dev libvdpau-dev libxkbcommon-dev wayland-protocols libdrm-dev`

View file

@ -93,8 +93,10 @@ static const std::map<uint32_t, AVPixelFormat> k_DrmToAvFormatMap
{DRM_FORMAT_NV21, AV_PIX_FMT_NV21}, {DRM_FORMAT_NV21, AV_PIX_FMT_NV21},
{DRM_FORMAT_P010, AV_PIX_FMT_P010LE}, {DRM_FORMAT_P010, AV_PIX_FMT_P010LE},
{DRM_FORMAT_YUV420, AV_PIX_FMT_YUV420P}, {DRM_FORMAT_YUV420, AV_PIX_FMT_YUV420P},
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 27, 100)
{DRM_FORMAT_NV24, AV_PIX_FMT_NV24}, {DRM_FORMAT_NV24, AV_PIX_FMT_NV24},
{DRM_FORMAT_NV42, AV_PIX_FMT_NV42}, {DRM_FORMAT_NV42, AV_PIX_FMT_NV42},
#endif
{DRM_FORMAT_YUV444, AV_PIX_FMT_YUV444P}, {DRM_FORMAT_YUV444, AV_PIX_FMT_YUV444P},
{DRM_FORMAT_Q410, AV_PIX_FMT_YUV444P10LE}, {DRM_FORMAT_Q410, AV_PIX_FMT_YUV444P10LE},
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 34, 100) #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 34, 100)
@ -111,7 +113,9 @@ static const std::map<uint32_t, AVPixelFormat> k_DrmToAvFormatMap
{DRM_FORMAT_NA12, AV_PIX_FMT_P010LE}, {DRM_FORMAT_NA12, AV_PIX_FMT_P010LE},
{DRM_FORMAT_NV15, AV_PIX_FMT_P010LE}, {DRM_FORMAT_NV15, AV_PIX_FMT_P010LE},
{DRM_FORMAT_P030, AV_PIX_FMT_P010LE}, {DRM_FORMAT_P030, AV_PIX_FMT_P010LE},
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 9, 100)
{DRM_FORMAT_NV30, AV_PIX_FMT_P410LE}, {DRM_FORMAT_NV30, AV_PIX_FMT_P410LE},
#endif
}; };
// This map is used to determine the required DRM format for dumb buffer upload. // This map is used to determine the required DRM format for dumb buffer upload.
@ -124,8 +128,10 @@ static const std::map<AVPixelFormat, uint32_t> k_AvToDrmFormatMap
{AV_PIX_FMT_P010LE, DRM_FORMAT_P010}, {AV_PIX_FMT_P010LE, DRM_FORMAT_P010},
{AV_PIX_FMT_YUV420P, DRM_FORMAT_YUV420}, {AV_PIX_FMT_YUV420P, DRM_FORMAT_YUV420},
{AV_PIX_FMT_YUVJ420P, DRM_FORMAT_YUV420}, {AV_PIX_FMT_YUVJ420P, DRM_FORMAT_YUV420},
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 27, 100)
{AV_PIX_FMT_NV24, DRM_FORMAT_NV24}, {AV_PIX_FMT_NV24, DRM_FORMAT_NV24},
{AV_PIX_FMT_NV42, DRM_FORMAT_NV42}, {AV_PIX_FMT_NV42, DRM_FORMAT_NV42},
#endif
{AV_PIX_FMT_YUV444P, DRM_FORMAT_YUV444}, {AV_PIX_FMT_YUV444P, DRM_FORMAT_YUV444},
{AV_PIX_FMT_YUVJ444P, DRM_FORMAT_YUV444}, {AV_PIX_FMT_YUVJ444P, DRM_FORMAT_YUV444},
{AV_PIX_FMT_YUV444P10LE, DRM_FORMAT_Q410}, {AV_PIX_FMT_YUV444P10LE, DRM_FORMAT_Q410},

View file

@ -343,6 +343,8 @@ ReadbackRetry:
m_RgbFrame->format = AV_PIX_FMT_BGR0; m_RgbFrame->format = AV_PIX_FMT_BGR0;
sws_freeContext(m_SwsContext); sws_freeContext(m_SwsContext);
#if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(6, 1, 100)
m_SwsContext = sws_alloc_context(); m_SwsContext = sws_alloc_context();
if (!m_SwsContext) { if (!m_SwsContext) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
@ -377,6 +379,19 @@ ReadbackRetry:
av_make_error_string(string, sizeof(string), err)); av_make_error_string(string, sizeof(string), err));
goto Exit; goto Exit;
} }
#else
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"CPU color conversion is slow on FFmpeg 4.x. Update FFmpeg for better performance.");
m_SwsContext = sws_getContext(frame->width, frame->height, (AVPixelFormat)frame->format,
m_RgbFrame->width, m_RgbFrame->height, (AVPixelFormat)m_RgbFrame->format,
0, nullptr, nullptr, nullptr);
if (!m_SwsContext) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"sws_getContext() failed");
goto Exit;
}
#endif
} }
else { else {
// SDL will perform YUV conversion on the GPU // SDL will perform YUV conversion on the GPU
@ -526,10 +541,18 @@ ReadbackRetry:
m_RgbFrame->data[0] = pixels; m_RgbFrame->data[0] = pixels;
m_RgbFrame->linesize[0] = texturePitch; m_RgbFrame->linesize[0] = texturePitch;
#if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(6, 1, 100)
// Perform multi-threaded color conversion into the locked texture buffer // Perform multi-threaded color conversion into the locked texture buffer
err = sws_scale_frame(m_SwsContext, m_RgbFrame, frame); err = sws_scale_frame(m_SwsContext, m_RgbFrame, frame);
#else
// Perform a single-threaded color conversion using the legacy swscale API
err = sws_scale(m_SwsContext, frame->data, frame->linesize, 0, frame->height,
m_RgbFrame->data, m_RgbFrame->linesize);
#endif
av_buffer_unref(&m_RgbFrame->buf[0]); av_buffer_unref(&m_RgbFrame->buf[0]);
SDL_UnlockTexture(m_Texture); SDL_UnlockTexture(m_Texture);
if (err < 0) { if (err < 0) {
char string[AV_ERROR_MAX_STRING_SIZE]; char string[AV_ERROR_MAX_STRING_SIZE];
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,