VideoFrame.cpp 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/NonnullOwnPtr.h>
  7. #include <AK/OwnPtr.h>
  8. #include <LibVideo/Color/ColorConverter.h>
  9. #include "VideoFrame.h"
  10. namespace Video {
  11. ErrorOr<NonnullOwnPtr<SubsampledYUVFrame>> SubsampledYUVFrame::try_create(
  12. Gfx::IntSize size,
  13. u8 bit_depth, CodingIndependentCodePoints cicp,
  14. bool subsampling_horizontal, bool subsampling_vertical,
  15. Span<u16> plane_y, Span<u16> plane_u, Span<u16> plane_v)
  16. {
  17. auto plane_y_array = TRY(FixedArray<u16>::create(plane_y));
  18. auto plane_u_array = TRY(FixedArray<u16>::create(plane_u));
  19. auto plane_v_array = TRY(FixedArray<u16>::create(plane_v));
  20. return adopt_nonnull_own_or_enomem(new (nothrow) SubsampledYUVFrame(size, bit_depth, cicp, subsampling_horizontal, subsampling_vertical, plane_y_array, plane_u_array, plane_v_array));
  21. }
  22. DecoderErrorOr<void> SubsampledYUVFrame::output_to_bitmap(Gfx::Bitmap& bitmap)
  23. {
  24. size_t width = this->width();
  25. size_t height = this->height();
  26. auto u_sample_row = DECODER_TRY_ALLOC(FixedArray<u16>::create(width));
  27. auto v_sample_row = DECODER_TRY_ALLOC(FixedArray<u16>::create(width));
  28. size_t uv_width = width >> m_subsampling_horizontal;
  29. auto converter = TRY(ColorConverter::create(bit_depth(), cicp()));
  30. for (size_t row = 0; row < height; row++) {
  31. auto uv_row = row >> m_subsampling_vertical;
  32. // Linearly interpolate the UV samples vertically first.
  33. // This will write all UV samples that are located on the Y sample as well,
  34. // so we only need to interpolate horizontally between UV samples in the next
  35. // step.
  36. if ((row & m_subsampling_vertical) == 0 || row == height - 1) {
  37. for (size_t uv_column = 0; uv_column < uv_width; uv_column++) {
  38. size_t column = uv_column << m_subsampling_horizontal;
  39. size_t index = uv_row * uv_width + uv_column;
  40. u_sample_row[column] = m_plane_u[index];
  41. v_sample_row[column] = m_plane_v[index];
  42. }
  43. } else {
  44. for (size_t uv_column = 0; uv_column < uv_width; uv_column++) {
  45. size_t column = uv_column << m_subsampling_horizontal;
  46. size_t index = (uv_row + 1) * uv_width + uv_column;
  47. u_sample_row[column] = (u_sample_row[column] + m_plane_u[index]) >> 1;
  48. v_sample_row[column] = (v_sample_row[column] + m_plane_v[index]) >> 1;
  49. }
  50. }
  51. // Fill in the last pixel of the row which may not be applied by the above
  52. // loops if the last pixel in each row is on an uneven index.
  53. if ((width & 1) == 0) {
  54. u_sample_row[width - 1] = u_sample_row[width - 2];
  55. v_sample_row[width - 1] = v_sample_row[width - 2];
  56. }
  57. // Interpolate the samples horizontally.
  58. if (m_subsampling_horizontal) {
  59. for (size_t column = 1; column < width - 1; column += 2) {
  60. u_sample_row[column] = (u_sample_row[column - 1] + u_sample_row[column + 1]) >> 1;
  61. v_sample_row[column] = (v_sample_row[column - 1] + v_sample_row[column + 1]) >> 1;
  62. }
  63. }
  64. for (size_t column = 0; column < width; column++) {
  65. auto y_sample = m_plane_y[row * width + column];
  66. auto u_sample = u_sample_row[column];
  67. auto v_sample = v_sample_row[column];
  68. bitmap.set_pixel(Gfx::IntPoint(column, row), converter.convert_yuv_to_full_range_rgb(y_sample, u_sample, v_sample));
  69. /*auto r_float = clamp(y_sample + (v_sample - 128) * 219.0f / 224.0f * 1.5748f, 0, 255);
  70. auto g_float = clamp(y_sample + (u_sample - 128) * 219.0f / 224.0f * -0.0722f * 1.8556f / 0.7152f + (v_sample - 128) * 219.0f / 224.0f * -0.2126f * 1.5748f / 0.7152f, 0, 255);
  71. auto b_float = clamp(y_sample + (u_sample - 128) * 219.0f / 224.0f * 1.8556f, 0, 255);
  72. auto r = static_cast<u8>(r_float);
  73. auto g = static_cast<u8>(g_float);
  74. auto b = static_cast<u8>(b_float);
  75. bitmap.set_pixel(Gfx::IntPoint(column, row), Color(r, g, b));*/
  76. }
  77. }
  78. return {};
  79. }
  80. }