From patchwork Tue Sep 24 14:43:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 51797 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:ad12:0:b0:48e:c0f8:d0de with SMTP id w18csp422598vqy; Tue, 24 Sep 2024 07:59:21 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVKO7tSlfzr6P93R51NIKLdD0FoLL+uqaMaocWMTSbX7Zm1Vo7+ZTNwcfYEH5JAkJYBuNle3Vv/OKiTaJhaxZs6@gmail.com X-Google-Smtp-Source: AGHT+IHTZt0vI88q7jpqQfSyfg5QBv5/18J1bbyeH0SBbX4VO+JxTto2yA0iXvVft1et4hv2EKXk X-Received: by 2002:a05:6512:1250:b0:536:7a88:616b with SMTP id 2adb3069b0e04-536ac2f462cmr8405967e87.26.1727189961499; Tue, 24 Sep 2024 07:59:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1727189961; cv=none; d=google.com; s=arc-20240605; b=eB1ARksbA+G07mx8AEWSM16o/CXghotwXmXAOKm2EzeeOKcA/nsoN69zj+OHimVCAS OeKYvcccX30cYpIZ5JIdc2qpsCLM9tYcYYBAEiOSROrU5wtG1iIhCF4cJliZEPKQwZl8 hSHH+rW5eIM+POrmD/xoI33Nwb7b1tUpO1CJdPUKbL6LCT6P5X2qoZDRJGaUu5SM/ktf LpLpXwHqYWVrpL6EUeXYG0GqSREaBVycbAJ6c4chIBZHj2B/sq/FBRnnYPMe8DzJLTmo sT9Ifomt4nw4vnc/Faycd0ZpyWtLeLEBgsPrI9l+jUoYN5GEKE3eLRPlwMfkAi80dP2r k36g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding: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=rU/gUfYtHYTAp3xEqBQM9iPienpB/su/FS/1+KGi6/M=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=h79UodvDC2QMWeoE4CU7yP6uOz+P4mBUbR+nhW/dpfjUDtWiL7hIMuUE6uLz8ES8nj 39aaTA5SBuHJp8kmdV+grNCesssIhBQJkBLts0BiiBcZ159g1VxWrAQGZx+aJqg9Goon GhiyKpY6lwu4roGvIIDCS0G+P6oHrsGZvHUuMiurTZnlzf7gO84B/68A5+h4Kj4HAByy V7E7dLcKcEIhzdPThxjAnV7VcdgI0fjZYvwIreb/KwwzR0r6AdeSx8FuRsqxgsSp4dFR k2zb3D+h9u3YAoM0vf5wiaiNbeRjMIdDaQBGTi/KhVLDyVD5xZyJ2mV2WSSnODn7MdYo LxBw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=A2deRPqO; 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; dara=fail header.i=@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 2adb3069b0e04-537a863ec68si581449e87.244.2024.09.24.07.59.21; Tue, 24 Sep 2024 07:59:21 -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=20230601 header.b=A2deRPqO; 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; dara=fail header.i=@gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8CFD768DBE9; Tue, 24 Sep 2024 17:42:55 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qv1-f48.google.com (mail-qv1-f48.google.com [209.85.219.48]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E696A68DBB0 for ; Tue, 24 Sep 2024 17:42:47 +0300 (EEST) Received: by mail-qv1-f48.google.com with SMTP id 6a1803df08f44-6c51d1df755so45536306d6.1 for ; Tue, 24 Sep 2024 07:42:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727188966; x=1727793766; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=5GPkVDFhKRKW+ihzglmg2nmgeWSjZTuKjlfCTj/cdSc=; b=A2deRPqO6BiPTw8mTqPfGXsaF1gkgoDD8TWXBekIC/LCC0+G+2PD2MFaxGC8XB4GeY /99c/4UWod8bitWmlHGEolwEwjMz0X+9fCwwAifXd9sm6Y8tcAz4EmJRJo9/LE0clBEG 3W6gveCQ/UEQELCkKufp7+XwLWVFJO9h9gFbEAgC87mU6NNz0XC0JVVx7KfiUqTD1SgZ EMBM8UJfaKycGcl7d0WghqnidfPzFifCzqQOa/uSP/ahFrppy4CKX1x5RXgrDSlx4Cll vUzpTsQ6I/VoeikCfDrdFQjUNNWTw3wXALoVwd5V3G0LkWzY+DM/G1E+Xt3/ULBAjD7d zf7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727188966; x=1727793766; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5GPkVDFhKRKW+ihzglmg2nmgeWSjZTuKjlfCTj/cdSc=; b=fr8eTqrWwVNPlPd1cgEjokc+Aqhem81FrTVyqWDc1imGV6T56PkHvldvN98yJmxvRL JFf+tvGqYk3UTjSRfiC1MCA4Ca/OFWpYUNvgRIwN4NcX0fAM/GgkPeA8HtZhnMf09P2y okB/JGbtPacDOWwPjGOy4aRb2U5W1EoRIbhFZGkUAu3u+QuRucohJlKOFrHaSXqgdkU2 9TH/b49AHIWIDmEwK2HgO40GIG1KVhRGOYp7NR61h4z/emMnUlIFqIsGK3JSZmzjH0pc CKzhWEpuoLw7nlbCwfNo2T5aywyccDVS9XaQVonq1/WfFZZl1TxN2VkVG3k8soJ3e84H lbuA== X-Gm-Message-State: AOJu0Yy3SGbI2j4ZP+cLIzBVHZxmSlwuwP6cpjlBrgw/OoSw/TjN9a5w Btl5yGUGJUIoJ0b5nGeYSkz1C8G7hwkyFpPKN/pe+TCH0F9YqeQ/uRW6WQ== X-Received: by 2002:a05:6214:3117:b0:6c4:c95a:6782 with SMTP id 6a1803df08f44-6c7bd5e0bd3mr176819546d6.51.1727188965736; Tue, 24 Sep 2024 07:42:45 -0700 (PDT) Received: from localhost.localdomain ([181.92.233.116]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6cb0f4c1b4fsm7152716d6.43.2024.09.24.07.42.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Sep 2024 07:42:45 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Tue, 24 Sep 2024 11:43:07 -0300 Message-ID: <20240924144308.1196-2-jamrial@gmail.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240924144308.1196-1-jamrial@gmail.com> References: <20240924144308.1196-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/3] fftools/ffmpeg_demux: factorize the bitstream filtering loop 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: Ua9SwjiHd/Qk Will be needed by the following patch. Signed-off-by: James Almer --- fftools/ffmpeg_demux.c | 74 ++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 13aef15eab..108a4a94bf 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -537,6 +537,47 @@ static int do_send(Demuxer *d, DemuxStream *ds, AVPacket *pkt, unsigned flags, return 0; } +static int demux_filter(Demuxer *d, DemuxThreadContext *dt, DemuxStream *ds, + AVBSFContext *bsf, AVPacket *pkt, void *logctx) +{ + int ret; + + if (pkt) + av_packet_rescale_ts(pkt, pkt->time_base, bsf->time_base_in); + + ret = av_bsf_send_packet(bsf, pkt); + if (ret < 0) { + if (pkt) + av_packet_unref(pkt); + av_log(logctx, AV_LOG_ERROR, "Error submitting a packet for filtering: %s\n", + av_err2str(ret)); + return ret; + } + + while (1) { + ret = av_bsf_receive_packet(bsf, dt->pkt_bsf); + if (ret == AVERROR(EAGAIN)) + return 0; + else if (ret < 0) { + if (ret != AVERROR_EOF) + av_log(logctx, AV_LOG_ERROR, + "Error applying bitstream filters to a packet: %s\n", + av_err2str(ret)); + break; + } + + dt->pkt_bsf->time_base = bsf->time_base_out; + + ret = do_send(d, ds, dt->pkt_bsf, 0, "filtered"); + if (ret < 0) { + av_packet_unref(dt->pkt_bsf); + break; + } + } + + return ret; +} + static int demux_send(Demuxer *d, DemuxThreadContext *dt, DemuxStream *ds, AVPacket *pkt, unsigned flags) { @@ -565,38 +606,9 @@ static int demux_send(Demuxer *d, DemuxThreadContext *dt, DemuxStream *ds, } if (ds->bsf) { - if (pkt) - av_packet_rescale_ts(pkt, pkt->time_base, ds->bsf->time_base_in); - - ret = av_bsf_send_packet(ds->bsf, pkt); - if (ret < 0) { - if (pkt) - av_packet_unref(pkt); - av_log(ds, AV_LOG_ERROR, "Error submitting a packet for filtering: %s\n", - av_err2str(ret)); + ret = demux_filter(d, dt, ds, ds->bsf, pkt, ds); + if (ret < 0) return ret; - } - - while (1) { - ret = av_bsf_receive_packet(ds->bsf, dt->pkt_bsf); - if (ret == AVERROR(EAGAIN)) - return 0; - else if (ret < 0) { - if (ret != AVERROR_EOF) - av_log(ds, AV_LOG_ERROR, - "Error applying bitstream filters to a packet: %s\n", - av_err2str(ret)); - return ret; - } - - dt->pkt_bsf->time_base = ds->bsf->time_base_out; - - ret = do_send(d, ds, dt->pkt_bsf, 0, "filtered"); - if (ret < 0) { - av_packet_unref(dt->pkt_bsf); - return ret; - } - } } else { ret = do_send(d, ds, pkt, flags, "demuxed"); if (ret < 0) From patchwork Tue Sep 24 14:43:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 51796 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:ad12:0:b0:48e:c0f8:d0de with SMTP id w18csp422578vqy; Tue, 24 Sep 2024 07:59:20 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCULW8IkL4NolA9Dr+qhvFXKb8mwW2YOjmDFh4xW5xfWjeXcY2V3GoEGELhRbSrbVX99Ov3INhmdj5qGzRAqIJPa@gmail.com X-Google-Smtp-Source: AGHT+IGaS4xgy6LS0bcoHkkLKa0zwSLGNlKS7+5G/yomZFWmsGoReIrMktwD+ISa3gJ5ZbOZ6DeT X-Received: by 2002:a05:6000:402b:b0:377:5c6e:a017 with SMTP id ffacd0b85a97d-37a422b861cmr4540949f8f.7.1727189959737; Tue, 24 Sep 2024 07:59:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1727189959; cv=none; d=google.com; s=arc-20240605; b=gK367/nA92A/ReaIJq2On5Bfupoz6c/PUAFZPDHMY2JvyxmJ+l6ejAuX6zlyOXyaZy GywGqR7yN/1zWGAl0vPwNsGxKdjOoS7dsb46GICe6VQTX2X0rofhQU9HzbWzVweVWqxl BLaZEMAcwMFd6VDfs44WpocPBXjXxMSiF/P2Y/zO0ewoDT3D7ary7f5eev97FdmexQ4l WHIzpeCcpvieX4pNvKpZAz5//44iKJq3YIxXuHD3fB0eazn8iTmieo4kjButQVGijFDO QsLmS7wZGea3rl5JKzGTPQEPc8fF6ZdtobP+oOw0tC6qGrQOhrF+ma/NgFF1T+tS3C62 YRRw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding: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=08c97fjByOKQBHH4Z+3tB4/S0py4cNYBOZJRJKFhLJ4=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=J88LSB2a5sScBPGWqHT6cvFZahZB+PwaboTG+1+ex2qzwaS2GWM3eNT8x3FqOsl/7f hx2GTjVcnm93fExPo9yAb7E7WHX+0DGCtLKemCvtXEVIBL6bBaDEmbfljWtZudt6n9rB KAEqDmZZNi1lBEwMZsnd/RpMHSr1yPap1k2s9ADXMWHQcZcj6BB3kJ1SoAKSnRMx3G0Q v5UsN2VUnVH3SVVJPTUiyPGxvZIKfEdwbawbhu125ahdPdRyeU6EQm+UID0YjOJfLqNp shlVj1JnMHSZASaUCIHdMU0DTYe0Sr3zJ/Q9yiGnya27jB05n9gusD0u3WOqJXPl55Hf EzUw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=Jq9r2Mpa; 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; dara=fail header.i=@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 a640c23a62f3a-a93930bc91bsi113739566b.357.2024.09.24.07.59.19; Tue, 24 Sep 2024 07:59:19 -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=20230601 header.b=Jq9r2Mpa; 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; dara=fail header.i=@gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DE86B68DC59; Tue, 24 Sep 2024 17:42:57 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qv1-f45.google.com (mail-qv1-f45.google.com [209.85.219.45]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id DDEB368D8E2 for ; Tue, 24 Sep 2024 17:42:51 +0300 (EEST) Received: by mail-qv1-f45.google.com with SMTP id 6a1803df08f44-6c579748bf4so53024406d6.1 for ; Tue, 24 Sep 2024 07:42:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727188969; x=1727793769; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=vCEQVNeB5xHd0hDJEzjFHkCLBXcRhnz9mAqH3IIbd8k=; b=Jq9r2MparlRgF/XXOQ76JQP8KHMQTxszSFQgkLMpScNS+BJSxkvIW2q+hzHXsDYEzV C3MtR7MuSgw1rfwmral8uXUTI8Oh0BqZXI6t5g0vkmkDLeajqg1qryXkS5VhS8ZCN5Aa 1N+iNaaBHd4M1EbVrPEtaI1Ex0e9FIsOTkIidW/NIRQ7wkzIP9Sn6gIIn9FAAJGUTyxC ZYwYbf/Ys6hwqem/shntszl0q2/UOGXv5K1i9S6PmlqDQn7/AGZN8ukdqXwkIGdj7wcG Rbr6IeEvycuxP7T0a/pX0HDy653FiyXAlFm22pB0CN8RCwQ2stC/NAQj5tcQsVT+Cq6/ u26A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727188969; x=1727793769; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vCEQVNeB5xHd0hDJEzjFHkCLBXcRhnz9mAqH3IIbd8k=; b=vaoC8CAFh8SEebKmHjjgONT579ppeRIqIdpr5kVNEa8zUY6Vid9wkLIg5rxRjwr56Q N/b7aO7zr4yrugfFEgpz5Sjw2LY45Co+3aA1kilRgbDx8ugRDyDDTXUKT14FL+lpub5R rg6HzIkgxBcW8dmz8AR2o9zFMbOxQyGEW4Xu1ixhhS7vBqzh6rAhDQXsf95wF+vbPrFF +6QOjZCI44mC/98Xm8pMEASX7TWO+3ncgxkgNNfUvTGsjsPzSlZSqQVvI3/Ej9YvRStf sPYxW8rlhY+WrZQpkR8HbmPJddZSHtRmorwbWudA4k4vuhniCnG5YFk4VdDIbpAt9+/k SGlA== X-Gm-Message-State: AOJu0YyziXipSmu0ZOCUC5mfYw502vIOo4tUyb2ThuOBh5BAfAkWBbIQ WMsJ24RQ3GcTEznDpISeNSdhmd/RX1uSogp7LGNAsmgudUm7lBfNVV5vGA== X-Received: by 2002:a05:6214:5690:b0:6b8:5afd:8f89 with SMTP id 6a1803df08f44-6c7bc8127d6mr245670866d6.37.1727188968780; Tue, 24 Sep 2024 07:42:48 -0700 (PDT) Received: from localhost.localdomain ([181.92.233.116]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6cb0f4c1b4fsm7152716d6.43.2024.09.24.07.42.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Sep 2024 07:42:47 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Tue, 24 Sep 2024 11:43:08 -0300 Message-ID: <20240924144308.1196-3-jamrial@gmail.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240924144308.1196-1-jamrial@gmail.com> References: <20240924144308.1196-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg_demux: merge streams in a LCEVC stream group 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: Tlgo0cIIoMtx Add the LCEVC data stream payloads as packet side data to the main video stream, ensuring the former is always output by the demuxer even if not used by the process. Signed-off-by: James Almer --- configure | 2 +- fftools/ffmpeg.h | 6 + fftools/ffmpeg_demux.c | 296 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 300 insertions(+), 4 deletions(-) diff --git a/configure b/configure index d77a55b653..434c73776b 100755 --- a/configure +++ b/configure @@ -4051,7 +4051,7 @@ ffmpeg_deps="avcodec avfilter avformat threads" ffmpeg_select="aformat_filter anull_filter atrim_filter crop_filter format_filter hflip_filter null_filter rotate_filter transpose_filter trim_filter vflip_filter" -ffmpeg_suggest="ole32 psapi shell32" +ffmpeg_suggest="ole32 psapi shell32 lcevc_merge_bsf" ffplay_deps="avcodec avformat avfilter swscale swresample sdl2" ffplay_select="crop_filter transpose_filter hflip_filter vflip_filter rotate_filter" ffplay_suggest="shell32 libplacebo vulkan" diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 733d551fa4..f598f6a46f 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -492,6 +492,12 @@ typedef struct InputFile { * if new streams appear dynamically during demuxing */ InputStream **streams; int nb_streams; + + /** + * stream groups that ffmpeg is aware of + */ + struct InputStreamGroup **stream_groups; + int nb_stream_groups; } InputFile; enum forced_keyframes_const { diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 108a4a94bf..6aa194e7ad 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -40,6 +40,18 @@ #include "libavformat/avformat.h" +// Defined here until it's needed in other modules and moved to ffmpeg.h +typedef struct InputStreamGroup { + const AVClass *class; + + /* parent source */ + struct InputFile *file; + + int index; + + AVStreamGroup *stg; +} InputStreamGroup; + typedef struct DemuxStream { InputStream ist; @@ -56,7 +68,7 @@ typedef struct DemuxStream { #define DECODING_FOR_OST 1 #define DECODING_FOR_FILTER 2 - /* true if stream data should be discarded */ + /* non-0 if stream data is not strictly used by an output */ int discard; // scheduler returned EOF for this stream @@ -90,12 +102,29 @@ typedef struct DemuxStream { AVBSFContext *bsf; + InputStreamGroup **stream_groups; + int nb_stream_groups; + /* number of packets successfully read for this stream */ uint64_t nb_packets; // combined size of all the packets read uint64_t data_size; } DemuxStream; +typedef struct DemuxStreamGroup { + InputStreamGroup istg; + + // main stream for merged output + InputStream *stream; + + // name used for logging + char log_name[32]; + + int discard; + + AVBSFContext *bsf; +} DemuxStreamGroup; + typedef struct Demuxer { InputFile f; @@ -142,13 +171,26 @@ typedef struct DemuxThreadContext { AVPacket *pkt_demux; // packet for reading from BSFs AVPacket *pkt_bsf; + AVPacket *pkt_group_bsf; } DemuxThreadContext; +enum { + // Stream is to be discarded without further processing + DEMUXER_DISCARD = 1, + // Stream is to be discarded after being processed in some form + DEMUXER_FILTER = 2, +}; + static DemuxStream *ds_from_ist(InputStream *ist) { return (DemuxStream*)ist; } +static DemuxStreamGroup *dsg_from_istg(InputStreamGroup *istg) +{ + return (DemuxStreamGroup*)istg; +} + static Demuxer *demuxer_from_ifile(InputFile *f) { return (Demuxer*)f; @@ -587,6 +629,17 @@ static int demux_send(Demuxer *d, DemuxThreadContext *dt, DemuxStream *ds, // pkt can be NULL only when flushing BSFs av_assert0(ds->bsf || pkt); + // the stream needs to be used by an output in some form + av_assert0(ds->discard != DEMUXER_DISCARD); + + // create a reference for the packet to be filtered by group bsfs + if (pkt && ds->nb_stream_groups) { + av_packet_unref(dt->pkt_group_bsf); + ret = av_packet_ref(dt->pkt_group_bsf, pkt); + if (ret < 0) + return ret; + } + // send heartbeat for sub2video streams if (d->pkt_heartbeat && pkt && pkt->pts != AV_NOPTS_VALUE) { for (int i = 0; i < f->nb_streams; i++) { @@ -605,6 +658,26 @@ static int demux_send(Demuxer *d, DemuxThreadContext *dt, DemuxStream *ds, } } + for (int i = 0; i < ds->nb_stream_groups; i++) { + DemuxStreamGroup *dsg = dsg_from_istg(ds->stream_groups[i]); + + // if the main stream is not used by an output, we don't want to filter + if (ds == ds_from_ist(dsg->stream) && ds->discard) + continue; + + ret = demux_filter(d, dt, ds_from_ist(dsg->stream), dsg->bsf, + pkt ? dt->pkt_group_bsf : NULL, dsg); + if (ret < 0) + return ret; + + // TODO handle streams belonging to more than one Stream group + if (i == (ds->nb_stream_groups - 1) && ds == ds_from_ist(dsg->stream)) + return 0; + } + + if (ds->discard) + return 0; + if (ds->bsf) { ret = demux_filter(d, dt, ds, ds->bsf, pkt, ds); if (ret < 0) @@ -672,6 +745,7 @@ static void demux_thread_uninit(DemuxThreadContext *dt) { av_packet_free(&dt->pkt_demux); av_packet_free(&dt->pkt_bsf); + av_packet_free(&dt->pkt_group_bsf); memset(dt, 0, sizeof(*dt)); } @@ -688,6 +762,10 @@ static int demux_thread_init(DemuxThreadContext *dt) if (!dt->pkt_bsf) return AVERROR(ENOMEM); + dt->pkt_group_bsf = av_packet_alloc(); + if (!dt->pkt_group_bsf) + return AVERROR(ENOMEM); + return 0; } @@ -760,11 +838,25 @@ static int input_thread(void *arg) dynamically in stream : we ignore them */ ds = dt.pkt_demux->stream_index < f->nb_streams ? ds_from_ist(f->streams[dt.pkt_demux->stream_index]) : NULL; - if (!ds || ds->discard || ds->finished) { + if (!ds || ds->finished) { report_new_stream(d, dt.pkt_demux); av_packet_unref(dt.pkt_demux); continue; } + if (ds->discard == DEMUXER_DISCARD) { + int i; + /* is the stream known and unused, but still needed to handle a group? */ + for (i = 0; i < ds->nb_stream_groups; i++) + if (!dsg_from_istg(ds->stream_groups[i])->discard) + break; + /* like above, if it's a new stream, we ignore it */ + if (i == ds->nb_stream_groups) { + report_new_stream(d, dt.pkt_demux); + av_packet_unref(dt.pkt_demux); + continue; + } + ds->discard = DEMUXER_FILTER; + } if (dt.pkt_demux->flags & AV_PKT_FLAG_CORRUPT) { av_log(d, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, @@ -861,9 +953,25 @@ static void ist_free(InputStream **pist) av_bsf_free(&ds->bsf); + av_freep(&ds->stream_groups); + av_freep(pist); } +static void istg_free(InputStreamGroup **pistg) +{ + InputStreamGroup *istg = *pistg; + DemuxStreamGroup *dsg; + + if (!istg) + return; + dsg = dsg_from_istg(istg); + + av_bsf_free(&dsg->bsf); + + av_freep(pistg); +} + void ifile_close(InputFile **pf) { InputFile *f = *pf; @@ -878,6 +986,9 @@ void ifile_close(InputFile **pf) for (int i = 0; i < f->nb_streams; i++) ist_free(&f->streams[i]); av_freep(&f->streams); + for (int i = 0; i < f->nb_stream_groups; i++) + istg_free(&f->stream_groups[i]); + av_freep(&f->stream_groups); avformat_close_input(&f->ctx); @@ -984,6 +1095,19 @@ static int ist_use(InputStream *ist, int decoding_needed, SCH_DSTREAM(d->f.index, ds->sch_idx_stream); } + // if this stream is the main one in any group, enable said group and + // all its streams, so lavf will return their packets + for (int i = 0; i < ds->nb_stream_groups; i++) { + DemuxStreamGroup *dsg = dsg_from_istg(ds->stream_groups[i]); + AVStreamGroup *stg = ds->stream_groups[i]->stg; + + if (ist != dsg->stream) + continue; + for (int j = 0; j < stg->nb_streams; j++) + stg->streams[j]->discard = 0; + dsg->discard = 0; + } + return 0; } @@ -1269,7 +1393,7 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona ist = &ds->ist; - ds->discard = 1; + ds->discard = DEMUXER_DISCARD; st->discard = AVDISCARD_ALL; ds->first_dts = AV_NOPTS_VALUE; ds->next_dts = AV_NOPTS_VALUE; @@ -1550,6 +1674,163 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona return 0; } +static const char *input_stream_group_item_name(void *obj) +{ + const DemuxStreamGroup *dsg = obj; + + return dsg->log_name; +} + +static const AVClass input_stream_group_class = { + .class_name = "InputStreamGroup", + .version = LIBAVUTIL_VERSION_INT, + .item_name = input_stream_group_item_name, + .category = AV_CLASS_CATEGORY_DEMUXER, +}; + +static DemuxStreamGroup *demux_stream_group_alloc(Demuxer *d, AVStreamGroup *stg) +{ + InputFile *f = &d->f; + DemuxStreamGroup *dsg; + + dsg = allocate_array_elem(&f->stream_groups, sizeof(*dsg), &f->nb_stream_groups); + if (!dsg) + return NULL; + + dsg->istg.stg = stg; + dsg->istg.file = f; + dsg->istg.index = stg->index; + dsg->istg.class = &input_stream_group_class; + + snprintf(dsg->log_name, sizeof(dsg->log_name), "istg#%d:%d/%s", + d->f.index, stg->index, avformat_stream_group_name(stg->type)); + + return dsg; +} + +static int istg_set_bidirectional_references(Demuxer *d, DemuxStreamGroup *dsg) +{ + InputFile *f = &d->f; + AVStreamGroup *stg = dsg->istg.stg; + + /* since the API lets us know what streams belong to a given group, but + * not what groups a given stream is part of, add a pointer to the + * DemuxStreamGroup to all relevant DemuxStream structs for this purpose */ + for (int i = 0; i < stg->nb_streams; i++) { + DemuxStreamGroup **dsg1; + DemuxStream *ds; + int j; + + for (j = 0; j < f->nb_streams; j++) + if (stg->streams[i] == f->streams[j]->st) + break; + + if (j == f->nb_streams) + return AVERROR_BUG; + + ds = ds_from_ist(f->streams[j]); + dsg1 = av_dynarray2_add((void **)&ds->stream_groups, &ds->nb_stream_groups, + sizeof(*dsg1), NULL); + if (!dsg1) + return AVERROR(ENOMEM); + + *dsg1 = dsg; + } + + return 0; +} + +static int istg_add_lcevc_group(Demuxer *d, AVStreamGroup *stg) +{ + InputFile *f = &d->f; + const AVBitStreamFilter *filter; + DemuxStreamGroup *dsg; + int base_idx = -1, enhancement_idx; + int ret; + + filter = av_bsf_get_by_name("lcevc_merge"); + if (!filter) + return AVERROR(ENOSYS); + + if (stg->nb_streams != 2) { + av_log(d, AV_LOG_WARNING, "LCEVC stream groups with more than 2 streams " + "are not supported.\n"); + return AVERROR_PATCHWELCOME; + } + + dsg = demux_stream_group_alloc(d, stg); + if (!dsg) + return AVERROR(ENOMEM); + + // set the main stream for the group + for (int i = 0; i < stg->nb_streams; i++) { + const AVStreamGroupLCEVC *lcevc = stg->params.lcevc; + int j; + + if (i == lcevc->lcevc_index) { + enhancement_idx = stg->streams[lcevc->lcevc_index]->index; + continue; + } + + for (j = 0; j < f->nb_streams; j++) + if (stg->streams[i] == f->streams[j]->st) + break; + + if (j == f->nb_streams) + return AVERROR_BUG; + + if (stg->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || base_idx >= 0) + return AVERROR_BUG; + + dsg->stream = f->streams[j]; + base_idx = f->streams[j]->st->index; + } + + ret = av_bsf_alloc(filter, &dsg->bsf); + if (ret < 0) + return ret; + + av_opt_set_int(dsg->bsf->priv_data, "base_idx", base_idx, 0); + av_opt_set_int(dsg->bsf->priv_data, "enhancement_idx", enhancement_idx, 0); + + dsg->bsf->time_base_in = stg->streams[base_idx]->time_base; + + ret = av_bsf_init(dsg->bsf); + if (ret < 0) + return ret; + + return 0; +} + +static int istg_add(Demuxer *d, AVStreamGroup *stg) +{ + InputFile *f = &d->f; + DemuxStreamGroup *dsg; + int ret = AVERROR_BUG; + + switch (stg->type) { + case AV_STREAM_GROUP_PARAMS_LCEVC: + ret = istg_add_lcevc_group(d, stg); + if (ret == AVERROR(ENOSYS)) + return 0; + break; + default: + return 0; + } + + if (ret < 0) + return ret; + + dsg = dsg_from_istg(f->stream_groups[f->nb_stream_groups - 1]); + ret = istg_set_bidirectional_references(d, dsg); + if (ret < 0) + return ret; + + dsg->discard = 1; + + return 0; +} + static int dump_attachment(InputStream *ist, const char *filename) { AVStream *st = ist->st; @@ -1904,6 +2185,15 @@ int ifile_open(const OptionsContext *o, const char *filename, Scheduler *sch) } } + /* Add all the stream groups from the given input file to the demuxer */ + for (int i = 0; i < ic->nb_stream_groups; i++) { + ret = istg_add(d, ic->stream_groups[i]); + if (ret < 0) { + av_dict_free(&opts_used); + return ret; + } + } + /* dump the file content */ av_dump_format(ic, f->index, filename, 0);