| @@ -345,6 +345,25 @@ static int decklink_setup_subtitle(AVFormatContext *avctx, AVStream *st) · 344 unmodified lines |
| 345 | 345 | return ret; |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | +static int decklink_setup_data(AVFormatContext *avctx, AVStream *st) |
| 349 | +{ |
| 350 | + int ret = -1; |
| 351 | + |
| 352 | + switch(st->codecpar->codec_id) { |
| 353 | +#if CONFIG_LIBKLVANC |
| 354 | + case AV_CODEC_ID_SMPTE_2038: |
| 355 | + /* No specific setup required */ |
| 356 | + ret = 0; |
| 357 | + break; |
| 358 | +#endif |
| 359 | + default: |
| 360 | + av_log(avctx, AV_LOG_ERROR, "Unsupported data codec specified\n"); |
| 361 | + break; |
| 362 | + } |
| 363 | + |
| 364 | + return ret; |
| 365 | +} |
| 366 | + |
| 348 | 367 | av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) |
| 349 | 368 | { |
| 350 | 369 | struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; |
| @@ -370,6 +389,7 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) · 19 unmodified lines |
| 370 | 389 | #if CONFIG_LIBKLVANC |
| 371 | 390 | klvanc_context_destroy(ctx->vanc_ctx); |
| 372 | 391 | #endif |
| 392 | + ff_decklink_packet_queue_end(&ctx->vanc_queue); |
| 373 | 393 | |
| 374 | 394 | ff_ccfifo_uninit(&ctx->cc_fifo); |
| 375 | 395 | av_freep(&cctx->ctx); |
| @@ -552,6 +572,58 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx * · 176 unmodified lines |
| 552 | 572 | construct_cc(avctx, ctx, pkt, &vanc_lines); |
| 553 | 573 | construct_afd(avctx, ctx, pkt, &vanc_lines, st); |
| 554 | 574 | |
| 575 | + /* See if there any pending data packets to process */ |
| 576 | + while (ff_decklink_packet_queue_size(&ctx->vanc_queue) > 0) { |
| 577 | + AVStream *vanc_st; |
| 578 | + AVPacket vanc_pkt; |
| 579 | + int64_t pts; |
| 580 | + |
| 581 | + pts = ff_decklink_packet_queue_peekpts(&ctx->vanc_queue); |
| 582 | + if (pts > ctx->last_pts) { |
| 583 | + /* We haven't gotten to the video frame we are supposed to inject |
| 584 | + the oldest VANC packet into yet, so leave it on the queue... */ |
| 585 | + break; |
| 586 | + } |
| 587 | + |
| 588 | + ret = ff_decklink_packet_queue_get(&ctx->vanc_queue, &vanc_pkt, 1); |
| 589 | + if (vanc_pkt.pts + 1 < ctx->last_pts) { |
| 590 | + av_log(avctx, AV_LOG_WARNING, "VANC packet too old, throwing away\n"); |
| 591 | + av_packet_unref(&vanc_pkt); |
| 592 | + continue; |
| 593 | + } |
| 594 | + |
| 595 | + vanc_st = avctx->streams[vanc_pkt.stream_index]; |
| 596 | + if (vanc_st->codecpar->codec_id == AV_CODEC_ID_SMPTE_2038) { |
| 597 | + struct klvanc_smpte2038_anc_data_packet_s *pkt_2038 = NULL; |
| 598 | + |
| 599 | + klvanc_smpte2038_parse_pes_payload(vanc_pkt.data, vanc_pkt.size, &pkt_2038); |
| 600 | + if (pkt_2038 == NULL) { |
| 601 | + av_log(avctx, AV_LOG_ERROR, "failed to decode SMPTE 2038 PES packet"); |
| 602 | + av_packet_unref(&vanc_pkt); |
| 603 | + continue; |
| 604 | + } |
| 605 | + for (int i = 0; i < pkt_2038->lineCount; i++) { |
| 606 | + struct klvanc_smpte2038_anc_data_line_s *l = &pkt_2038->lines[i]; |
| 607 | + uint16_t *vancWords = NULL; |
| 608 | + uint16_t vancWordCount; |
| 609 | + |
| 610 | + if (klvanc_smpte2038_convert_line_to_words(l, &vancWords, |
| 611 | + &vancWordCount) < 0) |
| 612 | + break; |
| 613 | + |
| 614 | + ret = klvanc_line_insert(ctx->vanc_ctx, &vanc_lines, vancWords, |
| 615 | + vancWordCount, l->line_number, 0); |
| 616 | + free(vancWords); |
| 617 | + if (ret != 0) { |
| 618 | + av_log(avctx, AV_LOG_ERROR, "VANC line insertion failed\n"); |
| 619 | + break; |
| 620 | + } |
| 621 | + } |
| 622 | + klvanc_smpte2038_anc_data_packet_free(pkt_2038); |
| 623 | + } |
| 624 | + av_packet_unref(&vanc_pkt); |
| 625 | + } |
| 626 | + |
| 555 | 627 | IDeckLinkVideoFrameAncillary *vanc; |
| 556 | 628 | int result = ctx->dlo->CreateAncillaryData(bmdFormat10BitYUV, &vanc); |
| 557 | 629 | if (result != S_OK) { |
| @@ -750,6 +822,18 @@ static int decklink_write_subtitle_packet(AVFormatContext *avctx, AVPacket *pkt) · 192 unmodified lines |
| 750 | 822 | return 0; |
| 751 | 823 | } |
| 752 | 824 | |
| 825 | +static int decklink_write_data_packet(AVFormatContext *avctx, AVPacket *pkt) |
| 826 | +{ |
| 827 | + struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; |
| 828 | + struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; |
| 829 | + |
| 830 | + if (ff_decklink_packet_queue_put(&ctx->vanc_queue, pkt) < 0) { |
| 831 | + av_log(avctx, AV_LOG_WARNING, "Failed to queue DATA packet\n"); |
| 832 | + } |
| 833 | + |
| 834 | + return 0; |
| 835 | +} |
| 836 | + |
| 753 | 837 | extern "C" { |
| 754 | 838 | |
| 755 | 839 | av_cold int ff_decklink_write_header(AVFormatContext *avctx) |
| @@ -814,6 +898,9 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) · 58 unmodified lines |
| 814 | 898 | } else if (c->codec_type == AVMEDIA_TYPE_VIDEO) { |
| 815 | 899 | if (decklink_setup_video(avctx, st)) |
| 816 | 900 | goto error; |
| 901 | + } else if (c->codec_type == AVMEDIA_TYPE_DATA) { |
| 902 | + if (decklink_setup_data(avctx, st)) |
| 903 | + goto error; |
| 817 | 904 | } else if (c->codec_type == AVMEDIA_TYPE_SUBTITLE) { |
| 818 | 905 | if (decklink_setup_subtitle(avctx, st)) |
| 819 | 906 | goto error; |
| @@ -823,13 +910,16 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) · 3 unmodified lines |
| 823 | 910 | } |
| 824 | 911 | } |
| 825 | 912 | |
| 913 | + /* Reconfigure the data/subtitle stream clocks to match the video */ |
| 826 | 914 | for (n = 0; n < avctx->nb_streams; n++) { |
| 827 | 915 | AVStream *st = avctx->streams[n]; |
| 828 | 916 | AVCodecParameters *c = st->codecpar; |
| 829 | 917 | |
| 830 | | − if(c->codec_type == AVMEDIA_TYPE_SUBTITLE) |
| 918 | + if(c->codec_type == AVMEDIA_TYPE_DATA || |
| 919 | + c->codec_type == AVMEDIA_TYPE_SUBTITLE) |
| 831 | 920 | avpriv_set_pts_info(st, 64, ctx->bmd_tb_num, ctx->bmd_tb_den); |
| 832 | 921 | } |
| 922 | + ff_decklink_packet_queue_init(avctx, &ctx->vanc_queue, cctx->vanc_queue_size); |
| 833 | 923 | |
| 834 | 924 | ret = ff_ccfifo_init(&ctx->cc_fifo, av_make_q(ctx->bmd_tb_den, ctx->bmd_tb_num), avctx); |
| 835 | 925 | if (ret < 0) { |
| @@ -852,6 +942,8 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt) · 16 unmodified lines |
| 852 | 942 | return decklink_write_video_packet(avctx, pkt); |
| 853 | 943 | else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) |
| 854 | 944 | return decklink_write_audio_packet(avctx, pkt); |
| 945 | + else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) |
| 946 | + return decklink_write_data_packet(avctx, pkt); |
| 855 | 947 | else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) |
| 856 | 948 | return decklink_write_subtitle_packet(avctx, pkt); |
| 857 | 949 | |