1 /*
2 * Blackmagic DeckLink input
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>
26
27 extern "C" {
36 #if CONFIG_LIBZVBI
37 #include <libzvbi.h>
38 #endif
39 }
40
43
44 #if CONFIG_LIBZVBI
45 static uint8_t calc_parity_and_line_offset(
int line)
46 {
47 uint8_t ret = (line < 313) << 5;
48 if (line >= 7 && line <= 22)
49 ret += line;
50 if (line >= 320 && line <= 335)
51 ret += (line - 313);
52 return ret;
53 }
54
56 {
57 vbi_bit_slicer slicer;
58
59 vbi_bit_slicer_init(&slicer, 720, 13500000, 6937500, 6937500, 0x00aaaae4, 0xffff, 18, 6, 42 * 8, VBI_MODULATION_NRZ_MSB, VBI_PIXFMT_UYVY);
60
61 if (vbi_bit_slice(&slicer, src, tgt + 4) ==
FALSE)
62 return -1;
63
64 tgt[0] = 0x02; // data_unit_id
65 tgt[1] = 0x2c; // data_unit_length
66 tgt[2] = calc_parity_and_line_offset(line); // field_parity, line_offset
67 tgt[3] = 0xe4; // framing code
68
69 return 0;
70 }
71 #endif
72
74 {
79 }
80
82 {
84
90 }
96 }
97
99 {
103 }
104
106 {
107 unsigned long long size;
112 }
113
115 {
117
118 // Drop Packet if queue size is > 1GB
121 return -1;
122 }
123 /* duplicate the packet */
125 return -1;
126 }
127
129 if (!pkt1) {
130 return -1;
131 }
134
136
139 } else {
141 }
142
146
148
150 return 0;
151 }
152
154 {
156 int ret;
157
159
160 for (;; ) {
162 if (pkt1) {
166 }
171 ret = 1;
172 break;
173 } else if (!block) {
174 ret = 0;
175 break;
176 } else {
178 }
179 }
181 return ret;
182 }
183
185 {
186 public:
189
193 virtual HRESULT STDMETHODCALLTYPE
VideoInputFormatChanged(BMDVideoInputFormatChangedEvents, IDeckLinkDisplayMode*, BMDDetectedVideoInputFormatFlags);
195
196 private:
204 };
205
207 {
213 }
214
216 {
218 }
219
221 {
225
227 }
228
230 {
234
236 delete this;
237 return 0;
238 }
239
241 }
242
244 IDeckLinkAudioInputPacket *audioFrame,
245 int64_t wallclock,
248 {
250 BMDTimeValue bmd_pts;
251 BMDTimeValue bmd_duration;
253 switch (pts_src) {
255 if (audioFrame)
256 res = audioFrame->GetPacketTime(&bmd_pts, time_base.
den);
257 break;
259 if (videoFrame)
260 res = videoFrame->GetStreamTime(&bmd_pts, &bmd_duration, time_base.
den);
261 break;
263 if (videoFrame)
264 res = videoFrame->GetHardwareReferenceTimestamp(time_base.
den, &bmd_pts, &bmd_duration);
265 break;
268 break;
269 }
271 pts = bmd_pts / time_base.
num;
272
276 pts -= *initial_pts;
277
279 }
280
282 IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame)
283 {
284 void *frameBytes;
285 void *audioFrameBytes;
286 BMDTimeValue frameTime;
287 BMDTimeValue frameDuration;
288 int64_t wallclock = 0;
289
293
294 // Handle Video Frame
295 if (videoFrame) {
301 "Frame received (#%lu) - Valid (%liB) - QSize %fMB\n",
303 videoFrame->GetRowBytes() * videoFrame->GetHeight(),
304 (double)qsize / 1024 / 1024);
305 }
306
307 videoFrame->GetBytes(&frameBytes);
308 videoFrame->GetStreamTime(&frameTime, &frameDuration,
310
311 if (videoFrame->GetFlags() & bmdFrameHasNoInputSource) {
312 if (
ctx->
draw_bars && videoFrame->GetPixelFormat() == bmdFormat8BitYUV) {
313 unsigned bars[8] = {
314 0xEA80EA80, 0xD292D210, 0xA910A9A5, 0x90229035,
315 0x6ADD6ACA, 0x51EF515A, 0x286D28EF, 0x10801080 };
316 int width = videoFrame->GetWidth();
317 int height = videoFrame->GetHeight();
318 unsigned *p = (unsigned *)frameBytes;
319
320 for (
int y = 0; y <
height; y++) {
321 for (
int x = 0; x <
width; x += 2)
322 *p++ = bars[(x * 8) /
width];
323 }
324 }
325
329 }
331 } else {
335 }
337 }
338
341
343 //To be made sure it still applies
347 pkt.
size = videoFrame->GetRowBytes() *
348 videoFrame->GetHeight();
349 //fprintf(stderr,"Video Frame size %d ts %d\n", pkt.size, pkt.pts);
350
351 #if CONFIG_LIBZVBI
352 if (!
no_video &&
ctx->
teletext_lines && videoFrame->GetPixelFormat() == bmdFormat8BitYUV && videoFrame->GetWidth() == 720) {
353 IDeckLinkVideoFrameAncillary *vanc;
355 uint8_t txt_buf0[1611];
// max 35 * 46 bytes decoded teletext lines + 1 byte data_identifier
357
358 if (videoFrame->GetAncillaryData(&vanc) ==
S_OK) {
359 int i;
360 int64_t line_mask = 1;
361 txt_buf[0] = 0x10; // data_identifier - EBU_data
362 txt_buf++;
363 for (i = 6; i < 336; i++, line_mask <<= 1) {
365 if ((
ctx->
teletext_lines & line_mask) && vanc->GetBufferForVerticalBlankingLine(i, (
void**)&buf) ==
S_OK) {
366 if (teletext_data_unit_from_vbi_data(i, buf, txt_buf) >= 0)
367 txt_buf += 46;
368 }
369 if (i == 22)
370 i = 317;
371 }
372 vanc->Release();
373 if (txt_buf - txt_buf0 > 1) {
374 int stuffing_units = (4 - ((45 + txt_buf - txt_buf0) / 46) % 4) % 4;
375 while (stuffing_units--) {
376 memset(txt_buf, 0xff, 46);
377 txt_buf[1] = 0x2c; // data_unit_length
378 txt_buf += 46;
379 }
384 txt_pkt.
data = txt_buf0;
385 txt_pkt.
size = txt_buf - txt_buf0;
388 }
389 }
390 }
391 }
392 #endif
393
396 }
397 }
398
399 // Handle Audio Frame
400 if (audioFrame) {
402 BMDTimeValue audio_pts;
404
405 //hack among hacks
407 audioFrame->GetBytes(&audioFrameBytes);
411
412 //fprintf(stderr,"Audio Frame size %d ts %d\n", pkt.size, pkt.pts);
416
419 }
420 }
421
423 }
424
426 BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *
mode,
427 BMDDetectedVideoInputFormatFlags)
428 {
430 }
431
433 {
436
438 ctx->dli->SetCallback(
ctx->input_callback);
439 return ctx->dli->StartStreams();
440 }
441
442 extern "C" {
443
445 {
448
449 if (
ctx->capture_started) {
450 ctx->dli->StopStreams();
451 ctx->dli->DisableVideoInput();
452 ctx->dli->DisableAudioInput();
453 }
454
457
459
460 return 0;
461 }
462
464 {
469 char fname[1024];
471 int mode_num = 0;
472 int ret;
473
490
491 #if !CONFIG_LIBZVBI
492 if (
ctx->teletext_lines) {
493 av_log(avctx,
AV_LOG_ERROR,
"Libzvbi support is needed for capturing teletext, please recompile FFmpeg.\n");
495 }
496 #endif
497
498 /* Check audio channel option for valid values: 2, 8 or 16 */
500 case 2:
501 case 8:
502 case 16:
503 break;
504 default:
507 }
508
509 /* List available devices. */
510 if (
ctx->list_devices) {
513 }
514
516 tmp=strchr (fname,
'@');
518 mode_num = atoi (
tmp+1);
520 }
521
523 if (ret < 0)
524 return ret;
525
526 /* Get input device. */
527 if (
ctx->dl->QueryInterface(IID_IDeckLinkInput, (
void **) &
ctx->dli) !=
S_OK) {
531 goto error;
532 }
533
534 /* List supported formats. */
535 if (
ctx->list_formats) {
538 goto error;
539 }
540
541 if (mode_num > 0) {
545 goto error;
546 }
547 }
548
549 /* Setup streams. */
551 if (!st) {
554 goto error;
555 }
558 st->codecpar->sample_rate = bmdAudioSampleRate48kHz;
562
564 if (!st) {
567 goto error;
568 }
570 st->codecpar->width =
ctx->bmd_width;
571 st->codecpar->height =
ctx->bmd_height;
572
573 st->time_base.den =
ctx->bmd_tb_den;
574 st->time_base.num =
ctx->bmd_tb_num;
576
579 st->codecpar->codec_tag =
MKTAG(
'V',
'2',
'1',
'0');
580 st->codecpar->bit_rate =
av_rescale(
ctx->bmd_width *
ctx->bmd_height * 64, st->time_base.den, st->time_base.num * 3);
581 } else {
584 st->codecpar->codec_tag =
MKTAG(
'U',
'Y',
'V',
'Y');
585 st->codecpar->bit_rate =
av_rescale(
ctx->bmd_width *
ctx->bmd_height * 16, st->time_base.den, st->time_base.num);
586 }
587
589
591
592 if (
ctx->teletext_lines) {
594 if (!st) {
597 goto error;
598 }
600 st->time_base.den =
ctx->bmd_tb_den;
601 st->time_base.num =
ctx->bmd_tb_num;
604 ctx->teletext_st = st;
605 }
606
608 result =
ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger,
ctx->audio_st->codecpar->channels);
609
610 if (result !=
S_OK) {
613 goto error;
614 }
615
616 result =
ctx->dli->EnableVideoInput(
ctx->bmd_mode,
617 cctx->
v210 ? bmdFormat10BitYUV : bmdFormat8BitYUV,
618 bmdVideoInputFlagDefault);
619
620 if (result !=
S_OK) {
623 goto error;
624 }
625
627
631 goto error;
632 }
633
634 return 0;
635
636 error:
638 return ret;
639 }
640
642 {
646
648 if (frame && (
ctx->bmd_field_dominance == bmdUpperFieldFirst ||
ctx->bmd_field_dominance == bmdLowerFieldFirst)) {
650 if (
ctx->bmd_field_dominance == bmdUpperFieldFirst) {
652 }
653 }
654
655 return 0;
656 }
657
658 } /* 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
Convenience header that includes libavutil's core.
static void avpacket_queue_init(AVFormatContext *avctx, AVPacketQueue *q)
int ff_decklink_init_device(AVFormatContext *avctx, const char *name)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
DecklinkPtsSource audio_pts_source
static const BMDVideoConnection decklink_video_connection_map[]
DecklinkPtsSource audio_pts_source
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
static const BMDAudioConnection decklink_audio_connection_map[]
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
#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.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
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.
char filename[1024]
input or output filename
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
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.
#define FF_ARRAY_ELEMS(a)
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
int ff_decklink_list_devices(AVFormatContext *avctx)
static AVRational av_make_q(int num, int den)
Create an AVRational.
DecklinkPtsSource video_pts_source
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
static HRESULT decklink_start_input(AVFormatContext *avctx)
static int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block)
Rational number (pair of numerator and denominator).
static int64_t pts
Global timestamp for the audio frames.
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
void ff_decklink_cleanup(AVFormatContext *avctx)
static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame, int64_t wallclock, DecklinkPtsSource pts_src, AVRational time_base, int64_t *initial_pts)
static void avpacket_queue_end(AVPacketQueue *q)
struct AVPacketList * next
common internal and external API header
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.
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...
DecklinkPtsSource video_pts_source
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
AVCodecParameters * codecpar
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.
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.