OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/video/capture/mac/video_capture_device_decklink_mac.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/memory/ref_counted.h" | |
9 #include "base/strings/sys_string_conversions.h" | |
10 #include "third_party/decklink/mac/include/DeckLinkAPI.h" | |
11 | |
12 namespace { | |
13 | |
14 // 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 // parts of base::win::ScopedComPtr<> for ref counting. | |
17 template <class T> | |
18 class ScopedDeckLinkPtr : public scoped_refptr<T> { | |
19 public: | |
20 using scoped_refptr<T>::ptr_; | |
21 | |
22 T** Receive() { | |
23 DCHECK(!ptr_) << "Object leak. Pointer must be NULL"; | |
24 return &ptr_; | |
25 } | |
26 | |
27 void** ReceiveVoid() { | |
28 return reinterpret_cast<void**>(Receive()); | |
29 } | |
30 | |
31 void Release() { | |
32 if (ptr_ != NULL) { | |
33 ptr_->Release(); | |
34 ptr_ = NULL; | |
35 } | |
36 } | |
37 }; | |
38 | |
39 } // namespace | |
40 | |
41 namespace media { | |
42 | |
43 //static | |
44 void VideoCaptureDeviceDeckLinkMac::EnumerateDevices( | |
45 VideoCaptureDevice::Names* device_names) { | |
46 scoped_refptr<IDeckLinkIterator> decklink_iter( | |
47 CreateDeckLinkIteratorInstance()); | |
48 DLOG_IF(ERROR, !decklink_iter) << "Error creating DeckLink iterator"; | |
49 if (!decklink_iter) | |
50 return; | |
51 | |
52 ScopedDeckLinkPtr<IDeckLink> decklink; | |
53 while (decklink_iter->Next(decklink.Receive()) == S_OK) { | |
54 CFStringRef device_model_name = NULL; | |
55 HRESULT hr = decklink->GetModelName(&device_model_name); | |
56 DVLOG_IF(1, hr != S_OK) << "Error reading Blackmagic device model name"; | |
57 CFStringRef device_display_name = NULL; | |
58 hr = decklink->GetDisplayName(&device_display_name); | |
59 DVLOG_IF(1, hr != S_OK) << "Error reading Blackmagic device display name"; | |
60 DVLOG_IF(1, hr == S_OK) << "Blackmagic camera found, name: " << | |
61 base::SysCFStringRefToUTF8(device_display_name); | |
62 | |
63 if (device_model_name || device_display_name) { | |
64 VideoCaptureDevice::Name name( | |
65 base::SysCFStringRefToUTF8(device_model_name), | |
66 base::SysCFStringRefToUTF8(device_display_name), | |
67 VideoCaptureDevice::Name::DECKLINK, | |
68 VideoCaptureDevice::Name::OTHER_TRANSPORT); | |
69 device_names->push_back(name); | |
70 } | |
71 decklink.Release(); | |
72 } | |
73 } | |
74 | |
75 // static | |
76 void VideoCaptureDeviceDeckLinkMac::EnumerateDeviceCapabilities( | |
77 const VideoCaptureDevice::Name& device, | |
78 VideoCaptureFormats* supported_formats) { | |
79 ScopedDeckLinkPtr<IDeckLink> decklink; | |
80 scoped_refptr<IDeckLinkIterator> decklink_iter( | |
81 CreateDeckLinkIteratorInstance()); | |
82 DLOG_IF(ERROR, !decklink_iter) << "Error creating DeckLink iterator"; | |
83 if (!decklink_iter) | |
84 return; | |
85 | |
86 while (decklink_iter->Next(decklink.Receive()) == S_OK) { | |
87 CFStringRef device_model_name = NULL; | |
88 if ((decklink->GetModelName(&device_model_name) != S_OK) || | |
89 (device.id() != base::SysCFStringRefToUTF8(device_model_name))) { | |
90 decklink.Release(); | |
mcasas
2014/09/04 10:00:36
Gosh we totally missed this one :'(
Lurking bug,
mcasas
2014/09/04 15:59:21
Acknowledged.
| |
91 continue; | |
92 } | |
93 | |
94 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input; | |
95 if (decklink->QueryInterface(IID_IDeckLinkInput, | |
96 decklink_input.ReceiveVoid()) != S_OK) { | |
97 DLOG(ERROR) << "Error Blackmagic querying input interface."; | |
98 return; | |
99 } | |
100 | |
101 ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; | |
102 if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) != | |
103 S_OK) { | |
104 continue; | |
Robert Sesek
2014/09/04 14:25:01
Do you need to declink.Release() here, too? Would
mcasas
2014/09/04 15:59:21
Done.
| |
105 } | |
106 | |
107 ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; | |
108 while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { | |
109 // IDeckLinkDisplayMode does not have information on pixel format, it | |
110 // is only available on capture. | |
111 media::VideoPixelFormat pixel_format = media::PIXEL_FORMAT_UNKNOWN; | |
112 BMDTimeValue time_value, time_scale; | |
113 float frame_rate = 0.0f; | |
114 if (display_mode->GetFrameRate(&time_value, &time_scale) == S_OK && | |
115 time_value > 0) { | |
116 frame_rate = static_cast<float>(time_scale) / time_value; | |
117 } | |
118 media::VideoCaptureFormat format( | |
119 gfx::Size(display_mode->GetWidth(), display_mode->GetHeight()), | |
120 frame_rate, | |
121 pixel_format); | |
122 supported_formats->push_back(format); | |
123 DVLOG(2) << device.name() << " resolution: " | |
124 << format.frame_size.ToString() << "@: " << format.frame_rate | |
125 << ", pixel format: " << format.pixel_format; | |
126 display_mode.Release(); | |
127 } | |
128 return; | |
129 } | |
130 } | |
131 | |
132 VideoCaptureDeviceDeckLinkMac::VideoCaptureDeviceDeckLinkMac( | |
133 const Name& device_name) {} | |
134 | |
135 VideoCaptureDeviceDeckLinkMac::~VideoCaptureDeviceDeckLinkMac() {} | |
136 | |
137 void VideoCaptureDeviceDeckLinkMac::AllocateAndStart( | |
138 const VideoCaptureParams& params, | |
139 scoped_ptr<VideoCaptureDevice::Client> client) { | |
140 NOTIMPLEMENTED(); | |
141 } | |
142 | |
143 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { | |
144 NOTIMPLEMENTED(); | |
145 } | |
146 | |
147 } // namespace media | |
OLD | NEW |