Chromium Code Reviews| 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/video/capture/mac/video_capture_device_decklink_mac.h" | 5 #include "media/video/capture/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/synchronization/lock.h" | |
| 9 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| 10 #include "third_party/decklink/mac/include/DeckLinkAPI.h" | 11 #include "third_party/decklink/mac/include/DeckLinkAPI.h" |
| 11 | 12 |
| 12 namespace { | 13 namespace { |
| 13 | 14 |
| 14 // DeckLink SDK uses ScopedComPtr-style APIs. Chrome ScopedComPtr is only | 15 // DeckLink SDK uses ScopedComPtr-style APIs. Chrome ScopedComPtr is only |
| 15 // available for Windows builds. This is a verbatim knock-off of the needed | 16 // available for Windows builds. This is a verbatim knock-off of the needed |
| 16 // parts of base::win::ScopedComPtr<> for ref counting. | 17 // parts of base::win::ScopedComPtr<> for ref counting. |
| 17 template <class T> | 18 template <class T> |
| 18 class ScopedDeckLinkPtr : public scoped_refptr<T> { | 19 class ScopedDeckLinkPtr : public scoped_refptr<T> { |
| 19 public: | 20 public: |
| 20 using scoped_refptr<T>::ptr_; | 21 using scoped_refptr<T>::ptr_; |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
see comment about this from a previous patch set
mcasas
2014/09/23 08:54:54
Made private, but I need it there otherwise clang
| |
| 21 | 22 |
| 22 T** Receive() { | 23 T** Receive() { |
| 23 DCHECK(!ptr_) << "Object leak. Pointer must be NULL"; | 24 DCHECK(!ptr_) << "Object leak. Pointer must be NULL"; |
| 24 return &ptr_; | 25 return &ptr_; |
| 25 } | 26 } |
| 26 | 27 |
| 27 void** ReceiveVoid() { | 28 void** ReceiveVoid() { |
| 28 return reinterpret_cast<void**>(Receive()); | 29 return reinterpret_cast<void**>(Receive()); |
| 29 } | 30 } |
| 30 | 31 |
| 31 void Release() { | 32 void Release() { |
| 32 if (ptr_ != NULL) { | 33 if (ptr_ != NULL) { |
| 33 ptr_->Release(); | 34 ptr_->Release(); |
| 34 ptr_ = NULL; | 35 ptr_ = NULL; |
| 35 } | 36 } |
| 36 } | 37 } |
| 37 }; | 38 }; |
| 38 | 39 |
| 40 // This class is used to interact directly with DeckLink SDK for video capture. | |
| 41 // Implements the reference counted interface IUnknown. Has a weak reference to | |
| 42 // VideoCaptureDeviceDeckLinkMac for sending captured frames, error messages and | |
| 43 // logs. | |
| 44 class DeckLinkCaptureDelegate : private IDeckLinkInputCallback { | |
| 45 public: | |
| 46 DeckLinkCaptureDelegate(const media::VideoCaptureDevice::Name& device_name, | |
| 47 media::VideoCaptureDeviceDeckLinkMac* frame_receiver); | |
| 48 virtual ~DeckLinkCaptureDelegate(); | |
| 49 | |
| 50 // IDeckLinkInputCallback interface implementation. | |
| 51 virtual HRESULT VideoInputFormatChanged ( | |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
make all of these private?
mcasas
2014/09/23 08:54:54
Made IDeckLinkInputCallback interface methods priv
tommi (sloooow) - chröme
2014/09/23 12:59:53
ah, makes sense.
(ultra nit could we add scoped_r
mcasas
2014/09/23 15:03:46
Done.
| |
| 52 BMDVideoInputFormatChangedEvents notification_events, | |
| 53 IDeckLinkDisplayMode *new_display_mode, | |
| 54 BMDDetectedVideoInputFormatFlags detected_signal_flags) OVERRIDE; | |
| 55 virtual HRESULT VideoInputFrameArrived ( | |
| 56 IDeckLinkVideoInputFrame* video_frame, | |
| 57 IDeckLinkAudioInputPacket* audio_packet) OVERRIDE; | |
| 58 | |
| 59 // IUnknown interface implementation. | |
| 60 virtual HRESULT QueryInterface (REFIID iid, LPVOID *ppv) OVERRIDE; | |
| 61 virtual ULONG AddRef() OVERRIDE; | |
| 62 virtual ULONG Release() OVERRIDE; | |
| 63 | |
| 64 void AllocateAndStart(const media::VideoCaptureParams& params); | |
| 65 void StopAndDeAllocate(); | |
| 66 | |
| 67 // Remove the VideoCaptureDeviceDeckLinkMac's weak reference. | |
| 68 void ResetVideoCaptureDeviceReference(); | |
| 69 | |
| 70 private: | |
| 71 // Forwarder to VideoCaptureDeviceDeckLinkMac::sendErrorString(). | |
| 72 void sendErrorString(const std::string& reason); | |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
why the lower case 's'?
mcasas
2014/09/23 08:54:54
My bad, that would be Obj-C.
| |
| 73 | |
| 74 // Forwarder to VideoCaptureDeviceDeckLinkMac::sendLogString(). | |
| 75 void sendLogString(const std::string& message); | |
| 76 | |
| 77 const media::VideoCaptureDevice::Name device_name_; | |
| 78 | |
| 79 // Protects concurrent setting and using of |frame_receiver_|. | |
| 80 base::Lock lock_; | |
| 81 media::VideoCaptureDeviceDeckLinkMac* frame_receiver_; // Weak. | |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
explain lifetime?
mcasas
2014/09/23 08:54:54
Done.
| |
| 82 | |
| 83 // This is used to control the video capturing device input interface. | |
| 84 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_; | |
| 85 // |decklink_| represents a physical device attached to the host. | |
| 86 ScopedDeckLinkPtr<IDeckLink> decklink_; | |
| 87 // Internal counter for IUnknown interface implementation. | |
| 88 int32_t ref_count_; | |
| 89 | |
| 90 base::ThreadChecker thread_checker_; | |
| 91 | |
| 92 DISALLOW_COPY_AND_ASSIGN(DeckLinkCaptureDelegate); | |
| 93 }; | |
| 94 | |
| 95 static float GetDisplayModeFrameRate( | |
| 96 const ScopedDeckLinkPtr<IDeckLinkDisplayMode>& display_mode) { | |
| 97 BMDTimeValue time_value, time_scale; | |
| 98 float display_mode_frame_rate = 0.0f; | |
| 99 if (display_mode->GetFrameRate(&time_value, &time_scale) == S_OK && | |
| 100 time_value > 0) { | |
| 101 display_mode_frame_rate = static_cast<float>(time_scale) / time_value; | |
| 102 } | |
| 103 // Interlaced formats are going to be marked as double the frame rate, | |
| 104 // which follows the general naming convention. | |
| 105 if (display_mode->GetFieldDominance() == bmdLowerFieldFirst || | |
| 106 display_mode->GetFieldDominance() == bmdUpperFieldFirst) { | |
| 107 display_mode_frame_rate *= 2.0f; | |
| 108 } | |
| 109 return display_mode_frame_rate; | |
| 110 } | |
| 111 | |
| 112 DeckLinkCaptureDelegate::DeckLinkCaptureDelegate( | |
| 113 const media::VideoCaptureDevice::Name& device_name, | |
| 114 media::VideoCaptureDeviceDeckLinkMac* frame_receiver) | |
| 115 : device_name_(device_name), | |
| 116 frame_receiver_(frame_receiver) { | |
| 117 } | |
| 118 | |
| 119 DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate() {} | |
| 120 | |
| 121 void DeckLinkCaptureDelegate::AllocateAndStart( | |
| 122 const media::VideoCaptureParams& params) { | |
| 123 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 124 scoped_refptr<IDeckLinkIterator> decklink_iter( | |
| 125 CreateDeckLinkIteratorInstance()); | |
| 126 DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; | |
| 127 if (!decklink_iter.get()) | |
| 128 return; | |
| 129 | |
| 130 while (decklink_iter->Next(decklink_.Receive()) == S_OK) { | |
| 131 CFStringRef device_model_name = NULL; | |
| 132 if ((decklink_->GetModelName(&device_model_name) == S_OK) || | |
| 133 (device_name_.id() == base::SysCFStringRefToUTF8(device_model_name))) { | |
| 134 break; | |
| 135 } | |
| 136 decklink_.Release(); | |
| 137 } | |
| 138 if (!decklink_.get()) { | |
| 139 sendErrorString("Device id not found in the system"); | |
| 140 return; | |
| 141 } | |
| 142 | |
| 143 if (decklink_->QueryInterface(IID_IDeckLinkInput, | |
| 144 decklink_input_.ReceiveVoid()) != S_OK) { | |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
indent
mcasas
2014/09/23 08:54:54
Done.
| |
| 145 sendErrorString("Error querying input interface."); | |
| 146 return; | |
| 147 } | |
| 148 | |
| 149 ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; | |
| 150 if (decklink_input_->GetDisplayModeIterator(display_mode_iter.Receive()) != | |
| 151 S_OK) { | |
| 152 sendErrorString("Error creating Display Mode Iterator"); | |
| 153 return; | |
| 154 } | |
| 155 | |
| 156 ScopedDeckLinkPtr<IDeckLinkDisplayMode> chosen_display_mode; | |
| 157 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; | |
| 158 float min_diff = FLT_MAX; | |
| 159 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { | |
| 160 const float diff = abs(display_mode->GetWidth() - | |
| 161 params.requested_format.frame_size.width()) + | |
| 162 abs(params.requested_format.frame_size.height() - | |
| 163 display_mode->GetHeight()) + fabs(params.requested_format.frame_rate - | |
| 164 GetDisplayModeFrameRate(display_mode)); | |
| 165 if (diff < min_diff) { | |
| 166 chosen_display_mode = display_mode; | |
| 167 min_diff = diff; | |
| 168 } | |
| 169 display_mode.Release(); | |
| 170 } | |
| 171 if (!chosen_display_mode.get()) { | |
| 172 sendErrorString("Could not find a display mode"); | |
| 173 return; | |
| 174 } | |
| 175 #if !defined(NDEBUG) | |
| 176 DVLOG(1) << "Requested format: " << params.requested_format.ToString(); | |
| 177 CFStringRef format_name = NULL; | |
| 178 if (chosen_display_mode->GetName(&format_name) == S_OK) | |
| 179 DVLOG(1) << "Chosen format: " << base::SysCFStringRefToUTF8(format_name); | |
| 180 #endif | |
| 181 | |
| 182 // Enable video input. Configure for no input video format change detection, | |
| 183 // this in turn will disable calls to VideoInputFormatChanged(). | |
| 184 if (decklink_input_->EnableVideoInput(chosen_display_mode->GetDisplayMode(), | |
| 185 bmdFormat8BitYUV, bmdVideoInputFlagDefault) != S_OK) { | |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
indent
mcasas
2014/09/23 08:54:54
Done.
| |
| 186 sendErrorString("Could not select the video format we like."); | |
| 187 return; | |
| 188 } | |
| 189 | |
| 190 decklink_input_->SetCallback(this); | |
| 191 if (decklink_input_->StartStreams() != S_OK) | |
| 192 sendErrorString("Could not start capturing"); | |
| 193 } | |
| 194 | |
| 195 void DeckLinkCaptureDelegate::StopAndDeAllocate() { | |
| 196 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 197 if (!decklink_input_.get()) { | |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
no {} (see next 'if')
mcasas
2014/09/23 08:54:54
Done.
| |
| 198 return; | |
| 199 } | |
| 200 if (decklink_input_->StopStreams() != S_OK) | |
| 201 sendLogString("Problem stopping capture."); | |
| 202 decklink_input_->SetCallback(NULL); | |
| 203 decklink_input_->DisableVideoInput(); | |
| 204 ResetVideoCaptureDeviceReference(); | |
| 205 } | |
| 206 | |
| 207 HRESULT DeckLinkCaptureDelegate::VideoInputFormatChanged ( | |
| 208 BMDVideoInputFormatChangedEvents notification_events, | |
| 209 IDeckLinkDisplayMode *new_display_mode, | |
| 210 BMDDetectedVideoInputFormatFlags detected_signal_flags) { | |
| 211 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 212 return S_OK; | |
| 213 } | |
| 214 | |
| 215 HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived ( | |
| 216 IDeckLinkVideoInputFrame* video_frame, | |
| 217 IDeckLinkAudioInputPacket* /* audio_packet */) { | |
| 218 // Capture frames are manipulated as an IDeckLinkVideoFrame. | |
| 219 void *video_data = NULL; | |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
void* video_data = NULL;
should this perhaps be u
mcasas
2014/09/23 08:54:54
Done.
| |
| 220 video_frame->GetBytes(&video_data); | |
| 221 | |
| 222 media::VideoPixelFormat pixel_format = media::PIXEL_FORMAT_UNKNOWN; | |
| 223 switch (video_frame->GetPixelFormat()) { | |
| 224 case bmdFormat8BitYUV: // A.k.a. '2vuy'; | |
| 225 pixel_format = media::PIXEL_FORMAT_UYVY; | |
| 226 break; | |
| 227 case bmdFormat8BitARGB: | |
| 228 pixel_format = media::PIXEL_FORMAT_ARGB; | |
| 229 break; | |
| 230 default: | |
| 231 sendErrorString("Unsupported pixel format"); | |
| 232 break; | |
| 233 } | |
| 234 | |
| 235 const media::VideoCaptureFormat capture_format( | |
| 236 gfx::Size(video_frame->GetWidth(), video_frame->GetHeight()), | |
| 237 0.0f, // Frame rate is not needed for captured data callback. | |
| 238 pixel_format); | |
| 239 base::AutoLock lock(lock_); | |
| 240 if (frame_receiver_) { | |
| 241 frame_receiver_->OnIncomingCapturedData( | |
| 242 static_cast<uint8*>(video_data), | |
| 243 video_frame->GetRowBytes() * video_frame->GetHeight(), | |
| 244 capture_format, | |
| 245 0, // Rotation. | |
| 246 base::TimeTicks::Now()); | |
| 247 } | |
| 248 return S_OK; | |
| 249 } | |
| 250 | |
| 251 HRESULT DeckLinkCaptureDelegate::QueryInterface(REFIID iid, LPVOID *ppv) { | |
| 252 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 253 CFUUIDBytes iunknown = CFUUIDGetUUIDBytes(IUnknownUUID); | |
| 254 if (memcmp(&iid, &iunknown, sizeof(REFIID)) == 0 || | |
| 255 memcmp(&iid, &IID_IDeckLinkNotificationCallback, sizeof(REFIID)) == 0) { | |
| 256 *ppv = reinterpret_cast<IDeckLinkNotificationCallback*>(this); | |
|
tommi (sloooow) - chröme
2014/09/22 20:26:38
static_cast
mcasas
2014/09/23 08:54:54
According to clang,
static_cast from 'DeckLinkCap
tommi (sloooow) - chröme
2014/09/23 12:59:53
yeah, that's because the inheritance was set to 'p
mcasas
2014/09/23 15:03:46
Actually, thanks for insisting here. The code is w
tommi (sloooow) - chröme
2014/09/23 17:15:28
Actually, we still need the cast in there to be sa
| |
| 257 AddRef(); | |
| 258 return S_OK; | |
| 259 } | |
| 260 return E_NOINTERFACE; | |
| 261 } | |
| 262 | |
| 263 ULONG DeckLinkCaptureDelegate::AddRef(void) { | |
| 264 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 265 return OSAtomicIncrement32(&ref_count_); | |
| 266 } | |
| 267 | |
| 268 ULONG DeckLinkCaptureDelegate::Release(void) { | |
| 269 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 270 int32_t newRefValue = OSAtomicDecrement32(&ref_count_); | |
| 271 if (newRefValue == 0) | |
| 272 delete this; | |
| 273 return newRefValue; | |
| 274 } | |
| 275 | |
| 276 void DeckLinkCaptureDelegate::sendErrorString(const std::string& reason) { | |
| 277 base::AutoLock lock(lock_); | |
| 278 if (frame_receiver_) | |
| 279 frame_receiver_->sendErrorString(reason); | |
| 280 } | |
| 281 | |
| 282 void DeckLinkCaptureDelegate::sendLogString(const std::string& message) { | |
| 283 base::AutoLock lock(lock_); | |
| 284 if (frame_receiver_) | |
| 285 frame_receiver_->sendLogString(message); | |
| 286 } | |
| 287 | |
| 288 void DeckLinkCaptureDelegate::ResetVideoCaptureDeviceReference() { | |
| 289 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 290 base::AutoLock lock(lock_); | |
| 291 frame_receiver_ = NULL; | |
| 292 } | |
| 293 | |
| 39 } // namespace | 294 } // namespace |
| 40 | 295 |
| 41 namespace media { | 296 namespace media { |
| 42 | 297 |
| 43 std::string JoinDeviceNameAndFormat(CFStringRef name, CFStringRef format) { | 298 static std::string JoinDeviceNameAndFormat(CFStringRef name, |
| 299 CFStringRef format) { | |
| 44 return base::SysCFStringRefToUTF8(name) + " - " + | 300 return base::SysCFStringRefToUTF8(name) + " - " + |
| 45 base::SysCFStringRefToUTF8(format); | 301 base::SysCFStringRefToUTF8(format); |
| 46 } | 302 } |
| 47 | 303 |
| 48 //static | 304 //static |
| 49 void VideoCaptureDeviceDeckLinkMac::EnumerateDevices( | 305 void VideoCaptureDeviceDeckLinkMac::EnumerateDevices( |
| 50 VideoCaptureDevice::Names* device_names) { | 306 VideoCaptureDevice::Names* device_names) { |
| 51 scoped_refptr<IDeckLinkIterator> decklink_iter( | 307 scoped_refptr<IDeckLinkIterator> decklink_iter( |
| 52 CreateDeckLinkIteratorInstance()); | 308 CreateDeckLinkIteratorInstance()); |
| 53 // At this point, not being able to create a DeckLink iterator means that | 309 // At this point, not being able to create a DeckLink iterator means that |
| 54 // there are no Blackmagic devices in the system but this isn't an error. | 310 // there are no Blackmagic DeckLink devices in the system, don't print error. |
| 55 DVLOG_IF(1, !decklink_iter.get()) << "Could not create DeckLink iterator"; | 311 DVLOG_IF(1, !decklink_iter.get()) << "Could not create DeckLink iterator"; |
| 56 if (!decklink_iter.get()) | 312 if (!decklink_iter.get()) |
| 57 return; | 313 return; |
| 58 | 314 |
| 59 ScopedDeckLinkPtr<IDeckLink> decklink; | 315 ScopedDeckLinkPtr<IDeckLink> decklink; |
| 60 while (decklink_iter->Next(decklink.Receive()) == S_OK) { | 316 while (decklink_iter->Next(decklink.Receive()) == S_OK) { |
| 61 ScopedDeckLinkPtr<IDeckLink> decklink_local; | 317 ScopedDeckLinkPtr<IDeckLink> decklink_local; |
| 62 decklink_local.swap(decklink); | 318 decklink_local.swap(decklink); |
| 63 | 319 |
| 64 CFStringRef device_model_name = NULL; | 320 CFStringRef device_model_name = NULL; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 if (!decklink_iter.get()) | 369 if (!decklink_iter.get()) |
| 114 return; | 370 return; |
| 115 | 371 |
| 116 ScopedDeckLinkPtr<IDeckLink> decklink; | 372 ScopedDeckLinkPtr<IDeckLink> decklink; |
| 117 while (decklink_iter->Next(decklink.Receive()) == S_OK) { | 373 while (decklink_iter->Next(decklink.Receive()) == S_OK) { |
| 118 ScopedDeckLinkPtr<IDeckLink> decklink_local; | 374 ScopedDeckLinkPtr<IDeckLink> decklink_local; |
| 119 decklink_local.swap(decklink); | 375 decklink_local.swap(decklink); |
| 120 | 376 |
| 121 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input; | 377 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input; |
| 122 if (decklink_local->QueryInterface(IID_IDeckLinkInput, | 378 if (decklink_local->QueryInterface(IID_IDeckLinkInput, |
| 123 decklink_input.ReceiveVoid()) != S_OK) { | 379 decklink_input.ReceiveVoid()) != S_OK) { |
| 124 DLOG(ERROR) << "Error Blackmagic querying input interface."; | 380 DLOG(ERROR) << "Error Blackmagic querying input interface."; |
| 125 return; | 381 return; |
| 126 } | 382 } |
| 127 | 383 |
| 128 ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; | 384 ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; |
| 129 if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) != | 385 if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) != |
| 130 S_OK) { | 386 S_OK) { |
| 131 continue; | 387 continue; |
| 132 } | 388 } |
| 133 | 389 |
| 134 CFStringRef device_model_name = NULL; | 390 CFStringRef device_model_name = NULL; |
| 135 if (decklink_local->GetModelName(&device_model_name) != S_OK) | 391 if (decklink_local->GetModelName(&device_model_name) != S_OK) |
| 136 continue; | 392 continue; |
| 137 | 393 |
| 138 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; | 394 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; |
| 139 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { | 395 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { |
| 140 CFStringRef format_name = NULL; | 396 CFStringRef format_name = NULL; |
| 141 if (display_mode->GetName(&format_name) == S_OK && device.id() != | 397 if (display_mode->GetName(&format_name) == S_OK && device.id() != |
| 142 JoinDeviceNameAndFormat(device_model_name, format_name)) { | 398 JoinDeviceNameAndFormat(device_model_name, format_name)) { |
| 143 display_mode.Release(); | 399 display_mode.Release(); |
| 144 continue; | 400 continue; |
| 145 } | 401 } |
| 146 | 402 |
| 147 // IDeckLinkDisplayMode does not have information on pixel format, this | 403 // IDeckLinkDisplayMode does not have information on pixel format, this |
| 148 // is only available on capture. | 404 // is only available on capture. |
| 149 media::VideoPixelFormat pixel_format = media::PIXEL_FORMAT_UNKNOWN; | 405 const media::VideoCaptureFormat format( |
| 150 BMDTimeValue time_value, time_scale; | |
| 151 float frame_rate = 0.0f; | |
| 152 if (display_mode->GetFrameRate(&time_value, &time_scale) == S_OK && | |
| 153 time_value > 0) { | |
| 154 frame_rate = static_cast<float>(time_scale) / time_value; | |
| 155 } | |
| 156 media::VideoCaptureFormat format( | |
| 157 gfx::Size(display_mode->GetWidth(), display_mode->GetHeight()), | 406 gfx::Size(display_mode->GetWidth(), display_mode->GetHeight()), |
| 158 frame_rate, | 407 GetDisplayModeFrameRate(display_mode), |
| 159 pixel_format); | 408 PIXEL_FORMAT_UNKNOWN); |
| 160 supported_formats->push_back(format); | 409 supported_formats->push_back(format); |
| 161 DVLOG(2) << device.name() << " " << format.ToString(); | 410 DVLOG(2) << device.name() << " " << format.ToString(); |
| 162 display_mode.Release(); | 411 display_mode.Release(); |
| 163 } | 412 } |
| 164 return; | 413 return; |
| 165 } | 414 } |
| 166 } | 415 } |
| 167 | 416 |
| 168 VideoCaptureDeviceDeckLinkMac::VideoCaptureDeviceDeckLinkMac( | 417 VideoCaptureDeviceDeckLinkMac::VideoCaptureDeviceDeckLinkMac( |
| 169 const Name& device_name) {} | 418 const Name& device_name) |
| 419 : decklink_capture_delegate_( | |
| 420 new DeckLinkCaptureDelegate(device_name, this)) { | |
| 421 } | |
| 170 | 422 |
| 171 VideoCaptureDeviceDeckLinkMac::~VideoCaptureDeviceDeckLinkMac() {} | 423 VideoCaptureDeviceDeckLinkMac::~VideoCaptureDeviceDeckLinkMac() { |
| 424 decklink_capture_delegate_->ResetVideoCaptureDeviceReference(); | |
| 425 } | |
| 426 | |
| 427 void VideoCaptureDeviceDeckLinkMac::OnIncomingCapturedData( | |
| 428 const uint8* data, | |
| 429 int length, | |
| 430 const VideoCaptureFormat& frame_format, | |
| 431 int rotation, // Clockwise. | |
| 432 base::TimeTicks timestamp) { | |
| 433 base::AutoLock lock(lock_); | |
| 434 if (client_) { | |
| 435 client_->OnIncomingCapturedData(data, length, frame_format, rotation, | |
| 436 timestamp); | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 void VideoCaptureDeviceDeckLinkMac::sendErrorString(const std::string& reason) { | |
| 441 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 442 base::AutoLock lock(lock_); | |
| 443 if (client_) | |
| 444 client_->OnError(reason); | |
| 445 } | |
| 446 | |
| 447 void VideoCaptureDeviceDeckLinkMac::sendLogString(const std::string& message) { | |
| 448 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 449 base::AutoLock lock(lock_); | |
| 450 if (client_) | |
| 451 client_->OnLog(message); | |
| 452 } | |
| 172 | 453 |
| 173 void VideoCaptureDeviceDeckLinkMac::AllocateAndStart( | 454 void VideoCaptureDeviceDeckLinkMac::AllocateAndStart( |
| 174 const VideoCaptureParams& params, | 455 const VideoCaptureParams& params, |
| 175 scoped_ptr<VideoCaptureDevice::Client> client) { | 456 scoped_ptr<VideoCaptureDevice::Client> client) { |
| 176 NOTIMPLEMENTED(); | 457 DCHECK(thread_checker_.CalledOnValidThread()); |
| 458 client_ = client.Pass(); | |
| 459 if (decklink_capture_delegate_.get()) | |
| 460 decklink_capture_delegate_->AllocateAndStart(params); | |
| 177 } | 461 } |
| 178 | 462 |
| 179 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { | 463 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { |
| 180 NOTIMPLEMENTED(); | 464 if (decklink_capture_delegate_.get()) |
| 465 decklink_capture_delegate_->StopAndDeAllocate(); | |
| 181 } | 466 } |
| 182 | 467 |
| 183 } // namespace media | 468 } // namespace media |
| OLD | NEW |