From patchwork Tue Jan 9 01:16:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devin Heitmueller X-Patchwork-Id: 7215 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.78.2 with SMTP id r2csp3317524jaa; Mon, 8 Jan 2018 17:17:49 -0800 (PST) X-Google-Smtp-Source: ACJfBou7Ir1ZZe1KxgXGzYhDX9Js6XWYbeMpye6BaspLc1SwreVBwI7dHA30Id3DZ97MBSgF5Td9 X-Received: by 10.223.179.88 with SMTP id k24mr7909096wrd.232.1515460669420; Mon, 08 Jan 2018 17:17:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515460669; cv=none; d=google.com; s=arc-20160816; b=gf8+PQsKy5AufFRSt8JtsGKMzUldKRnTB1eCK1qqs0YsunXAY6zrMHWhpPRdw8Er7u BfKTXGrGCkMY9DGOhXBzPxSKu2/ugWaPSNKhTaC1pFVjzv6GyXEQeTUhnKkJ/a83kW0g wJjiM5pd/kA3k26tmyUDHBf/ZLh2iFwYtuDbyOgcel/zdWRHqosRVr7uR6XU6f4U+Jcq yGIP1JK/l1G1EWfD5u3f5gNA9A3X2BSXqjd3kv0TG8hXCtI3YZ/brU5LyKWw5BTs6cTZ n7mAfR6TS5uP86V/UN2NdN07IlP23K+gMAGDyhE7yLzOXkN74y1xN6VwJEfbpJxp76OL ekjA== 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=BcVZXliMayj3zyzhmLYx2xD92MQ93Uo88sx2ko3Rpwo=; b=c8pf1+2CiNL+E1KgFLzNIJlHhFtUYEba7a0Dr+hIx8EnfmS9uhjDlNHjOW+akhBIP3 VOLYUtkVrY/cmQE8CM3jld9XUijEXftNTn30DrruE/QbCIvQ7D5i6vjtRpUKtu3Qe53B Eq5MUUxqT+U/GJP3OBp5YTq20EaMMdPSfwovOTwFOWVMPOGz1daeLmu9oxTPkx86a5ys DV26Jr31aKT+/WdpJuGFbDdk9gaZsfkyWchQQpC1UNApnXxmhrBz7bqsDot4P070Iz7y BbCnYkQpR0rRBLMr3bG5sPCTjFGLM8Rh2jdFDkDpxpv+BzO7zx/RsDGO5vyxOH43zp0D I9Ew== 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 z18si9619462wrh.408.2018.01.08.17.17.48; Mon, 08 Jan 2018 17:17:49 -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 847A268A04C; Tue, 9 Jan 2018 03:17:25 +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 8844D689EFC for ; Tue, 9 Jan 2018 03:17:23 +0200 (EET) Received: by was-smtp1.livetimenet.net with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.84_2) (envelope-from ) id 1eYiXa-0008Fd-GG; Mon, 08 Jan 2018 20:17:23 -0500 From: Devin Heitmueller To: ffmpeg-devel@ffmpeg.org Date: Mon, 8 Jan 2018 20:16:52 -0500 Message-Id: <20180109011658.72370-6-dheitmueller@ltnglobal.com> X-Mailer: git-send-email 2.13.2 In-Reply-To: <20180109011658.72370-1-dheitmueller@ltnglobal.com> References: <20180109011658.72370-1-dheitmueller@ltnglobal.com> X-Spam-Score: -1.9 (-) Subject: [FFmpeg-devel] [PATCH 05/11] 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 and Aaron Levinson . 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 16bd101..821dfb6 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -404,6 +404,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 12379ff..3bd787d 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 ); @@ -327,10 +329,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_freep(&x4->pic.extra_sei.payloads[i].payload); + av_freep(&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_freep(&x4->pic.extra_sei.payloads[i].payload); + av_freep(&x4->pic.extra_sei.payloads); + av_freep(&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++; } } } @@ -921,6 +959,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 4d736d2..340e097 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -2284,6 +2284,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;