| Index: media/video/capture/mac/video_capture_device_decklink_mac.mm
|
| diff --git a/media/video/capture/mac/video_capture_device_decklink_mac.mm b/media/video/capture/mac/video_capture_device_decklink_mac.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..57c2c020ef0c0646240b0a3009ddf22de58b31a9
|
| --- /dev/null
|
| +++ b/media/video/capture/mac/video_capture_device_decklink_mac.mm
|
| @@ -0,0 +1,183 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "media/video/capture/mac/video_capture_device_decklink_mac.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "third_party/decklink/mac/include/DeckLinkAPI.h"
|
| +
|
| +namespace {
|
| +
|
| +// DeckLink SDK uses ScopedComPtr-style APIs. Chrome ScopedComPtr is only
|
| +// available for Windows builds. This is a verbatim knock-off of the needed
|
| +// parts of base::win::ScopedComPtr<> for ref counting.
|
| +template <class T>
|
| +class ScopedDeckLinkPtr : public scoped_refptr<T> {
|
| + public:
|
| + using scoped_refptr<T>::ptr_;
|
| +
|
| + T** Receive() {
|
| + DCHECK(!ptr_) << "Object leak. Pointer must be NULL";
|
| + return &ptr_;
|
| + }
|
| +
|
| + void** ReceiveVoid() {
|
| + return reinterpret_cast<void**>(Receive());
|
| + }
|
| +
|
| + void Release() {
|
| + if (ptr_ != NULL) {
|
| + ptr_->Release();
|
| + ptr_ = NULL;
|
| + }
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +namespace media {
|
| +
|
| +std::string JoinDeviceNameAndFormat(CFStringRef name, CFStringRef format) {
|
| + return base::SysCFStringRefToUTF8(name) + " - " +
|
| + base::SysCFStringRefToUTF8(format);
|
| +}
|
| +
|
| +//static
|
| +void VideoCaptureDeviceDeckLinkMac::EnumerateDevices(
|
| + VideoCaptureDevice::Names* device_names) {
|
| + scoped_refptr<IDeckLinkIterator> decklink_iter(
|
| + CreateDeckLinkIteratorInstance());
|
| + // At this point, not being able to create a DeckLink iterator means that
|
| + // there are no Blackmagic devices in the system but this isn't an error.
|
| + DVLOG_IF(1, !decklink_iter.get()) << "Could not create DeckLink iterator";
|
| + if (!decklink_iter.get())
|
| + return;
|
| +
|
| + ScopedDeckLinkPtr<IDeckLink> decklink;
|
| + while (decklink_iter->Next(decklink.Receive()) == S_OK) {
|
| + ScopedDeckLinkPtr<IDeckLink> decklink_local;
|
| + decklink_local.swap(decklink);
|
| +
|
| + CFStringRef device_model_name = NULL;
|
| + HRESULT hr = decklink_local->GetModelName(&device_model_name);
|
| + DVLOG_IF(1, hr != S_OK) << "Error reading Blackmagic device model name";
|
| + CFStringRef device_display_name = NULL;
|
| + hr = decklink_local->GetDisplayName(&device_display_name);
|
| + DVLOG_IF(1, hr != S_OK) << "Error reading Blackmagic device display name";
|
| + DVLOG_IF(1, hr == S_OK) << "Blackmagic device found with name: " <<
|
| + base::SysCFStringRefToUTF8(device_display_name);
|
| +
|
| + if (!device_model_name && !device_display_name)
|
| + continue;
|
| +
|
| + ScopedDeckLinkPtr<IDeckLinkInput> decklink_input;
|
| + if (decklink_local->QueryInterface(IID_IDeckLinkInput,
|
| + decklink_input.ReceiveVoid()) != S_OK) {
|
| + DLOG(ERROR) << "Error Blackmagic querying input interface.";
|
| + return;
|
| + }
|
| +
|
| + ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter;
|
| + if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) !=
|
| + S_OK) {
|
| + continue;
|
| + }
|
| +
|
| + ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode;
|
| + while (display_mode_iter->Next(display_mode.Receive()) == S_OK) {
|
| + CFStringRef format_name = NULL;
|
| + if (display_mode->GetName(&format_name) == S_OK) {
|
| + VideoCaptureDevice::Name name(
|
| + JoinDeviceNameAndFormat(device_display_name, format_name),
|
| + JoinDeviceNameAndFormat(device_model_name, format_name),
|
| + VideoCaptureDevice::Name::DECKLINK,
|
| + VideoCaptureDevice::Name::OTHER_TRANSPORT);
|
| + device_names->push_back(name);
|
| + DVLOG(1) << "Blackmagic camera enumerated: " << name.name();
|
| + }
|
| + display_mode.Release();
|
| + }
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void VideoCaptureDeviceDeckLinkMac::EnumerateDeviceCapabilities(
|
| + const VideoCaptureDevice::Name& device,
|
| + VideoCaptureFormats* supported_formats) {
|
| + scoped_refptr<IDeckLinkIterator> decklink_iter(
|
| + CreateDeckLinkIteratorInstance());
|
| + DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator";
|
| + if (!decklink_iter.get())
|
| + return;
|
| +
|
| + ScopedDeckLinkPtr<IDeckLink> decklink;
|
| + while (decklink_iter->Next(decklink.Receive()) == S_OK) {
|
| + ScopedDeckLinkPtr<IDeckLink> decklink_local;
|
| + decklink_local.swap(decklink);
|
| +
|
| + ScopedDeckLinkPtr<IDeckLinkInput> decklink_input;
|
| + if (decklink_local->QueryInterface(IID_IDeckLinkInput,
|
| + decklink_input.ReceiveVoid()) != S_OK) {
|
| + DLOG(ERROR) << "Error Blackmagic querying input interface.";
|
| + return;
|
| + }
|
| +
|
| + ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter;
|
| + if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) !=
|
| + S_OK) {
|
| + continue;
|
| + }
|
| +
|
| + CFStringRef device_model_name = NULL;
|
| + if (decklink_local->GetModelName(&device_model_name) != S_OK)
|
| + continue;
|
| +
|
| + ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode;
|
| + while (display_mode_iter->Next(display_mode.Receive()) == S_OK) {
|
| + CFStringRef format_name = NULL;
|
| + if (display_mode->GetName(&format_name) == S_OK && device.id() !=
|
| + JoinDeviceNameAndFormat(device_model_name, format_name)) {
|
| + display_mode.Release();
|
| + continue;
|
| + }
|
| +
|
| + // IDeckLinkDisplayMode does not have information on pixel format, this
|
| + // is only available on capture.
|
| + media::VideoPixelFormat pixel_format = media::PIXEL_FORMAT_UNKNOWN;
|
| + BMDTimeValue time_value, time_scale;
|
| + float frame_rate = 0.0f;
|
| + if (display_mode->GetFrameRate(&time_value, &time_scale) == S_OK &&
|
| + time_value > 0) {
|
| + frame_rate = static_cast<float>(time_scale) / time_value;
|
| + }
|
| + media::VideoCaptureFormat format(
|
| + gfx::Size(display_mode->GetWidth(), display_mode->GetHeight()),
|
| + frame_rate,
|
| + pixel_format);
|
| + supported_formats->push_back(format);
|
| + DVLOG(2) << device.name() << " " << format.ToString();
|
| + display_mode.Release();
|
| + }
|
| + return;
|
| + }
|
| +}
|
| +
|
| +VideoCaptureDeviceDeckLinkMac::VideoCaptureDeviceDeckLinkMac(
|
| + const Name& device_name) {}
|
| +
|
| +VideoCaptureDeviceDeckLinkMac::~VideoCaptureDeviceDeckLinkMac() {}
|
| +
|
| +void VideoCaptureDeviceDeckLinkMac::AllocateAndStart(
|
| + const VideoCaptureParams& params,
|
| + scoped_ptr<VideoCaptureDevice::Client> client) {
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() {
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +} // namespace media
|
|
|