* [FFmpeg-devel] [PATCH v3 1/2] decklink: move queue_size to an argument for ff_decklink_packet_queue_init
@ 2023-06-30 21:14 Devin Heitmueller
2023-06-30 21:14 ` [FFmpeg-devel] [PATCH v3 2/2] decklink_enc: add support for SMPTE 2038 VANC packet output Devin Heitmueller
2023-07-02 16:10 ` [FFmpeg-devel] [PATCH v3 1/2] decklink: move queue_size to an argument for ff_decklink_packet_queue_init Marton Balint
0 siblings, 2 replies; 4+ messages in thread
From: Devin Heitmueller @ 2023-06-30 21:14 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
The existing queue initialization function would always sets it's
maximum queue size to ctx->queue_size. But because we are introducing
more queues we may want the sizes to differ between them.
Move the specification of the queue size into an argument, which can
be passed from the caller.
This patch makes no functional change to the behavior. It is being
made to accommodate Marton Balin's request to split out the queue
size for the new VANC queue being introduced in a later patch.
Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
---
libavdevice/decklink_common.cpp | 4 ++--
libavdevice/decklink_common.h | 2 +-
libavdevice/decklink_dec.cpp | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
index b6cc8d7..5e8d612 100644
--- a/libavdevice/decklink_common.cpp
+++ b/libavdevice/decklink_common.cpp
@@ -390,14 +390,14 @@ int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t directio
return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction);
}
-void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q)
+void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q, int64_t queue_size)
{
struct decklink_cctx *ctx = (struct decklink_cctx *)avctx->priv_data;
memset(q, 0, sizeof(DecklinkPacketQueue));
pthread_mutex_init(&q->mutex, NULL);
pthread_cond_init(&q->cond, NULL);
q->avctx = avctx;
- q->max_q_size = ctx->queue_size;
+ q->max_q_size = queue_size;
}
void ff_decklink_packet_queue_flush(DecklinkPacketQueue *q)
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index ebb5b94..53e9983 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -235,7 +235,7 @@ int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direct
void ff_decklink_cleanup(AVFormatContext *avctx);
int ff_decklink_init_device(AVFormatContext *avctx, const char* name);
-void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q);
+void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q, int64_t queue_size);
void ff_decklink_packet_queue_flush(DecklinkPacketQueue *q);
void ff_decklink_packet_queue_end(DecklinkPacketQueue *q);
unsigned long long ff_decklink_packet_queue_size(DecklinkPacketQueue *q);
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 66abee1..11640f7 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -1297,7 +1297,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
goto error;
}
- ff_decklink_packet_queue_init(avctx, &ctx->queue);
+ ff_decklink_packet_queue_init(avctx, &ctx->queue, cctx->queue_size);
if (ctx->dli->StartStreams() != S_OK) {
av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n");
--
1.8.3.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 4+ messages in thread
* [FFmpeg-devel] [PATCH v3 2/2] decklink_enc: add support for SMPTE 2038 VANC packet output
2023-06-30 21:14 [FFmpeg-devel] [PATCH v3 1/2] decklink: move queue_size to an argument for ff_decklink_packet_queue_init Devin Heitmueller
@ 2023-06-30 21:14 ` Devin Heitmueller
2023-07-02 17:22 ` Marton Balint
2023-07-02 16:10 ` [FFmpeg-devel] [PATCH v3 1/2] decklink: move queue_size to an argument for ff_decklink_packet_queue_init Marton Balint
1 sibling, 1 reply; 4+ messages in thread
From: Devin Heitmueller @ 2023-06-30 21:14 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
Support decoding and embedding VANC packets delivered via SMPTE 2038
into the SDI output. We leverage an intermediate queue because
data packets are announced separately from video but we need to embed
the data into the video frame when it is output.
Note that this patch has some additional abstraction for data
streams in general as opposed to just SMPTE 2038 packets. This is
because subsequent patches will introduce support for other
data codecs.
Thanks to Marton Balint for review/feedback.
Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
---
doc/outdevs.texi | 5 +++
libavdevice/decklink_common.cpp | 16 +++++++
libavdevice/decklink_common.h | 4 ++
libavdevice/decklink_common_c.h | 1 +
libavdevice/decklink_enc.cpp | 94 ++++++++++++++++++++++++++++++++++++++++-
libavdevice/decklink_enc_c.c | 1 +
6 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/doc/outdevs.texi b/doc/outdevs.texi
index 93391db..f0484bb 100644
--- a/doc/outdevs.texi
+++ b/doc/outdevs.texi
@@ -235,6 +235,11 @@ Enable SMPTE Level A mode on the used output.
Must be @samp{unset}, @samp{true} or @samp{false}.
Defaults to @option{unset}.
+@item vanc_queue_size
+Sets maximum output buffer size in bytes for VANC data. If the buffering reaches this value,
+outgoing VANC data will be dropped.
+Defaults to @samp{1048576}.
+
@end table
@subsection Examples
diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
index 5e8d612..6eefb6f1 100644
--- a/libavdevice/decklink_common.cpp
+++ b/libavdevice/decklink_common.cpp
@@ -485,6 +485,22 @@ int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int bloc
return ret;
}
+int64_t ff_decklink_packet_queue_peekpts(DecklinkPacketQueue *q)
+{
+ PacketListEntry *pkt1;
+ int64_t pts = -1;
+
+ pthread_mutex_lock(&q->mutex);
+ pkt1 = q->pkt_list.head;
+ if (pkt1) {
+ pts = pkt1->pkt.pts;
+ }
+ pthread_mutex_unlock(&q->mutex);
+
+ return pts;
+}
+
+
int ff_decklink_list_devices(AVFormatContext *avctx,
struct AVDeviceInfoList *device_list,
int show_inputs, int show_outputs)
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index 53e9983..34ab1b9 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -115,6 +115,9 @@ struct decklink_ctx {
CCFifo cc_fifo; ///< closed captions
+ /* Output VANC queue */
+ DecklinkPacketQueue vanc_queue;
+
/* Streams present */
int audio;
int video;
@@ -241,5 +244,6 @@ void ff_decklink_packet_queue_end(DecklinkPacketQueue *q);
unsigned long long ff_decklink_packet_queue_size(DecklinkPacketQueue *q);
int ff_decklink_packet_queue_put(DecklinkPacketQueue *q, AVPacket *pkt);
int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int block);
+int64_t ff_decklink_packet_queue_peekpts(DecklinkPacketQueue *q);
#endif /* AVDEVICE_DECKLINK_COMMON_H */
diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
index 75896ad..9c55d89 100644
--- a/libavdevice/decklink_common_c.h
+++ b/libavdevice/decklink_common_c.h
@@ -63,6 +63,7 @@ struct decklink_cctx {
char *format_code;
int raw_format;
int64_t queue_size;
+ int64_t vanc_queue_size;
int copyts;
int64_t timestamp_align;
int timing_offset;
diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
index 6906cb0..11e67c4 100644
--- a/libavdevice/decklink_enc.cpp
+++ b/libavdevice/decklink_enc.cpp
@@ -345,6 +345,25 @@ static int decklink_setup_subtitle(AVFormatContext *avctx, AVStream *st)
return ret;
}
+static int decklink_setup_data(AVFormatContext *avctx, AVStream *st)
+{
+ int ret = -1;
+
+ switch(st->codecpar->codec_id) {
+#if CONFIG_LIBKLVANC
+ case AV_CODEC_ID_SMPTE_2038:
+ /* No specific setup required */
+ ret = 0;
+ break;
+#endif
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unsupported data codec specified\n");
+ break;
+ }
+
+ return ret;
+}
+
av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
{
struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
@@ -370,6 +389,7 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
#if CONFIG_LIBKLVANC
klvanc_context_destroy(ctx->vanc_ctx);
#endif
+ ff_decklink_packet_queue_end(&ctx->vanc_queue);
ff_ccfifo_uninit(&ctx->cc_fifo);
av_freep(&cctx->ctx);
@@ -552,6 +572,58 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *
construct_cc(avctx, ctx, pkt, &vanc_lines);
construct_afd(avctx, ctx, pkt, &vanc_lines, st);
+ /* See if there any pending data packets to process */
+ while (ff_decklink_packet_queue_size(&ctx->vanc_queue) > 0) {
+ AVStream *vanc_st;
+ AVPacket vanc_pkt;
+ int64_t pts;
+
+ pts = ff_decklink_packet_queue_peekpts(&ctx->vanc_queue);
+ if (pts > ctx->last_pts) {
+ /* We haven't gotten to the video frame we are supposed to inject
+ the oldest VANC packet into yet, so leave it on the queue... */
+ break;
+ }
+
+ ret = ff_decklink_packet_queue_get(&ctx->vanc_queue, &vanc_pkt, 1);
+ if (vanc_pkt.pts + 1 < ctx->last_pts) {
+ av_log(avctx, AV_LOG_WARNING, "VANC packet too old, throwing away\n");
+ av_packet_unref(&vanc_pkt);
+ continue;
+ }
+
+ vanc_st = avctx->streams[vanc_pkt.stream_index];
+ if (vanc_st->codecpar->codec_id == AV_CODEC_ID_SMPTE_2038) {
+ struct klvanc_smpte2038_anc_data_packet_s *pkt_2038 = 0;
+
+ klvanc_smpte2038_parse_pes_payload(vanc_pkt.data, vanc_pkt.size, &pkt_2038);
+ if (pkt_2038 == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "failed to decode SMPTE 2038 PES packet");
+ av_packet_unref(&vanc_pkt);
+ continue;
+ }
+ for (int i = 0; i < pkt_2038->lineCount; i++) {
+ struct klvanc_smpte2038_anc_data_line_s *l = &pkt_2038->lines[i];
+ uint16_t *vancWords = NULL;
+ uint16_t vancWordCount;
+
+ if (klvanc_smpte2038_convert_line_to_words(l, &vancWords,
+ &vancWordCount) < 0)
+ break;
+
+ ret = klvanc_line_insert(ctx->vanc_ctx, &vanc_lines, vancWords,
+ vancWordCount, l->line_number, 0);
+ free(vancWords);
+ if (ret != 0) {
+ av_log(avctx, AV_LOG_ERROR, "VANC line insertion failed\n");
+ break;
+ }
+ }
+ klvanc_smpte2038_anc_data_packet_free(pkt_2038);
+ }
+ av_packet_unref(&vanc_pkt);
+ }
+
IDeckLinkVideoFrameAncillary *vanc;
int result = ctx->dlo->CreateAncillaryData(bmdFormat10BitYUV, &vanc);
if (result != S_OK) {
@@ -750,6 +822,18 @@ static int decklink_write_subtitle_packet(AVFormatContext *avctx, AVPacket *pkt)
return 0;
}
+static int decklink_write_data_packet(AVFormatContext *avctx, AVPacket *pkt)
+{
+ struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
+ struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
+
+ if (ff_decklink_packet_queue_put(&ctx->vanc_queue, pkt) < 0) {
+ av_log(avctx, AV_LOG_WARNING, "Failed to queue DATA packet\n");
+ }
+
+ return 0;
+}
+
extern "C" {
av_cold int ff_decklink_write_header(AVFormatContext *avctx)
@@ -814,6 +898,9 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
} else if (c->codec_type == AVMEDIA_TYPE_VIDEO) {
if (decklink_setup_video(avctx, st))
goto error;
+ } else if (c->codec_type == AVMEDIA_TYPE_DATA) {
+ if (decklink_setup_data(avctx, st))
+ goto error;
} else if (c->codec_type == AVMEDIA_TYPE_SUBTITLE) {
if (decklink_setup_subtitle(avctx, st))
goto error;
@@ -823,13 +910,16 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
}
}
+ /* Reconfigure the data/subtitle stream clocks to match the video */
for (n = 0; n < avctx->nb_streams; n++) {
AVStream *st = avctx->streams[n];
AVCodecParameters *c = st->codecpar;
- if(c->codec_type == AVMEDIA_TYPE_SUBTITLE)
+ if(c->codec_type == AVMEDIA_TYPE_DATA ||
+ c->codec_type == AVMEDIA_TYPE_SUBTITLE)
avpriv_set_pts_info(st, 64, ctx->bmd_tb_num, ctx->bmd_tb_den);
}
+ ff_decklink_packet_queue_init(avctx, &ctx->vanc_queue, cctx->vanc_queue_size);
ret = ff_ccfifo_init(&ctx->cc_fifo, av_make_q(ctx->bmd_tb_den, ctx->bmd_tb_num), avctx);
if (ret < 0) {
@@ -852,6 +942,8 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
return decklink_write_video_packet(avctx, pkt);
else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
return decklink_write_audio_packet(avctx, pkt);
+ else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
+ return decklink_write_data_packet(avctx, pkt);
else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
return decklink_write_subtitle_packet(avctx, pkt);
diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c
index 0a3984b..25ffe77 100644
--- a/libavdevice/decklink_enc_c.c
+++ b/libavdevice/decklink_enc_c.c
@@ -32,6 +32,7 @@ static const AVOption options[] = {
{ "list_devices", "use ffmpeg -sinks decklink instead", OFFSET(list_devices), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC | AV_OPT_FLAG_DEPRECATED},
{ "list_formats", "list supported formats" , OFFSET(list_formats), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, ENC },
{ "preroll" , "video preroll in seconds", OFFSET(preroll ), AV_OPT_TYPE_DOUBLE, { .dbl = 0.5 }, 0, 5, ENC },
+ { "vanc_queue_size", "VANC queue buffer size", OFFSET(vanc_queue_size), AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024)}, 0, INT64_MAX, ENC },
#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000
{ "duplex_mode" , "duplex mode" , OFFSET(duplex_mode ), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 5, ENC, "duplex_mode"},
#else
--
1.8.3.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 1/2] decklink: move queue_size to an argument for ff_decklink_packet_queue_init
2023-06-30 21:14 [FFmpeg-devel] [PATCH v3 1/2] decklink: move queue_size to an argument for ff_decklink_packet_queue_init Devin Heitmueller
2023-06-30 21:14 ` [FFmpeg-devel] [PATCH v3 2/2] decklink_enc: add support for SMPTE 2038 VANC packet output Devin Heitmueller
@ 2023-07-02 16:10 ` Marton Balint
1 sibling, 0 replies; 4+ messages in thread
From: Marton Balint @ 2023-07-02 16:10 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Fri, 30 Jun 2023, Devin Heitmueller wrote:
> The existing queue initialization function would always sets it's
> maximum queue size to ctx->queue_size. But because we are introducing
> more queues we may want the sizes to differ between them.
>
> Move the specification of the queue size into an argument, which can
> be passed from the caller.
>
> This patch makes no functional change to the behavior. It is being
> made to accommodate Marton Balin's request to split out the queue
> size for the new VANC queue being introduced in a later patch.
>
> Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
> ---
> libavdevice/decklink_common.cpp | 4 ++--
> libavdevice/decklink_common.h | 2 +-
> libavdevice/decklink_dec.cpp | 2 +-
> 3 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
> index b6cc8d7..5e8d612 100644
> --- a/libavdevice/decklink_common.cpp
> +++ b/libavdevice/decklink_common.cpp
> @@ -390,14 +390,14 @@ int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t directio
> return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction);
> }
>
> -void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q)
> +void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q, int64_t queue_size)
> {
> struct decklink_cctx *ctx = (struct decklink_cctx *)avctx->priv_data;
This is now unused.
> memset(q, 0, sizeof(DecklinkPacketQueue));
> pthread_mutex_init(&q->mutex, NULL);
> pthread_cond_init(&q->cond, NULL);
> q->avctx = avctx;
> - q->max_q_size = ctx->queue_size;
> + q->max_q_size = queue_size;
> }
Will apply with the change above.
Thanks,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 2/2] decklink_enc: add support for SMPTE 2038 VANC packet output
2023-06-30 21:14 ` [FFmpeg-devel] [PATCH v3 2/2] decklink_enc: add support for SMPTE 2038 VANC packet output Devin Heitmueller
@ 2023-07-02 17:22 ` Marton Balint
0 siblings, 0 replies; 4+ messages in thread
From: Marton Balint @ 2023-07-02 17:22 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Fri, 30 Jun 2023, Devin Heitmueller wrote:
> Support decoding and embedding VANC packets delivered via SMPTE 2038
> into the SDI output. We leverage an intermediate queue because
> data packets are announced separately from video but we need to embed
> the data into the video frame when it is output.
>
> Note that this patch has some additional abstraction for data
> streams in general as opposed to just SMPTE 2038 packets. This is
> because subsequent patches will introduce support for other
> data codecs.
Thanks, will apply with some minor cosmetic change and avdevice micro
version bump.
Regards,
Marton
>
> Thanks to Marton Balint for review/feedback.
>
> Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
> ---
> doc/outdevs.texi | 5 +++
> libavdevice/decklink_common.cpp | 16 +++++++
> libavdevice/decklink_common.h | 4 ++
> libavdevice/decklink_common_c.h | 1 +
> libavdevice/decklink_enc.cpp | 94 ++++++++++++++++++++++++++++++++++++++++-
> libavdevice/decklink_enc_c.c | 1 +
> 6 files changed, 120 insertions(+), 1 deletion(-)
>
> diff --git a/doc/outdevs.texi b/doc/outdevs.texi
> index 93391db..f0484bb 100644
> --- a/doc/outdevs.texi
> +++ b/doc/outdevs.texi
> @@ -235,6 +235,11 @@ Enable SMPTE Level A mode on the used output.
> Must be @samp{unset}, @samp{true} or @samp{false}.
> Defaults to @option{unset}.
>
> +@item vanc_queue_size
> +Sets maximum output buffer size in bytes for VANC data. If the buffering reaches this value,
> +outgoing VANC data will be dropped.
> +Defaults to @samp{1048576}.
> +
> @end table
>
> @subsection Examples
> diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
> index 5e8d612..6eefb6f1 100644
> --- a/libavdevice/decklink_common.cpp
> +++ b/libavdevice/decklink_common.cpp
> @@ -485,6 +485,22 @@ int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int bloc
> return ret;
> }
>
> +int64_t ff_decklink_packet_queue_peekpts(DecklinkPacketQueue *q)
> +{
> + PacketListEntry *pkt1;
> + int64_t pts = -1;
> +
> + pthread_mutex_lock(&q->mutex);
> + pkt1 = q->pkt_list.head;
> + if (pkt1) {
> + pts = pkt1->pkt.pts;
> + }
> + pthread_mutex_unlock(&q->mutex);
> +
> + return pts;
> +}
> +
> +
> int ff_decklink_list_devices(AVFormatContext *avctx,
> struct AVDeviceInfoList *device_list,
> int show_inputs, int show_outputs)
> diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
> index 53e9983..34ab1b9 100644
> --- a/libavdevice/decklink_common.h
> +++ b/libavdevice/decklink_common.h
> @@ -115,6 +115,9 @@ struct decklink_ctx {
>
> CCFifo cc_fifo; ///< closed captions
>
> + /* Output VANC queue */
> + DecklinkPacketQueue vanc_queue;
> +
> /* Streams present */
> int audio;
> int video;
> @@ -241,5 +244,6 @@ void ff_decklink_packet_queue_end(DecklinkPacketQueue *q);
> unsigned long long ff_decklink_packet_queue_size(DecklinkPacketQueue *q);
> int ff_decklink_packet_queue_put(DecklinkPacketQueue *q, AVPacket *pkt);
> int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int block);
> +int64_t ff_decklink_packet_queue_peekpts(DecklinkPacketQueue *q);
>
> #endif /* AVDEVICE_DECKLINK_COMMON_H */
> diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
> index 75896ad..9c55d89 100644
> --- a/libavdevice/decklink_common_c.h
> +++ b/libavdevice/decklink_common_c.h
> @@ -63,6 +63,7 @@ struct decklink_cctx {
> char *format_code;
> int raw_format;
> int64_t queue_size;
> + int64_t vanc_queue_size;
> int copyts;
> int64_t timestamp_align;
> int timing_offset;
> diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
> index 6906cb0..11e67c4 100644
> --- a/libavdevice/decklink_enc.cpp
> +++ b/libavdevice/decklink_enc.cpp
> @@ -345,6 +345,25 @@ static int decklink_setup_subtitle(AVFormatContext *avctx, AVStream *st)
> return ret;
> }
>
> +static int decklink_setup_data(AVFormatContext *avctx, AVStream *st)
> +{
> + int ret = -1;
> +
> + switch(st->codecpar->codec_id) {
> +#if CONFIG_LIBKLVANC
> + case AV_CODEC_ID_SMPTE_2038:
> + /* No specific setup required */
> + ret = 0;
> + break;
> +#endif
> + default:
> + av_log(avctx, AV_LOG_ERROR, "Unsupported data codec specified\n");
> + break;
> + }
> +
> + return ret;
> +}
> +
> av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
> {
> struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
> @@ -370,6 +389,7 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
> #if CONFIG_LIBKLVANC
> klvanc_context_destroy(ctx->vanc_ctx);
> #endif
> + ff_decklink_packet_queue_end(&ctx->vanc_queue);
>
> ff_ccfifo_uninit(&ctx->cc_fifo);
> av_freep(&cctx->ctx);
> @@ -552,6 +572,58 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *
> construct_cc(avctx, ctx, pkt, &vanc_lines);
> construct_afd(avctx, ctx, pkt, &vanc_lines, st);
>
> + /* See if there any pending data packets to process */
> + while (ff_decklink_packet_queue_size(&ctx->vanc_queue) > 0) {
> + AVStream *vanc_st;
> + AVPacket vanc_pkt;
> + int64_t pts;
> +
> + pts = ff_decklink_packet_queue_peekpts(&ctx->vanc_queue);
> + if (pts > ctx->last_pts) {
> + /* We haven't gotten to the video frame we are supposed to inject
> + the oldest VANC packet into yet, so leave it on the queue... */
> + break;
> + }
> +
> + ret = ff_decklink_packet_queue_get(&ctx->vanc_queue, &vanc_pkt, 1);
> + if (vanc_pkt.pts + 1 < ctx->last_pts) {
> + av_log(avctx, AV_LOG_WARNING, "VANC packet too old, throwing away\n");
> + av_packet_unref(&vanc_pkt);
> + continue;
> + }
> +
> + vanc_st = avctx->streams[vanc_pkt.stream_index];
> + if (vanc_st->codecpar->codec_id == AV_CODEC_ID_SMPTE_2038) {
> + struct klvanc_smpte2038_anc_data_packet_s *pkt_2038 = 0;
> +
> + klvanc_smpte2038_parse_pes_payload(vanc_pkt.data, vanc_pkt.size, &pkt_2038);
> + if (pkt_2038 == NULL) {
> + av_log(avctx, AV_LOG_ERROR, "failed to decode SMPTE 2038 PES packet");
> + av_packet_unref(&vanc_pkt);
> + continue;
> + }
> + for (int i = 0; i < pkt_2038->lineCount; i++) {
> + struct klvanc_smpte2038_anc_data_line_s *l = &pkt_2038->lines[i];
> + uint16_t *vancWords = NULL;
> + uint16_t vancWordCount;
> +
> + if (klvanc_smpte2038_convert_line_to_words(l, &vancWords,
> + &vancWordCount) < 0)
> + break;
> +
> + ret = klvanc_line_insert(ctx->vanc_ctx, &vanc_lines, vancWords,
> + vancWordCount, l->line_number, 0);
> + free(vancWords);
> + if (ret != 0) {
> + av_log(avctx, AV_LOG_ERROR, "VANC line insertion failed\n");
> + break;
> + }
> + }
> + klvanc_smpte2038_anc_data_packet_free(pkt_2038);
> + }
> + av_packet_unref(&vanc_pkt);
> + }
> +
> IDeckLinkVideoFrameAncillary *vanc;
> int result = ctx->dlo->CreateAncillaryData(bmdFormat10BitYUV, &vanc);
> if (result != S_OK) {
> @@ -750,6 +822,18 @@ static int decklink_write_subtitle_packet(AVFormatContext *avctx, AVPacket *pkt)
> return 0;
> }
>
> +static int decklink_write_data_packet(AVFormatContext *avctx, AVPacket *pkt)
> +{
> + struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
> + struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
> +
> + if (ff_decklink_packet_queue_put(&ctx->vanc_queue, pkt) < 0) {
> + av_log(avctx, AV_LOG_WARNING, "Failed to queue DATA packet\n");
> + }
> +
> + return 0;
> +}
> +
> extern "C" {
>
> av_cold int ff_decklink_write_header(AVFormatContext *avctx)
> @@ -814,6 +898,9 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
> } else if (c->codec_type == AVMEDIA_TYPE_VIDEO) {
> if (decklink_setup_video(avctx, st))
> goto error;
> + } else if (c->codec_type == AVMEDIA_TYPE_DATA) {
> + if (decklink_setup_data(avctx, st))
> + goto error;
> } else if (c->codec_type == AVMEDIA_TYPE_SUBTITLE) {
> if (decklink_setup_subtitle(avctx, st))
> goto error;
> @@ -823,13 +910,16 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
> }
> }
>
> + /* Reconfigure the data/subtitle stream clocks to match the video */
> for (n = 0; n < avctx->nb_streams; n++) {
> AVStream *st = avctx->streams[n];
> AVCodecParameters *c = st->codecpar;
>
> - if(c->codec_type == AVMEDIA_TYPE_SUBTITLE)
> + if(c->codec_type == AVMEDIA_TYPE_DATA ||
> + c->codec_type == AVMEDIA_TYPE_SUBTITLE)
> avpriv_set_pts_info(st, 64, ctx->bmd_tb_num, ctx->bmd_tb_den);
> }
> + ff_decklink_packet_queue_init(avctx, &ctx->vanc_queue, cctx->vanc_queue_size);
>
> ret = ff_ccfifo_init(&ctx->cc_fifo, av_make_q(ctx->bmd_tb_den, ctx->bmd_tb_num), avctx);
> if (ret < 0) {
> @@ -852,6 +942,8 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
> return decklink_write_video_packet(avctx, pkt);
> else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
> return decklink_write_audio_packet(avctx, pkt);
> + else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
> + return decklink_write_data_packet(avctx, pkt);
> else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
> return decklink_write_subtitle_packet(avctx, pkt);
>
> diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c
> index 0a3984b..25ffe77 100644
> --- a/libavdevice/decklink_enc_c.c
> +++ b/libavdevice/decklink_enc_c.c
> @@ -32,6 +32,7 @@ static const AVOption options[] = {
> { "list_devices", "use ffmpeg -sinks decklink instead", OFFSET(list_devices), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC | AV_OPT_FLAG_DEPRECATED},
> { "list_formats", "list supported formats" , OFFSET(list_formats), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, ENC },
> { "preroll" , "video preroll in seconds", OFFSET(preroll ), AV_OPT_TYPE_DOUBLE, { .dbl = 0.5 }, 0, 5, ENC },
> + { "vanc_queue_size", "VANC queue buffer size", OFFSET(vanc_queue_size), AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024)}, 0, INT64_MAX, ENC },
> #if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000
> { "duplex_mode" , "duplex mode" , OFFSET(duplex_mode ), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 5, ENC, "duplex_mode"},
> #else
> --
> 1.8.3.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-07-02 17:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-30 21:14 [FFmpeg-devel] [PATCH v3 1/2] decklink: move queue_size to an argument for ff_decklink_packet_queue_init Devin Heitmueller
2023-06-30 21:14 ` [FFmpeg-devel] [PATCH v3 2/2] decklink_enc: add support for SMPTE 2038 VANC packet output Devin Heitmueller
2023-07-02 17:22 ` Marton Balint
2023-07-02 16:10 ` [FFmpeg-devel] [PATCH v3 1/2] decklink: move queue_size to an argument for ff_decklink_packet_queue_init Marton Balint
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git