| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "media/capture/video/mac/video_capture_device_decklink_mac.h" | 5 #include "media/capture/video/mac/video_capture_device_decklink_mac.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
| 9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 10 #include "base/synchronization/lock.h" | 10 #include "base/synchronization/lock.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 HRESULT VideoInputFrameArrived( | 62 HRESULT VideoInputFrameArrived( |
| 63 IDeckLinkVideoInputFrame* video_frame, | 63 IDeckLinkVideoInputFrame* video_frame, |
| 64 IDeckLinkAudioInputPacket* audio_packet) override; | 64 IDeckLinkAudioInputPacket* audio_packet) override; |
| 65 | 65 |
| 66 // IUnknown interface implementation. | 66 // IUnknown interface implementation. |
| 67 HRESULT QueryInterface(REFIID iid, void** ppv) override; | 67 HRESULT QueryInterface(REFIID iid, void** ppv) override; |
| 68 ULONG AddRef() override; | 68 ULONG AddRef() override; |
| 69 ULONG Release() override; | 69 ULONG Release() override; |
| 70 | 70 |
| 71 // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString(). | 71 // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString(). |
| 72 void SendErrorString(const std::string& reason); | 72 void SendErrorString(const tracked_objects::Location& from_here, |
| 73 const std::string& reason); |
| 73 | 74 |
| 74 // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString(). | 75 // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString(). |
| 75 void SendLogString(const std::string& message); | 76 void SendLogString(const std::string& message); |
| 76 | 77 |
| 77 const media::VideoCaptureDevice::Name device_name_; | 78 const media::VideoCaptureDevice::Name device_name_; |
| 78 | 79 |
| 79 // Protects concurrent setting and using of |frame_receiver_|. | 80 // Protects concurrent setting and using of |frame_receiver_|. |
| 80 base::Lock lock_; | 81 base::Lock lock_; |
| 81 // Weak reference to the captured frames client, used also for error messages | 82 // Weak reference to the captured frames client, used also for error messages |
| 82 // and logging. Initialized on construction and used until cleared by calling | 83 // and logging. Initialized on construction and used until cleared by calling |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 | 137 |
| 137 ScopedDeckLinkPtr<IDeckLink> decklink_local; | 138 ScopedDeckLinkPtr<IDeckLink> decklink_local; |
| 138 while (decklink_iter->Next(decklink_local.Receive()) == S_OK) { | 139 while (decklink_iter->Next(decklink_local.Receive()) == S_OK) { |
| 139 CFStringRef device_model_name = NULL; | 140 CFStringRef device_model_name = NULL; |
| 140 if ((decklink_local->GetModelName(&device_model_name) == S_OK) || | 141 if ((decklink_local->GetModelName(&device_model_name) == S_OK) || |
| 141 (device_name_.id() == base::SysCFStringRefToUTF8(device_model_name))) { | 142 (device_name_.id() == base::SysCFStringRefToUTF8(device_model_name))) { |
| 142 break; | 143 break; |
| 143 } | 144 } |
| 144 } | 145 } |
| 145 if (!decklink_local.get()) { | 146 if (!decklink_local.get()) { |
| 146 SendErrorString("Device id not found in the system"); | 147 SendErrorString(FROM_HERE, "Device id not found in the system"); |
| 147 return; | 148 return; |
| 148 } | 149 } |
| 149 | 150 |
| 150 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_local; | 151 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_local; |
| 151 if (decklink_local->QueryInterface( | 152 if (decklink_local->QueryInterface( |
| 152 IID_IDeckLinkInput, decklink_input_local.ReceiveVoid()) != S_OK) { | 153 IID_IDeckLinkInput, decklink_input_local.ReceiveVoid()) != S_OK) { |
| 153 SendErrorString("Error querying input interface."); | 154 SendErrorString(FROM_HERE, "Error querying input interface."); |
| 154 return; | 155 return; |
| 155 } | 156 } |
| 156 | 157 |
| 157 ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; | 158 ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; |
| 158 if (decklink_input_local->GetDisplayModeIterator( | 159 if (decklink_input_local->GetDisplayModeIterator( |
| 159 display_mode_iter.Receive()) != S_OK) { | 160 display_mode_iter.Receive()) != S_OK) { |
| 160 SendErrorString("Error creating Display Mode Iterator"); | 161 SendErrorString(FROM_HERE, "Error creating Display Mode Iterator"); |
| 161 return; | 162 return; |
| 162 } | 163 } |
| 163 | 164 |
| 164 ScopedDeckLinkPtr<IDeckLinkDisplayMode> chosen_display_mode; | 165 ScopedDeckLinkPtr<IDeckLinkDisplayMode> chosen_display_mode; |
| 165 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; | 166 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; |
| 166 float min_diff = FLT_MAX; | 167 float min_diff = FLT_MAX; |
| 167 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { | 168 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { |
| 168 const float diff = labs(display_mode->GetWidth() - | 169 const float diff = labs(display_mode->GetWidth() - |
| 169 params.requested_format.frame_size.width()) + | 170 params.requested_format.frame_size.width()) + |
| 170 labs(params.requested_format.frame_size.height() - | 171 labs(params.requested_format.frame_size.height() - |
| 171 display_mode->GetHeight()) + | 172 display_mode->GetHeight()) + |
| 172 fabs(params.requested_format.frame_rate - | 173 fabs(params.requested_format.frame_rate - |
| 173 GetDisplayModeFrameRate(display_mode)); | 174 GetDisplayModeFrameRate(display_mode)); |
| 174 if (diff < min_diff) { | 175 if (diff < min_diff) { |
| 175 chosen_display_mode = display_mode; | 176 chosen_display_mode = display_mode; |
| 176 min_diff = diff; | 177 min_diff = diff; |
| 177 } | 178 } |
| 178 display_mode.Release(); | 179 display_mode.Release(); |
| 179 } | 180 } |
| 180 if (!chosen_display_mode.get()) { | 181 if (!chosen_display_mode.get()) { |
| 181 SendErrorString("Could not find a display mode"); | 182 SendErrorString(FROM_HERE, "Could not find a display mode"); |
| 182 return; | 183 return; |
| 183 } | 184 } |
| 184 #if !defined(NDEBUG) | 185 #if !defined(NDEBUG) |
| 185 DVLOG(1) << "Requested format: " | 186 DVLOG(1) << "Requested format: " |
| 186 << media::VideoCaptureFormat::ToString(params.requested_format); | 187 << media::VideoCaptureFormat::ToString(params.requested_format); |
| 187 CFStringRef format_name = NULL; | 188 CFStringRef format_name = NULL; |
| 188 if (chosen_display_mode->GetName(&format_name) == S_OK) | 189 if (chosen_display_mode->GetName(&format_name) == S_OK) |
| 189 DVLOG(1) << "Chosen format: " << base::SysCFStringRefToUTF8(format_name); | 190 DVLOG(1) << "Chosen format: " << base::SysCFStringRefToUTF8(format_name); |
| 190 #endif | 191 #endif |
| 191 | 192 |
| 192 // Enable video input. Configure for no input video format change detection, | 193 // Enable video input. Configure for no input video format change detection, |
| 193 // this in turn will disable calls to VideoInputFormatChanged(). | 194 // this in turn will disable calls to VideoInputFormatChanged(). |
| 194 if (decklink_input_local->EnableVideoInput( | 195 if (decklink_input_local->EnableVideoInput( |
| 195 chosen_display_mode->GetDisplayMode(), bmdFormat8BitYUV, | 196 chosen_display_mode->GetDisplayMode(), bmdFormat8BitYUV, |
| 196 bmdVideoInputFlagDefault) != S_OK) { | 197 bmdVideoInputFlagDefault) != S_OK) { |
| 197 SendErrorString("Could not select the video format we like."); | 198 SendErrorString(FROM_HERE, "Could not select the video format we like."); |
| 198 return; | 199 return; |
| 199 } | 200 } |
| 200 | 201 |
| 201 decklink_input_local->SetCallback(this); | 202 decklink_input_local->SetCallback(this); |
| 202 if (decklink_input_local->StartStreams() != S_OK) | 203 if (decklink_input_local->StartStreams() != S_OK) |
| 203 SendErrorString("Could not start capturing"); | 204 SendErrorString(FROM_HERE, "Could not start capturing"); |
| 204 | 205 |
| 205 decklink_.swap(decklink_local); | 206 decklink_.swap(decklink_local); |
| 206 decklink_input_.swap(decklink_input_local); | 207 decklink_input_.swap(decklink_input_local); |
| 207 } | 208 } |
| 208 | 209 |
| 209 void DeckLinkCaptureDelegate::StopAndDeAllocate() { | 210 void DeckLinkCaptureDelegate::StopAndDeAllocate() { |
| 210 DCHECK(thread_checker_.CalledOnValidThread()); | 211 DCHECK(thread_checker_.CalledOnValidThread()); |
| 211 if (!decklink_input_.get()) | 212 if (!decklink_input_.get()) |
| 212 return; | 213 return; |
| 213 if (decklink_input_->StopStreams() != S_OK) | 214 if (decklink_input_->StopStreams() != S_OK) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 237 media::VideoPixelFormat pixel_format = | 238 media::VideoPixelFormat pixel_format = |
| 238 media::PIXEL_FORMAT_UNKNOWN; | 239 media::PIXEL_FORMAT_UNKNOWN; |
| 239 switch (video_frame->GetPixelFormat()) { | 240 switch (video_frame->GetPixelFormat()) { |
| 240 case bmdFormat8BitYUV: // A.k.a. '2vuy'; | 241 case bmdFormat8BitYUV: // A.k.a. '2vuy'; |
| 241 pixel_format = media::PIXEL_FORMAT_UYVY; | 242 pixel_format = media::PIXEL_FORMAT_UYVY; |
| 242 break; | 243 break; |
| 243 case bmdFormat8BitARGB: | 244 case bmdFormat8BitARGB: |
| 244 pixel_format = media::PIXEL_FORMAT_ARGB; | 245 pixel_format = media::PIXEL_FORMAT_ARGB; |
| 245 break; | 246 break; |
| 246 default: | 247 default: |
| 247 SendErrorString("Unsupported pixel format"); | 248 SendErrorString(FROM_HERE, "Unsupported pixel format"); |
| 248 break; | 249 break; |
| 249 } | 250 } |
| 250 | 251 |
| 251 const media::VideoCaptureFormat capture_format( | 252 const media::VideoCaptureFormat capture_format( |
| 252 gfx::Size(video_frame->GetWidth(), video_frame->GetHeight()), | 253 gfx::Size(video_frame->GetWidth(), video_frame->GetHeight()), |
| 253 0.0f, // Frame rate is not needed for captured data callback. | 254 0.0f, // Frame rate is not needed for captured data callback. |
| 254 pixel_format); | 255 pixel_format); |
| 255 base::AutoLock lock(lock_); | 256 base::AutoLock lock(lock_); |
| 256 if (frame_receiver_) { | 257 if (frame_receiver_) { |
| 257 frame_receiver_->OnIncomingCapturedData( | 258 frame_receiver_->OnIncomingCapturedData( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 281 return 1; | 282 return 1; |
| 282 } | 283 } |
| 283 | 284 |
| 284 ULONG DeckLinkCaptureDelegate::Release() { | 285 ULONG DeckLinkCaptureDelegate::Release() { |
| 285 DCHECK(thread_checker_.CalledOnValidThread()); | 286 DCHECK(thread_checker_.CalledOnValidThread()); |
| 286 bool ret_value = !HasOneRef(); | 287 bool ret_value = !HasOneRef(); |
| 287 base::RefCountedThreadSafe<DeckLinkCaptureDelegate>::Release(); | 288 base::RefCountedThreadSafe<DeckLinkCaptureDelegate>::Release(); |
| 288 return ret_value; | 289 return ret_value; |
| 289 } | 290 } |
| 290 | 291 |
| 291 void DeckLinkCaptureDelegate::SendErrorString(const std::string& reason) { | 292 void DeckLinkCaptureDelegate::SendErrorString( |
| 293 const tracked_objects::Location& from_here, |
| 294 const std::string& reason) { |
| 292 base::AutoLock lock(lock_); | 295 base::AutoLock lock(lock_); |
| 293 if (frame_receiver_) | 296 if (frame_receiver_) |
| 294 frame_receiver_->SendErrorString(reason); | 297 frame_receiver_->SendErrorString(from_here, reason); |
| 295 } | 298 } |
| 296 | 299 |
| 297 void DeckLinkCaptureDelegate::SendLogString(const std::string& message) { | 300 void DeckLinkCaptureDelegate::SendLogString(const std::string& message) { |
| 298 base::AutoLock lock(lock_); | 301 base::AutoLock lock(lock_); |
| 299 if (frame_receiver_) | 302 if (frame_receiver_) |
| 300 frame_receiver_->SendLogString(message); | 303 frame_receiver_->SendLogString(message); |
| 301 } | 304 } |
| 302 | 305 |
| 303 void DeckLinkCaptureDelegate::ResetVideoCaptureDeviceReference() { | 306 void DeckLinkCaptureDelegate::ResetVideoCaptureDeviceReference() { |
| 304 DCHECK(thread_checker_.CalledOnValidThread()); | 307 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 const VideoCaptureFormat& frame_format, | 449 const VideoCaptureFormat& frame_format, |
| 447 int rotation, // Clockwise. | 450 int rotation, // Clockwise. |
| 448 base::TimeTicks timestamp) { | 451 base::TimeTicks timestamp) { |
| 449 base::AutoLock lock(lock_); | 452 base::AutoLock lock(lock_); |
| 450 if (client_) { | 453 if (client_) { |
| 451 client_->OnIncomingCapturedData(data, length, frame_format, rotation, | 454 client_->OnIncomingCapturedData(data, length, frame_format, rotation, |
| 452 timestamp); | 455 timestamp); |
| 453 } | 456 } |
| 454 } | 457 } |
| 455 | 458 |
| 456 void VideoCaptureDeviceDeckLinkMac::SendErrorString(const std::string& reason) { | 459 void VideoCaptureDeviceDeckLinkMac::SendErrorString( |
| 460 const tracked_objects::Location& from_here, |
| 461 const std::string& reason) { |
| 457 DCHECK(thread_checker_.CalledOnValidThread()); | 462 DCHECK(thread_checker_.CalledOnValidThread()); |
| 458 base::AutoLock lock(lock_); | 463 base::AutoLock lock(lock_); |
| 459 if (client_) | 464 if (client_) |
| 460 client_->OnError(reason); | 465 client_->OnError(from_here, reason); |
| 461 } | 466 } |
| 462 | 467 |
| 463 void VideoCaptureDeviceDeckLinkMac::SendLogString(const std::string& message) { | 468 void VideoCaptureDeviceDeckLinkMac::SendLogString(const std::string& message) { |
| 464 DCHECK(thread_checker_.CalledOnValidThread()); | 469 DCHECK(thread_checker_.CalledOnValidThread()); |
| 465 base::AutoLock lock(lock_); | 470 base::AutoLock lock(lock_); |
| 466 if (client_) | 471 if (client_) |
| 467 client_->OnLog(message); | 472 client_->OnLog(message); |
| 468 } | 473 } |
| 469 | 474 |
| 470 void VideoCaptureDeviceDeckLinkMac::AllocateAndStart( | 475 void VideoCaptureDeviceDeckLinkMac::AllocateAndStart( |
| 471 const VideoCaptureParams& params, | 476 const VideoCaptureParams& params, |
| 472 scoped_ptr<VideoCaptureDevice::Client> client) { | 477 scoped_ptr<VideoCaptureDevice::Client> client) { |
| 473 DCHECK(thread_checker_.CalledOnValidThread()); | 478 DCHECK(thread_checker_.CalledOnValidThread()); |
| 474 client_ = client.Pass(); | 479 client_ = client.Pass(); |
| 475 if (decklink_capture_delegate_.get()) | 480 if (decklink_capture_delegate_.get()) |
| 476 decklink_capture_delegate_->AllocateAndStart(params); | 481 decklink_capture_delegate_->AllocateAndStart(params); |
| 477 } | 482 } |
| 478 | 483 |
| 479 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { | 484 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { |
| 480 if (decklink_capture_delegate_.get()) | 485 if (decklink_capture_delegate_.get()) |
| 481 decklink_capture_delegate_->StopAndDeAllocate(); | 486 decklink_capture_delegate_->StopAndDeAllocate(); |
| 482 } | 487 } |
| 483 | 488 |
| 484 } // namespace media | 489 } // namespace media |
| OLD | NEW |