History

avdevice/decklink_dec: add support for extracting and outputing klv from vanc

Milos Zivkovic committed 6 years ago

Commit c4e08681 parent 4979afd7 files · +135 −2Browse files

Unified · Split

7 files
  1. configure +1 −1
  2. doc/indevs.texi +6 −0
  3. libavdevice/decklink_common.h +2 −0
  4. libavdevice/decklink_common_c.h +1 −0
  5. libavdevice/decklink_dec.cpp +123 −0
  6. libavdevice/decklink_dec_c.c +1 −0
  7. libavdevice/version.h +1 −1
configure+1−1
@@ -6281,7 +6281,7 @@ enabled avisynth && require_headers "avisynth/avisynth_c.h" · 6280 unmodified lines
6281enabled cuda_nvcc && { check_nvcc cuda_nvcc || die "ERROR: failed checking for nvcc."; }6281enabled cuda_nvcc && { check_nvcc cuda_nvcc || die "ERROR: failed checking for nvcc."; }
6282enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint6282enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint
6283enabled decklink && { require_headers DeckLinkAPI.h &&6283enabled decklink && { require_headers DeckLinkAPI.h &&
6284 { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a090500" || die "ERROR: Decklink API version must be >= 10.9.5."; } }6284 { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a0a0000" || die "ERROR: Decklink API version must be >= 10.10"; } }
6285enabled frei0r && require_headers "frei0r.h dlfcn.h"6285enabled frei0r && require_headers "frei0r.h dlfcn.h"
6286enabled gmp && require gmp gmp.h mpz_export -lgmp6286enabled gmp && require gmp gmp.h mpz_export -lgmp
6287enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init6287enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init
doc/indevs.texi+6−0
@@ -398,6 +398,12 @@ are dropped till a frame with timecode is received. · 397 unmodified lines
398Option @var{timecode_format} must be specified.398Option @var{timecode_format} must be specified.
399Defaults to @option{false}.399Defaults to @option{false}.
400 400
401@item enable_klv(@emph{bool})
402If set to @option{true}, extracts KLV data from VANC and outputs KLV packets.
403KLV VANC packets are joined based on MID and PSC fields and aggregated into
404one KLV packet.
405Defaults to @option{false}.
406
401@end table407@end table
402 408
403@subsection Examples409@subsection Examples
libavdevice/decklink_common.h+2−0
@@ -120,12 +120,14 @@ struct decklink_ctx { · 119 unmodified lines
120 unsigned int dropped;120 unsigned int dropped;
121 AVStream *audio_st;121 AVStream *audio_st;
122 AVStream *video_st;122 AVStream *video_st;
123 AVStream *klv_st;
123 AVStream *teletext_st;124 AVStream *teletext_st;
124 uint16_t cdp_sequence_num;125 uint16_t cdp_sequence_num;
125 126
126 /* Options */127 /* Options */
127 int list_devices;128 int list_devices;
128 int list_formats;129 int list_formats;
130 int enable_klv;
129 int64_t teletext_lines;131 int64_t teletext_lines;
130 double preroll;132 double preroll;
131 int duplex_mode;133 int duplex_mode;
libavdevice/decklink_common_c.h+1−0
@@ -40,6 +40,7 @@ struct decklink_cctx { · 39 unmodified lines
40 /* Options */40 /* Options */
41 int list_devices;41 int list_devices;
42 int list_formats;42 int list_formats;
43 int enable_klv;
43 int64_t teletext_lines;44 int64_t teletext_lines;
44 double preroll;45 double preroll;
45 int audio_channels;46 int audio_channels;
libavdevice/decklink_dec.cpp+123−0
@@ -22,6 +22,7 @@ · 21 unmodified lines
22 */22 */
23 23
24#include <atomic>24#include <atomic>
25#include <vector>
25using std::atomic;26using std::atomic;
26 27
27/* Include internal.h first to avoid conflict between winsock.h (used by28/* Include internal.h first to avoid conflict between winsock.h (used by
@@ -583,6 +584,109 @@ static int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block) · 555 unmodified lines
583 return ret;584 return ret;
584}585}
585 586
587static void handle_klv(AVFormatContext *avctx, decklink_ctx *ctx, IDeckLinkVideoInputFrame *videoFrame, int64_t pts)
588{
589 const uint8_t KLV_DID = 0x44;
590 const uint8_t KLV_IN_VANC_SDID = 0x04;
591
592 struct KLVPacket
593 {
594 uint16_t sequence_counter;
595 std::vector<uint8_t> data;
596 };
597
598 size_t total_size = 0;
599 std::vector<std::vector<KLVPacket>> klv_packets(256);
600
601 IDeckLinkVideoFrameAncillaryPackets *packets = nullptr;
602 if (videoFrame->QueryInterface(IID_IDeckLinkVideoFrameAncillaryPackets, (void**)&packets) != S_OK)
603 return;
604
605 IDeckLinkAncillaryPacketIterator *it = nullptr;
606 if (packets->GetPacketIterator(&it) != S_OK) {
607 packets->Release();
608 return;
609 }
610
611 IDeckLinkAncillaryPacket *packet = nullptr;
612 while (it->Next(&packet) == S_OK) {
613 uint8_t *data = nullptr;
614 uint32_t size = 0;
615
616 if (packet->GetDID() == KLV_DID && packet->GetSDID() == KLV_IN_VANC_SDID) {
617 av_log(avctx, AV_LOG_DEBUG, "Found KLV VANC packet on line: %d\n", packet->GetLineNumber());
618
619 if (packet->GetBytes(bmdAncillaryPacketFormatUInt8, (const void**) &data, &size) == S_OK) {
620 // MID and PSC
621 if (size > 3) {
622 uint8_t mid = data[0];
623 uint16_t psc = data[1] << 8 | data[2];
624
625 av_log(avctx, AV_LOG_DEBUG, "KLV with MID: %d and PSC: %d\n", mid, psc);
626
627 auto& list = klv_packets[mid];
628 uint16_t expected_psc = list.size() + 1;
629
630 if (psc == expected_psc) {
631 uint32_t data_len = size - 3;
632 total_size += data_len;
633
634 KLVPacket packet{ psc };
635 packet.data.resize(data_len);
636 memcpy(packet.data.data(), data + 3, data_len);
637
638 list.push_back(std::move(packet));
639 } else {
640 av_log(avctx, AV_LOG_WARNING, "Out of order PSC: %d for MID: %d\n", psc, mid);
641
642 if (!list.empty()) {
643 for (auto& klv : list)
644 total_size -= klv.data.size();
645
646 list.clear();
647 }
648 }
649 }
650 }
651 }
652
653 packet->Release();
654 }
655
656 it->Release();
657 packets->Release();
658
659 if (total_size > 0) {
660 std::vector<uint8_t> klv;
661 klv.reserve(total_size);
662
663 for (size_t i = 0; i < klv_packets.size(); ++i) {
664 auto& list = klv_packets[i];
665
666 if (list.empty())
667 continue;
668
669 av_log(avctx, AV_LOG_DEBUG, "Joining MID: %d\n", (int)i);
670
671 for (auto& packet : list)
672 klv.insert(klv.end(), packet.data.begin(), packet.data.end());
673 }
674
675 AVPacket klv_packet;
676 av_init_packet(&klv_packet);
677 klv_packet.pts = pts;
678 klv_packet.dts = pts;
679 klv_packet.flags |= AV_PKT_FLAG_KEY;
680 klv_packet.stream_index = ctx->klv_st->index;
681 klv_packet.data = klv.data();
682 klv_packet.size = klv.size();
683
684 if (avpacket_queue_put(&ctx->queue, &klv_packet) < 0) {
685 ++ctx->dropped;
686 }
687 }
688}
689
586class decklink_input_callback : public IDeckLinkInputCallback690class decklink_input_callback : public IDeckLinkInputCallback
587{691{
588public:692public:
@@ -821,6 +925,10 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( · 232 unmodified lines
821 uint8_t txt_buf0[3531]; // 35 * 46 bytes decoded teletext lines + 1 byte data_identifier + 1920 bytes OP47 decode buffer925 uint8_t txt_buf0[3531]; // 35 * 46 bytes decoded teletext lines + 1 byte data_identifier + 1920 bytes OP47 decode buffer
822 uint8_t *txt_buf = txt_buf0;926 uint8_t *txt_buf = txt_buf0;
823 927
928 if (ctx->enable_klv) {
929 handle_klv(avctx, ctx, videoFrame, pkt.pts);
930 }
931
824 if (videoFrame->GetAncillaryData(&vanc) == S_OK) {932 if (videoFrame->GetAncillaryData(&vanc) == S_OK) {
825 int i;933 int i;
826 int64_t line_mask = 1;934 int64_t line_mask = 1;
@@ -1012,6 +1120,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 185 unmodified lines
1012 return AVERROR(ENOMEM);1120 return AVERROR(ENOMEM);
1013 ctx->list_devices = cctx->list_devices;1121 ctx->list_devices = cctx->list_devices;
1014 ctx->list_formats = cctx->list_formats;1122 ctx->list_formats = cctx->list_formats;
1123 ctx->enable_klv = cctx->enable_klv;
1015 ctx->teletext_lines = cctx->teletext_lines;1124 ctx->teletext_lines = cctx->teletext_lines;
1016 ctx->preroll = cctx->preroll;1125 ctx->preroll = cctx->preroll;
1017 ctx->duplex_mode = cctx->duplex_mode;1126 ctx->duplex_mode = cctx->duplex_mode;
@@ -1202,6 +1311,20 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 184 unmodified lines
1202 1311
1203 ctx->video_st=st;1312 ctx->video_st=st;
1204 1313
1314 if (ctx->enable_klv) {
1315 st = avformat_new_stream(avctx, NULL);
1316 if (!st) {
1317 ret = AVERROR(ENOMEM);
1318 goto error;
1319 }
1320 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
1321 st->time_base.den = ctx->bmd_tb_den;
1322 st->time_base.num = ctx->bmd_tb_num;
1323 st->codecpar->codec_id = AV_CODEC_ID_SMPTE_KLV;
1324 avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
1325 ctx->klv_st = st;
1326 }
1327
1205 if (ctx->teletext_lines) {1328 if (ctx->teletext_lines) {
1206 st = avformat_new_stream(avctx, NULL);1329 st = avformat_new_stream(avctx, NULL);
1207 if (!st) {1330 if (!st) {
libavdevice/decklink_dec_c.c+1−0
@@ -39,6 +39,7 @@ static const AVOption options[] = { · 38 unmodified lines
39 { "argb", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, 0, 0, DEC, "raw_format"},39 { "argb", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, 0, 0, DEC, "raw_format"},
40 { "bgra", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MKBETAG('B','G','R','A') }, 0, 0, DEC, "raw_format"},40 { "bgra", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MKBETAG('B','G','R','A') }, 0, 0, DEC, "raw_format"},
41 { "rgb10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MKBETAG('r','2','1','0') }, 0, 0, DEC, "raw_format"},41 { "rgb10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MKBETAG('r','2','1','0') }, 0, 0, DEC, "raw_format"},
42 { "enable_klv", "output klv if present in vanc", OFFSET(enable_klv), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC },
42 { "teletext_lines", "teletext lines bitmask", OFFSET(teletext_lines), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, 0x7ffffffffLL, DEC, "teletext_lines"},43 { "teletext_lines", "teletext lines bitmask", OFFSET(teletext_lines), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, 0x7ffffffffLL, DEC, "teletext_lines"},
43 { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0, DEC, "teletext_lines"},44 { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0, DEC, "teletext_lines"},
44 { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0, DEC, "teletext_lines"},45 { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0, DEC, "teletext_lines"},
libavdevice/version.h+1−1
@@ -29,7 +29,7 @@ · 28 unmodified lines
29 29
30#define LIBAVDEVICE_VERSION_MAJOR 5830#define LIBAVDEVICE_VERSION_MAJOR 58
31#define LIBAVDEVICE_VERSION_MINOR 1131#define LIBAVDEVICE_VERSION_MINOR 11
32#define LIBAVDEVICE_VERSION_MICRO 10032#define LIBAVDEVICE_VERSION_MICRO 101
33 33
34#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \34#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
35 LIBAVDEVICE_VERSION_MINOR, \35 LIBAVDEVICE_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t