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

Showing the changes to libavdevice/decklink_dec.cpp (1 of 7 files). Show all

Unified · Split

libavdevice/decklink_dec.cpp+123−0
@@ -22,6 +22,7 @@ · 21 unmodified lines
2222 */
2323
2424 #include <atomic>
25+#include <vector>
2526 using std::atomic;
2627
2728 /* 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
583584 return ret;
584585 }
585586
587+static 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+
586690 class decklink_input_callback : public IDeckLinkInputCallback
587691 {
588692 public:
@@ -821,6 +925,10 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( · 232 unmodified lines
821925 uint8_t txt_buf0[3531]; // 35 * 46 bytes decoded teletext lines + 1 byte data_identifier + 1920 bytes OP47 decode buffer
822926 uint8_t *txt_buf = txt_buf0;
823927
928+ if (ctx->enable_klv) {
929+ handle_klv(avctx, ctx, videoFrame, pkt.pts);
930+ }
931+
824932 if (videoFrame->GetAncillaryData(&vanc) == S_OK) {
825933 int i;
826934 int64_t line_mask = 1;
@@ -1012,6 +1120,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 185 unmodified lines
10121120 return AVERROR(ENOMEM);
10131121 ctx->list_devices = cctx->list_devices;
10141122 ctx->list_formats = cctx->list_formats;
1123+ ctx->enable_klv = cctx->enable_klv;
10151124 ctx->teletext_lines = cctx->teletext_lines;
10161125 ctx->preroll = cctx->preroll;
10171126 ctx->duplex_mode = cctx->duplex_mode;
@@ -1202,6 +1311,20 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 184 unmodified lines
12021311
12031312 ctx->video_st=st;
12041313
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+
12051328 if (ctx->teletext_lines) {
12061329 st = avformat_new_stream(avctx, NULL);
12071330 if (!st) {

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