diff options
author | Marton Balint <cus@passwd.hu> | 2020-09-05 23:29:24 +0200 |
---|---|---|
committer | Marton Balint <cus@passwd.hu> | 2020-12-03 18:32:57 +0100 |
commit | ff373bb4a87a5b17dfa82aba5c7e74b125298fa8 (patch) | |
tree | 4198d61592a79d804d3fc0fce7b3ccc760351ee3 /libavdevice | |
parent | eca12f4d5a9231b0e6b71f55525518f104877ee6 (diff) | |
download | ffmpeg-ff373bb4a87a5b17dfa82aba5c7e74b125298fa8.tar.gz |
avdevice/decklink_dec: add support for 50/60 fps timecode
Signed-off-by: Marton Balint <cus@passwd.hu>
Diffstat (limited to 'libavdevice')
-rw-r--r-- | libavdevice/decklink_dec.cpp | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 2e41b587e8..090437a6b5 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -789,6 +789,52 @@ static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame, return pts; } +int get_bmd_timecode(AVFormatContext *avctx, AVTimecode *tc, AVRational frame_rate, BMDTimecodeFormat tc_format, IDeckLinkVideoInputFrame *videoFrame) +{ + IDeckLinkTimecode *timecode; + int ret = AVERROR(ENOENT); +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 + int hfr = (tc_format == bmdTimecodeRP188HighFrameRate); +#else + int hfr = 0; +#endif + if (videoFrame->GetTimecode(tc_format, &timecode) == S_OK) { + uint8_t hh, mm, ss, ff; + if (timecode->GetComponents(&hh, &mm, &ss, &ff) == S_OK) { + int flags = (timecode->GetFlags() & bmdTimecodeIsDropFrame) ? AV_TIMECODE_FLAG_DROPFRAME : 0; + if (!hfr && av_cmp_q(frame_rate, av_make_q(30, 1)) == 1) + ff = ff << 1 | !!(timecode->GetFlags() & bmdTimecodeFieldMark); + ret = av_timecode_init_from_components(tc, frame_rate, flags, hh, mm, ss, ff, avctx); + } + timecode->Release(); + } + return ret; +} + +int get_frame_timecode(AVFormatContext *avctx, decklink_ctx *ctx, AVTimecode *tc, IDeckLinkVideoInputFrame *videoFrame) +{ + AVRational frame_rate = ctx->video_st->r_frame_rate; + int ret; + /* 50/60 fps content has alternating VITC1 and VITC2 timecode (see SMPTE ST + * 12-2, section 7), so the native ordering of RP188Any (HFR, VITC1, LTC, + * VITC2) would not work because LTC might not contain the field flag. + * Therefore we query the types manually. */ + if (ctx->tc_format == bmdTimecodeRP188Any && av_cmp_q(frame_rate, av_make_q(30, 1)) == 1) { +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 + ret = get_bmd_timecode(avctx, tc, frame_rate, bmdTimecodeRP188HighFrameRate, videoFrame); + if (ret == AVERROR(ENOENT)) +#endif + ret = get_bmd_timecode(avctx, tc, frame_rate, bmdTimecodeRP188VITC1, videoFrame); + if (ret == AVERROR(ENOENT)) + ret = get_bmd_timecode(avctx, tc, frame_rate, bmdTimecodeRP188VITC2, videoFrame); + if (ret == AVERROR(ENOENT)) + ret = get_bmd_timecode(avctx, tc, frame_rate, bmdTimecodeRP188LTC, videoFrame); + } else { + ret = get_bmd_timecode(avctx, tc, frame_rate, ctx->tc_format, videoFrame); + } + return ret; +} + HRESULT decklink_input_callback::VideoInputFrameArrived( IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame) { @@ -870,22 +916,16 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( // Handle Timecode (if requested) if (ctx->tc_format) { - IDeckLinkTimecode *timecode; - if (videoFrame->GetTimecode(ctx->tc_format, &timecode) == S_OK) { - const char *tc = NULL; - DECKLINK_STR decklink_tc; - if (timecode->GetString(&decklink_tc) == S_OK) { - tc = DECKLINK_STRDUP(decklink_tc); - DECKLINK_FREE(decklink_tc); - } - timecode->Release(); + AVTimecode tcr; + if (get_frame_timecode(avctx, ctx, &tcr, videoFrame) >= 0) { + char tcstr[AV_TIMECODE_STR_SIZE]; + const char *tc = av_timecode_make_string(&tcr, tcstr, 0); if (tc) { AVDictionary* metadata_dict = NULL; int metadata_len; uint8_t* packed_metadata; - AVTimecode tcr; - if (av_timecode_init_from_string(&tcr, ctx->video_st->r_frame_rate, tc, ctx) >= 0) { + if (av_cmp_q(ctx->video_st->r_frame_rate, av_make_q(60, 1)) < 1) { uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0); int size = sizeof(uint32_t) * 4; uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size); @@ -896,7 +936,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( } } - if (av_dict_set(&metadata_dict, "timecode", tc, AV_DICT_DONT_STRDUP_VAL) >= 0) { + if (av_dict_set(&metadata_dict, "timecode", tc, 0) >= 0) { packed_metadata = av_packet_pack_dictionary(metadata_dict, &metadata_len); av_dict_free(&metadata_dict); if (packed_metadata) { |