From 44dcd66205e9662e89277e01d83c10db98836f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Garramu=C3=B1o?= Date: Mon, 11 Mar 2024 09:42:38 -0300 Subject: [PATCH] Made rotation be handled with metadata instead of C++ functions. --- lib/tlIO/FFmpegReadPrivate.h | 14 -- lib/tlIO/FFmpegReadVideo.cpp | 392 +---------------------------------- 2 files changed, 2 insertions(+), 404 deletions(-) diff --git a/lib/tlIO/FFmpegReadPrivate.h b/lib/tlIO/FFmpegReadPrivate.h index 52f44077..9159c7f6 100644 --- a/lib/tlIO/FFmpegReadPrivate.h +++ b/lib/tlIO/FFmpegReadPrivate.h @@ -76,20 +76,6 @@ namespace tl int _decode(const otime::RationalTime& currentTime); void _copy(std::shared_ptr&); float _getRotation(const AVStream*); - - template - void _rotateYUV420(T*, const T*, const bool); - template - void _rotateYUV422(T*, const T*, const bool); - template - void _rotateYUV444(T*, const T*, const bool); - - template - void _flipYUV420(T*, const T*); - template - void _flipYUV422(T*, const T*); - template - void _flipYUV444(T*, const T*); std::string _fileName; Options _options; diff --git a/lib/tlIO/FFmpegReadVideo.cpp b/lib/tlIO/FFmpegReadVideo.cpp index bc55dec2..a473a389 100644 --- a/lib/tlIO/FFmpegReadVideo.cpp +++ b/lib/tlIO/FFmpegReadVideo.cpp @@ -808,6 +808,7 @@ namespace tl const auto& info = image->getInfo(); const std::size_t w = info.size.w; const std::size_t h = info.size.h; + uint8_t* const data = image->getData(); if (canCopy(_avInputPixelFormat, _avOutputPixelFormat)) { @@ -843,7 +844,7 @@ namespace tl } break; case AV_PIX_FMT_YUV420P: - { + { const std::size_t w2 = w / 2; const std::size_t h2 = h / 2; const uint8_t* const data1 = _avFrame->data[1]; @@ -893,93 +894,6 @@ namespace tl _avFrame2->data, _avFrame2->linesize); } - - // Handle embedded rotation in movie file (as when taken from a - // phone). - if (_rotation != 0.F) - { - int rotation = static_cast(_rotation); - auto info = _info; - if (std::abs(rotation) != 180) - { - const auto tmp = info.size.w; - info.size.w = info.size.h; - info.size.h = tmp; - } - auto tmp = image::Image::create(info); - if (std::abs(rotation) == 180.F) - { - switch(info.pixelType) - { - case image::PixelType::YUV_420P_U8: - _flipYUV420(tmp->getData(), data); - break; - case image::PixelType::YUV_420P_U16: - _flipYUV420( - reinterpret_cast(tmp->getData()), - reinterpret_cast(data)); - break; - case image::PixelType::YUV_422P_U8: - _flipYUV422(tmp->getData(), data); - break; - case image::PixelType::YUV_422P_U16: - _flipYUV422( - reinterpret_cast(tmp->getData()), - reinterpret_cast(data)); - break; - case image::PixelType::YUV_444P_U8: - _flipYUV444(tmp->getData(), data); - break; - case image::PixelType::YUV_444P_U16: - _flipYUV444( - reinterpret_cast(tmp->getData()), - reinterpret_cast(data)); - break; - default: - return; // cannot flip - break; - } - } - else - { - bool clockwise = true; - if (rotation == 90 || rotation == -270) - clockwise = false; - - switch(info.pixelType) - { - case image::PixelType::YUV_420P_U8: - _rotateYUV420(tmp->getData(), data, clockwise); - break; - case image::PixelType::YUV_420P_U16: - _rotateYUV420( - reinterpret_cast(tmp->getData()), - reinterpret_cast(data), clockwise); - break; - case image::PixelType::YUV_422P_U8: - _rotateYUV422(tmp->getData(), data, clockwise); - break; - case image::PixelType::YUV_422P_U16: - _rotateYUV422( - reinterpret_cast(tmp->getData()), - reinterpret_cast(data), clockwise); - break; - case image::PixelType::YUV_444P_U8: - _rotateYUV444( - tmp->getData(), data, clockwise); - break; - case image::PixelType::YUV_444P_U16: - _rotateYUV444( - reinterpret_cast(tmp->getData()), - reinterpret_cast(data), clockwise); - break; - default: - return; // cannot rotate - break; - } - } - image = tmp; - } } float ReadVideo::_getRotation(const AVStream* st) @@ -996,307 +910,5 @@ namespace tl return out; } - template - void ReadVideo::_rotateYUV420(T* out, const T* in, - const bool clockwise) - { - const size_t w = _info.size.w; - const size_t h = _info.size.h; - const size_t w2 = w / 2; - const size_t h2 = h / 2; - const size_t size = w * h; - const size_t size4 = size / 4; - - if (clockwise) - { - // Transpose Y plane - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[x * h + ( h - 1 - y )] = in[y * w + x]; - } - } - - // Transpose U and V planes (downsampling) - for (size_t y = 0; y < h2; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - out[size + x * h2 + (h2 - y - 1)] = - in[size + y * w2 + x]; - out[size + size4 + x * h2 + (h2 - y - 1)] = - in[size + size4 + y * w2 + x]; - } - } - } - else - { - // Transpose Y plane counterclockwise - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[(w - 1 - x) * h + y] = in[y * w + x]; - } - } - - // Transpose U and V planes (downsampling) counterclockwise - for (size_t y = 0; y < h2; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - out[size + (w2 - 1 - x) * h2 + y] = - in[size + y * w2 + x]; - out[size + size4 + (w2 - 1 - x) * h2 + y] = - in[size + size4 + y * w2 + x]; - } - } - } - } - - template - void ReadVideo::_flipYUV420(T* out, const T* in) - { - // Calculate the size of each plane - const size_t w = _info.size.w; - const size_t h = _info.size.h; - const size_t w2 = w / 2; - const size_t h2 = h / 2; - const size_t size = w * h; - const size_t size4 = size / 4; - - // Flip Y plane vertically - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[(h - 1 - y) * w + (w - 1 - x)] = in[y * w + x]; - } - } - - // Flip U and V planes vertically - for (size_t y = 0; y < h2; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - // U plane - out[size + y * w2 + x] = - in[size + (h2 - 1 - y) * w2 + (w2 - 1 - x)]; - // V plane - out[size + size4 + y * w2 + x] = - in[size + size4 + (h2 - 1 - y) * w2 + (w2 - 1 - x)]; - } - } - } - - - template - void ReadVideo::_rotateYUV422(T* out, const T* in, - const bool clockwise) - { - const size_t w = _info.size.w; - const size_t h = _info.size.h; - const size_t w2 = w / 2; - const size_t size = w * h; - const size_t size2 = size + w2 * h; - - // Create temp buffer for U and V planes - auto* tmp = new T[w * h]; - - - if (clockwise) - { - // Rotate Y plane clockwise - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[x * h + ( h - y - 1 )] = in[y * w + x]; - } - } - - // Upsample and rotate U clockwise into temp buffer - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - tmp[x * 2 * h + ( h - y - 1 )] = in[size + y * w2 + x]; - tmp[(x * 2 + 1) * h + (h - y - 1)] = - in[size + y * w2 + x]; - } - } - - // Downsample U into final position - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - out[size + y * w2 + x] = tmp[y * w + x * 2]; - } - } - - // Upsample and rotate V clockwise into temp buffer - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - tmp[x * 2 * h + ( h - y - 1 )] = in[size2 + y * w2 + x]; - tmp[(x * 2 + 1) * h + (h - y - 1)] = - in[size2 + y * w2 + x]; - } - } - - } - else - { - // Rotate Y plane counterclockwise - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[(w - 1 - x) * h + y] = in[y * w + x]; - } - } - - // Upsample and rotate U counterclockwise into temp buffer - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - const size_t x2 = (w2 - 1 - x) * 2; - tmp[x2 * h + y] = in[size + y * w2 + x]; - tmp[(x2 + 1) * h + y] = in[size + y * w2 + x]; - } - } - - // Downsample U into final position - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - out[size + y * w2 + x] = tmp[y * w + x * 2]; - } - } - - // Upsample and rotate V counterclockwise into temp buffer - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - const size_t x2 = (w2 - 1 - x) * 2; - tmp[x2 * h + y] = in[size2 + y * w2 + x]; - tmp[(x2 + 1) * h + y] = in[size2 + y * w2 + x]; - } - } - } - - // Downsample V into final position - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - out[size2 + y * w2 + x] = tmp[y * w + x * 2]; - } - } - - // Delete tmp buffer - delete [] tmp; - } - - template - void ReadVideo::_flipYUV422(T* out, const T* in) - { - // Calculate the size of each plane - const size_t w = _info.size.w; - const size_t h = _info.size.h; - const size_t w2 = w / 2; - const size_t size = w * h; - const size_t size2 = size + w2 * h; - - // Flip Y plane vertically - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[(h - 1 - y) * w + (w - 1 - x)] = in[y * w + x]; - } - } - - // Flip U and V planes vertically - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w2; ++x) - { - out[size + y * w2 + x] = - in[size + (h - 1 - y) * w2 + (w2 - 1 - x)]; - out[size2 + y * w2 + x] = - in[size2 + (h - 1 - y) * w2 + (w2 - 1 - x)]; - } - } - } - - template - void ReadVideo::_rotateYUV444(T* out, const T* in, - const bool clockwise) - { - const size_t w = _info.size.w; - const size_t h = _info.size.h; - const size_t size = w * h; - - if (clockwise) - { - // Transpose YUV planes clockwise - for (int p = 0; p < 3; ++p) - { - size_t plane = p * size; - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[plane + x * h + ( h - 1 - y )] = in[plane + y * w + x]; - } - } - } - } - else - { - // Transpose YUV planes counterclockwise - for (int p = 0; p < 3; ++p) - { - size_t plane = p * size; - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[plane + (w - 1 - x) * h + y] = in[plane + y * w + x]; - } - } - } - } - } - - template - void ReadVideo::_flipYUV444(T* out, const T* in) - { - // Calculate the size of each plane - const size_t w = _info.size.w; - const size_t h = _info.size.h; - const size_t size = w * h; - - // Flip YUV planes vertically - for (int p = 0; p < 3; ++p) - { - size_t plane = p * size; - for (size_t y = 0; y < h; ++y) - { - for (size_t x = 0; x < w; ++x) - { - out[plane + (h - 1 - y) * w + (w - 1 - x)] = - in[plane + y * w + x]; - } - } - } - } } }