| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 if (error.Error() != S_OK) { | 111 if (error.Error() != S_OK) { |
| 112 LOG(LS_ERROR) << "Failed to release frame from IDXGIOutputDuplication, " | 112 LOG(LS_ERROR) << "Failed to release frame from IDXGIOutputDuplication, " |
| 113 "error" | 113 "error" |
| 114 << error.ErrorMessage() << ", code " << error.Error(); | 114 << error.ErrorMessage() << ", code " << error.Error(); |
| 115 return false; | 115 return false; |
| 116 } | 116 } |
| 117 return true; | 117 return true; |
| 118 } | 118 } |
| 119 | 119 |
| 120 bool DxgiOutputDuplicator::Duplicate(Context* context, | 120 bool DxgiOutputDuplicator::Duplicate(Context* context, |
| 121 const DesktopFrame* last_frame, | |
| 122 const DesktopVector offset, | 121 const DesktopVector offset, |
| 123 DesktopFrame* target) { | 122 SharedDesktopFrame* target) { |
| 124 RTC_DCHECK(duplication_); | 123 RTC_DCHECK(duplication_); |
| 125 RTC_DCHECK(texture_); | 124 RTC_DCHECK(texture_); |
| 126 RTC_DCHECK(target); | 125 RTC_DCHECK(target); |
| 126 if (!DesktopRect::MakeSize(target->size()) |
| 127 .ContainsRect(TranslatedDesktopRect(offset))) { |
| 128 // target size is not large enough to cover current output region. |
| 129 return false; |
| 130 } |
| 131 |
| 127 DXGI_OUTDUPL_FRAME_INFO frame_info; | 132 DXGI_OUTDUPL_FRAME_INFO frame_info; |
| 128 memset(&frame_info, 0, sizeof(frame_info)); | 133 memset(&frame_info, 0, sizeof(frame_info)); |
| 129 ComPtr<IDXGIResource> resource; | 134 ComPtr<IDXGIResource> resource; |
| 130 _com_error error = duplication_->AcquireNextFrame( | 135 _com_error error = duplication_->AcquireNextFrame( |
| 131 kAcquireTimeoutMs, &frame_info, resource.GetAddressOf()); | 136 kAcquireTimeoutMs, &frame_info, resource.GetAddressOf()); |
| 132 if (error.Error() != S_OK && error.Error() != DXGI_ERROR_WAIT_TIMEOUT) { | 137 if (error.Error() != S_OK && error.Error() != DXGI_ERROR_WAIT_TIMEOUT) { |
| 133 LOG(LS_ERROR) << "Failed to capture frame, error " << error.ErrorMessage() | 138 LOG(LS_ERROR) << "Failed to capture frame, error " << error.ErrorMessage() |
| 134 << ", code " << error.Error(); | 139 << ", code " << error.Error(); |
| 135 return false; | 140 return false; |
| 136 } | 141 } |
| 137 | 142 |
| 138 // We need to merge updated region with the one from last frame, since current | 143 // We need to merge updated region with the one from last frame, since current |
| 139 // frame contains the content one frame before. Note, this is for double | 144 // frame contains the content one frame before. Note, this is for double |
| 140 // buffering implementation, as what we have in ScreenCapturerWinDirectx. If | 145 // buffering implementation, as what we have in ScreenCapturerWinDirectx. If |
| 141 // a consumer uses single buffering, we should clear context->updated_region | 146 // a consumer uses single buffering, we should clear context->updated_region |
| 142 // after it has been merged to updated_region. | 147 // after it has been merged to updated_region. |
| 143 DesktopRegion updated_region = context->updated_region; | 148 DesktopRegion updated_region; |
| 149 updated_region.Swap(&context->updated_region); |
| 144 if (error.Error() == S_OK && frame_info.AccumulatedFrames > 0) { | 150 if (error.Error() == S_OK && frame_info.AccumulatedFrames > 0) { |
| 145 DetectUpdatedRegion(frame_info, offset, &context->updated_region); | 151 DetectUpdatedRegion(frame_info, offset, &context->updated_region); |
| 152 if (!texture_->CopyFrom(frame_info, resource.Get(), |
| 153 context->updated_region)) { |
| 154 return false; |
| 155 } |
| 146 SpreadContextChange(context); | 156 SpreadContextChange(context); |
| 147 updated_region.AddRegion(context->updated_region); | 157 updated_region.AddRegion(context->updated_region); |
| 148 if (!texture_->CopyFrom(frame_info, resource.Get(), updated_region)) { | |
| 149 return false; | |
| 150 } | |
| 151 | |
| 152 const DesktopFrame& source = texture_->AsDesktopFrame(); | 158 const DesktopFrame& source = texture_->AsDesktopFrame(); |
| 153 DesktopRect target_rect(DesktopRect::MakeSize(target->size())); | |
| 154 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); | 159 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); |
| 155 it.Advance()) { | 160 it.Advance()) { |
| 156 if (!target_rect.ContainsRect(it.rect())) { | |
| 157 // target size is not large enough to copy the pixel from texture. | |
| 158 return false; | |
| 159 } | |
| 160 target->CopyPixelsFrom(source, it.rect().top_left().subtract(offset), | 161 target->CopyPixelsFrom(source, it.rect().top_left().subtract(offset), |
| 161 it.rect()); | 162 it.rect()); |
| 162 } | 163 } |
| 164 last_frame_ = target->Share(); |
| 165 last_frame_offset_ = offset; |
| 163 target->mutable_updated_region()->AddRegion(updated_region); | 166 target->mutable_updated_region()->AddRegion(updated_region); |
| 164 return texture_->Release() && ReleaseFrame(); | 167 return texture_->Release() && ReleaseFrame(); |
| 165 } | 168 } |
| 166 | 169 |
| 167 if (last_frame != nullptr) { | 170 if (last_frame_) { |
| 168 // DxgiOutputDuplicatorContainer::Duplicate() makes sure target size and | |
| 169 // last frame size are consistent. | |
| 170 RTC_DCHECK(target->size().equals(last_frame->size())); | |
| 171 // No change since last frame or AcquireNextFrame() timed out, we will | 171 // No change since last frame or AcquireNextFrame() timed out, we will |
| 172 // export last frame to the target. | 172 // export last frame to the target. |
| 173 context->updated_region.Clear(); | 173 context->updated_region.Clear(); |
| 174 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); | 174 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); |
| 175 it.Advance()) { | 175 it.Advance()) { |
| 176 target->CopyPixelsFrom(*last_frame, it.rect().top_left(), it.rect()); | 176 target->CopyPixelsFrom(*last_frame_, last_frame_offset_, it.rect()); |
| 177 } | 177 } |
| 178 target->mutable_updated_region()->AddRegion(updated_region); | 178 target->mutable_updated_region()->AddRegion(updated_region); |
| 179 } | 179 } |
| 180 // If AcquireNextFrame() failed with timeout error, we do not need to release | 180 // If AcquireNextFrame() failed with timeout error, we do not need to release |
| 181 // the frame. | 181 // the frame. |
| 182 return error.Error() == DXGI_ERROR_WAIT_TIMEOUT || ReleaseFrame(); | 182 return error.Error() == DXGI_ERROR_WAIT_TIMEOUT || ReleaseFrame(); |
| 183 } | 183 } |
| 184 | 184 |
| 185 DesktopRect DxgiOutputDuplicator::TranslatedDesktopRect( | 185 DesktopRect DxgiOutputDuplicator::TranslatedDesktopRect( |
| 186 const DesktopVector offset) { | 186 const DesktopVector offset) { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 | 295 |
| 296 void DxgiOutputDuplicator::SpreadContextChange(const Context* const source) { | 296 void DxgiOutputDuplicator::SpreadContextChange(const Context* const source) { |
| 297 for (Context* dest : contexts_) { | 297 for (Context* dest : contexts_) { |
| 298 if (dest != source) { | 298 if (dest != source) { |
| 299 dest->updated_region.AddRegion(source->updated_region); | 299 dest->updated_region.AddRegion(source->updated_region); |
| 300 } | 300 } |
| 301 } | 301 } |
| 302 } | 302 } |
| 303 | 303 |
| 304 } // namespace webrtc | 304 } // namespace webrtc |
| OLD | NEW |