This option is useful for maintaining input synchronization across N different hardware devices deployed for 'N-way' redundancy. The system time of different hardware devices should be synchronized with protocols such as NTP or PTP, before using this option. Signed-off-by: Marton Balint <cus@passwd.hu>tags/n4.1
| @@ -371,6 +371,20 @@ If set to @option{true}, timestamps are forwarded as they are without removing | |||||
| the initial offset. | the initial offset. | ||||
| Defaults to @option{false}. | Defaults to @option{false}. | ||||
| @item timestamp_align | |||||
| Capture start time alignment in seconds. If set to nonzero, input frames are | |||||
| dropped till the system timestamp aligns with configured value. | |||||
| Alignment difference of upto one frame duration is tolerated. | |||||
| This is useful for maintaining input synchronization across N different | |||||
| hardware devices deployed for 'N-way' redundancy. The system time of different | |||||
| hardware devices should be synchronized with protocols such as NTP or PTP, | |||||
| before using this option. | |||||
| Note that this method is not foolproof. In some border cases input | |||||
| synchronization may not happen due to thread scheduling jitters in the OS. | |||||
| Either sync could go wrong by 1 frame or in a rarer case | |||||
| @option{timestamp_align} seconds. | |||||
| Defaults to @samp{0}. | |||||
| @end table | @end table | ||||
| @subsection Examples | @subsection Examples | ||||
| @@ -56,6 +56,7 @@ struct decklink_cctx { | |||||
| int raw_format; | int raw_format; | ||||
| int64_t queue_size; | int64_t queue_size; | ||||
| int copyts; | int copyts; | ||||
| int64_t timestamp_align; | |||||
| }; | }; | ||||
| #endif /* AVDEVICE_DECKLINK_COMMON_C_H */ | #endif /* AVDEVICE_DECKLINK_COMMON_C_H */ | ||||
| @@ -703,6 +703,16 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( | |||||
| return S_OK; | return S_OK; | ||||
| } | } | ||||
| // Drop the frames till system's timestamp aligns with the configured value. | |||||
| if (0 == ctx->frameCount && cctx->timestamp_align) { | |||||
| AVRational remainder = av_make_q(av_gettime() % cctx->timestamp_align, 1000000); | |||||
| AVRational frame_duration = av_inv_q(ctx->video_st->r_frame_rate); | |||||
| if (av_cmp_q(remainder, frame_duration) > 0) { | |||||
| ++ctx->dropped; | |||||
| return S_OK; | |||||
| } | |||||
| } | |||||
| ctx->frameCount++; | ctx->frameCount++; | ||||
| if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK) | if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK) | ||||
| wallclock = av_gettime_relative(); | wallclock = av_gettime_relative(); | ||||
| @@ -84,6 +84,7 @@ static const AVOption options[] = { | |||||
| { "queue_size", "input queue buffer size", OFFSET(queue_size), AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC }, | { "queue_size", "input queue buffer size", OFFSET(queue_size), AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC }, | ||||
| { "audio_depth", "audio bitdepth (16 or 32)", OFFSET(audio_depth), AV_OPT_TYPE_INT, { .i64 = 16}, 16, 32, DEC }, | { "audio_depth", "audio bitdepth (16 or 32)", OFFSET(audio_depth), AV_OPT_TYPE_INT, { .i64 = 16}, 16, 32, DEC }, | ||||
| { "decklink_copyts", "copy timestamps, do not remove the initial offset", OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, | { "decklink_copyts", "copy timestamps, do not remove the initial offset", OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, | ||||
| { "timestamp_align", "capture start time alignment (in seconds)", OFFSET(timestamp_align), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, DEC }, | |||||
| { NULL }, | { NULL }, | ||||
| }; | }; | ||||
| @@ -29,7 +29,7 @@ | |||||
| #define LIBAVDEVICE_VERSION_MAJOR 58 | #define LIBAVDEVICE_VERSION_MAJOR 58 | ||||
| #define LIBAVDEVICE_VERSION_MINOR 4 | #define LIBAVDEVICE_VERSION_MINOR 4 | ||||
| #define LIBAVDEVICE_VERSION_MICRO 104 | |||||
| #define LIBAVDEVICE_VERSION_MICRO 105 | |||||
| #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ | #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ | ||||
| LIBAVDEVICE_VERSION_MINOR, \ | LIBAVDEVICE_VERSION_MINOR, \ | ||||