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" {
32 #if CONFIG_LIBZVBI
33 #include <libzvbi.h>
34 #endif
35 }
36
39
40 #if CONFIG_LIBZVBI
41 static uint8_t calc_parity_and_line_offset(
int line)
42 {
43 uint8_t ret = (line < 313) << 5;
44 if (line >= 7 && line <= 22)
45 ret += line;
46 if (line >= 320 && line <= 335)
47 ret += (line - 313);
48 return ret;
49 }
50
52 {
53 vbi_bit_slicer slicer;
54
55 vbi_bit_slicer_init(&slicer, 720, 13500000, 6937500, 6937500, 0x00aaaae4, 0xffff, 18, 6, 42 * 8, VBI_MODULATION_NRZ_MSB, VBI_PIXFMT_UYVY);
56
57 if (vbi_bit_slice(&slicer, src, tgt + 4) ==
FALSE)
58 return -1;
59
60 tgt[0] = 0x02; // data_unit_id
61 tgt[1] = 0x2c; // data_unit_length
62 tgt[2] = calc_parity_and_line_offset(line); // field_parity, line_offset
63 tgt[3] = 0xe4; // framing code
64
65 return 0;
66 }
67 #endif
68
70 {
75 }
76
78 {
80
86 }
92 }
93
95 {
99 }
100
102 {
103 unsigned long long size;
108 }
109
111 {
113
114 // Drop Packet if queue size is > 1GB
117 return -1;
118 }
119 /* duplicate the packet */
121 return -1;
122 }
123
125 if (!pkt1) {
126 return -1;
127 }
130
132
135 } else {
137 }
138
142
144
146 return 0;
147 }
148
150 {
152 int ret;
153
155
156 for (;; ) {
158 if (pkt1) {
162 }
167 ret = 1;
168 break;
169 } else if (!block) {
170 ret = 0;
171 break;
172 } else {
174 }
175 }
177 return ret;
178 }
179
181 {
182 public:
185
189 virtual HRESULT STDMETHODCALLTYPE
VideoInputFormatChanged(BMDVideoInputFormatChangedEvents, IDeckLinkDisplayMode*, BMDDetectedVideoInputFormatFlags);
191
192 private:
200 };
201
203 {
209 }
210
212 {
214 }
215
217 {
221
223 }
224
226 {
230
232 delete this;
233 return 0;
234 }
235
237 }
238
240 IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame)
241 {
242 void *frameBytes;
243 void *audioFrameBytes;
244 BMDTimeValue frameTime;
245 BMDTimeValue frameDuration;
246
248
249 // Handle Video Frame
250 if (videoFrame) {
258 "Frame received (#%lu) - Valid (%liB) - QSize %fMB\n",
260 videoFrame->GetRowBytes() * videoFrame->GetHeight(),
261 (double)qsize / 1024 / 1024);
262 }
263
264 videoFrame->GetBytes(&frameBytes);
265 videoFrame->GetStreamTime(&frameTime, &frameDuration,
267
268 if (videoFrame->GetFlags() & bmdFrameHasNoInputSource) {
269 if (videoFrame->GetPixelFormat() == bmdFormat8BitYUV) {
270 unsigned bars[8] = {
271 0xEA80EA80, 0xD292D210, 0xA910A9A5, 0x90229035,
272 0x6ADD6ACA, 0x51EF515A, 0x286D28EF, 0x10801080 };
273 int width = videoFrame->GetWidth();
274 int height = videoFrame->GetHeight();
275 unsigned *p = (unsigned *)frameBytes;
276
277 for (
int y = 0; y <
height; y++) {
278 for (
int x = 0; x <
width; x += 2)
279 *p++ = bars[(x * 8) /
width];
280 }
281 }
282
286 }
288 } else {
292 }
294 }
295
297
300 }
301
304
306 //To be made sure it still applies
310 pkt.
size = videoFrame->GetRowBytes() *
311 videoFrame->GetHeight();
312 //fprintf(stderr,"Video Frame size %d ts %d\n", pkt.size, pkt.pts);
313
314 #if CONFIG_LIBZVBI
315 if (!
no_video &&
ctx->
teletext_lines && videoFrame->GetPixelFormat() == bmdFormat8BitYUV && videoFrame->GetWidth() == 720) {
316 IDeckLinkVideoFrameAncillary *vanc;
318 uint8_t txt_buf0[1611];
// max 35 * 46 bytes decoded teletext lines + 1 byte data_identifier
320
321 if (videoFrame->GetAncillaryData(&vanc) ==
S_OK) {
322 int i;
323 int64_t line_mask = 1;
324 txt_buf[0] = 0x10; // data_identifier - EBU_data
325 txt_buf++;
326 for (i = 6; i < 336; i++, line_mask <<= 1) {
328 if ((
ctx->
teletext_lines & line_mask) && vanc->GetBufferForVerticalBlankingLine(i, (
void**)&buf) ==
S_OK) {
329 if (teletext_data_unit_from_vbi_data(i, buf, txt_buf) >= 0)
330 txt_buf += 46;
331 }
332 if (i == 22)
333 i = 317;
334 }
335 vanc->Release();
336 if (txt_buf - txt_buf0 > 1) {
337 int stuffing_units = (4 - ((45 + txt_buf - txt_buf0) / 46) % 4) % 4;
338 while (stuffing_units--) {
339 memset(txt_buf, 0xff, 46);
340 txt_buf[1] = 0x2c; // data_unit_length
341 txt_buf += 46;
342 }
347 txt_pkt.
data = txt_buf0;
348 txt_pkt.
size = txt_buf - txt_buf0;
351 }
352 }
353 }
354 }
355 #endif
356
360 }
361 }
362
363 // Handle Audio Frame
364 if (audioFrame) {
367 BMDTimeValue audio_pts;
369
371 //hack among hacks
373 audioFrame->GetBytes(&audioFrameBytes);
376
379 }
380
383
384 //fprintf(stderr,"Audio Frame size %d ts %d\n", pkt.size, pkt.pts);
388
392 }
393 }
394
396 }
397
399 BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *
mode,
400 BMDDetectedVideoInputFormatFlags)
401 {
403 }
404
406 {
409
411 ctx->dli->SetCallback(
ctx->input_callback);
412 return ctx->dli->StartStreams();
413 }
414
415 extern "C" {
416
418 {
421
422 if (
ctx->capture_started) {
423 ctx->dli->StopStreams();
424 ctx->dli->DisableVideoInput();
425 ctx->dli->DisableAudioInput();
426 }
427
432
434
436
437 return 0;
438 }
439
441 {
444 IDeckLinkDisplayModeIterator *itermode;
445 IDeckLinkIterator *iter;
446 IDeckLink *dl =
NULL;
449 char fname[1024];
450 char *tmp;
451 int mode_num = 0;
452
461
462 #if !CONFIG_LIBZVBI
463 if (
ctx->teletext_lines) {
464 av_log(avctx,
AV_LOG_ERROR,
"Libzvbi support is needed for capturing teletext, please recompile FFmpeg.\n");
466 }
467 #endif
468
469 /* Check audio channel option for valid values: 2, 8 or 16 */
471 case 2:
472 case 8:
473 case 16:
474 break;
475 default:
478 }
479
480 iter = CreateDeckLinkIteratorInstance();
481 if (!iter) {
484 }
485
486 /* List available devices. */
487 if (
ctx->list_devices) {
490 }
491
493 tmp=strchr (fname, '@');
495 mode_num = atoi (tmp+1);
496 *tmp = 0;
497 }
498
499 /* Open device. */
500 while (iter->Next(&dl) ==
S_OK) {
501 const char *displayName;
503 if (!strcmp(fname, displayName)) {
506 break;
507 }
509 dl->Release();
510 }
511 iter->Release();
515 }
516
517 /* Get input device. */
518 if (
ctx->dl->QueryInterface(IID_IDeckLinkInput, (
void **) &
ctx->dli) !=
S_OK) {
523 }
524
525 /* List supported formats. */
526 if (
ctx->list_formats) {
531 }
532
533 if (
ctx->dli->GetDisplayModeIterator(&itermode) !=
S_OK) {
537 }
538
539 if (mode_num > 0) {
542 goto error;
543 }
544 }
545
546 itermode->Release();
547
548 /* Setup streams. */
550 if (!st) {
552 goto error;
553 }
556 st->codec->sample_rate = bmdAudioSampleRate48kHz;
560
562 if (!st) {
564 goto error;
565 }
567 st->codec->width =
ctx->bmd_width;
568 st->codec->height =
ctx->bmd_height;
569
570 st->codec->time_base.den =
ctx->bmd_tb_den;
571 st->codec->time_base.num =
ctx->bmd_tb_num;
573
576 st->codec->codec_tag =
MKTAG(
'V',
'2',
'1',
'0');
577 } else {
580 st->codec->codec_tag =
MKTAG(
'U',
'Y',
'V',
'Y');
581 }
582
584
586
587 if (
ctx->teletext_lines) {
589 if (!st) {
591 goto error;
592 }
594 st->codec->time_base.den =
ctx->bmd_tb_den;
595 st->codec->time_base.num =
ctx->bmd_tb_num;
598 ctx->teletext_st = st;
599 }
600
602 result =
ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger,
ctx->audio_st->codec->channels);
603
604 if (result !=
S_OK) {
606 goto error;
607 }
608
609 result =
ctx->dli->EnableVideoInput(
ctx->bmd_mode,
610 cctx->
v210 ? bmdFormat10BitYUV : bmdFormat8BitYUV,
611 bmdVideoInputFlagDefault);
612
613 if (result !=
S_OK) {
615 goto error;
616 }
617
619
622 goto error;
623 }
624
625 return 0;
626
627 error:
628
631
633 }
634
636 {
640
642 if (frame && (
ctx->bmd_field_dominance == bmdUpperFieldFirst ||
ctx->bmd_field_dominance == bmdLowerFieldFirst)) {
644 if (
ctx->bmd_field_dominance == bmdUpperFieldFirst) {
646 }
647 }
648
649 return 0;
650 }
651
652 } /* extern "C" */
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
This structure describes decoded (raw) audio or video data.
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
#define AV_LOG_WARNING
Something somehow does not look correct.
int index
stream index in AVFormatContext
int64_t bit_rate
Total stream bitrate in bit/s, 0 if not available.
static void avpacket_queue_init(AVFormatContext *avctx, AVPacketQueue *q)
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
static double av_q2d(AVRational a)
Convert rational to double.
#define AV_LOG_VERBOSE
Detailed information.
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
int interlaced_frame
The content of the picture is interlaced.
int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, decklink_direction_t direction, int num)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align)
Return the size in bytes of the amount of data required to store an image with the given parameters...
static void avpacket_queue_flush(AVPacketQueue *q)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
attribute_deprecated int av_dup_packet(AVPacket *pkt)
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
av_cold int ff_decklink_read_close(AVFormatContext *avctx)
int flags
A combination of AV_PKT_FLAG values.
AVCodecContext * codec
Codec context associated with this stream.
char filename[1024]
input or output filename
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt)
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
int ff_decklink_list_devices(AVFormatContext *avctx)
main external API structure.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
static HRESULT decklink_start_input(AVFormatContext *avctx)
HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName)
BYTE int const BYTE int int int height
static int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block)
static void avpacket_queue_end(AVPacketQueue *q)
struct AVPacketList * next
static unsigned long long avpacket_queue_size(AVPacketQueue *q)
int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt)
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
int top_field_first
If the content is interlaced, is top field displayed first.
int channels
number of audio channels
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
void * priv_data
Format private data.
av_cold int ff_decklink_read_header(AVFormatContext *avctx)
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
int frame_number
Frame counter, set by libavcodec.
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
#define MKTAG(a, b, c, d)
This structure stores compressed data.
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
#define AV_NOPTS_VALUE
Undefined timestamp value.