From patchwork Mon Jul 9 18:26:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 9658 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:104:0:0:0:0:0 with SMTP id c4-v6csp2802439jad; Mon, 9 Jul 2018 11:34:54 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfykOapvZJu62OK335QQLdgCiRN2/AF2itMLkMuz81IBH7rtmDbTaFXYa13TxkudecfkRl8 X-Received: by 2002:a1c:3610:: with SMTP id d16-v6mr13862544wma.126.1531161294355; Mon, 09 Jul 2018 11:34:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531161294; cv=none; d=google.com; s=arc-20160816; b=JPwIjG2DVdwYTnpJ/GlEslLa0FB4hGRCwG3nLTIfQm7fHks9Rtb668OP06fnHrI31A pf6u50sS78Ha2go0EfLqFEYAhgOyFo+l8XpEA2oN0861lpk2ZmwWHvcxmvQhUf38rDtd 8tZXL875l0lBe/LrQIFCWXX0M2SjoStZ+h/e5RbVOiNw6aW7ifVo30ifvl2BamuJv0cE mq4EhQKJwWBxcnAmM6LLvZvJmHhz3C8E/Dhc8cVkdlaWUn81mtlPC3xhEvct4366Ge2h b523qh94Vo0tNP6FPI31J7opbb/PhzHTzmvC2DjJauSQzrvrW7evHs4umHf6gBJDqsTL wU/Q== 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:dkim-signature:delivered-to:arc-authentication-results; bh=oFNVvGF1rG9JiTv9mLqLSrt2mfZnlQpvvCBRXJYHcSg=; b=TthgqIq/qalWVCiaFzWyYkRe5TByLBn83dauUzWbCFxpmgLvO3wS/ZlDDceamsOip7 0D/xjHON5CqaEWgqoKpd1KxLkI22/qve6FNL8UimktnZbnX8u5w03Rup/3rimrZGmDAI zFsRIbmheYpiLvoovWF1XFSZFVCu/uMl+4rviukRM2dFTNl5ZAtTpR0JufA6cu8qePiz k5olTfqWEYThQdpE0Ps2HBFtbXyN1ZcG0AdLEWtazyz9jxkLH/DfZ46HWj51fl5kJeEW L7hRwb3TfAeW9UAGMmebecky5r3ItMwttUhLr0N+R4yXxJFA6DSYLNnLtSh/uwvNzx7f OTiA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=K3vqZGAO; 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 31-v6si2384570wra.242.2018.07.09.11.34.53; Mon, 09 Jul 2018 11:34:54 -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=20161025 header.b=K3vqZGAO; 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 C45F468A4B0; Mon, 9 Jul 2018 21:34:45 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk0-f193.google.com (mail-qk0-f193.google.com [209.85.220.193]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D8FC3689CBE for ; Mon, 9 Jul 2018 21:34:39 +0300 (EEST) Received: by mail-qk0-f193.google.com with SMTP id y4-v6so10213846qka.5 for ; Mon, 09 Jul 2018 11:34:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=EVgijbX79xwHAgNNs6gnDrXJBIOwDhv25r05+KvFuQ4=; b=K3vqZGAOzE5XQ8oMyHjPEWbfH3tbfFk65I6IFIse0GI8vFsjBggvAC/IZl+zSD9Ygi 0pIlMYKEXTh2WqDrIpcvp30PXT/EWpwCuqIvmP2dh+cs/2CL+uwradG1wJTKxWYwsFx/ leKsAzZH/HwoAqvl1kznOnGkfe2bhqpyz4XCm+CFkGSbu+X7y6s6hCPDCHy9G3RhX+88 tcC+O6toAe3Z5bnq+QQnqDSsdBqaGF5kcIWEV5Bu3e30EZPvhVWp8MwGJ+6epZGei2du 5oWPPKwW0U4s7cPZT1lDaMjG1ToHaEAMTjvrqDRKTKWGXsvsB6Jhf/xVxa6Sk3VCMBrc zKbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=EVgijbX79xwHAgNNs6gnDrXJBIOwDhv25r05+KvFuQ4=; b=j/Ci0FNNNe3t5gm6iLWU/CsUsoKNO2yEWt3MezZ3fuHXnQ8PRROpbP6ZfgWS4hASzk H1aJCJBYo4mI/s9PgyLfpADECKzGtnwA3IXeInxKyAqymCGXcL55Mgc6C5sV1PWYhH+i VAI7qlOQllRNpbltV/QKccaDCZ6Xdg/UUh9iQ3zg4vWCRSm/8j6GfmBGbvZt/132Z3oO RIsmVcsdv3af+v+b803kVDNWsX2v5+TylDgtq7ai9ceIdmEE84mXoupL91zcvf3xg1mn AplzIJ4VHseVobP3AMf9k1YXYuDkI4uBD3FUYWKv+hkiqo+p7ICmwN0JZcwYvkUuVz1+ U2JA== X-Gm-Message-State: APt69E0ShoWNnLM8J663OezG+1xznhg/ImD9jG1sWFvYUZt+FyMwiJOk +yCEKYQDUdFJaIA4REDeHU2q8g== X-Received: by 2002:ae9:e009:: with SMTP id m9-v6mr18346642qkk.320.1531160966379; Mon, 09 Jul 2018 11:29:26 -0700 (PDT) Received: from localhost.localdomain ([190.188.171.140]) by smtp.gmail.com with ESMTPSA id f3-v6sm13138260qtf.61.2018.07.09.11.29.25 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 09 Jul 2018 11:29:26 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Mon, 9 Jul 2018 15:26:50 -0300 Message-Id: <20180709182654.9996-2-jamrial@gmail.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180709182654.9996-1-jamrial@gmail.com> References: <20180709182654.9996-1-jamrial@gmail.com> Subject: [FFmpeg-devel] [PATCH 1/5] avcodec: add AV1 packet split API 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" Signed-off-by: James Almer --- I talked with Mark Thompson about AV1 parsing code in libavcodec and he told me he prefered to keep everything within his upcoming CBS implementation. I very much agree the eventual decoder and avparser should use it given they will require deep bitstream parsing, but for the upcoming changes i only require to split the OBUs in a packet (Which require minimal OBU header parsing to find where each one of them start and end), so the overhead of parsing and writing full CBS packets seem unnecesary. This way i also have an inline function ready to be used in muxer related libavformat code. If there are still strong opinions about having AV1 parsing code in avcodec separate from CBS, even if minimal, then I can reimplement extract_extradata using the latter and move the header parsing code to libavformat. libavcodec/av1_parse.c | 103 +++++++++++++++++++++++++++++++++ libavcodec/av1_parse.h | 126 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 libavcodec/av1_parse.c create mode 100644 libavcodec/av1_parse.h diff --git a/libavcodec/av1_parse.c b/libavcodec/av1_parse.c new file mode 100644 index 0000000000..48feb9fb8a --- /dev/null +++ b/libavcodec/av1_parse.c @@ -0,0 +1,103 @@ +/* + * AV1 common parsing code + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/mem.h" + +#include "av1_parse.h" +#include "bytestream.h" + +int ff_av1_extract_obu(AV1OBU *obu, const uint8_t *buf, int length, void *logctx) +{ + int64_t obu_size; + int start_pos, type, temporal_id, spatial_id; + + int ret = parse_obu_header(buf, length, &obu_size, &start_pos, + &type, &temporal_id, &spatial_id); + if (ret < 0) + return ret; + + if (obu_size > INT_MAX / 8 || obu_size < 0) + return AVERROR(ERANGE); + + obu->type = type; + obu->temporal_id = temporal_id; + obu->spatial_id = spatial_id; + + length = obu_size + start_pos; + + obu->data = buf + start_pos; + obu->size = obu_size; + obu->raw_data = buf; + obu->raw_size = length; + + ret = init_get_bits(&obu->gb, obu->data, obu->size * 8); + if (ret < 0) + return ret; + + av_log(logctx, AV_LOG_DEBUG, + "obu_type: %d, temporal_id: %d, spatial_id: %d, payload size: %d\n", + obu->type, obu->temporal_id, obu->spatial_id, obu->size); + + return length; +} + +int ff_av1_packet_split(AV1Packet *pkt, const uint8_t *buf, int length, void *logctx) +{ + GetByteContext bc; + int consumed; + + bytestream2_init(&bc, buf, length); + pkt->nb_obus = 0; + + while (bytestream2_get_bytes_left(&bc) > 0) { + AV1OBU *obu; + + if (pkt->obus_allocated < pkt->nb_obus + 1) { + int new_size = pkt->obus_allocated + 1; + AV1OBU *tmp = av_realloc_array(pkt->obus, new_size, sizeof(*tmp)); + if (!tmp) + return AVERROR(ENOMEM); + + pkt->obus = tmp; + memset(pkt->obus + pkt->obus_allocated, 0, + (new_size - pkt->obus_allocated) * sizeof(*tmp)); + pkt->obus_allocated = new_size; + } + obu = &pkt->obus[pkt->nb_obus]; + + consumed = ff_av1_extract_obu(obu, bc.buffer, bytestream2_get_bytes_left(&bc), logctx); + if (consumed < 0) + return consumed; + + pkt->nb_obus++; + + bytestream2_skip(&bc, consumed); + } + + return 0; +} + +void ff_av1_packet_uninit(AV1Packet *pkt) +{ + av_freep(&pkt->obus); + pkt->obus_allocated = 0; +} diff --git a/libavcodec/av1_parse.h b/libavcodec/av1_parse.h new file mode 100644 index 0000000000..84fc71c925 --- /dev/null +++ b/libavcodec/av1_parse.h @@ -0,0 +1,126 @@ +/* + * AV1 common parsing code + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AV1_PARSE_H +#define AVCODEC_AV1_PARSE_H + +#include + +#include "avcodec.h" +#include "get_bits.h" + +typedef struct AV1OBU { + /** Size of payload */ + int size; + const uint8_t *data; + + /** Size of entire OBU, including header */ + int raw_size; + const uint8_t *raw_data; + + /** GetBitContext initialized to the start of the payload */ + GetBitContext gb; + + int type; + + int temporal_id; + int spatial_id; +} AV1OBU; + +/** An input packet split into OBUs */ +typedef struct AV1Packet { + AV1OBU *obus; + int nb_obus; + int obus_allocated; +} AV1Packet; + +/** + * Extract an OBU from a raw bitstream. + * + * @note This function does not copy or store any bistream data. All + * the pointers in the AV1OBU structure will be valid as long + * as the input buffer also is. + */ +int ff_av1_extract_obu(AV1OBU *obu, const uint8_t *buf, int length, + void *logctx); + +/** + * Split an input packet into OBUs. + * + * @note This function does not copy or store any bistream data. All + * the pointers in the AV1Packet structure will be valid as + * long as the input buffer also is. + */ +int ff_av1_packet_split(AV1Packet *pkt, const uint8_t *buf, int length, + void *logctx); + +/** + * Free all the allocated memory in the packet. + */ +void ff_av1_packet_uninit(AV1Packet *pkt); + +static inline int64_t leb128(GetBitContext *gb) { + int64_t ret = 0; + int i; + + for (i = 0; i < 8; i++) { + int byte = get_bits(gb, 8); + ret |= (int64_t)(byte & 0x7f) << (i * 7); + if (!(byte & 0x80)) + break; + } + return ret; +} + +static inline int parse_obu_header(const uint8_t *buf, int buf_size, + int64_t *obu_size, int *start_pos, int *type, + int *temporal_id, int *spatial_id) +{ + GetBitContext gb; + int ret, extension_flag, has_size_flag; + + ret = init_get_bits8(&gb, buf, FFMIN(buf_size, 2 + 8)); // OBU header fields + max leb128 length + if (ret < 0) + return ret; + + if (get_bits1(&gb) != 0) // obu_forbidden_bit + return AVERROR_INVALIDDATA; + + *type = get_bits(&gb, 4); + extension_flag = get_bits1(&gb); + has_size_flag = get_bits1(&gb); + skip_bits1(&gb); // obu_reserved_1bit + + if (extension_flag) { + *temporal_id = get_bits(&gb, 3); + *spatial_id = get_bits(&gb, 2); + skip_bits(&gb, 3); // extension_header_reserved_3bits + } else { + *temporal_id = *spatial_id = 0; + } + + *obu_size = has_size_flag ? leb128(&gb) + : buf_size - 1 - extension_flag; + *start_pos = get_bits_count(&gb) / 8; + + return 0; +} + +#endif /* AVCODEC_AV1_PARSE_H */