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 | #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) { |