From patchwork Thu May 18 08:11:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas George X-Patchwork-Id: 3694 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.10.2 with SMTP id 2csp553340vsk; Thu, 18 May 2017 01:11:28 -0700 (PDT) X-Received: by 10.28.109.29 with SMTP id i29mr1948584wmc.113.1495095088687; Thu, 18 May 2017 01:11:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1495095088; cv=none; d=google.com; s=arc-20160816; b=vRt2Ia7M9PyYGm0/MkzbRCFwcYxO8EV04K2b5n/Od+bsqeRaUllU8WZJSnQx9FzI9y 83unmjtSRJVwXgb0DZnOOdYnLzzRBraPu6UsaOeQRXWtpDzoJSxXOqWq5HRynDZWrvIf aBnZmQs+u2aSkcttDBWUkY5mC9vdDyOsO86ICMZB56Id8m1KFSA9qbWPV5i0nfFA0mMr 4eoC9JGntJsS1fp0T5Ss+kvVc2GlMwbfrW0BARCIJs39L8uVG2Z2SjofUPLWBMH4/bDu qyjzrfXKUA6cwuBf8z1presxi6xyIkbRA3EPnyQ/XHqcMvnPHohrJPXhHk47jKhx1/vh jztg== 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: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=HwQO7yc6wmsZw/sp3C8xPH4R/i1UFIQ+GgUHwM8DKNI=; b=cuuvBcfdMksGAQcj7aPBYoRh36ECz1t8/QTqnqIQNxn5HbgI0F3v1KdjgC3qrbTEKD Vx9MPUAVkxGrIk+g+/rQUvnJFL/wYf6Y2OBS7S8kns2MLCWW1TNH2s0ORm4W+Dl4/JC2 pw3hOynGk7JG5e67LSlELupd2uw3Sc5z9kksLJy8tDRbR/tMLTUYyGzH/amrdTwXdN4k 9dPiNhDNqjP+Qt1aE7ldFUEz/VNKRQ/5HD+yhpxKEi9NFX8NPzCBF5/ECoya8DQ8BK/h tZNk+PQU6Wn9Sz1iQlMkDzKyEocu3+7X8XKCjiYzWzEwKhwzNQ/DT3+NAzLQvtYolJYf xBDA== 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 o27si5227857wra.107.2017.05.18.01.11.27; Thu, 18 May 2017 01:11:28 -0700 (PDT) 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 A9884689207; Thu, 18 May 2017 11:11:24 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from nef2.ens.fr (nef2.ens.fr [129.199.96.40]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B5F1D688337 for ; Thu, 18 May 2017 11:11:17 +0300 (EEST) Received: from phare.normalesup.org (archicubes.ens.fr [129.199.129.80]) by nef2.ens.fr (8.13.6/1.01.28121999) with ESMTP id v4I8BHYe016225 for ; Thu, 18 May 2017 10:11:17 +0200 (CEST) Received: by phare.normalesup.org (Postfix, from userid 1001) id 226E1E00F2; Thu, 18 May 2017 10:11:17 +0200 (CEST) From: Nicolas George To: ffmpeg-devel@ffmpeg.org Date: Thu, 18 May 2017 10:11:13 +0200 Message-Id: <20170518081114.21425-2-george@nsup.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170518081114.21425-1-george@nsup.org> References: <20170518081114.21425-1-george@nsup.org> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.4.3 (nef2.ens.fr [129.199.96.32]); Thu, 18 May 2017 10:11:17 +0200 (CEST) Subject: [FFmpeg-devel] [PATCH 2/3] lavc: add a framework to fix alignment problems. 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" A lot of codecs require aligned frame data, but do not document it. It can result in crashes with perfectly valid uses of the API. Design rationale: - requiring frame data to be always aligned would be wasteful; - alignment requirements will evolve (the 16->32 bump is still recent); - requiring applications to worry about alignment is not convenient. For now, the default alignment is fixed at 32. Fix: trac ticket #6349 Signed-off-by: Nicolas George --- libavcodec/avcodec.h | 10 +++++++++ libavcodec/encode.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++--- libavcodec/utils.c | 2 ++ 3 files changed, 66 insertions(+), 3 deletions(-) Without the 1<<. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 00f9c82afc..1e45cf28b2 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3682,6 +3682,16 @@ typedef struct AVCodecContext { * (with the display dimensions being determined by the crop_* fields). */ int apply_cropping; + + /** + * Minimum alignment of frame data required by the codec. + * All frame data pointers must have the alignment lower bits cleared, + * i.e. be a multiple of alignment. + * - encoding: set by the encoder and used by the framework + * - decoding: unused + */ + unsigned alignment; + } AVCodecContext; AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 525ee1f5d6..11d5b2f7c7 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -115,6 +115,40 @@ fail: return ret; } +static int frame_realign(AVCodecContext *avctx, const AVFrame **frame, AVFrame **realigned) +{ + AVFrame *tmp; + int ret; + + if (!*frame || av_frame_check_align(*frame, avctx->alignment)) + return 0; + + tmp = av_frame_alloc(); + if (!tmp) + return AVERROR(ENOMEM); + tmp->format = (*frame)->format; + tmp->width = (*frame)->width; + tmp->height = (*frame)->height; + tmp->channels = (*frame)->channels; + tmp->channel_layout = (*frame)->channel_layout; + tmp->nb_samples = (*frame)->nb_samples; + ret = av_frame_get_buffer(tmp, avctx->alignment); + if (ret < 0) + goto fail; + ret = av_frame_copy(tmp, *frame); + if (ret < 0) + return ret; + ret = av_frame_copy_props(tmp, *frame); + if (ret < 0) + return ret; + *frame = *realigned = tmp; + return 0; + +fail: + av_frame_free(&tmp); + return ret; +} + int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, @@ -122,6 +156,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, { AVFrame *extended_frame = NULL; AVFrame *padded_frame = NULL; + AVFrame *realigned_frame = NULL; int ret; AVPacket user_pkt = *avpkt; int needs_realloc = !user_pkt.data; @@ -195,6 +230,9 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, av_assert0(avctx->codec->encode2); + ret = frame_realign(avctx, &frame, &realigned_frame); + if (ret < 0) + goto end; ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); if (!ret) { if (*got_packet_ptr) { @@ -252,6 +290,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, end: av_frame_free(&padded_frame); + av_frame_free(&realigned_frame); av_free(extended_frame); #if FF_API_AUDIOENC_DELAY @@ -269,6 +308,7 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, int ret; AVPacket user_pkt = *avpkt; int needs_realloc = !user_pkt.data; + AVFrame *realigned_frame = NULL; *got_packet_ptr = 0; @@ -301,7 +341,9 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, av_assert0(avctx->codec->encode2); - ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); + ret = frame_realign(avctx, &frame, &realigned_frame); + if (!ret) + ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); av_assert0(ret <= 0); emms_c(); @@ -340,6 +382,7 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, avctx->frame_number++; } + av_frame_free(&realigned_frame); if (ret < 0 || !*got_packet_ptr) av_packet_unref(avpkt); @@ -406,8 +449,16 @@ int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame return 0; } - if (avctx->codec->send_frame) - return avctx->codec->send_frame(avctx, frame); + if (avctx->codec->send_frame) { + AVFrame *realigned_frame = NULL; + int ret; + ret = frame_realign(avctx, &frame, &realigned_frame); + if (ret < 0) + return ret; + ret = avctx->codec->send_frame(avctx, frame); + av_frame_free(&realigned_frame); + return ret; + } // Emulation via old API. Do it here instead of avcodec_receive_packet, because: // 1. if the AVFrame is not refcounted, the copying will be much more diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 1336e921c9..cddeb70268 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1003,6 +1003,8 @@ FF_ENABLE_DEPRECATION_WARNINGS } avctx->sw_pix_fmt = frames_ctx->sw_format; } + + avctx->alignment = 32; } avctx->pts_correction_num_faulty_pts =