Showing the changes to libavdevice/decklink_dec.cpp (1 of 7 files). Show all
Unified · Split
| @@ -22,6 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | */ |
| 23 | 23 | |
| 24 | 24 | #include <atomic> |
| 25 | +#include <vector> | |
| 25 | 26 | using std::atomic; |
| 26 | 27 | |
| 27 | 28 | /* 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 | 584 | return ret; |
| 584 | 585 | } |
| 585 | 586 | |
| 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 | + | |
| 586 | 690 | class decklink_input_callback : public IDeckLinkInputCallback |
| 587 | 691 | { |
| 588 | 692 | public: |
| @@ -821,6 +925,10 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( · 232 unmodified lines | ||
| 821 | 925 | uint8_t txt_buf0[3531]; // 35 * 46 bytes decoded teletext lines + 1 byte data_identifier + 1920 bytes OP47 decode buffer |
| 822 | 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 | 932 | if (videoFrame->GetAncillaryData(&vanc) == S_OK) { |
| 825 | 933 | int i; |
| 826 | 934 | int64_t line_mask = 1; |
| @@ -1012,6 +1120,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 185 unmodified lines | ||
| 1012 | 1120 | return AVERROR(ENOMEM); |
| 1013 | 1121 | ctx->list_devices = cctx->list_devices; |
| 1014 | 1122 | ctx->list_formats = cctx->list_formats; |
| 1123 | + ctx->enable_klv = cctx->enable_klv; | |
| 1015 | 1124 | ctx->teletext_lines = cctx->teletext_lines; |
| 1016 | 1125 | ctx->preroll = cctx->preroll; |
| 1017 | 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 | 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 | 1328 | if (ctx->teletext_lines) { |
| 1206 | 1329 | st = avformat_new_stream(avctx, NULL); |
| 1207 | 1330 | if (!st) { |