]> git.sesse.net Git - ffmpeg/blobdiff - libavdevice/decklink_dec.cpp
avdevice/decklink: add missing include for buffer_size_t
[ffmpeg] / libavdevice / decklink_dec.cpp
index 92b8feed1426e8b851c3d1b4373c5b1a38cf6eec..0262b2f16aa82de14ced9225746aecf745a0efbf 100644 (file)
@@ -39,6 +39,7 @@ extern "C" {
 #include "libavutil/avassert.h"
 #include "libavutil/avutil.h"
 #include "libavutil/common.h"
+#include "libavutil/internal.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/time.h"
@@ -789,6 +790,52 @@ static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame,
     return pts;
 }
 
+static 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;
+}
+
+static 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 +917,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 +937,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) {
@@ -945,13 +986,13 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
 
             if (videoFrame->GetAncillaryData(&vanc) == S_OK) {
                 int i;
-                int64_t line_mask = 1;
                 BMDPixelFormat vanc_format = vanc->GetPixelFormat();
                 txt_buf[0] = 0x10;    // data_identifier - EBU_data
                 txt_buf++;
 #if CONFIG_LIBZVBI
                 if (ctx->bmd_mode == bmdModePAL && ctx->teletext_lines &&
                     (vanc_format == bmdFormat8BitYUV || vanc_format == bmdFormat10BitYUV)) {
+                    int64_t line_mask = 1;
                     av_assert0(videoFrame->GetWidth() == 720);
                     for (i = 6; i < 336; i++, line_mask <<= 1) {
                         uint8_t *buf;
@@ -1152,7 +1193,8 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     ctx->video_pts_source = cctx->video_pts_source;
     ctx->draw_bars = cctx->draw_bars;
     ctx->audio_depth = cctx->audio_depth;
-    ctx->raw_format = (BMDPixelFormat)cctx->raw_format;
+    if (cctx->raw_format > 0 && (unsigned int)cctx->raw_format < FF_ARRAY_ELEMS(decklink_raw_format_map))
+        ctx->raw_format = decklink_raw_format_map[cctx->raw_format];
     cctx->ctx = ctx;
 
     /* Check audio channel option for valid values: 2, 8 or 16 */
@@ -1178,7 +1220,6 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
 
     /* List available devices. */
     if (ctx->list_devices) {
-        av_log(avctx, AV_LOG_WARNING, "The -list_devices option is deprecated and will be removed. Please use ffmpeg -sources decklink instead.\n");
         ff_decklink_list_devices_legacy(avctx, 1, 0);
         return AVERROR_EXIT;
     }
@@ -1232,7 +1273,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
         }
         av_log(avctx, AV_LOG_INFO, "Autodetected the input mode\n");
     }
-    if (ctx->raw_format == bmdFormatUnspecified)
+    if (ctx->raw_format == (BMDPixelFormat)0)
         ctx->raw_format = bmdFormat8BitYUV;
     if (ff_decklink_set_format(avctx, DIRECTION_IN) < 0) {
         av_log(avctx, AV_LOG_ERROR, "Could not set format code %s for %s\n",
@@ -1280,34 +1321,26 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     switch(ctx->raw_format) {
     case bmdFormat8BitYUV:
         st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
-        st->codecpar->codec_tag   = MKTAG('U', 'Y', 'V', 'Y');
         st->codecpar->format      = AV_PIX_FMT_UYVY422;
         st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 16, st->time_base.den, st->time_base.num);
         break;
     case bmdFormat10BitYUV:
         st->codecpar->codec_id    = AV_CODEC_ID_V210;
-        st->codecpar->codec_tag   = MKTAG('V','2','1','0');
         st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 64, st->time_base.den, st->time_base.num * 3);
-        st->codecpar->bits_per_coded_sample = 10;
         break;
     case bmdFormat8BitARGB:
         st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
         st->codecpar->format      = AV_PIX_FMT_0RGB;
-        st->codecpar->codec_tag   = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format);
         st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 32, st->time_base.den, st->time_base.num);
         break;
     case bmdFormat8BitBGRA:
         st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
         st->codecpar->format      = AV_PIX_FMT_BGR0;
-        st->codecpar->codec_tag   = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format);
         st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 32, st->time_base.den, st->time_base.num);
         break;
     case bmdFormat10BitRGB:
         st->codecpar->codec_id    = AV_CODEC_ID_R210;
-        st->codecpar->codec_tag   = MKTAG('R','2','1','0');
-        st->codecpar->format      = AV_PIX_FMT_RGB48LE;
         st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 30, st->time_base.den, st->time_base.num);
-        st->codecpar->bits_per_coded_sample = 10;
         break;
     default:
         char fourcc_str[AV_FOURCC_MAX_STRING_SIZE] = {0};
@@ -1405,7 +1438,7 @@ int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt)
     avpacket_queue_get(&ctx->queue, pkt, 1);
 
     if (ctx->tc_format && !(av_dict_get(ctx->video_st->metadata, "timecode", NULL, 0))) {
-        int size;
+        buffer_size_t size;
         const uint8_t *side_metadata = av_packet_get_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, &size);
         if (side_metadata) {
            if (av_packet_unpack_dictionary(side_metadata, size, &ctx->video_st->metadata) < 0)