From patchwork Fri Dec 29 18:12:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devin Heitmueller X-Patchwork-Id: 7022 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.79.195 with SMTP id r64csp10786106jad; Fri, 29 Dec 2017 10:13:47 -0800 (PST) X-Google-Smtp-Source: ACJfBosuQMC0gyh1phztdcQogzDHMD+JqPTGHNQWF1t5pXwlQZTSlisT2SwKA43pdh0bkG1cn14L X-Received: by 10.28.143.139 with SMTP id r133mr30802517wmd.69.1514571227435; Fri, 29 Dec 2017 10:13:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1514571227; cv=none; d=google.com; s=arc-20160816; b=c1XsKM3zBkbpgzyTDS75av/QW5NutoxHMWCMemVeJQ2viApTVYM5jxgaU0i0UKScTL jnetrticPwWv0p6Jv2WB1pdG/a5qiEgWm8korAMFCCBB/RmjxkyNTKRpKrBPIHIbyPZG HMnd8fkTpWQ+kjV955mwrDjkU4ZqcPxltWsk9ouosmwdyUokiDc5TmwxXYugQ8goQq4h HRw0+rj0UWzTljePp+DuBYRUKBUmT6xM8b7f/cL7amnFQfuZnRRgMNYgTj8HzOGYoebq sUcaANClZBPke83lHQgmgvFB+f6pPPr4rLDuxB0ehlDh4O0PB8g6Bb5IXEed8Nln9I66 C0mg== 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=KgOcp+6nCI8kM3N3n0mbj1HxaZx+Y9YZ/tAV6acd9ng=; b=I8MrmN9r6Y8K3dP3b5HVPrZ23ADF+AFtFYlarfMMPxMmWAwvPjEKgcVsiMtT7/8P37 UukMy460MIlbWCk3hkSMTx0R6VVvhgH7wdF+Ih3BWk3tDBguOvtXSsLcS0FS8kn/uSMN A+u5LFbfJ4ETrda49fg37zAPv4b4ldPanaPtkRh+cuVcI394SwD5ipYQu9CKF0ZtKrr2 jVvoWCl274Ybamf8/5JXr+hSWe7T9q3FWzz64JLFor6HiCZfmFbzrW2A5e0zBgIGZQNt 3narNhUDiwHeqOBVrZ+u5MWL2CCSCGWr5Oj5DIG4ret7kBn7e87OqbgrKYEefL+XN5zh c4NQ== 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 11si16905622wmv.197.2017.12.29.10.13.47; Fri, 29 Dec 2017 10:13:47 -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 C0F49689C3C; Fri, 29 Dec 2017 20:12:46 +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 1FE39689C17 for ; Fri, 29 Dec 2017 20:12:40 +0200 (EET) Received: by was-smtp1.livetimenet.net with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.84_2) (envelope-from ) id 1eUz9H-0002Cw-VN; Fri, 29 Dec 2017 13:12:53 -0500 From: Devin Heitmueller To: ffmpeg-devel@ffmpeg.org Date: Fri, 29 Dec 2017 13:12:27 -0500 Message-Id: <20171229181230.99473-6-dheitmueller@ltnglobal.com> X-Mailer: git-send-email 2.13.2 In-Reply-To: <20171229181230.99473-1-dheitmueller@ltnglobal.com> References: <20171229181230.99473-1-dheitmueller@ltnglobal.com> X-Spam-Score: -1.9 (-) Subject: [FFmpeg-devel] [PATCH 5/8] 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). Updated to reflect feedback from Derek Buitenhuis Signed-off-by: Devin Heitmueller --- libavcodec/internal.h | 3 +++ libavcodec/libx264.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- libavcodec/utils.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 6deaf1d204..4db33eb020 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 9c67c91f33..9a9667079e 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,46 @@ 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) { + for (i = 0; i < num_payloads; i++) + av_free(x4->pic.extra_sei.payloads[i].payload); + av_free(x4->pic.extra_sei.payloads); + return AVERROR(ENOMEM); + } else if (sei_data) { + x264_sei_payload_t *payloads; + payloads = av_realloc(x4->pic.extra_sei.payloads, + sizeof(x4->pic.extra_sei.payloads[0]) * (num_payloads + 1)); + if (payloads == NULL) { + av_log(ctx, AV_LOG_ERROR, "Not enough memory for AFD, skipping\n"); + for (i = 0; i < num_payloads; i++) + av_free(x4->pic.extra_sei.payloads[i].payload); + av_free(x4->pic.extra_sei.payloads); + av_free(sei_data); + return AVERROR(ENOMEM); + } else { + x4->pic.extra_sei.payloads = payloads; + 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 +930,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 baf09119fe..5fc925b8cd 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -2403,6 +2403,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;