[FFmpeg-devel] [PATCH 2/2] decklink: Add support for output of Active Format Description (AFD)
Marton Balint
cus at passwd.hu
Sun Aug 26 18:34:12 EEST 2018
On Wed, 22 Aug 2018, Devin Heitmueller wrote:
> Implement support for including AFD in decklink output. This
> includes making sure the AFD data is preserved when going from
> an AVFrame to a V210 packet (needed for 10-bit support).
>
> Updated to reflect feedback from Marton Balint <cus at passwd.hu>,
> Carl Eugen Hoyos <ceffmpeg at gmail.com> and Aaron Levinson
> <alevinsn_dev at levland.net>.
>
> Signed-off-by: Devin Heitmueller <dheitmueller at ltnglobal.com>
> ---
> libavcodec/avcodec.h | 6 +++++
> libavcodec/v210enc.c | 8 +++++++
> libavdevice/decklink_enc.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 66 insertions(+), 2 deletions(-)
>
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 31e50d5a94..192e15746d 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -1362,6 +1362,12 @@ enum AVPacketSideDataType {
> AV_PKT_DATA_ENCRYPTION_INFO,
>
> /**
> + * Active Format Description data consisting of a single byte as specified
> + * in ETSI TS 101 154 using AVActiveFormatDescription enum.
> + */
> + AV_PKT_DATA_AFD,
> +
> + /**
> * The number of side data types.
> * This is not part of the public API/ABI in the sense that it may
> * change when new side data types are added.
Such addition requires a libavcodec minor version bump and maybe an entry
in doc/APIChanges.
> diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c
> index b9dcf9a672..b024806d0b 100644
> --- a/libavcodec/v210enc.c
> +++ b/libavcodec/v210enc.c
> @@ -242,6 +242,14 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
> memcpy(buf, side_data->data, side_data->size);
> }
>
> + side_data = av_frame_get_side_data(pic, AV_FRAME_DATA_AFD);
> + if (side_data && side_data->size) {
> + uint8_t *buf = av_packet_new_side_data(pkt, AV_PKT_DATA_AFD, side_data->size);
> + if (!buf)
> + return AVERROR(ENOMEM);
> + memcpy(buf, side_data->data, side_data->size);
> + }
> +
> pkt->flags |= AV_PKT_FLAG_KEY;
> *got_packet = 1;
> return 0;
A separate patch from decklink is preferred here as well for the API and
v210enc addition.
> diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
> index de7758cb91..2d03d33554 100644
> --- a/libavdevice/decklink_enc.cpp
> +++ b/libavdevice/decklink_enc.cpp
> @@ -303,7 +303,8 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
>
> #if CONFIG_LIBKLVANC
> static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *ctx,
> - AVPacket *pkt, decklink_frame *frame)
> + AVPacket *pkt, decklink_frame *frame,
> + AVStream *st)
> {
> struct klvanc_line_set_s vanc_lines = { 0 };
> int ret, size, i;
> @@ -363,6 +364,55 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *
> }
> }
>
> + data = av_packet_get_side_data(pkt, AV_PKT_DATA_AFD, &size);
> + if (data) {
if (data && size)
> + struct klvanc_packet_afd_s *pkt;
Maybe pkt is not the best name, can be confused with the AVPacket pkt...
> + uint16_t *afd;
> + uint16_t len;
> +
> + ret = klvanc_create_AFD(&pkt);
> + if (ret) {
> + for (i = 0; i < vanc_lines.num_lines; i++)
> + klvanc_line_free(vanc_lines.lines[i]);
> + return AVERROR(ENOMEM);
As I mentioned in the previous patch, replace these with something like:
ret = AVERROR(ENOMEM);
goto out;
> + }
> +
> + ret = klvanc_set_AFD_val(pkt, data[0]);
> + if (ret) {
> + av_log(avctx, AV_LOG_ERROR, "Invalid AFD value specified: %d\n",
> + data[0]);
> + klvanc_destroy_AFD(pkt);
> + for (i = 0; i < vanc_lines.num_lines; i++)
> + klvanc_line_free(vanc_lines.lines[i]);
> + return AVERROR(EINVAL);
here
> + }
> +
> + /* FIXME: Should really rely on the coded_width but seems like that
> + is not accessible to libavdevice outputs */
> + if (av_cmp_q((AVRational) {st->codecpar->width, st->codecpar->height}, (AVRational) {4, 3}) == 1)
> + pkt->aspectRatio = ASPECT_16x9;
> + else
> + pkt->aspectRatio = ASPECT_4x3;
> +
> + ret = klvanc_convert_AFD_to_words(pkt, &afd, &len);
> + klvanc_destroy_AFD(pkt);
> + if (ret) {
> + av_log(avctx, AV_LOG_ERROR, "Failed converting AFD packet to words\n");
> + for (i = 0; i < vanc_lines.num_lines; i++)
> + klvanc_line_free(vanc_lines.lines[i]);
> + return AVERROR(ENOMEM);
here
> + }
> +
> + ret = klvanc_line_insert(ctx->vanc_ctx, &vanc_lines, afd, len, 12, 0);
> + free(afd);
> + if (ret) {
> + av_log(avctx, AV_LOG_ERROR, "VANC line insertion failed\n");
> + for (i = 0; i < vanc_lines.num_lines; i++)
> + klvanc_line_free(vanc_lines.lines[i]);
> + return AVERROR(ENOMEM);
and here.
> + }
> + }
> +
> IDeckLinkVideoFrameAncillary *vanc;
> int result = ctx->dlo->CreateAncillaryData(bmdFormat10BitYUV, &vanc);
> if (result != S_OK) {
> @@ -457,7 +507,7 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt)
> frame = new decklink_frame(ctx, avpacket, st->codecpar->codec_id, ctx->bmd_height, ctx->bmd_width);
>
> #if CONFIG_LIBKLVANC
> - ret = decklink_construct_vanc(avctx, ctx, pkt, frame);
> + ret = decklink_construct_vanc(avctx, ctx, pkt, frame, st);
> if (ret)
> av_log(avctx, AV_LOG_ERROR, "Failed to construct VANC\n");
> #endif
Thanks,
Marton
More information about the ffmpeg-devel
mailing list