Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1006)

Unified Diff: media/capture/video/mac/video_capture_device_decklink_mac.mm

Issue 2143903003: [WIP] Move media/capture to device/capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/capture/video/mac/video_capture_device_decklink_mac.mm
diff --git a/media/capture/video/mac/video_capture_device_decklink_mac.mm b/media/capture/video/mac/video_capture_device_decklink_mac.mm
deleted file mode 100644
index 07a0a245c017043aeba774c38beb50841edd4015..0000000000000000000000000000000000000000
--- a/media/capture/video/mac/video_capture_device_decklink_mac.mm
+++ /dev/null
@@ -1,508 +0,0 @@
-// 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/capture/video/mac/video_capture_device_decklink_mac.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/synchronization/lock.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> {
- private:
- using scoped_refptr<T>::ptr_;
-
- public:
- 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;
- }
- }
-};
-
-// This class is used to interact directly with DeckLink SDK for video capture.
-// Implements the reference counted interface IUnknown. Has a weak reference to
-// VideoCaptureDeviceDeckLinkMac for sending captured frames, error messages and
-// logs.
-class DeckLinkCaptureDelegate
- : public IDeckLinkInputCallback,
- public base::RefCountedThreadSafe<DeckLinkCaptureDelegate> {
- public:
- DeckLinkCaptureDelegate(const media::VideoCaptureDevice::Name& device_name,
- media::VideoCaptureDeviceDeckLinkMac* frame_receiver);
-
- void AllocateAndStart(const media::VideoCaptureParams& params);
- void StopAndDeAllocate();
-
- // Remove the VideoCaptureDeviceDeckLinkMac's weak reference.
- void ResetVideoCaptureDeviceReference();
-
- private:
- // IDeckLinkInputCallback interface implementation.
- HRESULT VideoInputFormatChanged(
- BMDVideoInputFormatChangedEvents notification_events,
- IDeckLinkDisplayMode* new_display_mode,
- BMDDetectedVideoInputFormatFlags detected_signal_flags) override;
- HRESULT VideoInputFrameArrived(
- IDeckLinkVideoInputFrame* video_frame,
- IDeckLinkAudioInputPacket* audio_packet) override;
-
- // IUnknown interface implementation.
- HRESULT QueryInterface(REFIID iid, void** ppv) override;
- ULONG AddRef() override;
- ULONG Release() override;
-
- // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString().
- void SendErrorString(const tracked_objects::Location& from_here,
- const std::string& reason);
-
- // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString().
- void SendLogString(const std::string& message);
-
- const media::VideoCaptureDevice::Name device_name_;
-
- // Protects concurrent setting and using of |frame_receiver_|.
- base::Lock lock_;
- // Weak reference to the captured frames client, used also for error messages
- // and logging. Initialized on construction and used until cleared by calling
- // ResetVideoCaptureDeviceReference().
- media::VideoCaptureDeviceDeckLinkMac* frame_receiver_;
-
- // This is used to control the video capturing device input interface.
- ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_;
- // |decklink_| represents a physical device attached to the host.
- ScopedDeckLinkPtr<IDeckLink> decklink_;
-
- base::TimeTicks first_ref_time_;
-
- // Checks for Device (a.k.a. Audio) thread.
- base::ThreadChecker thread_checker_;
-
- friend class scoped_refptr<DeckLinkCaptureDelegate>;
- friend class base::RefCountedThreadSafe<DeckLinkCaptureDelegate>;
-
- ~DeckLinkCaptureDelegate() override;
-
- DISALLOW_COPY_AND_ASSIGN(DeckLinkCaptureDelegate);
-};
-
-static float GetDisplayModeFrameRate(
- const ScopedDeckLinkPtr<IDeckLinkDisplayMode>& display_mode) {
- BMDTimeValue time_value, time_scale;
- float display_mode_frame_rate = 0.0f;
- if (display_mode->GetFrameRate(&time_value, &time_scale) == S_OK &&
- time_value > 0) {
- display_mode_frame_rate = static_cast<float>(time_scale) / time_value;
- }
- // Interlaced formats are going to be marked as double the frame rate,
- // which follows the general naming convention.
- if (display_mode->GetFieldDominance() == bmdLowerFieldFirst ||
- display_mode->GetFieldDominance() == bmdUpperFieldFirst) {
- display_mode_frame_rate *= 2.0f;
- }
- return display_mode_frame_rate;
-}
-
-DeckLinkCaptureDelegate::DeckLinkCaptureDelegate(
- const media::VideoCaptureDevice::Name& device_name,
- media::VideoCaptureDeviceDeckLinkMac* frame_receiver)
- : device_name_(device_name), frame_receiver_(frame_receiver) {
-}
-
-DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate() {
-}
-
-void DeckLinkCaptureDelegate::AllocateAndStart(
- const media::VideoCaptureParams& params) {
- DCHECK(thread_checker_.CalledOnValidThread());
- scoped_refptr<IDeckLinkIterator> decklink_iter(
- CreateDeckLinkIteratorInstance());
- DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator";
- if (!decklink_iter.get())
- return;
-
- ScopedDeckLinkPtr<IDeckLink> decklink_local;
- while (decklink_iter->Next(decklink_local.Receive()) == S_OK) {
- CFStringRef device_model_name = NULL;
- if ((decklink_local->GetModelName(&device_model_name) == S_OK) ||
- (device_name_.id() == base::SysCFStringRefToUTF8(device_model_name))) {
- break;
- }
- }
- if (!decklink_local.get()) {
- SendErrorString(FROM_HERE, "Device id not found in the system");
- return;
- }
-
- ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_local;
- if (decklink_local->QueryInterface(
- IID_IDeckLinkInput, decklink_input_local.ReceiveVoid()) != S_OK) {
- SendErrorString(FROM_HERE, "Error querying input interface.");
- return;
- }
-
- ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter;
- if (decklink_input_local->GetDisplayModeIterator(
- display_mode_iter.Receive()) != S_OK) {
- SendErrorString(FROM_HERE, "Error creating Display Mode Iterator");
- return;
- }
-
- ScopedDeckLinkPtr<IDeckLinkDisplayMode> chosen_display_mode;
- ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode;
- float min_diff = FLT_MAX;
- while (display_mode_iter->Next(display_mode.Receive()) == S_OK) {
- const float diff = labs(display_mode->GetWidth() -
- params.requested_format.frame_size.width()) +
- labs(params.requested_format.frame_size.height() -
- display_mode->GetHeight()) +
- fabs(params.requested_format.frame_rate -
- GetDisplayModeFrameRate(display_mode));
- if (diff < min_diff) {
- chosen_display_mode = display_mode;
- min_diff = diff;
- }
- display_mode.Release();
- }
- if (!chosen_display_mode.get()) {
- SendErrorString(FROM_HERE, "Could not find a display mode");
- return;
- }
-#if !defined(NDEBUG)
- DVLOG(1) << "Requested format: "
- << media::VideoCaptureFormat::ToString(params.requested_format);
- CFStringRef format_name = NULL;
- if (chosen_display_mode->GetName(&format_name) == S_OK)
- DVLOG(1) << "Chosen format: " << base::SysCFStringRefToUTF8(format_name);
-#endif
-
- // Enable video input. Configure for no input video format change detection,
- // this in turn will disable calls to VideoInputFormatChanged().
- if (decklink_input_local->EnableVideoInput(
- chosen_display_mode->GetDisplayMode(), bmdFormat8BitYUV,
- bmdVideoInputFlagDefault) != S_OK) {
- SendErrorString(FROM_HERE, "Could not select the video format we like.");
- return;
- }
-
- decklink_input_local->SetCallback(this);
- if (decklink_input_local->StartStreams() != S_OK)
- SendErrorString(FROM_HERE, "Could not start capturing");
-
- decklink_.swap(decklink_local);
- decklink_input_.swap(decklink_input_local);
-}
-
-void DeckLinkCaptureDelegate::StopAndDeAllocate() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!decklink_input_.get())
- return;
- if (decklink_input_->StopStreams() != S_OK)
- SendLogString("Problem stopping capture.");
- decklink_input_->SetCallback(NULL);
- decklink_input_->DisableVideoInput();
- decklink_input_.Release();
- decklink_.Release();
- ResetVideoCaptureDeviceReference();
-}
-
-HRESULT DeckLinkCaptureDelegate::VideoInputFormatChanged(
- BMDVideoInputFormatChangedEvents notification_events,
- IDeckLinkDisplayMode* new_display_mode,
- BMDDetectedVideoInputFormatFlags detected_signal_flags) {
- DCHECK(thread_checker_.CalledOnValidThread());
- return S_OK;
-}
-
-HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(
- IDeckLinkVideoInputFrame* video_frame,
- IDeckLinkAudioInputPacket* /* audio_packet */) {
- // Capture frames are manipulated as an IDeckLinkVideoFrame.
- uint8_t* video_data = NULL;
- video_frame->GetBytes(reinterpret_cast<void**>(&video_data));
-
- media::VideoPixelFormat pixel_format =
- media::PIXEL_FORMAT_UNKNOWN;
- switch (video_frame->GetPixelFormat()) {
- case bmdFormat8BitYUV: // A.k.a. '2vuy';
- pixel_format = media::PIXEL_FORMAT_UYVY;
- break;
- case bmdFormat8BitARGB:
- pixel_format = media::PIXEL_FORMAT_ARGB;
- break;
- default:
- SendErrorString(FROM_HERE, "Unsupported pixel format");
- break;
- }
-
- const media::VideoCaptureFormat capture_format(
- gfx::Size(video_frame->GetWidth(), video_frame->GetHeight()),
- 0.0f, // Frame rate is not needed for captured data callback.
- pixel_format);
- base::TimeTicks now = base::TimeTicks::Now();
- if (first_ref_time_.is_null())
- first_ref_time_ = now;
- base::AutoLock lock(lock_);
- if (frame_receiver_) {
- const BMDTimeScale micros_time_scale = base::Time::kMicrosecondsPerSecond;
- BMDTimeValue frame_time;
- BMDTimeValue frame_duration;
- base::TimeDelta timestamp;
- if (SUCCEEDED(video_frame->GetStreamTime(&frame_time, &frame_duration,
- micros_time_scale))) {
- timestamp = base::TimeDelta::FromMicroseconds(frame_time);
- } else {
- timestamp = now - first_ref_time_;
- }
- frame_receiver_->OnIncomingCapturedData(
- video_data, video_frame->GetRowBytes() * video_frame->GetHeight(),
- capture_format,
- 0, // Rotation.
- now, timestamp);
- }
- return S_OK;
-}
-
-HRESULT DeckLinkCaptureDelegate::QueryInterface(REFIID iid, void** ppv) {
- DCHECK(thread_checker_.CalledOnValidThread());
- CFUUIDBytes iunknown = CFUUIDGetUUIDBytes(IUnknownUUID);
- if (memcmp(&iid, &iunknown, sizeof(REFIID)) == 0 ||
- memcmp(&iid, &IID_IDeckLinkInputCallback, sizeof(REFIID)) == 0) {
- *ppv = static_cast<IDeckLinkInputCallback*>(this);
- AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
-}
-
-ULONG DeckLinkCaptureDelegate::AddRef() {
- DCHECK(thread_checker_.CalledOnValidThread());
- base::RefCountedThreadSafe<DeckLinkCaptureDelegate>::AddRef();
- return 1;
-}
-
-ULONG DeckLinkCaptureDelegate::Release() {
- DCHECK(thread_checker_.CalledOnValidThread());
- bool ret_value = !HasOneRef();
- base::RefCountedThreadSafe<DeckLinkCaptureDelegate>::Release();
- return ret_value;
-}
-
-void DeckLinkCaptureDelegate::SendErrorString(
- const tracked_objects::Location& from_here,
- const std::string& reason) {
- base::AutoLock lock(lock_);
- if (frame_receiver_)
- frame_receiver_->SendErrorString(from_here, reason);
-}
-
-void DeckLinkCaptureDelegate::SendLogString(const std::string& message) {
- base::AutoLock lock(lock_);
- if (frame_receiver_)
- frame_receiver_->SendLogString(message);
-}
-
-void DeckLinkCaptureDelegate::ResetVideoCaptureDeviceReference() {
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock lock(lock_);
- frame_receiver_ = NULL;
-}
-
-} // namespace
-
-namespace media {
-
-static 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 DeckLink devices in the system, don't print 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.
- const media::VideoCaptureFormat format(
- gfx::Size(display_mode->GetWidth(), display_mode->GetHeight()),
- GetDisplayModeFrameRate(display_mode),
- PIXEL_FORMAT_UNKNOWN);
- supported_formats->push_back(format);
- DVLOG(2) << device.name() << " " << VideoCaptureFormat::ToString(format);
- display_mode.Release();
- }
- return;
- }
-}
-
-VideoCaptureDeviceDeckLinkMac::VideoCaptureDeviceDeckLinkMac(
- const Name& device_name)
- : decklink_capture_delegate_(
- new DeckLinkCaptureDelegate(device_name, this)) {
-}
-
-VideoCaptureDeviceDeckLinkMac::~VideoCaptureDeviceDeckLinkMac() {
- decklink_capture_delegate_->ResetVideoCaptureDeviceReference();
-}
-
-void VideoCaptureDeviceDeckLinkMac::OnIncomingCapturedData(
- const uint8_t* data,
- size_t length,
- const VideoCaptureFormat& frame_format,
- int rotation, // Clockwise.
- base::TimeTicks reference_time,
- base::TimeDelta timestamp) {
- base::AutoLock lock(lock_);
- if (client_) {
- client_->OnIncomingCapturedData(data, length, frame_format, rotation,
- reference_time, timestamp);
- }
-}
-
-void VideoCaptureDeviceDeckLinkMac::SendErrorString(
- const tracked_objects::Location& from_here,
- const std::string& reason) {
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock lock(lock_);
- if (client_)
- client_->OnError(from_here, reason);
-}
-
-void VideoCaptureDeviceDeckLinkMac::SendLogString(const std::string& message) {
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock lock(lock_);
- if (client_)
- client_->OnLog(message);
-}
-
-void VideoCaptureDeviceDeckLinkMac::AllocateAndStart(
- const VideoCaptureParams& params,
- std::unique_ptr<VideoCaptureDevice::Client> client) {
- DCHECK(thread_checker_.CalledOnValidThread());
- client_ = std::move(client);
- if (decklink_capture_delegate_.get())
- decklink_capture_delegate_->AllocateAndStart(params);
-}
-
-void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() {
- if (decklink_capture_delegate_.get())
- decklink_capture_delegate_->StopAndDeAllocate();
-}
-
-} // namespace media

Powered by Google App Engine
This is Rietveld 408576698