From patchwork Thu Nov 16 18:34:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devin Heitmueller X-Patchwork-Id: 6126 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.161.94 with SMTP id m30csp6149816jah; Thu, 16 Nov 2017 10:35:12 -0800 (PST) X-Google-Smtp-Source: AGs4zMaAflcJkSif+aXvmtEHo80jSm95w0TlMv/NKNFAj+G72AAaZdCCbmWDVKbWSdiarIXatuIi X-Received: by 10.28.19.73 with SMTP id 70mr2234135wmt.87.1510857312433; Thu, 16 Nov 2017 10:35:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1510857312; cv=none; d=google.com; s=arc-20160816; b=NvWIIjPGFT9RCW9mVrKF1PNnGm6wt7RXMEUKNOAmr9u4NPGaRcCp4zNZCM1i8bORFc tSup0/fFo4DqlDvbycOBwiFp7ZponP8tPzLZmMRdD2QSfTFGWf7atvQUmZX76pDqQnTs Y1SNHuhRs7u7rYnONFZd7nks1RmsAt9SznTVEXcdb1bRlcG2ypCumzvFUTwBuK5Hf8MR BG0OqkGOMh79KcyYaCo+psliUd5Hwppi0Rgk8CnoNAoFa3Oksio3/YTqg0BxtNXC1MpI LjMzQTPCpW3tXAl9cwTb11Yq9erKSRk7mdZtIDSM9KeQR9w/B8iFUKqYC7Yv4vfZDqI7 7HYQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:delivered-to:arc-authentication-results; bh=QNYR4prQvO/7xh65cyOUl9B8l73KdyZfY0FYA0a0TNo=; b=PIWlT09IOeD0oiptsOpv2fU2KZegcgTtAWnu9rCOlR9eDuUaOZimQcb8Ju+5eUIwZt nSue9QjJeRTZsDCYY0m9s0zIdaw/Gi5z/kBRECXpgvWI25xMaYjkPl9lCQ4r4ForFoQc HA97dQh7x5qOHaDvaOimtUzemgZoWXE67zC4Z/VPPbDgq0AuWYMpng7BHtXxYfBOfGRF TQxuAReyrNh8yVSvLsY57WszI4HPqctlFAaL82/rwoBD0Tq/FNJDxhiXvV2SycWLLT99 jhxwCvWfeOaHVzr0vJ/h42Jn6L0aqzTjsUruV7F440HCXckJGK+IJRxth0Sk6ywBKV3E WyRQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q27si1272118wra.200.2017.11.16.10.35.12; Thu, 16 Nov 2017 10:35:12 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D0D5268A02A; Thu, 16 Nov 2017 20:34:23 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from was-smtp1.livetimenet.net (50-206-97-56-static.hfc.comcastbusiness.net [50.206.97.56]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7D1E3689E62 for ; Thu, 16 Nov 2017 20:34:15 +0200 (EET) Received: by was-smtp1.livetimenet.net with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.84_2) (envelope-from ) id 1eFOzd-0002o7-7i; Thu, 16 Nov 2017 13:34:30 -0500 From: Devin Heitmueller To: ffmpeg-devel@ffmpeg.org Date: Thu, 16 Nov 2017 13:34:15 -0500 Message-Id: <20171116183417.93073-5-dheitmueller@ltnglobal.com> X-Mailer: git-send-email 2.13.2 In-Reply-To: <20171116183417.93073-1-dheitmueller@ltnglobal.com> References: <20171116183417.93073-1-dheitmueller@ltnglobal.com> X-Spam-Score: -1.9 (-) Subject: [FFmpeg-devel] [PATCH 4/6] Support encoding of Active Format Description (AFD) in libx264 X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: jgreen@ltnglobal.com, Devin Heitmueller MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" If AFD side data is present, include it in an H.264 SEI payload when encoding with libx264. This is done in the same manner that we currently handle A53 closed captions (where the business logic for constructing the SEI is in libavcodec/utils.c), so it should be portable to the other encoder types (i.e. videotoolbox, etc). Signed-off-by: Devin Heitmueller --- libavcodec/internal.h | 3 +++ libavcodec/libx264.c | 38 ++++++++++++++++++++++++++++++++++---- libavcodec/utils.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index d47ce0e..a2c7be4 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -408,6 +408,9 @@ int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, i int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, void **data, size_t *sei_size); +int ff_alloc_afd_sei(const AVFrame *frame, size_t prefix_len, + void **data, size_t *sei_size); + /** * Get an estimated video bitrate based on frame size, frame rate and coded * bits per pixel. diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 9c67c91..f0f3260 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -86,6 +86,7 @@ typedef struct X264Context { int forced_idr; int coder; int a53_cc; + int afd; int b_frame_strategy; int chroma_offset; int scenechange_threshold; @@ -275,6 +276,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, x264_nal_t *nal; int nnal, i, ret; x264_picture_t pic_out = {0}; + int num_payloads = 0; int pict_type; x264_picture_init( &x4->pic ); @@ -323,10 +325,37 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, } else { x4->pic.extra_sei.sei_free = av_free; - x4->pic.extra_sei.payloads[0].payload_size = sei_size; - x4->pic.extra_sei.payloads[0].payload = sei_data; - x4->pic.extra_sei.num_payloads = 1; - x4->pic.extra_sei.payloads[0].payload_type = 4; + x4->pic.extra_sei.payloads[num_payloads].payload_size = sei_size; + x4->pic.extra_sei.payloads[num_payloads].payload = sei_data; + x4->pic.extra_sei.payloads[num_payloads].payload_type = 4; + x4->pic.extra_sei.num_payloads++; + num_payloads++; + } + } + } + + /* Active Format Description */ + if (x4->afd) { + void *sei_data; + size_t sei_size; + + ret = ff_alloc_afd_sei(frame, 0, &sei_data, &sei_size); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Not enough memory for AFD, skipping\n"); + } else if (sei_data) { + x4->pic.extra_sei.payloads = av_realloc(x4->pic.extra_sei.payloads, + sizeof(x4->pic.extra_sei.payloads[0]) * (num_payloads + 1)); + if (x4->pic.extra_sei.payloads == NULL) { + av_log(ctx, AV_LOG_ERROR, "Not enough memory for AFD, skipping\n"); + av_free(sei_data); + } else { + x4->pic.extra_sei.sei_free = av_free; + + x4->pic.extra_sei.payloads[num_payloads].payload_size = sei_size; + x4->pic.extra_sei.payloads[num_payloads].payload = sei_data; + x4->pic.extra_sei.payloads[num_payloads].payload_type = 4; + x4->pic.extra_sei.num_payloads++; + num_payloads++; } } } @@ -892,6 +921,7 @@ static const AVOption options[] = { {"passlogfile", "Filename for 2 pass stats", OFFSET(stats), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, {"wpredp", "Weighted prediction for P-frames", OFFSET(wpredp), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, {"a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE}, + {"afd", "Use Active Format Description (AFD) (if available)",OFFSET(afd), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE}, {"x264opts", "x264 options", OFFSET(x264opts), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, { "crf", "Select the quality for constant quality mode", OFFSET(crf), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE }, { "crf_max", "In CRF mode, prevents VBV from lowering quality beyond this point.",OFFSET(crf_max), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE }, diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e50de6e..550b030 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -2396,6 +2396,42 @@ int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, return 0; } +/* Defined in SCTE 128-1 2013 Sec 8.1 */ +int ff_alloc_afd_sei(const AVFrame *frame, size_t prefix_len, + void **data, size_t *sei_size) +{ + AVFrameSideData *side_data = NULL; + uint8_t *sei_data; + + if (frame) + side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_AFD); + + if (!side_data) { + *data = NULL; + return 0; + } + + *sei_size = 9; + *data = av_mallocz(*sei_size + prefix_len); + if (!*data) + return AVERROR(ENOMEM); + sei_data = (uint8_t*)*data + prefix_len; + + /* country code (SCTE 128-1 Sec 8.1.1) */ + sei_data[0] = 181; + sei_data[1] = 0; + sei_data[2] = 49; + + /* country code (SCTE 128-1 Sec 8.1.2) */ + AV_WL32(sei_data + 3, MKTAG('D', 'T', 'G', '1')); + + /* country code (SCTE 128-1 Sec 8.2.5) */ + sei_data[7] = 0x41; + sei_data[8] = 0xf0 | side_data->data[0]; + + return 0; +} + int64_t ff_guess_coded_bitrate(AVCodecContext *avctx) { AVRational framerate = avctx->framerate;