video_util.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef MEDIA_BASE_VIDEO_UTIL_H_
  5. #define MEDIA_BASE_VIDEO_UTIL_H_
  6. #include <stdint.h>
  7. #include <vector>
  8. #include "base/memory/ref_counted.h"
  9. #include "media/base/encoder_status.h"
  10. #include "media/base/media_export.h"
  11. #include "media/base/video_types.h"
  12. #include "third_party/skia/include/core/SkImage.h"
  13. #include "ui/gfx/geometry/rect.h"
  14. #include "ui/gfx/geometry/size.h"
  15. class GrDirectContext;
  16. namespace base {
  17. class TimeDelta;
  18. }
  19. namespace gpu {
  20. namespace raster {
  21. class RasterInterface;
  22. } // namespace raster
  23. } // namespace gpu
  24. namespace media {
  25. class VideoFramePool;
  26. class VideoFrame;
  27. // Fills |frame| containing YUV data to the given color values.
  28. MEDIA_EXPORT void FillYUV(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v);
  29. // Fills |frame| containing YUVA data with the given color values.
  30. MEDIA_EXPORT void FillYUVA(VideoFrame* frame,
  31. uint8_t y,
  32. uint8_t u,
  33. uint8_t v,
  34. uint8_t a);
  35. // Creates a border in |frame| such that all pixels outside of |view_area| are
  36. // black. Only YV12 and ARGB format video frames are currently supported. If
  37. // format is YV12, the size and position of |view_area| must be even to align
  38. // correctly with the color planes.
  39. MEDIA_EXPORT void LetterboxVideoFrame(VideoFrame* frame,
  40. const gfx::Rect& view_area);
  41. // Rotates |src| plane by |rotation| degree with possible flipping vertically
  42. // and horizontally.
  43. // |rotation| is limited to {0, 90, 180, 270}.
  44. // |width| and |height| are expected to be even numbers.
  45. // Both |src| and |dest| planes are packed and have same |width| and |height|.
  46. // When |width| != |height| and rotated by 90/270, only the maximum square
  47. // portion located in the center is rotated. For example, for width=640 and
  48. // height=480, the rotated area is 480x480 located from row 0 through 479 and
  49. // from column 80 through 559. The leftmost and rightmost 80 columns are
  50. // ignored for both |src| and |dest|.
  51. // The caller is responsible for blanking out the margin area.
  52. MEDIA_EXPORT void RotatePlaneByPixels(const uint8_t* src,
  53. uint8_t* dest,
  54. int width,
  55. int height,
  56. int rotation, // Clockwise.
  57. bool flip_vert,
  58. bool flip_horiz);
  59. // Return the largest centered rectangle with the same aspect ratio of |content|
  60. // that fits entirely inside of |bounds|. If |content| is empty, its aspect
  61. // ratio would be undefined; and in this case an empty Rect would be returned.
  62. MEDIA_EXPORT gfx::Rect ComputeLetterboxRegion(const gfx::Rect& bounds,
  63. const gfx::Size& content);
  64. // Same as ComputeLetterboxRegion(), except ensure the result has even-numbered
  65. // x, y, width, and height. |bounds| must already have even-numbered
  66. // coordinates, but the |content| size can be anything.
  67. //
  68. // This is useful for ensuring content scaled and converted to I420 does not
  69. // have color distortions around the edges in a letterboxed video frame. Note
  70. // that, in cases where ComputeLetterboxRegion() would return a 1x1-sized Rect,
  71. // this function could return either a 0x0-sized Rect or a 2x2-sized Rect.
  72. // Note that calling this function with `bounds` that already have the aspect
  73. // ratio of `content` is not guaranteed to be a no-op (for context, see
  74. // https://crbug.com/1323367).
  75. MEDIA_EXPORT gfx::Rect ComputeLetterboxRegionForI420(const gfx::Rect& bounds,
  76. const gfx::Size& content);
  77. // Shrinks the given |rect| by the minimum amount necessary to align its corners
  78. // to even-numbered coordinates. |rect| is assumed to have bounded limit values,
  79. // and may have negative bounds.
  80. MEDIA_EXPORT gfx::Rect MinimallyShrinkRectForI420(const gfx::Rect& rect);
  81. // Return a scaled |size| whose area is less than or equal to |target|, where
  82. // one of its dimensions is equal to |target|'s. The aspect ratio of |size| is
  83. // preserved as closely as possible. If |size| is empty, the result will be
  84. // empty.
  85. MEDIA_EXPORT gfx::Size ScaleSizeToFitWithinTarget(const gfx::Size& size,
  86. const gfx::Size& target);
  87. // Return a scaled |size| whose area is greater than or equal to |target|, where
  88. // one of its dimensions is equal to |target|'s. The aspect ratio of |size| is
  89. // preserved as closely as possible. If |size| is empty, the result will be
  90. // empty.
  91. MEDIA_EXPORT gfx::Size ScaleSizeToEncompassTarget(const gfx::Size& size,
  92. const gfx::Size& target);
  93. // Calculates the largest sub-rectangle of a rectangle of size |size| with
  94. // roughly the same aspect ratio as |target| and centered both horizontally
  95. // and vertically within the rectangle. It's "roughly" the same aspect ratio
  96. // because its dimensions may be rounded down to be a multiple of |alignment|.
  97. // The origin of the rectangle is also aligned down to a multiple of
  98. // |alignment|. Note that |alignment| must be a power of 2.
  99. MEDIA_EXPORT gfx::Rect CropSizeForScalingToTarget(const gfx::Size& size,
  100. const gfx::Size& target,
  101. size_t alignment = 1u);
  102. // Returns the size of a rectangle whose upper left corner is at the origin (0,
  103. // 0) and whose bottom right corner is the same as that of |rect|. This is
  104. // useful to get the size of a buffer that contains the visible rectangle plus
  105. // the non-visible area above and to the left of the visible rectangle.
  106. //
  107. // An example to illustrate: suppose the visible rectangle of a decoded frame is
  108. // 10,10,100,100. The size of this rectangle is 90x90. However, we need to
  109. // create a texture of size 100x100 because the client will want to sample from
  110. // the texture starting with uv coordinates corresponding to 10,10.
  111. MEDIA_EXPORT gfx::Size GetRectSizeFromOrigin(const gfx::Rect& rect);
  112. // Returns |size| with only one of its dimensions increased such that the result
  113. // matches the aspect ratio of |target|. This is different from
  114. // ScaleSizeToEncompassTarget() in two ways: 1) The goal is to match the aspect
  115. // ratio of |target| rather than that of |size|. 2) Only one of the dimensions
  116. // of |size| may change, and it may only be increased (padded). If either
  117. // |size| or |target| is empty, the result will be empty.
  118. MEDIA_EXPORT gfx::Size PadToMatchAspectRatio(const gfx::Size& size,
  119. const gfx::Size& target);
  120. // A helper function to map GpuMemoryBuffer-based VideoFrame. This function
  121. // maps the given GpuMemoryBuffer of |frame| as-is without converting pixel
  122. // format, unless the video frame is backed by DXGI GMB.
  123. // The returned VideoFrame owns the |frame|.
  124. // If the underlying buffer is DXGI, then it will be copied to shared memory
  125. // in GPU process.
  126. MEDIA_EXPORT scoped_refptr<VideoFrame> ConvertToMemoryMappedFrame(
  127. scoped_refptr<VideoFrame> frame);
  128. // This function synchronously reads pixel data from textures associated with
  129. // |txt_frame| and creates a new CPU memory backed frame. It's needed because
  130. // existing video encoders can't handle texture backed frames.
  131. //
  132. // TODO(crbug.com/1162530): Combine this function with
  133. // media::ConvertAndScaleFrame and put it into a new class
  134. // media:FrameSizeAndFormatConverter.
  135. MEDIA_EXPORT scoped_refptr<VideoFrame> ReadbackTextureBackedFrameToMemorySync(
  136. const VideoFrame& txt_frame,
  137. gpu::raster::RasterInterface* ri,
  138. GrDirectContext* gr_context,
  139. VideoFramePool* pool = nullptr);
  140. // Synchronously reads a single plane. |src_rect| is relative to the plane,
  141. // which may be smaller than |frame| due to subsampling.
  142. MEDIA_EXPORT bool ReadbackTexturePlaneToMemorySync(
  143. const VideoFrame& src_frame,
  144. size_t src_plane,
  145. gfx::Rect& src_rect,
  146. uint8_t* dest_pixels,
  147. size_t dest_stride,
  148. gpu::raster::RasterInterface* ri,
  149. GrDirectContext* gr_context);
  150. // Converts a frame with I420A format into I420 by dropping alpha channel.
  151. MEDIA_EXPORT scoped_refptr<VideoFrame> WrapAsI420VideoFrame(
  152. scoped_refptr<VideoFrame> frame);
  153. // Copy I420 video frame to match the required coded size and pad the region
  154. // outside the visible rect repeatly with the last column / row up to the coded
  155. // size of |dst_frame|. Return false when |dst_frame| is empty or visible rect
  156. // is empty.
  157. // One application is content mirroring using HW encoder. As the required coded
  158. // size for encoder is unknown before capturing, memory copy is needed when the
  159. // coded size does not match the requirement. Padding can improve the encoding
  160. // efficiency in this case, as the encoder will encode the whole coded region.
  161. // Performance-wise, this function could be expensive as it does memory copy of
  162. // the whole visible rect.
  163. // Note:
  164. // 1. |src_frame| and |dst_frame| should have same size of visible rect.
  165. // 2. The visible rect's origin of |dst_frame| should be (0,0).
  166. // 3. |dst_frame|'s coded size (both width and height) should be larger than or
  167. // equal to the visible size, since the visible region in both frames should be
  168. // identical.
  169. [[nodiscard]] MEDIA_EXPORT bool I420CopyWithPadding(const VideoFrame& src_frame,
  170. VideoFrame* dst_frame);
  171. // Copy pixel data from |src_frame| to |dst_frame| applying scaling and pixel
  172. // format conversion as needed. Both frames need to be mappabale and have either
  173. // I420 or NV12 pixel format.
  174. [[nodiscard]] MEDIA_EXPORT EncoderStatus
  175. ConvertAndScaleFrame(const VideoFrame& src_frame,
  176. VideoFrame& dst_frame,
  177. std::vector<uint8_t>& tmp_buf);
  178. // Converts kRGBA_8888_SkColorType and kBGRA_8888_SkColorType to the appropriate
  179. // ARGB, XRGB, ABGR, or XBGR format.
  180. MEDIA_EXPORT VideoPixelFormat
  181. VideoPixelFormatFromSkColorType(SkColorType sk_color_type, bool is_opaque);
  182. // Backs a VideoFrame with a SkImage. The created frame takes a ref on the
  183. // provided SkImage to make this operation zero copy. Only works with CPU
  184. // backed images.
  185. MEDIA_EXPORT scoped_refptr<VideoFrame> CreateFromSkImage(
  186. sk_sp<SkImage> sk_image,
  187. const gfx::Rect& visible_rect,
  188. const gfx::Size& natural_size,
  189. base::TimeDelta timestamp,
  190. bool force_opaque = false);
  191. } // namespace media
  192. #endif // MEDIA_BASE_VIDEO_UTIL_H_