1 /*
2 * Blackmagic DeckLink output
3 * Copyright (c) 2013-2014 Luca Barbato, Deti Fliegl
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <DeckLinkAPI.h>
23
24 #include <pthread.h>
25 #include <semaphore.h>
26
27 extern "C" {
31 }
32
35
37 {
42 }
43
45 {
47
53 }
59 }
60
62 {
66 }
67
69 {
70 unsigned long long size;
75 }
76
78 {
80
81 // Drop Packet if queue size is > 1GB
84 return -1;
85 }
86 /* duplicate the packet */
88 return -1;
89 }
90
92 if (!pkt1) {
93 return -1;
94 }
97
99
102 } else {
104 }
105
109
111
113 return 0;
114 }
115
117 {
120
122
123 for (;; ) {
125 if (pkt1) {
129 }
134 ret = 1;
135 break;
136 } else if (!block) {
137 ret = 0;
138 break;
139 } else {
141 }
142 }
145 }
146
148 {
149 public:
152
156 virtual HRESULT STDMETHODCALLTYPE
VideoInputFormatChanged(BMDVideoInputFormatChangedEvents, IDeckLinkDisplayMode*, BMDDetectedVideoInputFormatFlags);
158
159 private:
167 };
168
170 {
176 }
177
179 {
181 }
182
184 {
188
190 }
191
193 {
197
199 delete this;
200 return 0;
201 }
202
204 }
205
207 IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame)
208 {
209 void *frameBytes;
210 void *audioFrameBytes;
211 BMDTimeValue frameTime;
212 BMDTimeValue frameDuration;
213
215
216 // Handle Video Frame
217 if (videoFrame) {
225 "Frame received (#%lu) - Valid (%liB) - QSize %fMB\n",
227 videoFrame->GetRowBytes() * videoFrame->GetHeight(),
228 (double)qsize / 1024 / 1024);
229 }
230
231 videoFrame->GetBytes(&frameBytes);
232 videoFrame->GetStreamTime(&frameTime, &frameDuration,
234
235 if (videoFrame->GetFlags() & bmdFrameHasNoInputSource) {
236 if (videoFrame->GetPixelFormat() == bmdFormat8BitYUV) {
237 unsigned bars[8] = {
238 0xEA80EA80, 0xD292D210, 0xA910A9A5, 0x90229035,
239 0x6ADD6ACA, 0x51EF515A, 0x286D28EF, 0x10801080 };
240 int width = videoFrame->GetWidth();
241 int height = videoFrame->GetHeight();
242 unsigned *p = (unsigned *)frameBytes;
243
245 for (
int x = 0; x <
width; x += 2)
246 *p++ = bars[(x * 8) /
width];
247 }
248 }
249
253 }
255 } else {
259 }
261 }
262
264
267 }
268
271
273 //To be made sure it still applies
277 pkt.
size = videoFrame->GetRowBytes() *
278 videoFrame->GetHeight();
279 //fprintf(stderr,"Video Frame size %d ts %d\n", pkt.size, pkt.pts);
283 }
284 }
285
286 // Handle Audio Frame
287 if (audioFrame) {
290 BMDTimeValue audio_pts;
292
294 //hack among hacks
296 audioFrame->GetBytes(&audioFrameBytes);
299
302 }
303
306
307 //fprintf(stderr,"Audio Frame size %d ts %d\n", pkt.size, pkt.pts);
311
315 }
316 }
317
319 }
320
322 BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *
mode,
323 BMDDetectedVideoInputFormatFlags)
324 {
326 }
327
329 {
332
334 ctx->dli->SetCallback(
ctx->input_callback);
335 return ctx->dli->StartStreams();
336 }
337
338 extern "C" {
339
341 {
344
345 if (
ctx->capture_started) {
346 ctx->dli->StopStreams();
347 ctx->dli->DisableVideoInput();
348 ctx->dli->DisableAudioInput();
349 }
350
355
357
359
360 return 0;
361 }
362
364 {
367 IDeckLinkDisplayModeIterator *itermode;
368 IDeckLinkIterator *iter;
369 IDeckLink *dl =
NULL;
372 char fname[1024];
373 char *tmp;
374 int mode_num = 0;
375
383
384 iter = CreateDeckLinkIteratorInstance();
385 if (!iter) {
388 }
389
390 /* List available devices. */
391 if (
ctx->list_devices) {
394 }
395
397 tmp=strchr (fname, '@');
399 mode_num = atoi (tmp+1);
400 *tmp = 0;
401 }
402
403 /* Open device. */
404 while (iter->Next(&dl) ==
S_OK) {
405 const char *displayName;
407 if (!strcmp(fname, displayName)) {
410 break;
411 }
413 dl->Release();
414 }
415 iter->Release();
419 }
420
421 /* Get input device. */
422 if (
ctx->dl->QueryInterface(IID_IDeckLinkInput, (
void **) &
ctx->dli) !=
S_OK) {
427 }
428
429 /* List supported formats. */
430 if (
ctx->list_formats) {
435 }
436
437 if (
ctx->dli->GetDisplayModeIterator(&itermode) !=
S_OK) {
441 }
442
443 if (mode_num > 0) {
446 goto error;
447 }
448 }
449
450 itermode->Release();
451
452 /* Setup streams. */
454 if (!st) {
456 goto error;
457 }
460 st->codec->sample_rate = bmdAudioSampleRate48kHz;
461 st->codec->channels = 2;
464
466 if (!st) {
468 goto error;
469 }
471 st->codec->width =
ctx->bmd_width;
472 st->codec->height =
ctx->bmd_height;
473
474 st->codec->time_base.den =
ctx->bmd_tb_den;
475 st->codec->time_base.num =
ctx->bmd_tb_num;
477
480 st->codec->codec_tag =
MKTAG(
'V',
'2',
'1',
'0');
481 } else {
484 st->codec->codec_tag =
MKTAG(
'U',
'Y',
'V',
'Y');
485 }
486
488
490
491 result =
ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2);
492
493 if (result !=
S_OK) {
495 goto error;
496 }
497
498 result =
ctx->dli->EnableVideoInput(
ctx->bmd_mode,
499 cctx->
v210 ? bmdFormat10BitYUV : bmdFormat8BitYUV,
500 bmdVideoInputFlagDefault);
501
502 if (result !=
S_OK) {
504 goto error;
505 }
506
508
511 goto error;
512 }
513
514 return 0;
515
516 error:
517
520
522 }
523
525 {
529
531 if (frame && (
ctx->bmd_field_dominance == bmdUpperFieldFirst ||
ctx->bmd_field_dominance == bmdLowerFieldFirst)) {
533 if (
ctx->bmd_field_dominance == bmdUpperFieldFirst) {
535 }
536 }
537
538 return 0;
539 }
540
541 } /* extern "C" */