diff --git a/CMakeLists.txt b/CMakeLists.txt index 76fb3c5b9..3e88968bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -556,7 +556,7 @@ if(USE_FFMPEG) endif() include_directories(AFTER ${FFMPEG_INCLUDE_DIRS} ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFILTER_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWRESAMPLE_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS}) link_directories(${FFMPEG_LIBRARY_DIRS} ${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFILTER_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWRESAMPLE_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS}) - list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-decoder.c") + list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-decoder.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-scale.c") list(APPEND DEPENDENCY_LIB ${FFMPEG_LIBRARIES} ${LIBAVCODEC_LIBRARIES} ${LIBAVFILTER_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES} ${LIBSWRESAMPLE_LIBRARIES}) if(WIN32 AND NOT DEFINED VCPKG_TARGET_TRIPLET) list(APPEND DEPENDENCY_LIB bcrypt) diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index ca42bca7b..177483597 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -164,6 +164,7 @@ enum mColorFormat { mCOLOR_BGRA5 = 0x08000, mCOLOR_RGB8 = 0x10000, mCOLOR_BGR8 = 0x20000, + mCOLOR_L8 = 0x40000, mCOLOR_ANY = -1 }; diff --git a/src/feature/ffmpeg/ffmpeg-common.h b/src/feature/ffmpeg/ffmpeg-common.h index d006c83ce..0f94cfbeb 100644 --- a/src/feature/ffmpeg/ffmpeg-common.h +++ b/src/feature/ffmpeg/ffmpeg-common.h @@ -10,6 +10,8 @@ CXX_GUARD_START +#include + #include #include @@ -32,6 +34,54 @@ CXX_GUARD_START #define FFMPEG_USE_PACKET_UNREF #endif +static inline enum AVPixelFormat mColorFormatToFFmpegPixFmt(enum mColorFormat format) { + switch (format) { +#ifndef USE_LIBAV + case mCOLOR_XRGB8: + return AV_PIX_FMT_0RGB; + case mCOLOR_XBGR8: + return AV_PIX_FMT_0BGR; + case mCOLOR_RGBX8: + return AV_PIX_FMT_RGB0; + case mCOLOR_BGRX8: + return AV_PIX_FMT_BGR0; +#else + case mCOLOR_XRGB8: + return AV_PIX_FMT_ARGB; + case mCOLOR_XBGR8: + return AV_PIX_FMT_ABGR; + case mCOLOR_RGBX8: + return AV_PIX_FMT_RGBA; + case mCOLOR_BGRX8: + return AV_PIX_FMT_BGRA; +#endif + case mCOLOR_ARGB8: + return AV_PIX_FMT_ARGB; + case mCOLOR_ABGR8: + return AV_PIX_FMT_ABGR; + case mCOLOR_RGBA8: + return AV_PIX_FMT_RGBA; + case mCOLOR_BGRA8: + return AV_PIX_FMT_BGRA; + case mCOLOR_RGB5: + return AV_PIX_FMT_RGB555; + case mCOLOR_BGR5: + return AV_PIX_FMT_BGR555; + case mCOLOR_RGB565: + return AV_PIX_FMT_RGB565; + case mCOLOR_BGR565: + return AV_PIX_FMT_BGR565; + case mCOLOR_RGB8: + return AV_PIX_FMT_RGB24; + case mCOLOR_BGR8: + return AV_PIX_FMT_BGR24; + case mCOLOR_L8: + return AV_PIX_FMT_GRAY8; + default: + return AV_PIX_FMT_NONE; + } +} + CXX_GUARD_END #endif diff --git a/src/feature/ffmpeg/ffmpeg-scale.c b/src/feature/ffmpeg/ffmpeg-scale.c new file mode 100644 index 000000000..a28600e2f --- /dev/null +++ b/src/feature/ffmpeg/ffmpeg-scale.c @@ -0,0 +1,36 @@ +/* Copyright (c) 2013-2021 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "ffmpeg-scale.h" + +#include + +static const int _qualityToFlags[] = { + SWS_POINT, + SWS_FAST_BILINEAR, + SWS_BILINEAR, + SWS_BICUBIC, + SWS_LANCZOS, + SWS_SINC, +}; + +void FFmpegScale(const void* input, int iwidth, int iheight, unsigned istride, + void* output, int owidth, int oheight, unsigned ostride, + enum mColorFormat format, int quality) { + enum AVPixelFormat pixFormat = mColorFormatToFFmpegPixFmt(format); + int flags; + if (quality < 0) { + quality = 0; + } else if ((unsigned) quality >= sizeof(_qualityToFlags) / sizeof(_qualityToFlags[0])) { + quality = sizeof(_qualityToFlags) / sizeof(_qualityToFlags[0]) - 1; + } + flags = _qualityToFlags[quality]; + + struct SwsContext* scaleContext = sws_getContext(iwidth, iheight, pixFormat, + owidth, oheight, pixFormat, + flags, 0, 0, 0); + sws_scale(scaleContext, (const uint8_t* const*) &input, (const int*) &istride, 0, iheight, (uint8_t* const*) &output, (const int*) &ostride); + sws_freeContext(scaleContext); +} diff --git a/src/feature/ffmpeg/ffmpeg-scale.h b/src/feature/ffmpeg/ffmpeg-scale.h new file mode 100644 index 000000000..e447708df --- /dev/null +++ b/src/feature/ffmpeg/ffmpeg-scale.h @@ -0,0 +1,21 @@ +/* Copyright (c) 2013-2021 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef FFMPEG_SCALE +#define FFMPEG_SCALE + +#include + +CXX_GUARD_START + +#include "feature/ffmpeg/ffmpeg-common.h" + +void FFmpegScale(const void* input, int iwidth, int iheight, unsigned istride, + void* output, int owidth, int oheight, unsigned ostride, + enum mColorFormat format, int quality); + +CXX_GUARD_END + +#endif