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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 // This is used to control the video capturing device input interface. | 91 // This is used to control the video capturing device input interface. |
92 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_; | 92 ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_; |
93 // |decklink_| represents a physical device attached to the host. | 93 // |decklink_| represents a physical device attached to the host. |
94 ScopedDeckLinkPtr<IDeckLink> decklink_; | 94 ScopedDeckLinkPtr<IDeckLink> decklink_; |
95 | 95 |
96 base::TimeTicks first_ref_time_; | 96 base::TimeTicks first_ref_time_; |
97 | 97 |
98 // Checks for Device (a.k.a. Audio) thread. | 98 // Checks for Device (a.k.a. Audio) thread. |
99 base::ThreadChecker thread_checker_; | 99 base::ThreadChecker thread_checker_; |
100 | 100 |
| 101 bool capture_; |
| 102 |
101 friend class scoped_refptr<DeckLinkCaptureDelegate>; | 103 friend class scoped_refptr<DeckLinkCaptureDelegate>; |
102 friend class base::RefCountedThreadSafe<DeckLinkCaptureDelegate>; | 104 friend class base::RefCountedThreadSafe<DeckLinkCaptureDelegate>; |
103 | 105 |
104 ~DeckLinkCaptureDelegate() override; | 106 ~DeckLinkCaptureDelegate() override; |
105 | 107 |
106 DISALLOW_COPY_AND_ASSIGN(DeckLinkCaptureDelegate); | 108 DISALLOW_COPY_AND_ASSIGN(DeckLinkCaptureDelegate); |
107 }; | 109 }; |
108 | 110 |
109 static float GetDisplayModeFrameRate( | 111 static float GetDisplayModeFrameRate( |
110 const ScopedDeckLinkPtr<IDeckLinkDisplayMode>& display_mode) { | 112 const ScopedDeckLinkPtr<IDeckLinkDisplayMode>& display_mode) { |
111 BMDTimeValue time_value, time_scale; | 113 BMDTimeValue time_value, time_scale; |
112 float display_mode_frame_rate = 0.0f; | 114 float display_mode_frame_rate = 0.0f; |
113 if (display_mode->GetFrameRate(&time_value, &time_scale) == S_OK && | 115 if (display_mode->GetFrameRate(&time_value, &time_scale) == S_OK && |
114 time_value > 0) { | 116 time_value > 0) { |
115 display_mode_frame_rate = static_cast<float>(time_scale) / time_value; | 117 display_mode_frame_rate = static_cast<float>(time_scale) / time_value; |
116 } | 118 } |
117 // Interlaced formats are going to be marked as double the frame rate, | 119 // Interlaced formats are going to be marked as double the frame rate, |
118 // which follows the general naming convention. | 120 // which follows the general naming convention. |
119 if (display_mode->GetFieldDominance() == bmdLowerFieldFirst || | 121 if (display_mode->GetFieldDominance() == bmdLowerFieldFirst || |
120 display_mode->GetFieldDominance() == bmdUpperFieldFirst) { | 122 display_mode->GetFieldDominance() == bmdUpperFieldFirst) { |
121 display_mode_frame_rate *= 2.0f; | 123 display_mode_frame_rate *= 2.0f; |
122 } | 124 } |
123 return display_mode_frame_rate; | 125 return display_mode_frame_rate; |
124 } | 126 } |
125 | 127 |
126 DeckLinkCaptureDelegate::DeckLinkCaptureDelegate( | 128 DeckLinkCaptureDelegate::DeckLinkCaptureDelegate( |
127 const media::VideoCaptureDeviceDescriptor& device_descriptor, | 129 const media::VideoCaptureDeviceDescriptor& device_descriptor, |
128 media::VideoCaptureDeviceDeckLinkMac* frame_receiver) | 130 media::VideoCaptureDeviceDeckLinkMac* frame_receiver) |
129 : device_descriptor_(device_descriptor), frame_receiver_(frame_receiver) {} | 131 : device_descriptor_(device_descriptor), |
| 132 frame_receiver_(frame_receiver), |
| 133 capture_(false) {} |
130 | 134 |
131 DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate() { | 135 DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate() { |
132 } | 136 } |
133 | 137 |
134 void DeckLinkCaptureDelegate::AllocateAndStart( | 138 void DeckLinkCaptureDelegate::AllocateAndStart( |
135 const media::VideoCaptureParams& params) { | 139 const media::VideoCaptureParams& params) { |
136 DCHECK(thread_checker_.CalledOnValidThread()); | 140 DCHECK(thread_checker_.CalledOnValidThread()); |
137 scoped_refptr<IDeckLinkIterator> decklink_iter( | 141 scoped_refptr<IDeckLinkIterator> decklink_iter( |
138 CreateDeckLinkIteratorInstance()); | 142 CreateDeckLinkIteratorInstance()); |
139 DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; | 143 DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 chosen_display_mode->GetDisplayMode(), bmdFormat8BitYUV, | 206 chosen_display_mode->GetDisplayMode(), bmdFormat8BitYUV, |
203 bmdVideoInputFlagDefault) != S_OK) { | 207 bmdVideoInputFlagDefault) != S_OK) { |
204 SendErrorString(FROM_HERE, "Could not select the video format we like."); | 208 SendErrorString(FROM_HERE, "Could not select the video format we like."); |
205 return; | 209 return; |
206 } | 210 } |
207 | 211 |
208 decklink_input_local->SetCallback(this); | 212 decklink_input_local->SetCallback(this); |
209 if (decklink_input_local->StartStreams() != S_OK) | 213 if (decklink_input_local->StartStreams() != S_OK) |
210 SendErrorString(FROM_HERE, "Could not start capturing"); | 214 SendErrorString(FROM_HERE, "Could not start capturing"); |
211 | 215 |
| 216 if (frame_receiver_) |
| 217 frame_receiver_->ReportStarted(); |
| 218 |
| 219 capture_ = true; |
| 220 |
212 decklink_.swap(decklink_local); | 221 decklink_.swap(decklink_local); |
213 decklink_input_.swap(decklink_input_local); | 222 decklink_input_.swap(decklink_input_local); |
214 } | 223 } |
215 | 224 |
216 void DeckLinkCaptureDelegate::StopAndDeAllocate() { | 225 void DeckLinkCaptureDelegate::StopAndDeAllocate() { |
217 DCHECK(thread_checker_.CalledOnValidThread()); | 226 DCHECK(thread_checker_.CalledOnValidThread()); |
| 227 capture_ = false; |
218 if (!decklink_input_.get()) | 228 if (!decklink_input_.get()) |
219 return; | 229 return; |
220 if (decklink_input_->StopStreams() != S_OK) | 230 if (decklink_input_->StopStreams() != S_OK) |
221 SendLogString("Problem stopping capture."); | 231 SendLogString("Problem stopping capture."); |
222 decklink_input_->SetCallback(NULL); | 232 decklink_input_->SetCallback(NULL); |
223 decklink_input_->DisableVideoInput(); | 233 decklink_input_->DisableVideoInput(); |
224 decklink_input_.Release(); | 234 decklink_input_.Release(); |
225 decklink_.Release(); | 235 decklink_.Release(); |
226 ResetVideoCaptureDeviceReference(); | 236 ResetVideoCaptureDeviceReference(); |
227 } | 237 } |
228 | 238 |
229 HRESULT DeckLinkCaptureDelegate::VideoInputFormatChanged( | 239 HRESULT DeckLinkCaptureDelegate::VideoInputFormatChanged( |
230 BMDVideoInputFormatChangedEvents notification_events, | 240 BMDVideoInputFormatChangedEvents notification_events, |
231 IDeckLinkDisplayMode* new_display_mode, | 241 IDeckLinkDisplayMode* new_display_mode, |
232 BMDDetectedVideoInputFormatFlags detected_signal_flags) { | 242 BMDDetectedVideoInputFormatFlags detected_signal_flags) { |
233 DCHECK(thread_checker_.CalledOnValidThread()); | 243 DCHECK(thread_checker_.CalledOnValidThread()); |
234 return S_OK; | 244 return S_OK; |
235 } | 245 } |
236 | 246 |
237 HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived( | 247 HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived( |
238 IDeckLinkVideoInputFrame* video_frame, | 248 IDeckLinkVideoInputFrame* video_frame, |
239 IDeckLinkAudioInputPacket* /* audio_packet */) { | 249 IDeckLinkAudioInputPacket* /* audio_packet */) { |
| 250 if (!capture_) |
| 251 return S_OK; |
| 252 |
240 // Capture frames are manipulated as an IDeckLinkVideoFrame. | 253 // Capture frames are manipulated as an IDeckLinkVideoFrame. |
241 uint8_t* video_data = NULL; | 254 uint8_t* video_data = NULL; |
242 video_frame->GetBytes(reinterpret_cast<void**>(&video_data)); | 255 video_frame->GetBytes(reinterpret_cast<void**>(&video_data)); |
243 | 256 |
244 media::VideoPixelFormat pixel_format = | 257 media::VideoPixelFormat pixel_format = |
245 media::PIXEL_FORMAT_UNKNOWN; | 258 media::PIXEL_FORMAT_UNKNOWN; |
246 switch (video_frame->GetPixelFormat()) { | 259 switch (video_frame->GetPixelFormat()) { |
247 case bmdFormat8BitYUV: // A.k.a. '2vuy'; | 260 case bmdFormat8BitYUV: // A.k.a. '2vuy'; |
248 pixel_format = media::PIXEL_FORMAT_UYVY; | 261 pixel_format = media::PIXEL_FORMAT_UYVY; |
249 break; | 262 break; |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 client_->OnError(from_here, reason); | 500 client_->OnError(from_here, reason); |
488 } | 501 } |
489 | 502 |
490 void VideoCaptureDeviceDeckLinkMac::SendLogString(const std::string& message) { | 503 void VideoCaptureDeviceDeckLinkMac::SendLogString(const std::string& message) { |
491 DCHECK(thread_checker_.CalledOnValidThread()); | 504 DCHECK(thread_checker_.CalledOnValidThread()); |
492 base::AutoLock lock(lock_); | 505 base::AutoLock lock(lock_); |
493 if (client_) | 506 if (client_) |
494 client_->OnLog(message); | 507 client_->OnLog(message); |
495 } | 508 } |
496 | 509 |
| 510 void VideoCaptureDeviceDeckLinkMac::ReportStarted() { |
| 511 DCHECK(thread_checker_.CalledOnValidThread()); |
| 512 base::AutoLock lock(lock_); |
| 513 if (client_) |
| 514 client_->OnStarted(); |
| 515 } |
| 516 |
497 void VideoCaptureDeviceDeckLinkMac::AllocateAndStart( | 517 void VideoCaptureDeviceDeckLinkMac::AllocateAndStart( |
498 const VideoCaptureParams& params, | 518 const VideoCaptureParams& params, |
499 std::unique_ptr<VideoCaptureDevice::Client> client) { | 519 std::unique_ptr<VideoCaptureDevice::Client> client) { |
500 DCHECK(thread_checker_.CalledOnValidThread()); | 520 DCHECK(thread_checker_.CalledOnValidThread()); |
501 client_ = std::move(client); | 521 client_ = std::move(client); |
502 if (decklink_capture_delegate_.get()) | 522 if (decklink_capture_delegate_.get()) |
503 decklink_capture_delegate_->AllocateAndStart(params); | 523 decklink_capture_delegate_->AllocateAndStart(params); |
504 } | 524 } |
505 | 525 |
506 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { | 526 void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { |
507 if (decklink_capture_delegate_.get()) | 527 if (decklink_capture_delegate_.get()) |
508 decklink_capture_delegate_->StopAndDeAllocate(); | 528 decklink_capture_delegate_->StopAndDeAllocate(); |
509 } | 529 } |
510 | 530 |
511 } // namespace media | 531 } // namespace media |
OLD | NEW |