VideoFrameAdapter.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include "pch.h"
  2. #include <api/video/video_frame.h>
  3. #include "VideoFrameAdapter.h"
  4. namespace unity
  5. {
  6. namespace webrtc
  7. {
  8. template<typename T>
  9. bool Contains(rtc::ArrayView<T> arr, T value)
  10. {
  11. for (auto e : arr)
  12. {
  13. if (e == value)
  14. return true;
  15. }
  16. return false;
  17. }
  18. ::webrtc::VideoFrame VideoFrameAdapter::CreateVideoFrame(rtc::scoped_refptr<VideoFrame> frame)
  19. {
  20. rtc::scoped_refptr<VideoFrameAdapter> adapter(new rtc::RefCountedObject<VideoFrameAdapter>(std::move(frame)));
  21. return ::webrtc::VideoFrame::Builder().set_video_frame_buffer(adapter).build();
  22. }
  23. VideoFrameAdapter::ScaledBuffer::ScaledBuffer(rtc::scoped_refptr<VideoFrameAdapter> parent, int width, int height)
  24. : parent_(parent)
  25. , width_(width)
  26. , height_(height)
  27. {
  28. }
  29. VideoFrameAdapter::ScaledBuffer::~ScaledBuffer() { }
  30. VideoFrameBuffer::Type VideoFrameAdapter::ScaledBuffer::type() const { return parent_->type(); }
  31. rtc::scoped_refptr<webrtc::I420BufferInterface> VideoFrameAdapter::ScaledBuffer::ToI420()
  32. {
  33. return parent_->GetOrCreateFrameBufferForSize(Size(width_, height_))->ToI420();
  34. }
  35. const I420BufferInterface* VideoFrameAdapter::ScaledBuffer::GetI420() const
  36. {
  37. return parent_->GetOrCreateFrameBufferForSize(Size(width_, height_))->GetI420();
  38. }
  39. rtc::scoped_refptr<VideoFrameBuffer>
  40. VideoFrameAdapter::ScaledBuffer::GetMappedFrameBuffer(rtc::ArrayView<VideoFrameBuffer::Type> types)
  41. {
  42. auto buffer = parent_->GetOrCreateFrameBufferForSize(Size(width_, height_));
  43. return Contains(types, buffer->type()) ? buffer : nullptr;
  44. }
  45. rtc::scoped_refptr<VideoFrameBuffer> VideoFrameAdapter::ScaledBuffer::CropAndScale(
  46. int offset_x, int offset_y, int crop_width, int crop_height, int scaled_width, int scaled_height)
  47. {
  48. RTC_NOTREACHED();
  49. return nullptr;
  50. }
  51. VideoFrameAdapter::VideoFrameAdapter(rtc::scoped_refptr<VideoFrame> frame)
  52. : frame_(std::move(frame))
  53. , size_(frame_->size())
  54. {
  55. }
  56. VideoFrameBuffer::Type VideoFrameAdapter::type() const
  57. {
  58. #if UNITY_IOS || UNITY_OSX || UNITY_ANDROID
  59. // todo(kazuki): support for kNative type for mobile platform and macOS.
  60. // Need to pass ObjCFrameBuffer instead of VideoFrameAdapter on macOS/iOS.
  61. // Need to pass AndroidVideoBuffer instead of VideoFrameAdapter on Android.
  62. return VideoFrameBuffer::Type::kI420;
  63. #else
  64. return VideoFrameBuffer::Type::kNative;
  65. #endif
  66. }
  67. const I420BufferInterface* VideoFrameAdapter::GetI420() const
  68. {
  69. return ConvertToVideoFrameBuffer(frame_)->GetI420();
  70. }
  71. rtc::scoped_refptr<I420BufferInterface> VideoFrameAdapter::ToI420()
  72. {
  73. return ConvertToVideoFrameBuffer(frame_)->ToI420();
  74. }
  75. rtc::scoped_refptr<VideoFrameBuffer> VideoFrameAdapter::CropAndScale(
  76. int offset_x, int offset_y, int crop_width, int crop_height, int scaled_width, int scaled_height)
  77. {
  78. return rtc::scoped_refptr<VideoFrameBuffer>(
  79. new rtc::RefCountedObject<ScaledBuffer>(this, scaled_width, scaled_height));
  80. }
  81. rtc::scoped_refptr<VideoFrameBuffer> VideoFrameAdapter::GetOrCreateFrameBufferForSize(const Size& size)
  82. {
  83. std::unique_lock<std::mutex> guard(scaleLock_);
  84. for (auto scaledI420buffer : scaledI40Buffers_)
  85. {
  86. Size bufferSize(scaledI420buffer->width(), scaledI420buffer->height());
  87. if (size == bufferSize)
  88. {
  89. return scaledI420buffer;
  90. }
  91. }
  92. auto buffer = VideoFrameBuffer::CropAndScale(0, 0, width(), height(), size.width(), size.height());
  93. scaledI40Buffers_.push_back(buffer);
  94. RTC_LOG(LS_INFO) << "size.width:" << size.width() << " size.height:" << size.height();
  95. return buffer;
  96. }
  97. rtc::scoped_refptr<I420BufferInterface>
  98. VideoFrameAdapter::ConvertToVideoFrameBuffer(rtc::scoped_refptr<VideoFrame> video_frame) const
  99. {
  100. std::unique_lock<std::mutex> guard(convertLock_);
  101. if (i420Buffer_)
  102. return i420Buffer_;
  103. RTC_DCHECK(video_frame);
  104. RTC_DCHECK(video_frame->HasGpuMemoryBuffer());
  105. auto gmb = video_frame->GetGpuMemoryBuffer();
  106. i420Buffer_ = gmb->ToI420();
  107. return i420Buffer_;
  108. }
  109. }
  110. }