From patchwork Sat Mar 28 18:15:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 18464 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 9792844B3B0 for ; Sat, 28 Mar 2020 20:15:29 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6FC2068B436; Sat, 28 Mar 2020 20:15:29 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5577268B3C6 for ; Sat, 28 Mar 2020 20:15:23 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id A318FE33DE; Sat, 28 Mar 2020 19:15:22 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id H0AYfYssiGNM; Sat, 28 Mar 2020 19:15:21 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 16177E1D61; Sat, 28 Mar 2020 19:15:21 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Mar 2020 19:15:08 +0100 Message-Id: <20200328181515.5333-1-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 Subject: [FFmpeg-devel] [PATCH 1/8] fftools/ffmpeg: also flush encoders which have a variable frame size 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Marton Balint --- fftools/ffmpeg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index aaaf241314..6cc3c5a14d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1913,9 +1913,6 @@ static void flush_encoders(void) } } - if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) - continue; - if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) continue; From patchwork Sat Mar 28 18:15:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 18465 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 14F6B44B3B0 for ; Sat, 28 Mar 2020 20:15:33 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 01E5868B4AC; Sat, 28 Mar 2020 20:15:33 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5C3E068B4A2 for ; Sat, 28 Mar 2020 20:15:26 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 0116CE37AF; Sat, 28 Mar 2020 19:15:26 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qAJu8dJYdpVv; Sat, 28 Mar 2020 19:15:24 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id A9F5FE1D61; Sat, 28 Mar 2020 19:15:24 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Mar 2020 19:15:09 +0100 Message-Id: <20200328181515.5333-2-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200328181515.5333-1-cus@passwd.hu> References: <20200328181515.5333-1-cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 2/8] avformat/mux: fix check_packet with null packet 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Marton Balint --- libavformat/mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index bfd1bf491b..dfb21c8aa5 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -798,7 +798,7 @@ static int prepare_input_packet(AVFormatContext *s, AVPacket *pkt) #if !FF_API_COMPUTE_PKT_FIELDS2 || !FF_API_LAVF_AVCTX /* sanitize the timestamps */ - if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { + if (pkt && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { AVStream *st = s->streams[pkt->stream_index]; /* when there is no reordering (so dts is equal to pts), but From patchwork Sat Mar 28 18:15:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 18466 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 0AF4944B3B0 for ; Sat, 28 Mar 2020 20:15:37 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E63E468B578; Sat, 28 Mar 2020 20:15:36 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0B98968B550 for ; Sat, 28 Mar 2020 20:15:30 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 9C2D2E33DE; Sat, 28 Mar 2020 19:15:29 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Zf2INsFA2hNs; Sat, 28 Mar 2020 19:15:28 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 1BEF3E1D61; Sat, 28 Mar 2020 19:15:27 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Mar 2020 19:15:10 +0100 Message-Id: <20200328181515.5333-3-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200328181515.5333-1-cus@passwd.hu> References: <20200328181515.5333-1-cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 3/8] avformat/mux: factorize interleaved write_packet 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Marton Balint --- libavformat/mux.c | 58 +++++++++++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index dfb21c8aa5..f68f962a92 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -1187,6 +1187,28 @@ static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, in return ff_interleave_packet_per_dts(s, out, in, flush); } +static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush) +{ + for (;; ) { + AVPacket opkt; + int ret = interleave_packet(s, &opkt, pkt, flush); + if (pkt) { + memset(pkt, 0, sizeof(*pkt)); + av_init_packet(pkt); + pkt = NULL; + } + if (ret <= 0) //FIXME cleanup needed for ret<0 ? + return ret; + + ret = write_packet(s, &opkt); + + av_packet_unref(&opkt); + + if (ret < 0) + return ret; + } +} + int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) { int ret, flush = 0; @@ -1221,25 +1243,8 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n"); flush = 1; } + return interleaved_write_packet(s, pkt, flush); - for (;; ) { - AVPacket opkt; - int ret = interleave_packet(s, &opkt, pkt, flush); - if (pkt) { - memset(pkt, 0, sizeof(*pkt)); - av_init_packet(pkt); - pkt = NULL; - } - if (ret <= 0) //FIXME cleanup needed for ret<0 ? - return ret; - - ret = write_packet(s, &opkt); - - av_packet_unref(&opkt); - - if (ret < 0) - return ret; - } fail: av_packet_unref(pkt); return ret; @@ -1249,23 +1254,8 @@ int av_write_trailer(AVFormatContext *s) { int ret, i; - for (;; ) { - AVPacket pkt; - ret = interleave_packet(s, &pkt, NULL, 1); - if (ret < 0) - goto fail; - if (!ret) - break; - - ret = write_packet(s, &pkt); + ret = interleaved_write_packet(s, NULL, 1); - av_packet_unref(&pkt); - - if (ret < 0) - goto fail; - } - -fail: if (s->oformat->write_trailer) { if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); From patchwork Sat Mar 28 18:15:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 18467 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 F1F7044B3B0 for ; Sat, 28 Mar 2020 20:15:38 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E2B8E68B5E7; Sat, 28 Mar 2020 20:15:38 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 806B568B5C2 for ; Sat, 28 Mar 2020 20:15:32 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 23F0BE37AF; Sat, 28 Mar 2020 19:15:32 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PDef5dInHTIc; Sat, 28 Mar 2020 19:15:30 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 9B54CE1D61; Sat, 28 Mar 2020 19:15:30 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Mar 2020 19:15:11 +0100 Message-Id: <20200328181515.5333-4-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200328181515.5333-1-cus@passwd.hu> References: <20200328181515.5333-1-cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 4/8] avformat/mux: factorize writing a packet 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" In preparation for N:M bsf support. Signed-off-by: Marton Balint --- libavformat/mux.c | 82 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index f68f962a92..8c2d6a8060 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -883,6 +883,49 @@ static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) { return 1; } +static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush); + +static int write_packet_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, int interleaved) +{ + int ret; + + if (s->debug & FF_FDEBUG_TS) + av_log(s, AV_LOG_DEBUG, "%s size:%d dts:%s pts:%s\n", __FUNCTION__, + pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts)); + +#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX + if ((ret = compute_muxer_pkt_fields(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) + return ret; +#endif + + if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) + return AVERROR(EINVAL); + + if (interleaved) + return interleaved_write_packet(s, pkt, 0); + else + return write_packet(s, pkt); +} + +static int write_packets_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, int interleaved) +{ + int ret = do_packet_auto_bsf(s, pkt); + if (ret == 0) + return 0; + else if (ret < 0) + goto fail; + + ret = write_packet_common(s, st, pkt, interleaved); + if (ret < 0) + goto fail; + return ret; + +fail: + if (interleaved) + av_packet_unref(pkt); + return ret; +} + int av_write_frame(AVFormatContext *s, AVPacket *pkt) { int ret; @@ -902,18 +945,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) return 1; } - ret = do_packet_auto_bsf(s, pkt); - if (ret <= 0) - return ret; - -#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX - ret = compute_muxer_pkt_fields(s, s->streams[pkt->stream_index], pkt); - - if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) - return ret; -#endif - - return write_packet(s, pkt); + return write_packets_common(s, s->streams[pkt->stream_index], pkt, 0/*non-interleaved*/); } #define CHUNK_START 0x1000 @@ -1211,7 +1243,7 @@ static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) { - int ret, flush = 0; + int ret; ret = prepare_input_packet(s, pkt); if (ret < 0) @@ -1219,31 +1251,11 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) if (pkt) { AVStream *st = s->streams[pkt->stream_index]; - - ret = do_packet_auto_bsf(s, pkt); - if (ret == 0) - return 0; - else if (ret < 0) - goto fail; - - if (s->debug & FF_FDEBUG_TS) - av_log(s, AV_LOG_DEBUG, "av_interleaved_write_frame size:%d dts:%s pts:%s\n", - pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts)); - -#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX - if ((ret = compute_muxer_pkt_fields(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) - goto fail; -#endif - - if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { - ret = AVERROR(EINVAL); - goto fail; - } + return write_packets_common(s, st, pkt, 1/*interleaved*/); } else { av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n"); - flush = 1; + return interleaved_write_packet(s, NULL, 1/*flush*/); } - return interleaved_write_packet(s, pkt, flush); fail: av_packet_unref(pkt); From patchwork Sat Mar 28 18:15:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 18468 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 EDF6144B3B0 for ; Sat, 28 Mar 2020 20:15:45 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D9D9E68B614; Sat, 28 Mar 2020 20:15:45 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 199B768B4A2 for ; Sat, 28 Mar 2020 20:15:40 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 7955BE1D61; Sat, 28 Mar 2020 19:15:39 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7NM_K6qBZtdy; Sat, 28 Mar 2020 19:15:38 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 74E16E33DE; Sat, 28 Mar 2020 19:15:37 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Mar 2020 19:15:12 +0100 Message-Id: <20200328181515.5333-5-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200328181515.5333-1-cus@passwd.hu> References: <20200328181515.5333-1-cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 5/8] avformat/mux: add proper support for full N:M bitstream filtering 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Previously only 1:1 bitstream filters were supported, the end of the stream was not signalled to the bitstream filters and time base changes were ignored. Signed-off-by: Marton Balint --- libavformat/internal.h | 1 + libavformat/mux.c | 128 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 91 insertions(+), 38 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index 332477a532..45aeef717a 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -158,6 +158,7 @@ struct AVStreamInternal { */ AVBSFContext **bsfcs; int nb_bsfcs; + int bsfcs_idx; /** * Whether or not check_bitstream should still be run on each packet diff --git a/libavformat/mux.c b/libavformat/mux.c index 8c2d6a8060..3054ab8644 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -840,14 +840,48 @@ static int prepare_input_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) { - AVStream *st = s->streams[pkt->stream_index]; - int i, ret; +static int auto_bsf_receive_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt) +{ + AVStreamInternal *sti = st->internal; + int ret = AVERROR(EAGAIN); + int eof = 0; + + while (sti->bsfcs_idx) { + /* get a packet from the previous filter up the chain */ + ret = av_bsf_receive_packet(sti->bsfcs[sti->bsfcs_idx - 1], pkt); + if (ret == AVERROR(EAGAIN)) { + sti->bsfcs_idx--; + continue; + } else if (ret == AVERROR_EOF) { + eof = 1; + } else if (ret < 0) + break; + + /* send it to the next filter down the chain */ + if (sti->bsfcs_idx < sti->nb_bsfcs) { + ret = av_bsf_send_packet(sti->bsfcs[sti->bsfcs_idx], eof ? NULL : pkt); + av_assert2(ret != AVERROR(EAGAIN)); + if (ret < 0) + break; + sti->bsfcs_idx++; + eof = 0; + } else if (eof) { + break; + } else { + return 0; + } + } + + return ret; +} + +static int need_auto_bsf(AVFormatContext *s, AVStream *st, AVPacket *pkt) { + int ret; if (!(s->flags & AVFMT_FLAG_AUTO_BSF)) - return 1; + return 0; - if (s->oformat->check_bitstream) { + if (pkt && s->oformat->check_bitstream) { if (!st->internal->bitstream_checked) { if ((ret = s->oformat->check_bitstream(s, pkt)) < 0) return ret; @@ -856,31 +890,7 @@ static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) { } } - for (i = 0; i < st->internal->nb_bsfcs; i++) { - AVBSFContext *ctx = st->internal->bsfcs[i]; - // TODO: when any bitstream filter requires flushing at EOF, we'll need to - // flush each stream's BSF chain on write_trailer. - if ((ret = av_bsf_send_packet(ctx, pkt)) < 0) { - av_log(ctx, AV_LOG_ERROR, - "Failed to send packet to filter %s for stream %d\n", - ctx->filter->name, pkt->stream_index); - return ret; - } - // TODO: when any automatically-added bitstream filter is generating multiple - // output packets for a single input one, we'll need to call this in a loop - // and write each output packet. - if ((ret = av_bsf_receive_packet(ctx, pkt)) < 0) { - if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) - return 0; - av_log(ctx, AV_LOG_ERROR, - "Failed to receive packet from filter %s for stream %d\n", - ctx->filter->name, pkt->stream_index); - if (s->error_recognition & AV_EF_EXPLODE) - return ret; - return 0; - } - } - return 1; + return st->internal->nb_bsfcs; } static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush); @@ -909,19 +919,54 @@ static int write_packet_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, static int write_packets_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, int interleaved) { - int ret = do_packet_auto_bsf(s, pkt); - if (ret == 0) - return 0; - else if (ret < 0) + AVStreamInternal *sti = st->internal; + int ret; + + ret = need_auto_bsf(s, st, pkt); + if (ret < 0) goto fail; - ret = write_packet_common(s, st, pkt, interleaved); + if (ret) { + AVPacket opkt = {0}; + int consumed_packet = 0; + + do { + ret = auto_bsf_receive_packet(s, st, &opkt); + if (ret < 0) { + if (ret == AVERROR(EAGAIN) && !consumed_packet) { + av_assert2(sti->bsfcs_idx == 0); + ret = av_bsf_send_packet(sti->bsfcs[0], pkt); + av_assert2(ret != AVERROR(EAGAIN)); + if (ret >= 0) { + consumed_packet = 1; + sti->bsfcs_idx = 1; + continue; + } + } + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + ret = 0; + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Error applying bitstream filters to an output " + "packet for stream #%d: %s\n", st->index, av_err2str(ret)); + if (!(s->error_recognition & AV_EF_EXPLODE)) + ret = 0; + } + goto fail; + } + av_packet_rescale_ts(&opkt, sti->bsfcs[sti->nb_bsfcs-1]->time_base_out, st->time_base); + ret = write_packet_common(s, st, &opkt, interleaved); + if (!interleaved) + av_packet_unref(&opkt); + } while (ret >= 0); + } else { + ret = pkt ? write_packet_common(s, st, pkt, interleaved) : 0; + } if (ret < 0) goto fail; return ret; fail: - if (interleaved) + if (interleaved && pkt) av_packet_unref(pkt); return ret; } @@ -1264,9 +1309,16 @@ fail: int av_write_trailer(AVFormatContext *s) { - int ret, i; + int i, ret1, ret = 0; - ret = interleaved_write_packet(s, NULL, 1); + for (i = 0; i < s->nb_streams; i++) { + ret1 = write_packets_common(s, s->streams[i], NULL, 1/*interleaved*/); + if (ret >= 0) + ret = ret1; + } + ret1 = interleaved_write_packet(s, NULL, 1); + if (ret >= 0) + ret = ret1; if (s->oformat->write_trailer) { if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) From patchwork Sat Mar 28 18:15:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 18469 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 BAEC04400C2 for ; Sat, 28 Mar 2020 20:15:47 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A00DC68B6AB; Sat, 28 Mar 2020 20:15:47 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2865B68B4A2 for ; Sat, 28 Mar 2020 20:15:42 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 13AFDE3517; Sat, 28 Mar 2020 19:15:42 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hx9p70glfDzc; Sat, 28 Mar 2020 19:15:40 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id B4518E33DE; Sat, 28 Mar 2020 19:15:40 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Mar 2020 19:15:13 +0100 Message-Id: <20200328181515.5333-6-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200328181515.5333-1-cus@passwd.hu> References: <20200328181515.5333-1-cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 6/8] avformat/mux: do not destroy packets of av_write_frame on bitstream filtering 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" av_write_frame() does not take ownership of the packet. Signed-off-by: Marton Balint --- libavformat/mux.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index 3054ab8644..706fdcbbf4 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -935,7 +935,16 @@ static int write_packets_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, if (ret < 0) { if (ret == AVERROR(EAGAIN) && !consumed_packet) { av_assert2(sti->bsfcs_idx == 0); - ret = av_bsf_send_packet(sti->bsfcs[0], pkt); + if (!interleaved && pkt) { + AVPacket tmp; + ret = av_packet_ref(&tmp, pkt); + if (ret < 0) + goto fail; + ret = av_bsf_send_packet(sti->bsfcs[0], &tmp); + av_packet_unref(&tmp); + } else { + ret = av_bsf_send_packet(sti->bsfcs[0], pkt); + } av_assert2(ret != AVERROR(EAGAIN)); if (ret >= 0) { consumed_packet = 1; From patchwork Sat Mar 28 18:15:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 18470 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 7366744936F for ; Sat, 28 Mar 2020 20:15:48 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 62E5B68B6C5; Sat, 28 Mar 2020 20:15:48 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 64C9668B4A2 for ; Sat, 28 Mar 2020 20:15:47 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 3C24EE33DE; Sat, 28 Mar 2020 19:15:47 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aRpl-pKvpddu; Sat, 28 Mar 2020 19:15:45 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 39F46E3F2B; Sat, 28 Mar 2020 19:15:43 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Mar 2020 19:15:14 +0100 Message-Id: <20200328181515.5333-7-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200328181515.5333-1-cus@passwd.hu> References: <20200328181515.5333-1-cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 7/8] avcodec/pcm_rechunk_bsf: add bitstream filter to rechunk pcm audio 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Marton Balint --- Changelog | 1 + doc/bitstream_filters.texi | 30 ++++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/pcm_rechunk_bsf.c | 206 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 4 +- 6 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 libavcodec/pcm_rechunk_bsf.c diff --git a/Changelog b/Changelog index 05b9a84562..dddaf02199 100644 --- a/Changelog +++ b/Changelog @@ -55,6 +55,7 @@ version : - CRI HCA decoder - CRI HCA demuxer - overlay_cuda filter +- pcm_rechunk bitstream filter version 4.2: diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 8fe5b3ad75..70c276feed 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -548,6 +548,36 @@ ffmpeg -i INPUT -c copy -bsf noise[=1] output.mkv @section null This bitstream filter passes the packets through unchanged. +@section pcm_rechunk + +Repacketize PCM audio to a fixed number of samples per packet or a fixed packet +rate per second. This is similar to the @ref{asetnsamples,,asetnsamples audio +filter,ffmpeg-filters} but works on audio packets instead of audio frames. + +@table @option +@item nb_out_samples, n +Set the number of samples per each output audio packet. The number is intended +as the number of samples @emph{per each channel}. Default value is 1024. + +@item pad, p +If set to 1, the filter will pad the last audio packet with silence, so that it +will contain the same number of samples (or roughly the same number of samples, +see @option{frame_rate}) as the previous ones. Default value is 1. + +@item frame_rate, r +This option makes the filter output a fixed numer of packets per second instead +of a fixed number of samples per packet. If the audio sample rate is not +divisible by the frame rate then the number of samples will not be constant but +will vary slightly so that each packet will start as close as to the frame +boundary as possible. Using this option has precedence over @option{nb_out_samples}. +@end table + +You can generate the well known 1602-1601-1602-1601-1602 pattern of 48kHz audio +for NTSC frame rate using the @option{frame_rate} option. +@example +ffmpeg -f lavfi -i sine=r=48000:d=1 -c pcm_s16le -bsf pcm_rechunk=r=30000/1001 -f framecrc - +@end example + @section prores_metadata Modify color property metadata embedded in prores stream. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index c1c9a44f2b..a49391f97f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1110,6 +1110,7 @@ OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \ OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o +OBJS-$(CONFIG_PCM_RECHUNK_BSF) += pcm_rechunk_bsf.o OBJS-$(CONFIG_PRORES_METADATA_BSF) += prores_metadata_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 6b5ffe4d70..9e701191f8 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -49,6 +49,7 @@ extern const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf; extern const AVBitStreamFilter ff_mov2textsub_bsf; extern const AVBitStreamFilter ff_noise_bsf; extern const AVBitStreamFilter ff_null_bsf; +extern const AVBitStreamFilter ff_pcm_rechunk_bsf; extern const AVBitStreamFilter ff_prores_metadata_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; diff --git a/libavcodec/pcm_rechunk_bsf.c b/libavcodec/pcm_rechunk_bsf.c new file mode 100644 index 0000000000..e02a205eb6 --- /dev/null +++ b/libavcodec/pcm_rechunk_bsf.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2020 Marton Balint + * + * 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 "libavutil/avassert.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +typedef struct PCMContext { + const AVClass *class; + + int nb_out_samples; + int pad; + AVRational frame_rate; + + AVPacket *in_pkt; + AVPacket *out_pkt; + int sample_size; + int max_packet_size; + int64_t n; + int64_t dts; +} PCMContext; + +static int init(AVBSFContext *ctx) +{ + PCMContext *s = ctx->priv_data; + AVRational sr = av_make_q(ctx->par_in->sample_rate, 1); + int64_t max_samples; + + ctx->time_base_out = av_inv_q(sr); + s->in_pkt = av_packet_alloc(); + s->out_pkt = av_packet_alloc(); + if (!s->in_pkt || !s->out_pkt) + return AVERROR(ENOMEM); + + s->sample_size = ctx->par_in->channels * av_get_bits_per_sample(ctx->par_in->codec_id) / 8; + + if (s->frame_rate.num) { + if (av_rescale_q_rnd(1, sr, s->frame_rate, AV_ROUND_DOWN) <= 0) + return AVERROR(EINVAL); + max_samples = av_rescale_q_rnd(1, sr, s->frame_rate, AV_ROUND_UP); + } else { + max_samples = s->nb_out_samples; + } + if (max_samples > INT_MAX / s->sample_size) + return AVERROR(EINVAL); + + s->max_packet_size = max_samples * s->sample_size; + return 0; +} + +static void uninit(AVBSFContext *ctx) +{ + PCMContext *s = ctx->priv_data; + av_packet_free(&s->in_pkt); + av_packet_free(&s->out_pkt); +} + +static void flush(AVBSFContext *ctx) +{ + PCMContext *s = ctx->priv_data; + av_packet_unref(s->in_pkt); + av_packet_unref(s->out_pkt); + s->n = 0; + s->dts = 0; +} + +static int send_packet(PCMContext *s, int nb_samples, AVPacket *pkt) +{ + pkt->dts = pkt->pts = s->dts; + pkt->duration = nb_samples; + s->dts += nb_samples; + s->n++; + return 0; +} + +static int rechunk_filter(AVBSFContext *ctx, AVPacket *pkt) +{ + PCMContext *s = ctx->priv_data; + AVRational sr = av_make_q(ctx->par_in->sample_rate, 1); + int nb_samples = s->frame_rate.num ? (av_rescale_q(s->n + 1, sr, s->frame_rate) - s->dts) : s->nb_out_samples; + int data_size = nb_samples * s->sample_size; + int ret; + + if (!s->out_pkt->data) { + ret = av_new_packet(s->out_pkt, s->max_packet_size); + if (ret < 0) + return ret; + s->out_pkt->size = 0; + } + + do { + if (s->in_pkt->size) { + if (s->out_pkt->size || s->in_pkt->size < data_size) { + int drain = FFMIN(s->in_pkt->size, data_size - s->out_pkt->size); + if (!s->out_pkt->size) { + ret = av_packet_copy_props(s->out_pkt, s->in_pkt); + if (ret < 0) + return ret; + } + memcpy(s->out_pkt->data + s->out_pkt->size, s->in_pkt->data, drain); + s->out_pkt->size += drain; + s->in_pkt->size -= drain; + s->in_pkt->data += drain; + if (s->out_pkt->size == data_size) { + av_packet_move_ref(pkt, s->out_pkt); + return send_packet(s, nb_samples, pkt); + } + av_packet_unref(s->in_pkt); + } else if (s->in_pkt->size > data_size) { + ret = av_packet_ref(pkt, s->in_pkt); + if (ret < 0) + return ret; + pkt->size = data_size; + s->in_pkt->size -= data_size; + s->in_pkt->data += data_size; + return send_packet(s, nb_samples, pkt); + } else { + av_assert0(s->in_pkt->size == data_size); + av_packet_move_ref(pkt, s->in_pkt); + return send_packet(s, nb_samples, pkt); + } + } + + ret = ff_bsf_get_packet_ref(ctx, s->in_pkt); + if (ret == AVERROR_EOF && s->out_pkt->size) { + if (s->pad) { + memset(s->out_pkt->data + s->out_pkt->size, 0, data_size - s->out_pkt->size); + s->out_pkt->size = data_size; + } else { + nb_samples = s->out_pkt->size / s->sample_size; + } + av_packet_move_ref(pkt, s->out_pkt); + return send_packet(s, nb_samples, pkt); + } + } while (ret >= 0); + + return ret; +} + +#define OFFSET(x) offsetof(PCMContext, x) +#define FLAGS (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_BSF_PARAM) +static const AVOption options[] = { + { "nb_out_samples", "set the number of per-packet output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS }, + { "n", "set the number of per-packet output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS }, + { "pad", "pad last packet with zeros", OFFSET(pad), AV_OPT_TYPE_BOOL, {.i64=1} , 0, 1, FLAGS }, + { "p", "pad last packet with zeros", OFFSET(pad), AV_OPT_TYPE_BOOL, {.i64=1} , 0, 1, FLAGS }, + { "frame_rate", "set number of packets per second", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS }, + { "r", "set number of packets per second", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS }, + { NULL }, +}; + +static const AVClass metadata_class = { + .class_name = "pcm_rechunk_bsf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_PCM_S16LE, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_S64LE, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_pcm_rechunk_bsf = { + .name = "pcm_rechunk", + .priv_data_size = sizeof(PCMContext), + .priv_class = &metadata_class, + .filter = rechunk_filter, + .init = init, + .flush = flush, + .close = uninit, + .codec_ids = codec_ids, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index f4d1d4de21..e62d1a7925 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 77 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 78 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From patchwork Sat Mar 28 18:15:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 18471 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 39F97448EC3 for ; Sat, 28 Mar 2020 20:15:54 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1DF7E68B6D0; Sat, 28 Mar 2020 20:15:54 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 139CC68B4BF for ; Sat, 28 Mar 2020 20:15:53 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id E8724E3517; Sat, 28 Mar 2020 19:15:52 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id LDk8knkdPdo4; Sat, 28 Mar 2020 19:15:50 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 215E2E33DE; Sat, 28 Mar 2020 19:15:50 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Mar 2020 19:15:15 +0100 Message-Id: <20200328181515.5333-8-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200328181515.5333-1-cus@passwd.hu> References: <20200328181515.5333-1-cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 8/8] avformat/audiointerleave: only keep the retime functionality of the audio interleaver 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" And rename it to retimeinterleave, use the pcm_rechunk bitstream filter for rechunking. By seperating the two functions we hopefully get cleaner code. Signed-off-by: Marton Balint --- configure | 2 + libavformat/Makefile | 4 +- libavformat/audiointerleave.c | 148 --------------------- libavformat/gxfenc.c | 29 ++-- libavformat/mux.c | 1 - libavformat/mxfenc.c | 32 +++-- libavformat/retimeinterleave.c | 51 +++++++ .../{audiointerleave.h => retimeinterleave.h} | 31 ++--- libavformat/utils.c | 1 - 9 files changed, 111 insertions(+), 188 deletions(-) delete mode 100644 libavformat/audiointerleave.c create mode 100644 libavformat/retimeinterleave.c rename libavformat/{audiointerleave.h => retimeinterleave.h} (57%) diff --git a/configure b/configure index 21827eeb45..0640514a53 100755 --- a/configure +++ b/configure @@ -2722,6 +2722,7 @@ fraps_decoder_select="bswapdsp huffman" g2m_decoder_deps="zlib" g2m_decoder_select="blockdsp idctdsp jpegtables" g729_decoder_select="audiodsp" +gxf_encoder_select="pcm_rechunk_bsf" h261_decoder_select="mpegvideo" h261_encoder_select="mpegvideoenc" h263_decoder_select="h263_parser h263dsp mpegvideo qpeldsp" @@ -2793,6 +2794,7 @@ mts2_decoder_select="mss34dsp" mvha_decoder_deps="zlib" mvha_decoder_select="llviddsp" mwsc_decoder_deps="zlib" +mxf_encoder_select="pcm_rechunk_bsf" mxpeg_decoder_select="mjpeg_decoder" nellymoser_decoder_select="mdct sinewin" nellymoser_encoder_select="audio_frame_queue mdct sinewin" diff --git a/libavformat/Makefile b/libavformat/Makefile index 8fd0d43721..017b230baa 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -205,7 +205,7 @@ OBJS-$(CONFIG_GIF_DEMUXER) += gifdec.o OBJS-$(CONFIG_GSM_DEMUXER) += gsmdec.o OBJS-$(CONFIG_GSM_MUXER) += rawenc.o OBJS-$(CONFIG_GXF_DEMUXER) += gxf.o -OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o audiointerleave.o +OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o retimeinterleave.o OBJS-$(CONFIG_G722_DEMUXER) += g722.o rawdec.o OBJS-$(CONFIG_G722_MUXER) += rawenc.o OBJS-$(CONFIG_G723_1_DEMUXER) += g723_1.o @@ -347,7 +347,7 @@ OBJS-$(CONFIG_MUSX_DEMUXER) += musx.o OBJS-$(CONFIG_MV_DEMUXER) += mvdec.o OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxf.o -OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o audiointerleave.o avc.o +OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o retimeinterleave.o avc.o OBJS-$(CONFIG_MXG_DEMUXER) += mxg.o OBJS-$(CONFIG_NC_DEMUXER) += ncdec.o OBJS-$(CONFIG_NISTSPHERE_DEMUXER) += nistspheredec.o pcm.o diff --git a/libavformat/audiointerleave.c b/libavformat/audiointerleave.c deleted file mode 100644 index 2e83031bd6..0000000000 --- a/libavformat/audiointerleave.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Audio Interleaving functions - * - * Copyright (c) 2009 Baptiste Coudurier - * - * 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 "libavutil/fifo.h" -#include "libavutil/mathematics.h" -#include "avformat.h" -#include "audiointerleave.h" -#include "internal.h" - -void ff_audio_interleave_close(AVFormatContext *s) -{ - int i; - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - AudioInterleaveContext *aic = st->priv_data; - - if (aic && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) - av_fifo_freep(&aic->fifo); - } -} - -int ff_audio_interleave_init(AVFormatContext *s, - const int samples_per_frame, - AVRational time_base) -{ - int i; - - if (!time_base.num) { - av_log(s, AV_LOG_ERROR, "timebase not set for audio interleave\n"); - return AVERROR(EINVAL); - } - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - AudioInterleaveContext *aic = st->priv_data; - - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - int max_samples = samples_per_frame ? samples_per_frame : - av_rescale_rnd(st->codecpar->sample_rate, time_base.num, time_base.den, AV_ROUND_UP); - aic->sample_size = (st->codecpar->channels * - av_get_bits_per_sample(st->codecpar->codec_id)) / 8; - if (!aic->sample_size) { - av_log(s, AV_LOG_ERROR, "could not compute sample size\n"); - return AVERROR(EINVAL); - } - aic->samples_per_frame = samples_per_frame; - aic->time_base = time_base; - - if (!(aic->fifo = av_fifo_alloc_array(100, max_samples))) - return AVERROR(ENOMEM); - aic->fifo_size = 100 * max_samples; - } - } - - return 0; -} - -static int interleave_new_audio_packet(AVFormatContext *s, AVPacket *pkt, - int stream_index, int flush) -{ - AVStream *st = s->streams[stream_index]; - AudioInterleaveContext *aic = st->priv_data; - int ret; - int nb_samples = aic->samples_per_frame ? aic->samples_per_frame : - (av_rescale_q(aic->n + 1, av_make_q(st->codecpar->sample_rate, 1), av_inv_q(aic->time_base)) - aic->nb_samples); - int frame_size = nb_samples * aic->sample_size; - int size = FFMIN(av_fifo_size(aic->fifo), frame_size); - if (!size || (!flush && size == av_fifo_size(aic->fifo))) - return 0; - - ret = av_new_packet(pkt, frame_size); - if (ret < 0) - return ret; - av_fifo_generic_read(aic->fifo, pkt->data, size, NULL); - - if (size < pkt->size) - memset(pkt->data + size, 0, pkt->size - size); - - pkt->dts = pkt->pts = aic->dts; - pkt->duration = av_rescale_q(nb_samples, st->time_base, aic->time_base); - pkt->stream_index = stream_index; - aic->dts += pkt->duration; - aic->nb_samples += nb_samples; - aic->n++; - - return pkt->size; -} - -int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush, - int (*get_packet)(AVFormatContext *, AVPacket *, AVPacket *, int), - int (*compare_ts)(AVFormatContext *, const AVPacket *, const AVPacket *)) -{ - int i, ret; - - if (pkt) { - AVStream *st = s->streams[pkt->stream_index]; - AudioInterleaveContext *aic = st->priv_data; - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - unsigned new_size = av_fifo_size(aic->fifo) + pkt->size; - if (new_size > aic->fifo_size) { - if (av_fifo_realloc2(aic->fifo, new_size) < 0) - return AVERROR(ENOMEM); - aic->fifo_size = new_size; - } - av_fifo_generic_write(aic->fifo, pkt->data, pkt->size, NULL); - } else { - // rewrite pts and dts to be decoded time line position - pkt->pts = pkt->dts = aic->dts; - aic->dts += pkt->duration; - if ((ret = ff_interleave_add_packet(s, pkt, compare_ts)) < 0) - return ret; - } - pkt = NULL; - } - - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - AVPacket new_pkt = { 0 }; - while ((ret = interleave_new_audio_packet(s, &new_pkt, i, flush)) > 0) { - if ((ret = ff_interleave_add_packet(s, &new_pkt, compare_ts)) < 0) - return ret; - } - if (ret < 0) - return ret; - } - } - - return get_packet(s, out, NULL, flush); -} diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index e7536a6a7e..e95ae99cba 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -27,7 +27,7 @@ #include "avformat.h" #include "internal.h" #include "gxf.h" -#include "audiointerleave.h" +#include "retimeinterleave.h" #define GXF_AUDIO_PACKET_SIZE 65536 @@ -44,7 +44,7 @@ typedef struct GXFTimecode{ } GXFTimecode; typedef struct GXFStreamContext { - AudioInterleaveContext aic; + RetimeInterleaveContext aic; uint32_t track_type; uint32_t sample_size; uint32_t sample_rate; @@ -813,14 +813,12 @@ static int gxf_write_header(AVFormatContext *s) return -1; } } + ff_retime_interleave_init(&sc->aic, st->time_base); /* FIXME first 10 audio tracks are 0 to 9 next 22 are A to V */ sc->media_info = media_info<<8 | ('0'+tracks[media_info]++); sc->order = s->nb_streams - st->index; } - if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0) - return -1; - if (tcr && vsc) gxf_init_timecode(s, &gxf->tc, tcr->value, vsc->fields); @@ -877,8 +875,6 @@ static void gxf_deinit(AVFormatContext *s) { GXFContext *gxf = s->priv_data; - ff_audio_interleave_close(s); - av_freep(&gxf->flt_entries); av_freep(&gxf->map_offsets); } @@ -1016,8 +1012,22 @@ static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pk { if (pkt && s->streams[pkt->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) pkt->duration = 2; // enforce 2 fields - return ff_audio_rechunk_interleave(s, out, pkt, flush, - ff_interleave_packet_per_dts, gxf_compare_field_nb); + return ff_retime_interleave(s, out, pkt, flush, + ff_interleave_packet_per_dts, gxf_compare_field_nb); +} + +static int gxf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +{ + int ret = 1; + AVStream *st = s->streams[pkt->stream_index]; + + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + char arg[32]; + snprintf(arg, sizeof(arg), "n=%d", GXF_samples_per_frame); + ret = ff_stream_add_bitstream_filter(st, "pcm_rechunk", arg); + } + + return ret; } AVOutputFormat ff_gxf_muxer = { @@ -1031,5 +1041,6 @@ AVOutputFormat ff_gxf_muxer = { .write_packet = gxf_write_packet, .write_trailer = gxf_write_trailer, .deinit = gxf_deinit, + .check_bitstream = gxf_check_bitstream, .interleave_packet = gxf_interleave_packet, }; diff --git a/libavformat/mux.c b/libavformat/mux.c index 706fdcbbf4..278e760aab 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -37,7 +37,6 @@ #include "libavutil/parseutils.h" #include "libavutil/time.h" #include "riff.h" -#include "audiointerleave.h" #include "url.h" #include #if CONFIG_NETWORK diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index bfce531f54..d381821116 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -52,7 +52,7 @@ #include "libavcodec/h264_ps.h" #include "libavcodec/golomb.h" #include "libavcodec/internal.h" -#include "audiointerleave.h" +#include "retimeinterleave.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -79,7 +79,7 @@ typedef struct MXFIndexEntry { } MXFIndexEntry; typedef struct MXFStreamContext { - AudioInterleaveContext aic; + RetimeInterleaveContext aic; UID track_essence_element_key; int index; ///< index in mxf_essence_container_uls table const UID *codec_ul; @@ -2593,6 +2593,7 @@ static int mxf_write_header(AVFormatContext *s) return -1; } } + ff_retime_interleave_init(&sc->aic, av_inv_q(mxf->tc.rate)); if (sc->index == -1) { sc->index = mxf_get_essence_container_ul_index(st->codecpar->codec_id); @@ -2646,9 +2647,6 @@ static int mxf_write_header(AVFormatContext *s) return AVERROR(ENOMEM); mxf->timecode_track->index = -1; - if (ff_audio_interleave_init(s, 0, av_inv_q(mxf->tc.rate)) < 0) - return -1; - return 0; } @@ -3010,8 +3008,6 @@ static void mxf_deinit(AVFormatContext *s) { MXFContext *mxf = s->priv_data; - ff_audio_interleave_close(s); - av_freep(&mxf->index_entries); av_freep(&mxf->body_partition_offset); if (mxf->timecode_track) { @@ -3087,8 +3083,23 @@ static int mxf_compare_timestamps(AVFormatContext *s, const AVPacket *next, static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) { - return ff_audio_rechunk_interleave(s, out, pkt, flush, - mxf_interleave_get_packet, mxf_compare_timestamps); + return ff_retime_interleave(s, out, pkt, flush, + mxf_interleave_get_packet, mxf_compare_timestamps); +} + +static int mxf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +{ + int ret = 1; + AVStream *st = s->streams[pkt->stream_index]; + MXFStreamContext *sc = st->priv_data; + + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + char arg[32]; + snprintf(arg, sizeof(arg), "r=%d/%d", sc->aic.time_base.den, sc->aic.time_base.num); + ret = ff_stream_add_bitstream_filter(st, "pcm_rechunk", arg); + } + + return ret; } #define MXF_COMMON_OPTIONS \ @@ -3171,6 +3182,7 @@ AVOutputFormat ff_mxf_muxer = { .deinit = mxf_deinit, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, + .check_bitstream = mxf_check_bitstream, .priv_class = &mxf_muxer_class, }; @@ -3187,6 +3199,7 @@ AVOutputFormat ff_mxf_d10_muxer = { .deinit = mxf_deinit, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, + .check_bitstream = mxf_check_bitstream, .priv_class = &mxf_d10_muxer_class, }; @@ -3204,5 +3217,6 @@ AVOutputFormat ff_mxf_opatom_muxer = { .deinit = mxf_deinit, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, + .check_bitstream = mxf_check_bitstream, .priv_class = &mxf_opatom_muxer_class, }; diff --git a/libavformat/retimeinterleave.c b/libavformat/retimeinterleave.c new file mode 100644 index 0000000000..9f874e3626 --- /dev/null +++ b/libavformat/retimeinterleave.c @@ -0,0 +1,51 @@ +/* + * Retime Interleaving functions + * + * Copyright (c) 2009 Baptiste Coudurier + * + * 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 "libavutil/mathematics.h" +#include "avformat.h" +#include "retimeinterleave.h" +#include "internal.h" + +void ff_retime_interleave_init(RetimeInterleaveContext *aic, AVRational time_base) +{ + aic->time_base = time_base; +} + +int ff_retime_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush, + int (*get_packet)(AVFormatContext *, AVPacket *, AVPacket *, int), + int (*compare_ts)(AVFormatContext *, const AVPacket *, const AVPacket *)) +{ + int ret; + + if (pkt) { + AVStream *st = s->streams[pkt->stream_index]; + RetimeInterleaveContext *aic = st->priv_data; + pkt->duration = av_rescale_q(pkt->duration, st->time_base, aic->time_base); + // rewrite pts and dts to be decoded time line position + pkt->pts = pkt->dts = aic->dts; + aic->dts += pkt->duration; + if ((ret = ff_interleave_add_packet(s, pkt, compare_ts)) < 0) + return ret; + } + + return get_packet(s, out, NULL, flush); +} diff --git a/libavformat/audiointerleave.h b/libavformat/retimeinterleave.h similarity index 57% rename from libavformat/audiointerleave.h rename to libavformat/retimeinterleave.h index 0933310f4c..de0a7442b0 100644 --- a/libavformat/audiointerleave.h +++ b/libavformat/retimeinterleave.h @@ -20,36 +20,31 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVFORMAT_AUDIOINTERLEAVE_H -#define AVFORMAT_AUDIOINTERLEAVE_H +#ifndef AVFORMAT_RETIMEINTERLEAVE_H +#define AVFORMAT_RETIMEINTERLEAVE_H -#include "libavutil/fifo.h" #include "avformat.h" -typedef struct AudioInterleaveContext { - AVFifoBuffer *fifo; - unsigned fifo_size; ///< size of currently allocated FIFO - int64_t n; ///< number of generated packets - int64_t nb_samples; ///< number of generated samples +typedef struct RetimeInterleaveContext { uint64_t dts; ///< current dts - int sample_size; ///< size of one sample all channels included - int samples_per_frame; ///< samples per frame if fixed, 0 otherwise - AVRational time_base; ///< time base of output audio packets -} AudioInterleaveContext; + AVRational time_base; ///< time base of output packets +} RetimeInterleaveContext; -int ff_audio_interleave_init(AVFormatContext *s, const int samples_per_frame, AVRational time_base); -void ff_audio_interleave_close(AVFormatContext *s); +/** + * Init the retime interleave context + */ +void ff_retime_interleave_init(RetimeInterleaveContext *aic, AVRational time_base); /** - * Rechunk audio PCM packets per AudioInterleaveContext->samples_per_frame - * and interleave them correctly. - * The first element of AVStream->priv_data must be AudioInterleaveContext + * Retime packets per RetimeInterleaveContext->time_base and interleave them + * correctly. + * The first element of AVStream->priv_data must be RetimeInterleaveContext * when using this function. * * @param get_packet function will output a packet when streams are correctly interleaved. * @param compare_ts function will compare AVPackets and decide interleaving order. */ -int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush, +int ff_retime_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush, int (*get_packet)(AVFormatContext *, AVPacket *, AVPacket *, int), int (*compare_ts)(AVFormatContext *, const AVPacket *, const AVPacket *)); diff --git a/libavformat/utils.c b/libavformat/utils.c index a58e47fabc..1ab3d416fc 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -41,7 +41,6 @@ #include "libavcodec/internal.h" #include "libavcodec/raw.h" -#include "audiointerleave.h" #include "avformat.h" #include "avio_internal.h" #include "id3v2.h"