Browse Source

avdevice/decklink_dec: capture timecode to metadata when requested

If the user provides a valid timecode_format look for timecode of that
format in the capture and if found store it on the video avstream's
metadata.

Slightly modified by Marton Balint to capture per-frame timecode as well.

Signed-off-by: Marton Balint <cus@passwd.hu>
tags/n4.1
Jon Morley Marton Balint 7 years ago
parent
commit
0946c0ec17
6 changed files with 69 additions and 1 deletions
  1. +6
    -0
      doc/indevs.texi
  2. +12
    -0
      libavdevice/decklink_common.h
  3. +1
    -0
      libavdevice/decklink_common_c.h
  4. +40
    -0
      libavdevice/decklink_dec.cpp
  5. +9
    -0
      libavdevice/decklink_dec_c.c
  6. +1
    -1
      libavdevice/version.h

+ 6
- 0
doc/indevs.texi View File

@@ -326,6 +326,12 @@ Defaults to @samp{2}.
Sets the decklink device duplex mode. Must be @samp{unset}, @samp{half} or @samp{full}.
Defaults to @samp{unset}.

@item timecode_format
Timecode type to include in the frame and video stream metadata. Must be
@samp{none}, @samp{rp188vitc}, @samp{rp188vitc2}, @samp{rp188ltc},
@samp{rp188any}, @samp{vitc}, @samp{vitc2}, or @samp{serial}. Defaults to
@samp{none} (not included).

@item video_input
Sets the video input source. Must be @samp{unset}, @samp{sdi}, @samp{hdmi},
@samp{optical_sdi}, @samp{component}, @samp{composite} or @samp{s_video}.


+ 12
- 0
libavdevice/decklink_common.h View File

@@ -93,6 +93,7 @@ struct decklink_ctx {
BMDDisplayMode bmd_mode;
BMDVideoConnection video_input;
BMDAudioConnection audio_input;
BMDTimecodeFormat tc_format;
int bmd_width;
int bmd_height;
int bmd_field_dominance;
@@ -169,6 +170,17 @@ static const BMDVideoConnection decklink_video_connection_map[] = {
bmdVideoConnectionSVideo,
};

static const BMDTimecodeFormat decklink_timecode_format_map[] = {
(BMDTimecodeFormat)0,
bmdTimecodeRP188VITC1,
bmdTimecodeRP188VITC2,
bmdTimecodeRP188LTC,
bmdTimecodeRP188Any,
bmdTimecodeVITC,
bmdTimecodeVITCField2,
bmdTimecodeSerial,
};

HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName);
int ff_decklink_set_configs(AVFormatContext *avctx, decklink_direction_t direction);
int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction = DIRECTION_OUT, int num = 0);


+ 1
- 0
libavdevice/decklink_common_c.h View File

@@ -50,6 +50,7 @@ struct decklink_cctx {
DecklinkPtsSource video_pts_source;
int audio_input;
int video_input;
int tc_format;
int draw_bars;
char *format_code;
int raw_format;


+ 40
- 0
libavdevice/decklink_dec.cpp View File

@@ -752,6 +752,35 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
"- Frames dropped %u\n", ctx->frameCount, ++ctx->dropped);
}
no_video = 0;

// 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();
if (tc) {
AVDictionary* metadata_dict = NULL;
int metadata_len;
uint8_t* packed_metadata;
if (av_dict_set(&metadata_dict, "timecode", tc, AV_DICT_DONT_STRDUP_VAL) >= 0) {
packed_metadata = av_packet_pack_dictionary(metadata_dict, &metadata_len);
av_dict_free(&metadata_dict);
if (packed_metadata) {
if (av_packet_add_side_data(&pkt, AV_PKT_DATA_STRINGS_METADATA, packed_metadata, metadata_len) < 0)
av_freep(&packed_metadata);
}
}
}
} else {
av_log(avctx, AV_LOG_DEBUG, "Unable to find timecode.\n");
}
}
}

pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, abs_wallclock, ctx->video_pts_source, ctx->video_st->time_base, &initial_video_pts, cctx->copyts);
@@ -969,6 +998,8 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
ctx->teletext_lines = cctx->teletext_lines;
ctx->preroll = cctx->preroll;
ctx->duplex_mode = cctx->duplex_mode;
if (cctx->tc_format > 0 && (unsigned int)cctx->tc_format < FF_ARRAY_ELEMS(decklink_timecode_format_map))
ctx->tc_format = decklink_timecode_format_map[cctx->tc_format];
if (cctx->video_input > 0 && (unsigned int)cctx->video_input < FF_ARRAY_ELEMS(decklink_video_connection_map))
ctx->video_input = decklink_video_connection_map[cctx->video_input];
if (cctx->audio_input > 0 && (unsigned int)cctx->audio_input < FF_ARRAY_ELEMS(decklink_audio_connection_map))
@@ -1222,6 +1253,15 @@ 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;
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)
av_log(avctx, AV_LOG_ERROR, "Unable to set timecode\n");
}
}

return 0;
}



+ 9
- 0
libavdevice/decklink_dec_c.c View File

@@ -48,6 +48,15 @@ static const AVOption options[] = {
{ "unset", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0, DEC, "duplex_mode"},
{ "half", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, DEC, "duplex_mode"},
{ "full", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0, DEC, "duplex_mode"},
{ "timecode_format", "timecode format", OFFSET(tc_format), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 7, DEC, "tc_format"},
{ "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0, DEC, "tc_format"},
{ "rp188vitc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, DEC, "tc_format"},
{ "rp188vitc2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0, DEC, "tc_format"},
{ "rp188ltc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3}, 0, 0, DEC, "tc_format"},
{ "rp188any", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 4}, 0, 0, DEC, "tc_format"},
{ "vitc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 5}, 0, 0, DEC, "tc_format"},
{ "vitc2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 6}, 0, 0, DEC, "tc_format"},
{ "serial", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 7}, 0, 0, DEC, "tc_format"},
{ "video_input", "video input", OFFSET(video_input), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 6, DEC, "video_input"},
{ "unset", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0, DEC, "video_input"},
{ "sdi", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, DEC, "video_input"},


+ 1
- 1
libavdevice/version.h View File

@@ -29,7 +29,7 @@

#define LIBAVDEVICE_VERSION_MAJOR 58
#define LIBAVDEVICE_VERSION_MINOR 4
#define LIBAVDEVICE_VERSION_MICRO 100
#define LIBAVDEVICE_VERSION_MICRO 101

#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
LIBAVDEVICE_VERSION_MINOR, \


Loading…
Cancel
Save