From patchwork Mon Nov 11 13:36:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 16209 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 B53604481AC for ; Mon, 11 Nov 2019 16:02:25 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9BB3C68A91A; Mon, 11 Nov 2019 16:02:25 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qt1-f194.google.com (mail-qt1-f194.google.com [209.85.160.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5279E68A115 for ; Mon, 11 Nov 2019 16:02:19 +0200 (EET) Received: by mail-qt1-f194.google.com with SMTP id p20so15751609qtq.5 for ; Mon, 11 Nov 2019 06:02:19 -0800 (PST) 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:mime-version :content-transfer-encoding; bh=xEhmoPc+aa8KL7oHErvVjmcdCnXdD7uZh585bb6ZVIs=; b=tmY+eXd9LspaE6yAfrwA5jtjq4WUI6UUN5/9U9OkW1cUC4jjMXM4SM2wtsR9NQsb0k 5oDE1U5Iw9WPIaU+yxmhUdnMvDkM9AIiKHxdl5n3+njvYyQUqzuunwRIvCxbFj9nnKhH zUCjejmI29hEDQQlP4mUzjdEy13Tce3UTfoECxfqMKp+bRdAdxdUld0Q5xWyof2ouqGc t0WygaOW/xMA2/8mfmVCzIIo/wfZc4WcwtWtKQTbr1o17lrmrisLTFBazUwGB+XptMWH otaww5PB/SbV5NMa8HD6FeEFiO+ArZ9scUvuRgTu/U4SXw8LBq7gCRCEKLBoNnutxQfA 0VDw== 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:mime-version:content-transfer-encoding; bh=xEhmoPc+aa8KL7oHErvVjmcdCnXdD7uZh585bb6ZVIs=; b=HY7PjTZtFp9LH148z6SghxD3uToHNuiBkhy7cSP8SywIp9IbRpg6Q0LqdZIwHVimgx jpXqhMCXA2n3HTSOTzZw8qG468SuVbOdm13b8cjB7ck0VYg6jR3kovQnOeGY6+etB6Hf vAmgulaBQJZ/zHqveh91WfW5Oc5qS7IRMLsYMawcRVvwnBEB8YqZUhSJMnkDZaN6U+OL CR77MdR/RA4/a6lh9gE1quXYF+eStKttsW0oVGzAOanE93mdqD0eTf6oQUu0LZlqHGcS VxOjtVPoRfKO+Rri7JLwvwZfXEfPLFpNEGb8SRy8GfQjQTK2g3KxukQM84UCTlAespkF +0xQ== X-Gm-Message-State: APjAAAUoieZDxoZToE02ShuMzOfV6qcGdSUjnFF7yvD1I48fnz6yFF28 Fz6ba/OAJPx/WifL7qVYshW/yCnq X-Google-Smtp-Source: APXvYqxYlCiN/5BTPU3zirdbChuPagJXo7OTUjykzt5AznUHF32YxAjNtB7yGnsZKpZyefeBV7mvLA== X-Received: by 2002:ae9:c10c:: with SMTP id z12mr9987533qki.411.1573479427638; Mon, 11 Nov 2019 05:37:07 -0800 (PST) Received: from localhost.localdomain ([181.23.83.211]) by smtp.gmail.com with ESMTPSA id d139sm7547567qkb.36.2019.11.11.05.37.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Nov 2019 05:37:07 -0800 (PST) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Mon, 11 Nov 2019 10:36:12 -0300 Message-Id: <20191111133615.543-3-jamrial@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111133615.543-1-jamrial@gmail.com> References: <20191111133615.543-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/5] avcodec: add an AV1 frame merge bitstream filter 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This BSF takes Temporal Units split across different AVPackets and merges them by looking for Temporal Delimiter OBUs. Signed-off-by: James Almer --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/av1_frame_merge_bsf.c | 153 +++++++++++++++++++++++++++++++ libavcodec/bitstream_filters.c | 1 + 4 files changed, 156 insertions(+) create mode 100644 libavcodec/av1_frame_merge_bsf.c diff --git a/configure b/configure index 1de90e93fd..70f60997c1 100755 --- a/configure +++ b/configure @@ -3115,6 +3115,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters aac_adtstoasc_bsf_select="adts_header" +av1_frame_merge_bsf_select="cbs_av1" av1_frame_split_bsf_select="cbs_av1" av1_metadata_bsf_select="cbs_av1" eac3_core_bsf_select="ac3_parser" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b990c6ba87..006a472a6d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1075,6 +1075,7 @@ OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o # bitstream filters OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o OBJS-$(CONFIG_AV1_METADATA_BSF) += av1_metadata_bsf.o +OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF) += av1_frame_merge_bsf.o OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF) += av1_frame_split_bsf.o OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o diff --git a/libavcodec/av1_frame_merge_bsf.c b/libavcodec/av1_frame_merge_bsf.c new file mode 100644 index 0000000000..943cfcb426 --- /dev/null +++ b/libavcodec/av1_frame_merge_bsf.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2019 James Almer + * + * 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 "avcodec.h" +#include "bsf.h" +#include "cbs.h" +#include "cbs_av1.h" + +typedef struct AV1FMergeContext { + CodedBitstreamContext *cbc; + CodedBitstreamFragment temporal_unit; + CodedBitstreamFragment frag; +} AV1FMergeContext; + +static int av1_frame_merge_filter(AVBSFContext *bsf, AVPacket *pkt) +{ + AV1FMergeContext *ctx = bsf->priv_data; + CodedBitstreamFragment *frag = &ctx->frag, *tu = &ctx->temporal_unit; + int err, i; + + err = ff_bsf_get_packet_ref(bsf, pkt); + if (err < 0) { + if (err == AVERROR_EOF && tu->nb_units > 0) + goto eof; + return err; + } + + err = ff_cbs_read_packet(ctx->cbc, frag, pkt); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + if (frag->nb_units == 0) { + av_log(bsf, AV_LOG_ERROR, "No OBU in packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + if (tu->nb_units == 0 && frag->units[0].type != AV1_OBU_TEMPORAL_DELIMITER) { + av_log(bsf, AV_LOG_ERROR, "Missing Temporal Delimiter.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + if (tu->nb_units > 0 && frag->units[0].type == AV1_OBU_TEMPORAL_DELIMITER) { +eof: + err = ff_cbs_write_packet(ctx->cbc, pkt, tu); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + ff_cbs_fragment_reset(ctx->cbc, tu); + + for (i = 0; i < frag->nb_units; i++) { + if (i && frag->units[i].type == AV1_OBU_TEMPORAL_DELIMITER) { + av_log(bsf, AV_LOG_ERROR, "Temporal Delimiter in the middle of a packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + err = ff_cbs_insert_unit_content(ctx->cbc, tu, -1, frag->units[i].type, + frag->units[i].content, frag->units[i].content_ref); + if (err < 0) + goto fail; + } + ff_cbs_fragment_reset(ctx->cbc, frag); + + return err; + } + + for (i = 0; i < frag->nb_units; i++) { + if (i && frag->units[i].type == AV1_OBU_TEMPORAL_DELIMITER) { + av_log(bsf, AV_LOG_ERROR, "Temporal Delimiter in the middle of a packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + err = ff_cbs_insert_unit_content(ctx->cbc, tu, -1, frag->units[i].type, + frag->units[i].content, frag->units[i].content_ref); + if (err < 0) + goto fail; + } + ff_cbs_fragment_reset(ctx->cbc, frag); + av_packet_unref(pkt); + + return err < 0 ? err : AVERROR(EAGAIN); + +fail: + ff_cbs_fragment_reset(ctx->cbc, tu); + ff_cbs_fragment_reset(ctx->cbc, frag); + av_packet_unref(pkt); + + return err; +} + +static int av1_frame_merge_init(AVBSFContext *bsf) +{ + AV1FMergeContext *ctx = bsf->priv_data; + int ret; + + ret = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_AV1, bsf); + if (ret < 0) + return ret; + + return 0; +} + +static void av1_frame_merge_flush(AVBSFContext *bsf) +{ + AV1FMergeContext *ctx = bsf->priv_data; + + ff_cbs_fragment_reset(ctx->cbc, &ctx->temporal_unit); + ff_cbs_fragment_reset(ctx->cbc, &ctx->frag); +} + +static void av1_frame_merge_close(AVBSFContext *bsf) +{ + AV1FMergeContext *ctx = bsf->priv_data; + + ff_cbs_fragment_free(ctx->cbc, &ctx->temporal_unit); + ff_cbs_fragment_free(ctx->cbc, &ctx->frag); + ff_cbs_close(&ctx->cbc); +} + +static const enum AVCodecID av1_frame_merge_codec_ids[] = { + AV_CODEC_ID_AV1, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_av1_frame_merge_bsf = { + .name = "av1_frame_merge", + .priv_data_size = sizeof(AV1FMergeContext), + .init = av1_frame_merge_init, + .flush = av1_frame_merge_flush, + .close = av1_frame_merge_close, + .filter = av1_frame_merge_filter, + .codec_ids = av1_frame_merge_codec_ids, +}; diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 463003966a..6b5ffe4d70 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -25,6 +25,7 @@ #include "bsf.h" extern const AVBitStreamFilter ff_aac_adtstoasc_bsf; +extern const AVBitStreamFilter ff_av1_frame_merge_bsf; extern const AVBitStreamFilter ff_av1_frame_split_bsf; extern const AVBitStreamFilter ff_av1_metadata_bsf; extern const AVBitStreamFilter ff_chomp_bsf;