| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 }; | 40 }; |
| 41 | 41 |
| 42 // This class is used to interact directly with DeckLink SDK for video capture. | 42 // This class is used to interact directly with DeckLink SDK for video capture. |
| 43 // Implements the reference counted interface IUnknown. Has a weak reference to | 43 // Implements the reference counted interface IUnknown. Has a weak reference to |
| 44 // VideoCaptureDeviceDeckLinkMac for sending captured frames, error messages and | 44 // VideoCaptureDeviceDeckLinkMac for sending captured frames, error messages and |
| 45 // logs. | 45 // logs. |
| 46 class DeckLinkCaptureDelegate | 46 class DeckLinkCaptureDelegate |
| 47 : public IDeckLinkInputCallback, | 47 : public IDeckLinkInputCallback, |
| 48 public base::RefCountedThreadSafe<DeckLinkCaptureDelegate> { | 48 public base::RefCountedThreadSafe<DeckLinkCaptureDelegate> { |
| 49 public: | 49 public: |
| 50 DeckLinkCaptureDelegate(const media::VideoCaptureDevice::Name& device_name, | 50 DeckLinkCaptureDelegate( |
| 51 media::VideoCaptureDeviceDeckLinkMac* frame_receiver); | 51 const media::VideoCaptureDeviceDescriptor& device_descriptor, |
| 52 media::VideoCaptureDeviceDeckLinkMac* frame_receiver); |
| 52 | 53 |
| 53 void AllocateAndStart(const media::VideoCaptureParams& params); | 54 void AllocateAndStart(const media::VideoCaptureParams& params); |
| 54 void StopAndDeAllocate(); | 55 void StopAndDeAllocate(); |
| 55 | 56 |
| 56 // Remove the VideoCaptureDeviceDeckLinkMac's weak reference. | 57 // Remove the VideoCaptureDeviceDeckLinkMac's weak reference. |
| 57 void ResetVideoCaptureDeviceReference(); | 58 void ResetVideoCaptureDeviceReference(); |
| 58 | 59 |
| 59 private: | 60 private: |
| 60 // IDeckLinkInputCallback interface implementation. | 61 // IDeckLinkInputCallback interface implementation. |
| 61 HRESULT VideoInputFormatChanged( | 62 HRESULT VideoInputFormatChanged( |
| 62 BMDVideoInputFormatChangedEvents notification_events, | 63 BMDVideoInputFormatChangedEvents notification_events, |
| 63 IDeckLinkDisplayMode* new_display_mode, | 64 IDeckLinkDisplayMode* new_display_mode, |
| 64 BMDDetectedVideoInputFormatFlags detected_signal_flags) override; | 65 BMDDetectedVideoInputFormatFlags detected_signal_flags) override; |
| 65 HRESULT VideoInputFrameArrived( | 66 HRESULT VideoInputFrameArrived( |
| 66 IDeckLinkVideoInputFrame* video_frame, | 67 IDeckLinkVideoInputFrame* video_frame, |
| 67 IDeckLinkAudioInputPacket* audio_packet) override; | 68 IDeckLinkAudioInputPacket* audio_packet) override; |
| 68 | 69 |
| 69 // IUnknown interface implementation. | 70 // IUnknown interface implementation. |
| 70 HRESULT QueryInterface(REFIID iid, void** ppv) override; | 71 HRESULT QueryInterface(REFIID iid, void** ppv) override; |
| 71 ULONG AddRef() override; | 72 ULONG AddRef() override; |
| 72 ULONG Release() override; | 73 ULONG Release() override; |
| 73 | 74 |
| 74 // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString(). | 75 // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString(). |
| 75 void SendErrorString(const tracked_objects::Location& from_here, | 76 void SendErrorString(const tracked_objects::Location& from_here, |
| 76 const std::string& reason); | 77 const std::string& reason); |
| 77 | 78 |
| 78 // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString(). | 79 // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString(). |
| 79 void SendLogString(const std::string& message); | 80 void SendLogString(const std::string& message); |
| 80 | 81 |
| 81 const media::VideoCaptureDevice::Name device_name_; | 82 const media::VideoCaptureDeviceDescriptor device_descriptor_; |
| 82 | 83 |
| 83 // Protects concurrent setting and using of |frame_receiver_|. | 84 // Protects concurrent setting and using of |frame_receiver_|. |
| 84 base::Lock lock_; | 85 base::Lock lock_; |
| 85 // Weak reference to the captured frames client, used also for error messages | 86 // Weak reference to the captured frames client, used also for error messages |
| 86 // and logging. Initialized on construction and used until cleared by calling | 87 // and logging. Initialized on construction and used until cleared by calling |
| 87 // ResetVideoCaptureDeviceReference(). | 88 // ResetVideoCaptureDeviceReference(). |
| 88 media::VideoCaptureDeviceDeckLinkMac* frame_receiver_; | 89 media::VideoCaptureDeviceDeckLinkMac* frame_receiver_; |
| 89 | 90 |
| 90 // This is used to control the video capturing device input interface. | 91 // This is used to control the video capturing device input interface. |
| 91 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_; | 92 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 116 // Interlaced formats are going to be marked as double the frame rate, | 117 // Interlaced formats are going to be marked as double the frame rate, |
| 117 // which follows the general naming convention. | 118 // which follows the general naming convention. |
| 118 if (display_mode->GetFieldDominance() == bmdLowerFieldFirst || | 119 if (display_mode->GetFieldDominance() == bmdLowerFieldFirst || |
| 119 display_mode->GetFieldDominance() == bmdUpperFieldFirst) { | 120 display_mode->GetFieldDominance() == bmdUpperFieldFirst) { |
| 120 display_mode_frame_rate *= 2.0f; | 121 display_mode_frame_rate *= 2.0f; |
| 121 } | 122 } |
| 122 return display_mode_frame_rate; | 123 return display_mode_frame_rate; |
| 123 } | 124 } |
| 124 | 125 |
| 125 DeckLinkCaptureDelegate::DeckLinkCaptureDelegate( | 126 DeckLinkCaptureDelegate::DeckLinkCaptureDelegate( |
| 126 const media::VideoCaptureDevice::Name& device_name, | 127 const media::VideoCaptureDeviceDescriptor& device_descriptor, |
| 127 media::VideoCaptureDeviceDeckLinkMac* frame_receiver) | 128 media::VideoCaptureDeviceDeckLinkMac* frame_receiver) |
| 128 : device_name_(device_name), frame_receiver_(frame_receiver) { | 129 : device_descriptor_(device_descriptor), frame_receiver_(frame_receiver) {} |
| 129 } | |
| 130 | 130 |
| 131 DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate() { | 131 DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate() { |
| 132 } | 132 } |
| 133 | 133 |
| 134 void DeckLinkCaptureDelegate::AllocateAndStart( | 134 void DeckLinkCaptureDelegate::AllocateAndStart( |
| 135 const media::VideoCaptureParams& params) { | 135 const media::VideoCaptureParams& params) { |
| 136 DCHECK(thread_checker_.CalledOnValidThread()); | 136 DCHECK(thread_checker_.CalledOnValidThread()); |
| 137 scoped_refptr<IDeckLinkIterator> decklink_iter( | 137 scoped_refptr<IDeckLinkIterator> decklink_iter( |
| 138 CreateDeckLinkIteratorInstance()); | 138 CreateDeckLinkIteratorInstance()); |
| 139 DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; | 139 DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; |
| 140 if (!decklink_iter.get()) | 140 if (!decklink_iter.get()) |
| 141 return; | 141 return; |
| 142 | 142 |
| 143 ScopedDeckLinkPtr<IDeckLink> decklink_local; | 143 ScopedDeckLinkPtr<IDeckLink> decklink_local; |
| 144 while (decklink_iter->Next(decklink_local.Receive()) == S_OK) { | 144 while (decklink_iter->Next(decklink_local.Receive()) == S_OK) { |
| 145 CFStringRef device_model_name = NULL; | 145 CFStringRef device_model_name = NULL; |
| 146 if ((decklink_local->GetModelName(&device_model_name) == S_OK) || | 146 if ((decklink_local->GetModelName(&device_model_name) == S_OK) || |
| 147 (device_name_.id() == base::SysCFStringRefToUTF8(device_model_name))) { | 147 (device_descriptor_.device_id == |
| 148 base::SysCFStringRefToUTF8(device_model_name))) { |
| 148 break; | 149 break; |
| 149 } | 150 } |
| 150 } | 151 } |
| 151 if (!decklink_local.get()) { | 152 if (!decklink_local.get()) { |
| 152 SendErrorString(FROM_HERE, "Device id not found in the system"); | 153 SendErrorString(FROM_HERE, "Device id not found in the system"); |
| 153 return; | 154 return; |
| 154 } | 155 } |
| 155 | 156 |
| 156 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_local; | 157 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_local; |
| 157 if (decklink_local->QueryInterface( | 158 if (decklink_local->QueryInterface( |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 namespace media { | 333 namespace media { |
| 333 | 334 |
| 334 static std::string JoinDeviceNameAndFormat(CFStringRef name, | 335 static std::string JoinDeviceNameAndFormat(CFStringRef name, |
| 335 CFStringRef format) { | 336 CFStringRef format) { |
| 336 return base::SysCFStringRefToUTF8(name) + " - " + | 337 return base::SysCFStringRefToUTF8(name) + " - " + |
| 337 base::SysCFStringRefToUTF8(format); | 338 base::SysCFStringRefToUTF8(format); |
| 338 } | 339 } |
| 339 | 340 |
| 340 // static | 341 // static |
| 341 void VideoCaptureDeviceDeckLinkMac::EnumerateDevices( | 342 void VideoCaptureDeviceDeckLinkMac::EnumerateDevices( |
| 342 VideoCaptureDevice::Names* device_names) { | 343 VideoCaptureDeviceDescriptors* device_descriptors) { |
| 343 scoped_refptr<IDeckLinkIterator> decklink_iter( | 344 scoped_refptr<IDeckLinkIterator> decklink_iter( |
| 344 CreateDeckLinkIteratorInstance()); | 345 CreateDeckLinkIteratorInstance()); |
| 345 // At this point, not being able to create a DeckLink iterator means that | 346 // At this point, not being able to create a DeckLink iterator means that |
| 346 // there are no Blackmagic DeckLink devices in the system, don't print error. | 347 // there are no Blackmagic DeckLink devices in the system, don't print error. |
| 347 DVLOG_IF(1, !decklink_iter.get()) << "Could not create DeckLink iterator"; | 348 DVLOG_IF(1, !decklink_iter.get()) << "Could not create DeckLink iterator"; |
| 348 if (!decklink_iter.get()) | 349 if (!decklink_iter.get()) |
| 349 return; | 350 return; |
| 350 | 351 |
| 351 ScopedDeckLinkPtr<IDeckLink> decklink; | 352 ScopedDeckLinkPtr<IDeckLink> decklink; |
| 352 while (decklink_iter->Next(decklink.Receive()) == S_OK) { | 353 while (decklink_iter->Next(decklink.Receive()) == S_OK) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 375 ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; | 376 ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; |
| 376 if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) != | 377 if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) != |
| 377 S_OK) { | 378 S_OK) { |
| 378 continue; | 379 continue; |
| 379 } | 380 } |
| 380 | 381 |
| 381 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; | 382 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; |
| 382 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { | 383 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { |
| 383 CFStringRef format_name = NULL; | 384 CFStringRef format_name = NULL; |
| 384 if (display_mode->GetName(&format_name) == S_OK) { | 385 if (display_mode->GetName(&format_name) == S_OK) { |
| 385 VideoCaptureDevice::Name name( | 386 VideoCaptureDeviceDescriptor descriptor; |
| 386 JoinDeviceNameAndFormat(device_display_name, format_name), | 387 descriptor.friendly_name = |
| 387 JoinDeviceNameAndFormat(device_model_name, format_name), | 388 JoinDeviceNameAndFormat(device_display_name, format_name); |
| 388 VideoCaptureDevice::Name::DECKLINK, | 389 descriptor.device_id = |
| 389 VideoCaptureDevice::Name::OTHER_TRANSPORT); | 390 JoinDeviceNameAndFormat(device_model_name, format_name); |
| 390 device_names->push_back(name); | 391 descriptor.capture_api = VideoCaptureApiType::MACOSX_DECKLINK; |
| 391 DVLOG(1) << "Blackmagic camera enumerated: " << name.name(); | 392 descriptor.transport_type = VideoCaptureTransportType::OTHER_TRANSPORT; |
| 393 device_descriptors->push_back(descriptor); |
| 394 DVLOG(1) << "Blackmagic camera enumerated: " |
| 395 << descriptor.friendly_name; |
| 392 } | 396 } |
| 393 display_mode.Release(); | 397 display_mode.Release(); |
| 394 } | 398 } |
| 395 } | 399 } |
| 396 } | 400 } |
| 397 | 401 |
| 398 // static | 402 // static |
| 399 void VideoCaptureDeviceDeckLinkMac::EnumerateDeviceCapabilities( | 403 void VideoCaptureDeviceDeckLinkMac::EnumerateDeviceCapabilities( |
| 400 const VideoCaptureDevice::Name& device, | 404 const VideoCaptureDeviceDescriptor& device, |
| 401 VideoCaptureFormats* supported_formats) { | 405 VideoCaptureFormats* supported_formats) { |
| 402 scoped_refptr<IDeckLinkIterator> decklink_iter( | 406 scoped_refptr<IDeckLinkIterator> decklink_iter( |
| 403 CreateDeckLinkIteratorInstance()); | 407 CreateDeckLinkIteratorInstance()); |
| 404 DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; | 408 DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; |
| 405 if (!decklink_iter.get()) | 409 if (!decklink_iter.get()) |
| 406 return; | 410 return; |
| 407 | 411 |
| 408 ScopedDeckLinkPtr<IDeckLink> decklink; | 412 ScopedDeckLinkPtr<IDeckLink> decklink; |
| 409 while (decklink_iter->Next(decklink.Receive()) == S_OK) { | 413 while (decklink_iter->Next(decklink.Receive()) == S_OK) { |
| 410 ScopedDeckLinkPtr<IDeckLink> decklink_local; | 414 ScopedDeckLinkPtr<IDeckLink> decklink_local; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 424 } | 428 } |
| 425 | 429 |
| 426 CFStringRef device_model_name = NULL; | 430 CFStringRef device_model_name = NULL; |
| 427 if (decklink_local->GetModelName(&device_model_name) != S_OK) | 431 if (decklink_local->GetModelName(&device_model_name) != S_OK) |
| 428 continue; | 432 continue; |
| 429 | 433 |
| 430 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; | 434 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; |
| 431 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { | 435 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { |
| 432 CFStringRef format_name = NULL; | 436 CFStringRef format_name = NULL; |
| 433 if (display_mode->GetName(&format_name) == S_OK && | 437 if (display_mode->GetName(&format_name) == S_OK && |
| 434 device.id() != | 438 device.device_id != |
| 435 JoinDeviceNameAndFormat(device_model_name, format_name)) { | 439 JoinDeviceNameAndFormat(device_model_name, format_name)) { |
| 436 display_mode.Release(); | 440 display_mode.Release(); |
| 437 continue; | 441 continue; |
| 438 } | 442 } |
| 439 | 443 |
| 440 // IDeckLinkDisplayMode does not have information on pixel format, this | 444 // IDeckLinkDisplayMode does not have information on pixel format, this |
| 441 // is only available on capture. | 445 // is only available on capture. |
| 442 const media::VideoCaptureFormat format( | 446 const media::VideoCaptureFormat format( |
| 443 gfx::Size(display_mode->GetWidth(), display_mode->GetHeight()), | 447 gfx::Size(display_mode->GetWidth(), display_mode->GetHeight()), |
| 444 GetDisplayModeFrameRate(display_mode), | 448 GetDisplayModeFrameRate(display_mode), |
| 445 PIXEL_FORMAT_UNKNOWN); | 449 PIXEL_FORMAT_UNKNOWN); |
| 446 supported_formats->push_back(format); | 450 supported_formats->push_back(format); |
| 447 DVLOG(2) << device.name() << " " << VideoCaptureFormat::ToString(format); | 451 DVLOG(2) << device.friendly_name << " " |
| 452 << VideoCaptureFormat::ToString(format); |
| 448 display_mode.Release(); | 453 display_mode.Release(); |
| 449 } | 454 } |
| 450 return; | 455 return; |
| 451 } | 456 } |
| 452 } | 457 } |
| 453 | 458 |
| 454 VideoCaptureDeviceDeckLinkMac::VideoCaptureDeviceDeckLinkMac( | 459 VideoCaptureDeviceDeckLinkMac::VideoCaptureDeviceDeckLinkMac( |
| 455 const Name& device_name) | 460 const VideoCaptureDeviceDescriptor& device_descriptor) |
| 456 : decklink_capture_delegate_( | 461 : decklink_capture_delegate_( |
| 457 new DeckLinkCaptureDelegate(device_name, this)) { | 462 new DeckLinkCaptureDelegate(device_descriptor, this)) {} |
| 458 } | |
| 459 | 463 |
| 460 VideoCaptureDeviceDeckLinkMac::~VideoCaptureDeviceDeckLinkMac() { | 464 VideoCaptureDeviceDeckLinkMac::~VideoCaptureDeviceDeckLinkMac() { |
| 461 decklink_capture_delegate_->ResetVideoCaptureDeviceReference(); | 465 decklink_capture_delegate_->ResetVideoCaptureDeviceReference(); |
| 462 } | 466 } |
| 463 | 467 |
| 464 void VideoCaptureDeviceDeckLinkMac::OnIncomingCapturedData( | 468 void VideoCaptureDeviceDeckLinkMac::OnIncomingCapturedData( |
| 465 const uint8_t* data, | 469 const uint8_t* data, |
| 466 size_t length, | 470 size_t length, |
| 467 const VideoCaptureFormat& frame_format, | 471 const VideoCaptureFormat& frame_format, |
| 468 int rotation, // Clockwise. | 472 int rotation, // Clockwise. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 499 if (decklink_capture_delegate_.get()) | 503 if (decklink_capture_delegate_.get()) |
| 500 decklink_capture_delegate_->AllocateAndStart(params); | 504 decklink_capture_delegate_->AllocateAndStart(params); |
| 501 } | 505 } |
| 502 | 506 |
| 503 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { | 507 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { |
| 504 if (decklink_capture_delegate_.get()) | 508 if (decklink_capture_delegate_.get()) |
| 505 decklink_capture_delegate_->StopAndDeAllocate(); | 509 decklink_capture_delegate_->StopAndDeAllocate(); |
| 506 } | 510 } |
| 507 | 511 |
| 508 } // namespace media | 512 } // namespace media |
| OLD | NEW |