From patchwork Thu Jul 9 19:20:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 20932 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id D839244B0C4 for ; Thu, 9 Jul 2020 22:20:44 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BFE2F68B58A; Thu, 9 Jul 2020 22:20:44 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 740A868B53E for ; Thu, 9 Jul 2020 22:20:38 +0300 (EEST) Received: by mail-wr1-f66.google.com with SMTP id f2so3530558wrp.7 for ; Thu, 09 Jul 2020 12:20:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=4FmibtMG4qeH31Mjm+6n3Z2VmGsec+h854RHHqchcGc=; b=dRB5HAhOlpzIWOyrLR0gNQAV+VLFTY3yeMxboPEHLtiLdaDlyIZCuE00yeUcEUHlBN 1eVxr7cbEiJ4YVQSg1nXRlRiPcNbrJjsCiYNz3adkMeEp4NXX+Vc1+7xbqYInZBoV5Gm 7Gmcv3FUBpVGwcbv1vCZ5plZQ5iCjC+2mfO9u++FLYea3ggEg++6C4bZiN6USouUbt2A 4IEi3N+yAM4xS+c2Vz7KK6uVXG5crwNpzs+DlRcl3KvdxL2H8w8Z8Pvy2W4JQmMeIdpY crthJwGsV9Sk2GxmenIe+/10eiauBU49okWkoSucbu+ZzbJbUlKzobvX4mgo3xTr4hnG /Txw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=4FmibtMG4qeH31Mjm+6n3Z2VmGsec+h854RHHqchcGc=; b=X42vFNrdRcoFaVo+oLcBig9UyxHiLvjZEBaKHw0ozggVPGYZa4YV81LQIW0Rw0Ivy4 3FmVFZunTPek6dJ6/H7zRUXnUmz0C0laRimhOe220hw0cwW72mGGFcL0dMDMQHfe/Buy Xf8qCcHd5PIMIzEjW5HeajkbAyqDBXe1Xk53IYXwNRMxmIgvkY7XdGYTCgqbcvjLPwZ9 M9yJmhBnky3Zc6KSaQ1jItXp86kZAY8tjWYenHcV6+RFlLbte7M8b2fwr4Gj6VVd9C0q FbK+9XdE+oZ0DgSjSHOJEjT2tEKJ0jGBxubHO52kzQnCAB0abkY+mFL+PUbjgctuPKpt ZB0w== X-Gm-Message-State: AOAM530UkaAD8MtKaMbEKuZYzv/RPLXqI6waXoCRjK+pEvCQvSxRfHha hl4+u90yjQF6WFOCBBJkV0OTrbYj X-Google-Smtp-Source: ABdhPJydsZNSuFE3hQeLBpSvTTKyJsAjBHH+w4Odj6/ak4irwI8B7DyXvtp/QUiklGobE3sV8cHk3g== X-Received: by 2002:a5d:69c5:: with SMTP id s5mr64511215wrw.197.1594322437439; Thu, 09 Jul 2020 12:20:37 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc10296.dynamic.kabel-deutschland.de. [188.193.2.150]) by smtp.gmail.com with ESMTPSA id p25sm5485330wmg.39.2020.07.09.12.20.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Jul 2020 12:20:36 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Thu, 9 Jul 2020 21:20:16 +0200 Message-Id: <20200709192022.9412-3-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200709103542.19909-1-andreas.rheinhardt@gmail.com> References: <20200709103542.19909-1-andreas.rheinhardt@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 11/17] avformat/avc, hevc: Avoid intermediate buffers when parsing annex B 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: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" When creating H.264 or HEVC extradata from annex B extradata or when transforming annex B into HEVC while also filtering parameter sets away, the whole input has first been transformed into mp4-style H.264/HEVC in order to simplify parsing at the next step. By using ff_avc_parse_nalu, one can avoid these intermediate steps (which involved (re)allocations). Signed-off-by: Andreas Rheinhardt --- libavformat/avc.c | 28 ++++++++----------------- libavformat/hevc.c | 52 +++++++++++++--------------------------------- 2 files changed, 23 insertions(+), 57 deletions(-) diff --git a/libavformat/avc.c b/libavformat/avc.c index d089051034..98462940ad 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -147,7 +147,7 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) { AVIOContext *sps_pb = NULL, *pps_pb = NULL, *sps_ext_pb = NULL; - uint8_t *buf, *end, *start; + const uint8_t *nal, *nal_end, *end; uint8_t *sps, *pps, *sps_ext; uint32_t sps_size = 0, pps_size = 0, sps_ext_size = 0; int ret, nb_sps = 0, nb_pps = 0, nb_sps_ext = 0; @@ -162,12 +162,6 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) return 0; } - ret = ff_avc_parse_nal_units_buf(data, &buf, &len); - if (ret < 0) - return ret; - start = buf; - end = buf + len; - ret = avio_open_dyn_buf(&sps_pb); if (ret < 0) goto fail; @@ -179,12 +173,11 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) goto fail; /* look for sps and pps */ - while (end - buf > 4) { - uint32_t size; - uint8_t nal_type; - size = FFMIN(AV_RB32(buf), end - buf - 4); - buf += 4; - nal_type = buf[0] & 0x1f; + nal_end = NULL; + end = data + len; + while (nal = ff_avc_parse_nalu(&data, &nal_end, end)) { + uint32_t size = nal_end - nal; + uint8_t nal_type = nal[0] & 0x1f; if (nal_type == 7) { /* SPS */ nb_sps++; @@ -193,7 +186,7 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) goto fail; } avio_wb16(sps_pb, size); - avio_write(sps_pb, buf, size); + avio_write(sps_pb, nal, size); } else if (nal_type == 8) { /* PPS */ nb_pps++; if (size > UINT16_MAX || nb_pps >= H264_MAX_PPS_COUNT) { @@ -201,7 +194,7 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) goto fail; } avio_wb16(pps_pb, size); - avio_write(pps_pb, buf, size); + avio_write(pps_pb, nal, size); } else if (nal_type == 13) { /* SPS_EXT */ nb_sps_ext++; if (size > UINT16_MAX || nb_sps_ext >= 256) { @@ -209,10 +202,8 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) goto fail; } avio_wb16(sps_ext_pb, size); - avio_write(sps_ext_pb, buf, size); + avio_write(sps_ext_pb, nal, size); } - - buf += size; } sps_size = avio_get_dyn_buf(sps_pb, &sps); pps_size = avio_get_dyn_buf(pps_pb, &pps); @@ -252,7 +243,6 @@ fail: ffio_free_dyn_buf(&sps_pb); ffio_free_dyn_buf(&pps_pb); ffio_free_dyn_buf(&sps_ext_pb); - av_free(start); return ret; } diff --git a/libavformat/hevc.c b/libavformat/hevc.c index 94eb3a9cb1..095988b7df 100644 --- a/libavformat/hevc.c +++ b/libavformat/hevc.c @@ -35,7 +35,7 @@ typedef struct HVCCNALUnitArray { uint8_t NAL_unit_type; uint16_t numNalus; uint16_t *nalUnitLength; - uint8_t **nalUnit; + const uint8_t **nalUnit; } HVCCNALUnitArray; typedef struct HEVCDecoderConfigurationRecord { @@ -657,7 +657,7 @@ static void nal_unit_parse_header(GetBitContext *gb, uint8_t *nal_type) skip_bits(gb, 9); } -static int hvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, +static int hvcc_array_add_nal_unit(const uint8_t *nal_buf, uint32_t nal_size, uint8_t nal_type, int ps_array_completeness, HEVCDecoderConfigurationRecord *hvcc) { @@ -710,7 +710,7 @@ static int hvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, return 0; } -static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, +static int hvcc_add_nal_unit(const uint8_t *nal_buf, uint32_t nal_size, int ps_array_completeness, HEVCDecoderConfigurationRecord *hvcc) { @@ -1000,26 +1000,16 @@ int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in, int size, int filter_ps, int *ps_count) { int num_ps = 0, ret = 0; - uint8_t *buf, *end, *start = NULL; + const uint8_t *nal, *nal_end = NULL, *end = buf_in + size; if (!filter_ps) { ret = ff_avc_parse_nal_units(pb, buf_in, size); goto end; } - ret = ff_avc_parse_nal_units_buf(buf_in, &start, &size); - if (ret < 0) - goto end; - - ret = 0; - buf = start; - end = start + size; - - while (end - buf > 4) { - uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4); - uint8_t type = (buf[4] >> 1) & 0x3f; - - buf += 4; + while (nal = ff_avc_parse_nalu(&buf_in, &nal_end, end)) { + uint32_t len = nal_end - nal; + uint8_t type = (nal[0] >> 1) & 0x3f; switch (type) { case HEVC_NAL_VPS: @@ -1030,15 +1020,12 @@ int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in, default: ret += 4 + len; avio_wb32(pb, len); - avio_write(pb, buf, len); + avio_write(pb, nal, len); break; } - - buf += len; } end: - av_free(start); if (ps_count) *ps_count = num_ps; return ret; @@ -1069,7 +1056,7 @@ int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, int size, int ps_array_completeness) { HEVCDecoderConfigurationRecord hvcc; - uint8_t *buf, *end, *start; + const uint8_t *nal, *nal_end = NULL, *end; int ret; if (size < 6) { @@ -1084,20 +1071,12 @@ int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, return AVERROR_INVALIDDATA; } - ret = ff_avc_parse_nal_units_buf(data, &start, &size); - if (ret < 0) - return ret; - hvcc_init(&hvcc); - buf = start; - end = start + size; - - while (end - buf > 4) { - uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4); - uint8_t type = (buf[4] >> 1) & 0x3f; - - buf += 4; + end = data + size; + while (nal = ff_avc_parse_nalu(&data, &nal_end, end)) { + uint32_t len = nal_end - nal; + uint8_t type = (nal[0] >> 1) & 0x3f; switch (type) { case HEVC_NAL_VPS: @@ -1105,21 +1084,18 @@ int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, case HEVC_NAL_PPS: case HEVC_NAL_SEI_PREFIX: case HEVC_NAL_SEI_SUFFIX: - ret = hvcc_add_nal_unit(buf, len, ps_array_completeness, &hvcc); + ret = hvcc_add_nal_unit(nal, len, ps_array_completeness, &hvcc); if (ret < 0) goto end; break; default: break; } - - buf += len; } ret = hvcc_write(pb, &hvcc); end: hvcc_close(&hvcc); - av_free(start); return ret; }