osr_video_consumer.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright (c) 2019 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "atom/browser/osr/osr_video_consumer.h"
  5. #include <utility>
  6. #include "atom/browser/osr/osr_render_widget_host_view.h"
  7. #include "media/base/video_frame_metadata.h"
  8. #include "media/capture/mojom/video_capture_types.mojom.h"
  9. #include "ui/gfx/skbitmap_operations.h"
  10. namespace atom {
  11. OffScreenVideoConsumer::OffScreenVideoConsumer(
  12. OffScreenRenderWidgetHostView* view,
  13. OnPaintCallback callback)
  14. : callback_(callback),
  15. view_(view),
  16. video_capturer_(view->CreateVideoCapturer()),
  17. weak_ptr_factory_(this) {
  18. video_capturer_->SetResolutionConstraints(view_->SizeInPixels(),
  19. view_->SizeInPixels(), true);
  20. video_capturer_->SetAutoThrottlingEnabled(false);
  21. video_capturer_->SetMinSizeChangePeriod(base::TimeDelta());
  22. video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB,
  23. gfx::ColorSpace::CreateREC709());
  24. SetFrameRate(view_->GetFrameRate());
  25. }
  26. OffScreenVideoConsumer::~OffScreenVideoConsumer() = default;
  27. void OffScreenVideoConsumer::SetActive(bool active) {
  28. if (active) {
  29. video_capturer_->Start(this);
  30. } else {
  31. video_capturer_->Stop();
  32. }
  33. }
  34. void OffScreenVideoConsumer::SetFrameRate(int frame_rate) {
  35. video_capturer_->SetMinCapturePeriod(base::TimeDelta::FromSeconds(1) /
  36. frame_rate);
  37. }
  38. void OffScreenVideoConsumer::SizeChanged() {
  39. video_capturer_->SetResolutionConstraints(view_->SizeInPixels(),
  40. view_->SizeInPixels(), true);
  41. video_capturer_->RequestRefreshFrame();
  42. }
  43. void OffScreenVideoConsumer::OnFrameCaptured(
  44. base::ReadOnlySharedMemoryRegion data,
  45. ::media::mojom::VideoFrameInfoPtr info,
  46. const gfx::Rect& update_rect,
  47. const gfx::Rect& content_rect,
  48. viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) {
  49. if (!CheckContentRect(content_rect)) {
  50. gfx::Size view_size = view_->SizeInPixels();
  51. video_capturer_->SetResolutionConstraints(view_size, view_size, true);
  52. video_capturer_->RequestRefreshFrame();
  53. return;
  54. }
  55. if (!data.IsValid()) {
  56. callbacks->Done();
  57. return;
  58. }
  59. base::ReadOnlySharedMemoryMapping mapping = data.Map();
  60. if (!mapping.IsValid()) {
  61. DLOG(ERROR) << "Shared memory mapping failed.";
  62. return;
  63. }
  64. if (mapping.size() <
  65. media::VideoFrame::AllocationSize(info->pixel_format, info->coded_size)) {
  66. DLOG(ERROR) << "Shared memory size was less than expected.";
  67. return;
  68. }
  69. // The SkBitmap's pixels will be marked as immutable, but the installPixels()
  70. // API requires a non-const pointer. So, cast away the const.
  71. void* const pixels = const_cast<void*>(mapping.memory());
  72. // Call installPixels() with a |releaseProc| that: 1) notifies the capturer
  73. // that this consumer has finished with the frame, and 2) releases the shared
  74. // memory mapping.
  75. struct FramePinner {
  76. // Keeps the shared memory that backs |frame_| mapped.
  77. base::ReadOnlySharedMemoryMapping mapping;
  78. // Prevents FrameSinkVideoCapturer from recycling the shared memory that
  79. // backs |frame_|.
  80. viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr releaser;
  81. };
  82. SkBitmap bitmap;
  83. bitmap.installPixels(
  84. SkImageInfo::MakeN32(content_rect.width(), content_rect.height(),
  85. kPremul_SkAlphaType),
  86. pixels,
  87. media::VideoFrame::RowBytes(media::VideoFrame::kARGBPlane,
  88. info->pixel_format, info->coded_size.width()),
  89. [](void* addr, void* context) {
  90. delete static_cast<FramePinner*>(context);
  91. },
  92. new FramePinner{std::move(mapping), std::move(callbacks)});
  93. bitmap.setImmutable();
  94. media::VideoFrameMetadata metadata;
  95. metadata.MergeInternalValuesFrom(info->metadata);
  96. callback_.Run(update_rect, bitmap);
  97. }
  98. void OffScreenVideoConsumer::OnStopped() {}
  99. bool OffScreenVideoConsumer::CheckContentRect(const gfx::Rect& content_rect) {
  100. gfx::Size view_size = view_->SizeInPixels();
  101. gfx::Size content_size = content_rect.size();
  102. if (std::abs(view_size.width() - content_size.width()) > 2) {
  103. return false;
  104. }
  105. if (std::abs(view_size.height() - content_size.height()) > 2) {
  106. return false;
  107. }
  108. return true;
  109. }
  110. } // namespace atom