Created
May 25, 2018 19:39
-
-
Save dericed/af69d60a99ad235b17722a64ea9413ba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Subject: [PATCH] Limited timecode support for lavd/decklink | |
--- | |
libavdevice/decklink_common.cpp | 30 ----------------------- | |
libavdevice/decklink_common.h | 42 +++++++++++++++++++++++++++++++++ | |
libavdevice/decklink_common_c.h | 1 + | |
libavdevice/decklink_dec.cpp | 19 +++++++++++++++ | |
libavdevice/decklink_dec_c.c | 9 +++++++ | |
5 files changed, 71 insertions(+), 30 deletions(-) | |
diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp | |
index d8cced7c74..aab9d85b94 100644 | |
--- a/libavdevice/decklink_common.cpp | |
+++ b/libavdevice/decklink_common.cpp | |
@@ -77,36 +77,6 @@ static IDeckLinkIterator *decklink_create_iterator(AVFormatContext *avctx) | |
return iter; | |
} | |
-#ifdef _WIN32 | |
-static char *dup_wchar_to_utf8(wchar_t *w) | |
-{ | |
- char *s = NULL; | |
- int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0); | |
- s = (char *) av_malloc(l); | |
- if (s) | |
- WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0); | |
- return s; | |
-} | |
-#define DECKLINK_STR OLECHAR * | |
-#define DECKLINK_STRDUP dup_wchar_to_utf8 | |
-#define DECKLINK_FREE(s) SysFreeString(s) | |
-#elif defined(__APPLE__) | |
-static char *dup_cfstring_to_utf8(CFStringRef w) | |
-{ | |
- char s[256]; | |
- CFStringGetCString(w, s, 255, kCFStringEncodingUTF8); | |
- return av_strdup(s); | |
-} | |
-#define DECKLINK_STR const __CFString * | |
-#define DECKLINK_STRDUP dup_cfstring_to_utf8 | |
-#define DECKLINK_FREE(s) CFRelease(s) | |
-#else | |
-#define DECKLINK_STR const char * | |
-#define DECKLINK_STRDUP av_strdup | |
-/* free() is needed for a string returned by the DeckLink SDL. */ | |
-#define DECKLINK_FREE(s) free((void *) s) | |
-#endif | |
- | |
HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName) | |
{ | |
DECKLINK_STR tmpDisplayName; | |
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h | |
index 57ee7d1d68..8c5f8e9f06 100644 | |
--- a/libavdevice/decklink_common.h | |
+++ b/libavdevice/decklink_common.h | |
@@ -34,6 +34,36 @@ | |
#define DECKLINK_BOOL bool | |
#endif | |
+#ifdef _WIN32 | |
+static char *dup_wchar_to_utf8(wchar_t *w) | |
+{ | |
+ char *s = NULL; | |
+ int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0); | |
+ s = (char *) av_malloc(l); | |
+ if (s) | |
+ WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0); | |
+ return s; | |
+} | |
+#define DECKLINK_STR OLECHAR * | |
+#define DECKLINK_STRDUP dup_wchar_to_utf8 | |
+#define DECKLINK_FREE(s) SysFreeString(s) | |
+#elif defined(__APPLE__) | |
+static char *dup_cfstring_to_utf8(CFStringRef w) | |
+{ | |
+ char s[256]; | |
+ CFStringGetCString(w, s, 255, kCFStringEncodingUTF8); | |
+ return av_strdup(s); | |
+} | |
+#define DECKLINK_STR const __CFString * | |
+#define DECKLINK_STRDUP dup_cfstring_to_utf8 | |
+#define DECKLINK_FREE(s) CFRelease(s) | |
+#else | |
+#define DECKLINK_STR const char * | |
+#define DECKLINK_STRDUP av_strdup | |
+/* free() is needed for a string returned by the DeckLink SDL. */ | |
+#define DECKLINK_FREE(s) free((void *) s) | |
+#endif | |
+ | |
class decklink_output_callback; | |
class decklink_input_callback; | |
@@ -64,6 +94,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; | |
@@ -140,6 +171,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); | |
diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h | |
index 08e9f9bbd5..32a5d70ee1 100644 | |
--- a/libavdevice/decklink_common_c.h | |
+++ b/libavdevice/decklink_common_c.h | |
@@ -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; | |
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp | |
index 510637676c..818235bfa6 100644 | |
--- a/libavdevice/decklink_dec.cpp | |
+++ b/libavdevice/decklink_dec.cpp | |
@@ -726,6 +726,23 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( | |
no_video = 0; | |
} | |
+ // Handle Timecode (if requested) | |
+ if (ctx->tc_format && !(av_dict_get(ctx->video_st->metadata, "timecode", NULL, 0)) && !no_video) { | |
+ IDeckLinkTimecode *timecode; | |
+ if (videoFrame->GetTimecode(ctx->tc_format, &timecode) == S_OK) { | |
+ DECKLINK_STR timecodeString = NULL; | |
+ timecode->GetString(&timecodeString); | |
+ const char* tc = DECKLINK_STRDUP(timecodeString); | |
+ if (!(av_dict_set(&ctx->video_st->metadata, "timecode", tc, 0))) | |
+ av_log(avctx, AV_LOG_ERROR, "Unable to set timecode\n"); | |
+ if (timecodeString) | |
+ DECKLINK_FREE(timecodeString); | |
+ timecode->Release(); | |
+ } else { | |
+ av_log(avctx, AV_LOG_ERROR, "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); | |
pkt.dts = pkt.pts; | |
@@ -939,6 +956,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)) | |
diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c | |
index 47018dc681..a90e60a7db 100644 | |
--- a/libavdevice/decklink_dec_c.c | |
+++ b/libavdevice/decklink_dec_c.c | |
@@ -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"}, | |
-- | |
2.17.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment