| @@ -22,6 +22,7 @@ · 21 unmodified lines |
| 22 | */ | 22 | */ |
| 23 | | 23 | |
| 24 | #include <atomic> | 24 | #include <atomic> |
| | 25 | #include <vector> |
| 25 | using std::atomic; | 26 | using std::atomic; |
| 26 | | 27 | |
| 27 | /* Include internal.h first to avoid conflict between winsock.h (used by | 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 | return ret; | 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 | class decklink_input_callback : public IDeckLinkInputCallback | 690 | class decklink_input_callback : public IDeckLinkInputCallback |
| 587 | { | 691 | { |
| 588 | public: | 692 | public: |
| @@ -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 buffer | 925 | 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) { |