From patchwork Fri Sep 16 18:20:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Scott Theisen X-Patchwork-Id: 37967 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:3b1c:b0:96:9ee8:5cfd with SMTP id c28csp1139966pzh; Fri, 16 Sep 2022 11:21:27 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5z/KG5ATXyHYpdhuugKiefazs1qr+Dhrn9U3oxMtWBnlrDn8m1WTylPuqsJ2qSlaL4W/1l X-Received: by 2002:a05:6402:540d:b0:450:bda7:f76e with SMTP id ev13-20020a056402540d00b00450bda7f76emr4911253edb.249.1663352486915; Fri, 16 Sep 2022 11:21:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1663352486; cv=none; d=google.com; s=arc-20160816; b=aWazFgTB2r9a/UU0B74rVFv68jXNXv4OetetWEVDX3LRUGSsHNzCXE3J/dVUUNKniT /jfBVOTBkUK4WWijiTa4UUXrhQfv8nYNTobqX3ck4HivQOQV2YcEPowsj5ET4LwhxOFQ pkX33Q87wHAh1qJbAXaBWH9G29hrQsa959MJwSzb6iNeZo8SFmUz6G1gWpjAZmbbBSB7 O66SSoNRLd9uFx04j9txMwQdaVop114WFflWOJwvJHxODrEAvA2l4cHZmwN2Z4f2s4BR EDIGdZa7B7Cuod3f8Cyc0PBRpgkfWqPXbFJTt1wlZF8bvr37kyxjgYXSSxsyFXxSi5kr MaAA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=sHQ4CRcjZyRdW0VoSixzb0hSdKN7VzmPEqjoWI92SpQ=; b=ikyOREaJUsjnVYplgI1WObyadVVbVzWmyojymvD8Ma3kToq9IY9u42bUgBiwuYJ7EP 7ff/Kj+p//x0Xdkc+4qqkzkjV0gZDG/NK2oSIkS8wuJy+FEdfxT/yK4+rYslZPXc2xxH PfhgBLt/KhBehcYORZqJAmpzFZB9RopYgGF+vgLnlvb4fGL9P7hTc7ND29JPCP1jWTBf 9qZ74WtQEiuoeCGk0BHOqiNHkL2WjGHYEPe4fStz1TFpvMTKwetvwPy6kOkK7LwyYm2e yOfbyGh0pNlKXIRoKFH1i7Qk1Xrspa3E1TVEPOR5rN4G9Ept5e8Tm/8CTptYyKhzHs0j 5QeA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=dNEMv8kr; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id qb25-20020a1709077e9900b0073d8a8fedbfsi17169114ejc.386.2022.09.16.11.21.26; Fri, 16 Sep 2022 11:21:26 -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; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=dNEMv8kr; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1691668BC5F; Fri, 16 Sep 2022 21:20:26 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk1-f169.google.com (mail-qk1-f169.google.com [209.85.222.169]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id F286268BC4F for ; Fri, 16 Sep 2022 21:20:16 +0300 (EEST) Received: by mail-qk1-f169.google.com with SMTP id d15so16335046qka.9 for ; Fri, 16 Sep 2022 11:20:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=OZG+38/taxoWLn6M5z3ejPbiIbNKmtBIXLBQx+qsbPI=; b=dNEMv8krf+a6nT4oZmFwXFMdXotC88fPOU0U6Yox3MugEgDkICNbD4u4aPFzV2mkc7 J3aVXaOqETMJU3Txccy29Ik6YkajphnZA8ElkcQ+huwcus/ranENOOACsFg3F7eIjqwm MrYEsRWEV3pH6PUDK3r/bYKz9IfIDjPi54QJgbZNeZxK/5cuMkYKWNdnsa3thPxm3E/N rIbeEbofKqxIdso4cHFpZuTiCEo2Be3m5lqQP6XT8LsJ2hqIFw693LXDinuJK/xvQsVR HHF0E+Q7oJGCgt+A2TxoAd+Y7jZ+eK8dyRqX1S5jSYrNp1oFnnV6me+/yIuwkgLpnnDP 25bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=OZG+38/taxoWLn6M5z3ejPbiIbNKmtBIXLBQx+qsbPI=; b=pdy/W3p+NOtIfLvknhtukcypkF/1BrqQSrPPwFrSnqvALHeCBfUg1lyIZZNL86WMkj yYcMhNR/wHmZpUjUYhfN7XM41Za3IahD8ZJrwYtvUva5LdeLDJaMytQkzTP7L2Sa3q79 hviutgxZS20HJfkhmLp/JuC5bnhebf0qd9XWg1wGQF8/2hz8gkEByGjGW7qJ2FIESZuz iHbvEUo5EJSCzb6KWegDfHTR7Agnq6szfeXFKT0JmUa4paQEjeF1p00ideQWa5ZoHpN+ f+CchewDsriMepVeZ71cY1c7xfKsMrMWWDIj+pyk39k43ZWdadz9BNad85Blm+VMtsR1 8dcw== X-Gm-Message-State: ACrzQf2N420wOoS8EdBH7+N4f64phOeSdJI7vkWjIX1HH0l4uJRiL4Gd gysZWwm82VIAZUdkQfeiCrTTPjt6ZpA= X-Received: by 2002:a05:620a:129b:b0:6ce:6ba5:74fa with SMTP id w27-20020a05620a129b00b006ce6ba574famr4888656qki.85.1663352415470; Fri, 16 Sep 2022 11:20:15 -0700 (PDT) Received: from scott-desktop.. (pool-71-114-80-52.washdc.fios.verizon.net. [71.114.80.52]) by smtp.gmail.com with ESMTPSA id l10-20020ac8724a000000b0035cb9531851sm5148098qtp.65.2022.09.16.11.20.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Sep 2022 11:20:14 -0700 (PDT) From: Scott Theisen To: ffmpeg-devel@ffmpeg.org Date: Fri, 16 Sep 2022 14:20:02 -0400 Message-Id: <20220916182002.122699-9-scott.the.elm@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220916182002.122699-1-scott.the.elm@gmail.com> References: <20220201212056.29712-1-scott.the.elm@gmail.com> <20220916182002.122699-1-scott.the.elm@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 8/8] avpriv_find_start_code(): make start_code output only X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Scott Theisen Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: +Go6nUzWDTx9 The input/output functionality was used by only (ff_)mpeg1_find_frame_end(). If the state/start_code input is a local variable and only one buffer is used, then no history is needed. In loops and inline functions: if ignoring history, don't initialize start_code, so it isn't reset twice each time. There is a slight functional change: 00 00 01 00 01 XX no longer incorrectly returns a start code at offset 7 that overlaps the start code at offset 4 if the start_code input is not modified between the two calls. --- libavcodec/cbs_mpeg2.c | 5 ---- libavcodec/h264_parser.c | 2 +- libavcodec/mpeg12.c | 41 +++++++++++++++++++++++++- libavcodec/mpeg4_unpack_bframes_bsf.c | 1 - libavcodec/mpegvideo_parser.c | 42 +++++++++++++++++++++++++-- libavcodec/startcode.h | 14 +++------ libavcodec/utils.c | 16 ++++------ libavcodec/vc1_common.h | 2 +- libavformat/rtpenc_mpv.c | 2 +- 9 files changed, 92 insertions(+), 33 deletions(-) diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 23839ca47b..fd235a43a7 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -160,11 +160,6 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, const uint8_t *end; size_t unit_size; - // Reset start_code to ensure that avpriv_find_start_code() - // really reads a new start code and does not reuse the old - // start code in any way (as e.g. happens when there is a - // Sequence End unit at the very end of a packet). - start_code = UINT32_MAX; end = avpriv_find_start_code(start--, frag->data + frag->data_size, &start_code); diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 50810f1789..b67830d40e 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -69,7 +69,7 @@ typedef struct H264ParseContext { static int find_start_code(const uint8_t *buf, int buf_size, int buf_index, int next_avc) { - uint32_t state = -1; + uint32_t state; buf_index = avpriv_find_start_code(buf + buf_index, buf + next_avc + 1, &state) - buf - 1; diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 5ff1830496..9e3c7e5814 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -166,6 +166,45 @@ av_cold void ff_mpeg12_init_vlcs(void) } #if FF_API_FLAG_TRUNCATED +/** + * By preserving the @p start_code value between subsequent calls, the caller can + * detect start codes across buffer boundaries. + * + * @param[in,out] start_code A pointer to a mutable @c uint32_t.
+ * As input: For no history preset to @c ~0 , otherwise preset to the last + * returned start code to enable detecting start codes across + * buffer boundaries.
+ * On output: Set to the found start code if it exists or an invalid + * start code (the 4 bytes prior to the returned value, + * using the input history if @f$ end - p < 4 @f$). + * + * @sa avpriv_find_start_code() + */ +static const uint8_t *find_start_code_truncated(const uint8_t *av_restrict p, + const uint8_t * const end, + uint32_t * const av_restrict start_code) +{ + av_assert0(p <= end); + if (p >= end) + return end; + + if (*start_code == 0x100) + *start_code = ~0; + // invalidate byte 0 so overlapping start codes are not erroneously detected + + // read up to the first three bytes in p to enable reading a start code across + // two (to four) buffers + for (int i = 0; i < 3; i++) { + *start_code <<= 8; + *start_code += *p; + p++; + if (start_code_is_valid(*start_code) || p == end) + return p; + } + // buffer length is at least 4 + return avpriv_find_start_code(p - 3, end, start_code); +} + /** * Find the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 @@ -200,7 +239,7 @@ int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, } state++; } else { - i = avpriv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1; + i = find_start_code_truncated(buf + i, buf + buf_size, &state) - buf - 1; if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) { i++; pc->frame_start_found = 4; diff --git a/libavcodec/mpeg4_unpack_bframes_bsf.c b/libavcodec/mpeg4_unpack_bframes_bsf.c index 3a3aad795f..dd351d9d0f 100644 --- a/libavcodec/mpeg4_unpack_bframes_bsf.c +++ b/libavcodec/mpeg4_unpack_bframes_bsf.c @@ -36,7 +36,6 @@ static void scan_buffer(const uint8_t *buf, int buf_size, const uint8_t *end = buf + buf_size, *pos = buf; while (pos < end) { - startcode = -1; pos = avpriv_find_start_code(pos, end, &startcode); if (startcode == USER_DATA_STARTCODE && pos_p) { diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index f5afa95981..d76e8ba069 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -34,6 +34,45 @@ struct MpvParseContext { }; #if !FF_API_FLAG_TRUNCATED +/** + * By preserving the @p start_code value between subsequent calls, the caller can + * detect start codes across buffer boundaries. + * + * @param[in,out] start_code A pointer to a mutable @c uint32_t.
+ * As input: For no history preset to @c ~0 , otherwise preset to the last + * returned start code to enable detecting start codes across + * buffer boundaries.
+ * On output: Set to the found start code if it exists or an invalid + * start code (the 4 bytes prior to the returned value, + * using the input history if @f$ end - p < 4 @f$). + * + * @sa avpriv_find_start_code() + */ +static const uint8_t *find_start_code_truncated(const uint8_t *av_restrict p, + const uint8_t * const end, + uint32_t * const av_restrict start_code) +{ + av_assert0(p <= end); + if (p >= end) + return end; + + if (*start_code == 0x100) + *start_code = ~0; + // invalidate byte 0 so overlapping start codes are not erroneously detected + + // read up to the first three bytes in p to enable reading a start code across + // two (to four) buffers + for (int i = 0; i < 3; i++) { + *start_code <<= 8; + *start_code += *p; + p++; + if (start_code_is_valid(*start_code) || p == end) + return p; + } + // buffer length is at least 4 + return avpriv_find_start_code(p - 3, end, start_code); +} + /** * Find the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 @@ -69,7 +108,7 @@ static int mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, } state++; } else { - i = avpriv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1; + i = find_start_code_truncated(buf + i, buf + buf_size, &state) - buf - 1; if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) { i++; pc->frame_start_found = 4; @@ -121,7 +160,6 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, s->repeat_pict = 0; while (buf < buf_end) { - start_code= -1; buf= avpriv_find_start_code(buf, buf_end, &start_code); bytes_left = buf_end - buf; switch(start_code) { diff --git a/libavcodec/startcode.h b/libavcodec/startcode.h index 69389c729c..7e1df68a3b 100644 --- a/libavcodec/startcode.h +++ b/libavcodec/startcode.h @@ -50,20 +50,14 @@ static av_always_inline int start_code_is_valid(uint32_t start_code) { * A start code is a sequence of 4 bytes with the hexadecimal value 00 00 01 XX , * where XX represents any value and memory address increases left to right. * - * By preserving the @p start_code value between subsequent calls, the caller can - * detect start codes across buffer boundaries. - * * @param[in] p A pointer to the start of the memory buffer to scan. * @param[in] end A pointer to the past-the-end memory address for the buffer * given by @p p. @p p must be ≤ @p end. * - * @param[in,out] start_code A pointer to a mutable @c uint32_t.
- * As input: For no history preset to @c ~0 , otherwise preset to the last - * returned start code to enable detecting start codes across - * buffer boundaries.
- * On output: Set to the found start code if it exists or an invalid - * start code (the 4 bytes prior to the returned value, - * using the input history if @f$ end - p < 4 @f$). + * @param[out] start_code A pointer to a mutable @c uint32_t.
+ * Set to the found start code if it exists or an invalid start code + * (the 4 bytes prior to the returned value or @c ~0 if + * @f$ end - p < 4 @f$). * * @return A pointer to the memory address following the found start code, or @p end * if no start code was found. diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 0635c5dcaa..2a6067ca4e 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -984,19 +984,13 @@ const uint8_t *avpriv_find_start_code(const uint8_t *av_restrict p, uint32_t * const av_restrict start_code) { av_assert0(p <= end); - if (p >= end) + // minimum length for a start code + if (p + 4 > end) { + *start_code = ~0; // set to an invalid start code return end; - - // read up to the first three bytes in p to enable reading a start code across - // two (to four) buffers - for (int i = 0; i < 3; i++) { - *start_code <<= 8; - *start_code += *p; - p++; - if (start_code_is_valid(*start_code) || p == end) - return p; } - // p is now properly incremented for the negative indices in the while loop + + p += 3; // offset for negative indices in while loop /* with memory address increasing left to right, we are looking for (in hexadecimal): * 00 00 01 XX diff --git a/libavcodec/vc1_common.h b/libavcodec/vc1_common.h index 8ff9802a51..ac8dbe3fb6 100644 --- a/libavcodec/vc1_common.h +++ b/libavcodec/vc1_common.h @@ -57,7 +57,7 @@ enum Profile { static av_always_inline const uint8_t* find_next_marker(const uint8_t *src, const uint8_t *end) { if (end - src >= 4) { - uint32_t mrk = 0xFFFFFFFF; + uint32_t mrk; src = avpriv_find_start_code(src, end, &mrk); if (start_code_is_valid(mrk)) return src - 4; diff --git a/libavformat/rtpenc_mpv.c b/libavformat/rtpenc_mpv.c index 9c0816ef95..dbd4acd474 100644 --- a/libavformat/rtpenc_mpv.c +++ b/libavformat/rtpenc_mpv.c @@ -54,7 +54,7 @@ void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size) r1 = buf1; while (1) { - uint32_t start_code = ~0; + uint32_t start_code; r = avpriv_find_start_code(r1, end, &start_code); if (start_code_is_valid(start_code)) { /* New start code found */