UnityVideoRenderer.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "pch.h"
  2. #include <api/video/i420_buffer.h>
  3. #include "UnityVideoRenderer.h"
  4. namespace unity
  5. {
  6. namespace webrtc
  7. {
  8. UnityVideoRenderer::UnityVideoRenderer(uint32_t id, DelegateVideoFrameResize callback, bool needFlipVertical)
  9. : m_id(id)
  10. , m_last_renderered_timestamp(0)
  11. , m_timestamp(0)
  12. , m_callback(callback)
  13. , m_needFlipVertical(needFlipVertical)
  14. {
  15. DebugLog("Create UnityVideoRenderer Id:%d", id);
  16. }
  17. UnityVideoRenderer::~UnityVideoRenderer()
  18. {
  19. DebugLog("Destroy UnityVideoRenderer Id:%d", m_id);
  20. {
  21. std::unique_lock<std::mutex> lock(m_mutex);
  22. }
  23. }
  24. void UnityVideoRenderer::OnFrame(const webrtc::VideoFrame& frame)
  25. {
  26. rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer = frame.video_frame_buffer();
  27. if (frame_buffer->type() == webrtc::VideoFrameBuffer::Type::kNative)
  28. {
  29. frame_buffer = frame_buffer->ToI420();
  30. }
  31. SetFrameBuffer(frame_buffer, frame.timestamp_us());
  32. }
  33. uint32_t UnityVideoRenderer::GetId() { return m_id; }
  34. rtc::scoped_refptr<webrtc::VideoFrameBuffer> UnityVideoRenderer::GetFrameBuffer()
  35. {
  36. std::unique_lock<std::mutex> lock(m_mutex);
  37. if (!lock.owns_lock())
  38. {
  39. return nullptr;
  40. }
  41. if (m_last_renderered_timestamp == m_timestamp)
  42. {
  43. // skipped copying texture
  44. return nullptr;
  45. }
  46. m_last_renderered_timestamp = m_timestamp;
  47. return m_frameBuffer;
  48. }
  49. void UnityVideoRenderer::SetFrameBuffer(rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer, int64_t timestamp)
  50. {
  51. std::unique_lock<std::mutex> lock(m_mutex);
  52. if (!lock.owns_lock())
  53. {
  54. return;
  55. }
  56. if (m_frameBuffer == nullptr || m_frameBuffer->width() != buffer->width() ||
  57. m_frameBuffer->height() != buffer->height())
  58. {
  59. m_callback(this, buffer->width(), buffer->height());
  60. }
  61. m_frameBuffer = buffer;
  62. m_timestamp = timestamp;
  63. }
  64. void* UnityVideoRenderer::ConvertVideoFrameToTextureAndWriteToBuffer(int width, int height, libyuv::FourCC format)
  65. {
  66. auto frame = GetFrameBuffer();
  67. size_t size = static_cast<size_t>(width * height * 4);
  68. if (tempBuffer.size() != size)
  69. tempBuffer.resize(size);
  70. // return a previous texture buffer when framebuffer is returned null.
  71. if (frame == nullptr)
  72. return tempBuffer.data();
  73. rtc::scoped_refptr<webrtc::I420BufferInterface> i420_buffer;
  74. if (width == frame->width() && height == frame->height())
  75. {
  76. i420_buffer = frame->ToI420();
  77. }
  78. else
  79. {
  80. auto temp = webrtc::I420Buffer::Create(width, height);
  81. temp->ScaleFrom(*frame->ToI420());
  82. i420_buffer = temp;
  83. }
  84. if (m_needFlipVertical)
  85. height = -height;
  86. int result = libyuv::ConvertFromI420(
  87. i420_buffer->DataY(),
  88. i420_buffer->StrideY(),
  89. i420_buffer->DataU(),
  90. i420_buffer->StrideU(),
  91. i420_buffer->DataV(),
  92. i420_buffer->StrideV(),
  93. tempBuffer.data(),
  94. 0,
  95. width,
  96. height,
  97. static_cast<uint32_t>(format));
  98. if (result)
  99. {
  100. RTC_LOG(LS_INFO) << "libyuv::ConvertFromI420 failed. error:" << result;
  101. }
  102. return tempBuffer.data();
  103. }
  104. } // end namespace webrtc
  105. } // end namespace unity