[Scummvm-git-logs] scummvm master -> 237cb4d52a314386402a01c236dc7c95bed025ca
bluegr
noreply at scummvm.org
Mon Jun 19 05:43:43 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
237cb4d52a VIDEO: Add YUV422 and YUV444 to Theora decoder
Commit: 237cb4d52a314386402a01c236dc7c95bed025ca
https://github.com/scummvm/scummvm/commit/237cb4d52a314386402a01c236dc7c95bed025ca
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-06-19T08:43:40+03:00
Commit Message:
VIDEO: Add YUV422 and YUV444 to Theora decoder
Changed paths:
graphics/yuv_to_rgb.cpp
graphics/yuv_to_rgb.h
video/theora_decoder.cpp
video/theora_decoder.h
diff --git a/graphics/yuv_to_rgb.cpp b/graphics/yuv_to_rgb.cpp
index ce42a547743..d68217bce1f 100644
--- a/graphics/yuv_to_rgb.cpp
+++ b/graphics/yuv_to_rgb.cpp
@@ -252,6 +252,58 @@ void YUVToRGBManager::convert444(Graphics::Surface *dst, YUVToRGBManager::Lumina
convertYUV444ToRGB<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
}
+template<typename PixelInt>
+void convertYUV422ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, int16 *colorTab, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+ int halfWidth = yWidth >> 1;
+
+ // Keep the tables in pointers here to avoid a dereference on each pixel
+ const int16 *Cr_r_tab = colorTab;
+ const int16 *Cr_g_tab = Cr_r_tab + 256;
+ const int16 *Cb_g_tab = Cr_g_tab + 256;
+ const int16 *Cb_b_tab = Cb_g_tab + 256;
+ const uint32 *rgbToPix = lookup->getRGBToPix();
+
+ for (int h = 0; h < yHeight; h++) {
+ for (int w = 0; w < halfWidth; w++) {
+ const uint32 *L;
+
+ int16 cr_r = Cr_r_tab[*vSrc];
+ int16 crb_g = Cr_g_tab[*vSrc] + Cb_g_tab[*uSrc];
+ int16 cb_b = Cb_b_tab[*uSrc];
+ ++uSrc;
+ ++vSrc;
+
+ PUT_PIXEL(*ySrc, dstPtr);
+ ySrc++;
+ dstPtr += sizeof(PixelInt);
+ PUT_PIXEL(*ySrc, dstPtr);
+ ySrc++;
+ dstPtr += sizeof(PixelInt);
+ }
+
+ dstPtr += dstPitch - yWidth * sizeof(PixelInt);
+ ySrc += yPitch - yWidth;
+ uSrc += uvPitch - halfWidth;
+ vSrc += uvPitch - halfWidth;
+ }
+}
+
+void YUVToRGBManager::convert422(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+ // Sanity checks
+ assert(dst && dst->getPixels());
+ assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
+ assert(ySrc && uSrc && vSrc);
+ assert((yWidth & 1) == 0);
+
+ const YUVToRGBLookup *lookup = getLookup(dst->format, scale);
+
+ // Use a templated function to avoid an if check on every pixel
+ if (dst->format.bytesPerPixel == 2)
+ convertYUV422ToRGB<uint16>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ else
+ convertYUV422ToRGB<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+}
+
template<typename PixelInt>
void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, int16 *colorTab, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
int halfHeight = yHeight >> 1;
diff --git a/graphics/yuv_to_rgb.h b/graphics/yuv_to_rgb.h
index 75c98ceb061..c0d28c809ad 100644
--- a/graphics/yuv_to_rgb.h
+++ b/graphics/yuv_to_rgb.h
@@ -68,6 +68,21 @@ public:
*/
void convert444(Graphics::Surface *dst, LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+ /**
+ * Convert a YUV422 image to an RGB surface
+ *
+ * @param dst the destination surface
+ * @param scale the scale of the luminance values
+ * @param ySrc the source of the y component
+ * @param uSrc the source of the u component
+ * @param vSrc the source of the v component
+ * @param yWidth the width of the y surface (must be divisible by 2)
+ * @param yHeight the height of the y surface
+ * @param yPitch the pitch of the y surface
+ * @param uvPitch the pitch of the u and v surfaces
+ */
+ void convert422(Graphics::Surface *dst, LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+
/**
* Convert a YUV420 image to an RGB surface
*
diff --git a/video/theora_decoder.cpp b/video/theora_decoder.cpp
index dca4b82a450..d42b483d3b5 100644
--- a/video/theora_decoder.cpp
+++ b/video/theora_decoder.cpp
@@ -257,8 +257,9 @@ Common::Rational TheoraDecoder::getFrameRate() const {
TheoraDecoder::TheoraVideoTrack::TheoraVideoTrack(th_info &theoraInfo, th_setup_info *theoraSetup) {
_theoraDecode = th_decode_alloc(&theoraInfo, theoraSetup);
- if (theoraInfo.pixel_fmt != TH_PF_420)
- error("Only theora YUV420 is supported");
+ if (theoraInfo.pixel_fmt != TH_PF_420 && theoraInfo.pixel_fmt != TH_PF_422 && theoraInfo.pixel_fmt != TH_PF_444) {
+ error("Found unknown Theora format (must be YUV420, YUV422 or YUV444)");
+ }
int postProcessingMax;
th_decode_ctl(_theoraDecode, TH_DECCTL_GET_PPLEVEL_MAX, &postProcessingMax, sizeof(postProcessingMax));
@@ -272,6 +273,7 @@ TheoraDecoder::TheoraVideoTrack::TheoraVideoTrack(th_info &theoraInfo, th_setup_
_surfaceHeight = theoraInfo.frame_height;
_pixelFormat = g_system->getScreenFormat();
+ _theoraPixelFormat = theoraInfo.pixel_fmt;
// Default to a 32bpp format, if in 8bpp mode
if (_pixelFormat.bytesPerPixel == 1)
@@ -342,11 +344,11 @@ void TheoraDecoder::TheoraVideoTrack::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuf
assert((YUVBuffer[kBufferU].width & 1) == 0);
assert((YUVBuffer[kBufferV].width & 1) == 0);
- // UV images have to have a quarter of the Y image resolution
- assert(YUVBuffer[kBufferU].width == YUVBuffer[kBufferY].width >> 1);
- assert(YUVBuffer[kBufferV].width == YUVBuffer[kBufferY].width >> 1);
- assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1);
- assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1);
+ // UV components must be half or equal the Y component
+ assert((YUVBuffer[kBufferU].width == YUVBuffer[kBufferY].width >> 1) || (YUVBuffer[kBufferU].width == YUVBuffer[kBufferY].width));
+ assert((YUVBuffer[kBufferV].width == YUVBuffer[kBufferY].width >> 1) || (YUVBuffer[kBufferV].width == YUVBuffer[kBufferY].width));
+ assert((YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1) || (YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height));
+ assert((YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1) || (YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height));
if (!_surface) {
_surface = new Graphics::Surface();
@@ -360,7 +362,19 @@ void TheoraDecoder::TheoraVideoTrack::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuf
_surface->getBasePtr(_x, _y), _surface->format);
}
- YUVToRGBMan.convert420(_surface, Graphics::YUVToRGBManager::kScaleITU, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
+ switch (_theoraPixelFormat) {
+ case TH_PF_420:
+ YUVToRGBMan.convert420(_surface, Graphics::YUVToRGBManager::kScaleITU, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
+ break;
+ case TH_PF_422:
+ YUVToRGBMan.convert422(_surface, Graphics::YUVToRGBManager::kScaleITU, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
+ break;
+ case TH_PF_444:
+ YUVToRGBMan.convert444(_surface, Graphics::YUVToRGBManager::kScaleITU, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
+ break;
+ default:
+ error("Unsupported Theora pixel format");
+ }
}
static vorbis_info *info = 0;
diff --git a/video/theora_decoder.h b/video/theora_decoder.h
index 6adf2123cec..a0f0a2e2703 100644
--- a/video/theora_decoder.h
+++ b/video/theora_decoder.h
@@ -112,6 +112,7 @@ private:
uint16 _surfaceHeight;
th_dec_ctx *_theoraDecode;
+ th_pixel_fmt _theoraPixelFormat;
void translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer);
};
More information about the Scummvm-git-logs
mailing list