| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/media/capture/desktop_capture_device.h" | 5 #include "content/browser/media/capture/desktop_capture_device.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 storage == media::PIXEL_STORAGE_CPU); | 104 storage == media::PIXEL_STORAGE_CPU); |
| 105 DoResurrectLastOutputBuffer(); | 105 DoResurrectLastOutputBuffer(); |
| 106 return std::unique_ptr<Buffer>(); | 106 return std::unique_ptr<Buffer>(); |
| 107 } | 107 } |
| 108 double GetBufferPoolUtilization() const override { return 0.0; } | 108 double GetBufferPoolUtilization() const override { return 0.0; } |
| 109 }; | 109 }; |
| 110 | 110 |
| 111 // Creates a DesktopFrame that has the first pixel bytes set to | 111 // Creates a DesktopFrame that has the first pixel bytes set to |
| 112 // kFakePixelValueFirst, and the rest of the bytes set to kFakePixelValue, for | 112 // kFakePixelValueFirst, and the rest of the bytes set to kFakePixelValue, for |
| 113 // UnpackedFrame and InvertedFrame verification. | 113 // UnpackedFrame and InvertedFrame verification. |
| 114 webrtc::BasicDesktopFrame* CreateBasicFrame(const webrtc::DesktopSize& size) { | 114 std::unique_ptr<webrtc::BasicDesktopFrame> CreateBasicFrame( |
| 115 webrtc::BasicDesktopFrame* frame = new webrtc::BasicDesktopFrame(size); | 115 const webrtc::DesktopSize& size) { |
| 116 std::unique_ptr<webrtc::BasicDesktopFrame> frame( |
| 117 new webrtc::BasicDesktopFrame(size)); |
| 116 DCHECK_EQ(frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel, | 118 DCHECK_EQ(frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel, |
| 117 frame->stride()); | 119 frame->stride()); |
| 118 memset(frame->data(), | 120 memset(frame->data(), kFakePixelValue, |
| 119 kFakePixelValue, | |
| 120 frame->stride() * frame->size().height()); | 121 frame->stride() * frame->size().height()); |
| 121 memset(frame->data(), | 122 memset(frame->data(), kFakePixelValueFirst, |
| 122 kFakePixelValueFirst, | |
| 123 webrtc::DesktopFrame::kBytesPerPixel); | 123 webrtc::DesktopFrame::kBytesPerPixel); |
| 124 return frame; | 124 return frame; |
| 125 } | 125 } |
| 126 | 126 |
| 127 // DesktopFrame wrapper that flips wrapped frame upside down by inverting | 127 // DesktopFrame wrapper that flips wrapped frame upside down by inverting |
| 128 // stride. | 128 // stride. |
| 129 class InvertedDesktopFrame : public webrtc::DesktopFrame { | 129 class InvertedDesktopFrame : public webrtc::DesktopFrame { |
| 130 public: | 130 public: |
| 131 // Takes ownership of |frame|. | 131 // Takes ownership of |frame|. |
| 132 explicit InvertedDesktopFrame(webrtc::DesktopFrame* frame) | 132 explicit InvertedDesktopFrame(std::unique_ptr<webrtc::DesktopFrame> frame) |
| 133 : webrtc::DesktopFrame( | 133 : webrtc::DesktopFrame( |
| 134 frame->size(), | 134 frame->size(), |
| 135 -frame->stride(), | 135 -frame->stride(), |
| 136 frame->data() + (frame->size().height() - 1) * frame->stride(), | 136 frame->data() + (frame->size().height() - 1) * frame->stride(), |
| 137 frame->shared_memory()), | 137 frame->shared_memory()) { |
| 138 original_frame_(frame) { | |
| 139 set_dpi(frame->dpi()); | 138 set_dpi(frame->dpi()); |
| 140 set_capture_time_ms(frame->capture_time_ms()); | 139 set_capture_time_ms(frame->capture_time_ms()); |
| 141 mutable_updated_region()->Swap(frame->mutable_updated_region()); | 140 mutable_updated_region()->Swap(frame->mutable_updated_region()); |
| 141 original_frame_ = std::move(frame); |
| 142 } | 142 } |
| 143 ~InvertedDesktopFrame() override {} | 143 ~InvertedDesktopFrame() override {} |
| 144 | 144 |
| 145 private: | 145 private: |
| 146 std::unique_ptr<webrtc::DesktopFrame> original_frame_; | 146 std::unique_ptr<webrtc::DesktopFrame> original_frame_; |
| 147 | 147 |
| 148 DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame); | 148 DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame); |
| 149 }; | 149 }; |
| 150 | 150 |
| 151 // DesktopFrame wrapper that copies the input frame and doubles the stride. | 151 // DesktopFrame wrapper that copies the input frame and doubles the stride. |
| 152 class UnpackedDesktopFrame : public webrtc::DesktopFrame { | 152 class UnpackedDesktopFrame : public webrtc::DesktopFrame { |
| 153 public: | 153 public: |
| 154 // Takes ownership of |frame|. | 154 // Takes ownership of |frame|. |
| 155 explicit UnpackedDesktopFrame(webrtc::DesktopFrame* frame) | 155 explicit UnpackedDesktopFrame(std::unique_ptr<webrtc::DesktopFrame> frame) |
| 156 : webrtc::DesktopFrame( | 156 : webrtc::DesktopFrame( |
| 157 frame->size(), | 157 frame->size(), |
| 158 frame->stride() * 2, | 158 frame->stride() * 2, |
| 159 new uint8_t[frame->stride() * 2 * frame->size().height()], | 159 new uint8_t[frame->stride() * 2 * frame->size().height()], |
| 160 NULL) { | 160 nullptr) { |
| 161 memset(data(), kFramePaddingValue, stride() * size().height()); | 161 memset(data(), kFramePaddingValue, stride() * size().height()); |
| 162 CopyPixelsFrom(*frame, | 162 CopyPixelsFrom(*frame, webrtc::DesktopVector(), |
| 163 webrtc::DesktopVector(), | |
| 164 webrtc::DesktopRect::MakeSize(size())); | 163 webrtc::DesktopRect::MakeSize(size())); |
| 165 delete frame; | |
| 166 } | 164 } |
| 167 ~UnpackedDesktopFrame() override { | 165 ~UnpackedDesktopFrame() override { |
| 168 delete[] data_; | 166 delete[] data_; |
| 169 } | 167 } |
| 170 | 168 |
| 171 private: | 169 private: |
| 172 DISALLOW_COPY_AND_ASSIGN(UnpackedDesktopFrame); | 170 DISALLOW_COPY_AND_ASSIGN(UnpackedDesktopFrame); |
| 173 }; | 171 }; |
| 174 | 172 |
| 175 // TODO(sergeyu): Move this to a separate file where it can be reused. | 173 // TODO(sergeyu): Move this to a separate file where it can be reused. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 196 | 194 |
| 197 void Capture(const webrtc::DesktopRegion& region) override { | 195 void Capture(const webrtc::DesktopRegion& region) override { |
| 198 webrtc::DesktopSize size; | 196 webrtc::DesktopSize size; |
| 199 if (frame_index_ % 2 == 0) { | 197 if (frame_index_ % 2 == 0) { |
| 200 size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1); | 198 size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1); |
| 201 } else { | 199 } else { |
| 202 size = webrtc::DesktopSize(kTestFrameWidth2, kTestFrameHeight2); | 200 size = webrtc::DesktopSize(kTestFrameWidth2, kTestFrameHeight2); |
| 203 } | 201 } |
| 204 frame_index_++; | 202 frame_index_++; |
| 205 | 203 |
| 206 webrtc::DesktopFrame* frame = CreateBasicFrame(size); | 204 std::unique_ptr<webrtc::DesktopFrame> frame = CreateBasicFrame(size); |
| 207 | 205 |
| 208 if (generate_inverted_frames_) { | 206 if (generate_inverted_frames_) { |
| 209 frame = new InvertedDesktopFrame(frame); | 207 frame.reset(new InvertedDesktopFrame(std::move(frame))); |
| 210 } else if (generate_cropped_frames_) { | 208 } else if (generate_cropped_frames_) { |
| 211 frame = new UnpackedDesktopFrame(frame); | 209 frame.reset(new UnpackedDesktopFrame(std::move(frame))); |
| 212 } | 210 } |
| 213 callback_->OnCaptureCompleted(frame); | 211 callback_->OnCaptureResult(webrtc::DesktopCapturer::Result::SUCCESS, |
| 212 std::move(frame)); |
| 214 } | 213 } |
| 215 | 214 |
| 216 bool GetScreenList(ScreenList* screens) override { return false; } | 215 bool GetScreenList(ScreenList* screens) override { return false; } |
| 217 | 216 |
| 218 bool SelectScreen(webrtc::ScreenId id) override { return false; } | 217 bool SelectScreen(webrtc::ScreenId id) override { return false; } |
| 219 | 218 |
| 220 private: | 219 private: |
| 221 Callback* callback_; | 220 Callback* callback_; |
| 222 int frame_index_; | 221 int frame_index_; |
| 223 bool generate_inverted_frames_; | 222 bool generate_inverted_frames_; |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 media::PIXEL_FORMAT_I420; | 490 media::PIXEL_FORMAT_I420; |
| 492 | 491 |
| 493 capture_device_->AllocateAndStart(capture_params, std::move(client)); | 492 capture_device_->AllocateAndStart(capture_params, std::move(client)); |
| 494 | 493 |
| 495 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 494 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); |
| 496 done_event.Reset(); | 495 done_event.Reset(); |
| 497 capture_device_->StopAndDeAllocate(); | 496 capture_device_->StopAndDeAllocate(); |
| 498 | 497 |
| 499 // Verifies that |output_frame_| has the same data as a packed frame of the | 498 // Verifies that |output_frame_| has the same data as a packed frame of the |
| 500 // same size. | 499 // same size. |
| 501 std::unique_ptr<webrtc::BasicDesktopFrame> expected_frame(CreateBasicFrame( | 500 std::unique_ptr<webrtc::BasicDesktopFrame> expected_frame = CreateBasicFrame( |
| 502 webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1))); | 501 webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1)); |
| 503 EXPECT_EQ(output_frame_->stride() * output_frame_->size().height(), | 502 EXPECT_EQ(output_frame_->stride() * output_frame_->size().height(), |
| 504 frame_size); | 503 frame_size); |
| 505 EXPECT_EQ( | 504 EXPECT_EQ( |
| 506 0, memcmp(output_frame_->data(), expected_frame->data(), frame_size)); | 505 0, memcmp(output_frame_->data(), expected_frame->data(), frame_size)); |
| 507 } | 506 } |
| 508 | 507 |
| 509 // The test verifies that a bottom-to-top frame is converted to top-to-bottom. | 508 // The test verifies that a bottom-to-top frame is converted to top-to-bottom. |
| 510 TEST_F(DesktopCaptureDeviceTest, InvertedFrame) { | 509 TEST_F(DesktopCaptureDeviceTest, InvertedFrame) { |
| 511 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); | 510 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); |
| 512 mock_capturer->set_generate_inverted_frames(true); | 511 mock_capturer->set_generate_inverted_frames(true); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 frame_size); | 550 frame_size); |
| 552 for (int i = 0; i < output_frame_->size().height(); ++i) { | 551 for (int i = 0; i < output_frame_->size().height(); ++i) { |
| 553 EXPECT_EQ(0, | 552 EXPECT_EQ(0, |
| 554 memcmp(inverted_frame->data() + i * inverted_frame->stride(), | 553 memcmp(inverted_frame->data() + i * inverted_frame->stride(), |
| 555 output_frame_->data() + i * output_frame_->stride(), | 554 output_frame_->data() + i * output_frame_->stride(), |
| 556 output_frame_->stride())); | 555 output_frame_->stride())); |
| 557 } | 556 } |
| 558 } | 557 } |
| 559 | 558 |
| 560 } // namespace content | 559 } // namespace content |
| OLD | NEW |