From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 0985A47F32 for ; Mon, 6 Nov 2023 15:05:09 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 51D5D68C798; Mon, 6 Nov 2023 17:05:06 +0200 (EET) Received: from mail-qv1-f54.google.com (mail-qv1-f54.google.com [209.85.219.54]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9779168BEFE for ; Mon, 6 Nov 2023 17:04:59 +0200 (EET) Received: by mail-qv1-f54.google.com with SMTP id 6a1803df08f44-670e7ae4a2eso46727816d6.1 for ; Mon, 06 Nov 2023 07:04:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699283097; x=1699887897; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=eddAj+o6uCQb1kAspSResdJUAh+bMZ62UVNWiVpj6Mo=; b=eJBBfZ4xoT2yjesSeux74Q/NCSAjgYefV0PaSa9mOOaFyIprAJl+ZpJqSH1lCYvN6x jO6Nh6jBy/DBXnlCQe88gz2mw6dMB55friq0JsHKKS+LCs7GMffDLJmCXvLOJcU5INPG 7XuSmQI1i12xP0FiPZdE9Q02y+xP5xz5hk2AbY1flD5NuPiPd4gqLdcvqsiGQyhYdDau fcQZitYYCQTbdvNgVMIgsfmY5jutoZioGcQJYrg8K4f0jSa8ZcI7jSLQVcW9YMqMoPV1 iK0haaWfZ+ePEfalkEQKPs0W6GEYaTnCiyvv2+kRAvU8GCUn+73gDJ4XDoG8Wc8w4n92 Aq5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699283097; x=1699887897; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=eddAj+o6uCQb1kAspSResdJUAh+bMZ62UVNWiVpj6Mo=; b=RNuEXX8+tgZIQcpsJTOTtrZi/E6b6QNtaac9M4+y0lyJyIMLYlk7b4PalqbHeaBOPA LO99v7tSbo44dTbBcYI9pWD0mfpPnnfE2NwkRtixSZh06zaumjpcGnqaVumn/1SAKaUn 1C+waqmXE3xYUWsTy9GaBSWphc7xK7qOoNgYFuqbAE+dkthJiojF4cYlFjyuwAsPaKaK kvR7yZcaw8dh1dhn+geVwX55jeOvWRjFyvONUl4DQK49r0Um0C+aIFq5rsbdLE4mtszI mBhZ7OVyOq3F19s+dOMI+YqVGO+O00EdW730eWY3XkePmpzKwzJSv6MPP5U7XsVSVdG5 5Brw== X-Gm-Message-State: AOJu0YxoTq6NokxeSB4kUG49IjOQtQKh8PWy5WhATRjWt0k8Lw4wMhf7 M8nDxS8/l+G4mM1EoDfjyf2M9nQ+dLc= X-Google-Smtp-Source: AGHT+IGmsdycF12MIYJw6ISp/ecNYSp50WEvMmSHHNu8gIiq5NsjRG7wqXAVex+v7U9OlG07rqFvXw== X-Received: by 2002:ad4:5dc9:0:b0:66d:81bb:5234 with SMTP id m9-20020ad45dc9000000b0066d81bb5234mr13256527qvh.11.1699283096082; Mon, 06 Nov 2023 07:04:56 -0800 (PST) Received: from localhost.localdomain (host197.190-225-105.telecom.net.ar. [190.225.105.197]) by smtp.gmail.com with ESMTPSA id nd13-20020a056214420d00b0065b11053445sm3539430qvb.54.2023.11.06.07.04.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Nov 2023 07:04:55 -0800 (PST) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Mon, 6 Nov 2023 12:04:49 -0300 Message-ID: <20231106150449.7898-1-jamrial@gmail.com> X-Mailer: git-send-email 2.42.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avformat: move internal AVStream related functions and structs to a separate header 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 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: Signed-off-by: James Almer --- libavformat/Makefile | 1 + libavformat/avformat.c | 214 -------------------------- libavformat/demux.h | 29 ---- libavformat/internal.h | 291 +---------------------------------- libavformat/stream.c | 243 +++++++++++++++++++++++++++++ libavformat/stream.h | 338 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 583 insertions(+), 533 deletions(-) create mode 100644 libavformat/stream.c create mode 100644 libavformat/stream.h diff --git a/libavformat/Makefile b/libavformat/Makefile index 329055ccfd..7e457d4695 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -27,6 +27,7 @@ OBJS = allformats.o \ riff.o \ sdp.o \ seek.o \ + stream.o \ url.o \ utils.o \ version.o \ diff --git a/libavformat/avformat.c b/libavformat/avformat.c index 5b8bb7879e..437b043ffd 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -40,54 +40,6 @@ #include "mux.h" #include "internal.h" -void ff_free_stream(AVStream **pst) -{ - AVStream *st = *pst; - FFStream *const sti = ffstream(st); - - if (!st) - return; - -#if FF_API_AVSTREAM_SIDE_DATA -FF_DISABLE_DEPRECATION_WARNINGS - for (int i = 0; i < st->nb_side_data; i++) - av_freep(&st->side_data[i].data); - av_freep(&st->side_data); -FF_ENABLE_DEPRECATION_WARNINGS -#endif - - if (st->attached_pic.data) - av_packet_unref(&st->attached_pic); - - av_parser_close(sti->parser); - avcodec_free_context(&sti->avctx); - av_bsf_free(&sti->bsfc); - av_freep(&sti->priv_pts); - av_freep(&sti->index_entries); - av_freep(&sti->probe_data.buf); - - av_bsf_free(&sti->extract_extradata.bsf); - - if (sti->info) { - av_freep(&sti->info->duration_error); - av_freep(&sti->info); - } - - av_dict_free(&st->metadata); - avcodec_parameters_free(&st->codecpar); - av_freep(&st->priv_data); - - av_freep(pst); -} - -void ff_remove_stream(AVFormatContext *s, AVStream *st) -{ - av_assert0(s->nb_streams>0); - av_assert0(s->streams[ s->nb_streams - 1 ] == st); - - ff_free_stream(&s->streams[ --s->nb_streams ]); -} - /* XXX: suppress the packet queue */ void ff_flush_packet_queue(AVFormatContext *s) { @@ -144,140 +96,6 @@ void avformat_free_context(AVFormatContext *s) av_free(s); } -#if FF_API_AVSTREAM_SIDE_DATA -FF_DISABLE_DEPRECATION_WARNINGS -uint8_t *av_stream_get_side_data(const AVStream *st, - enum AVPacketSideDataType type, size_t *size) -{ - for (int i = 0; i < st->nb_side_data; i++) { - if (st->side_data[i].type == type) { - if (size) - *size = st->side_data[i].size; - return st->side_data[i].data; - } - } - if (size) - *size = 0; - return NULL; -} - -int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, - uint8_t *data, size_t size) -{ - AVPacketSideData *sd, *tmp; - - for (int i = 0; i < st->nb_side_data; i++) { - sd = &st->side_data[i]; - - if (sd->type == type) { - av_freep(&sd->data); - sd->data = data; - sd->size = size; - return 0; - } - } - - if (st->nb_side_data + 1U > FFMIN(INT_MAX, SIZE_MAX / sizeof(*tmp))) - return AVERROR(ERANGE); - - tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); - if (!tmp) { - return AVERROR(ENOMEM); - } - - st->side_data = tmp; - st->nb_side_data++; - - sd = &st->side_data[st->nb_side_data - 1]; - sd->type = type; - sd->data = data; - sd->size = size; - - return 0; -} - -uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, - size_t size) -{ - int ret; - uint8_t *data = av_malloc(size); - - if (!data) - return NULL; - - ret = av_stream_add_side_data(st, type, data, size); - if (ret < 0) { - av_freep(&data); - return NULL; - } - - return data; -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif - -/** - * Copy all stream parameters from source to destination stream, with the - * exception of the index field, which is usually set by avformat_new_stream(). - * - * @param dst pointer to destination AVStream - * @param src pointer to source AVStream - * @return >=0 on success, AVERROR code on error - */ -static int stream_params_copy(AVStream *dst, const AVStream *src) -{ - int ret; - - dst->id = src->id; - dst->time_base = src->time_base; - dst->start_time = src->start_time; - dst->duration = src->duration; - dst->nb_frames = src->nb_frames; - dst->disposition = src->disposition; - dst->discard = src->discard; - dst->sample_aspect_ratio = src->sample_aspect_ratio; - dst->avg_frame_rate = src->avg_frame_rate; - dst->event_flags = src->event_flags; - dst->r_frame_rate = src->r_frame_rate; - dst->pts_wrap_bits = src->pts_wrap_bits; - - av_dict_free(&dst->metadata); - ret = av_dict_copy(&dst->metadata, src->metadata, 0); - if (ret < 0) - return ret; - - ret = avcodec_parameters_copy(dst->codecpar, src->codecpar); - if (ret < 0) - return ret; - - av_packet_unref(&dst->attached_pic); - if (src->attached_pic.data) { - ret = av_packet_ref(&dst->attached_pic, &src->attached_pic); - if (ret < 0) - return ret; - } - - return 0; -} - -AVStream *ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src) -{ - AVStream *st; - int ret; - - st = avformat_new_stream(dst_ctx, NULL); - if (!st) - return NULL; - - ret = stream_params_copy(st, src); - if (ret < 0) { - ff_remove_stream(dst_ctx, st); - return NULL; - } - - return st; -} - AVProgram *av_new_program(AVFormatContext *ac, int id) { AVProgram *program = NULL; @@ -752,38 +570,6 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } -AVRational av_stream_get_codec_timebase(const AVStream *st) -{ - // See avformat_transfer_internal_stream_timing_info() TODO. - return cffstream(st)->avctx->time_base; -} - -void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, - unsigned int pts_num, unsigned int pts_den) -{ - FFStream *const sti = ffstream(st); - AVRational new_tb; - if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) { - if (new_tb.num != pts_num) - av_log(NULL, AV_LOG_DEBUG, - "st:%d removing common factor %d from timebase\n", - st->index, pts_num / new_tb.num); - } else - av_log(NULL, AV_LOG_WARNING, - "st:%d has too large timebase, reducing\n", st->index); - - if (new_tb.num <= 0 || new_tb.den <= 0) { - av_log(NULL, AV_LOG_ERROR, - "Ignoring attempt to set invalid timebase %d/%d for st:%d\n", - new_tb.num, new_tb.den, - st->index); - return; - } - st->time_base = new_tb; - sti->avctx->pkt_timebase = new_tb; - st->pts_wrap_bits = pts_wrap_bits; -} - const AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st, enum AVCodecID codec_id) { diff --git a/libavformat/demux.h b/libavformat/demux.h index 1f57e062f6..0682147776 100644 --- a/libavformat/demux.h +++ b/libavformat/demux.h @@ -26,35 +26,6 @@ #include "libavcodec/packet.h" #include "avformat.h" -#define MAX_STD_TIMEBASES (30*12+30+3+6) -typedef struct FFStreamInfo { - int64_t last_dts; - int64_t duration_gcd; - int duration_count; - int64_t rfps_duration_sum; - double (*duration_error)[2][MAX_STD_TIMEBASES]; - int64_t codec_info_duration; - int64_t codec_info_duration_fields; - int frame_delay_evidence; - - /** - * 0 -> decoder has not been searched for yet. - * >0 -> decoder found - * <0 -> decoder with codec_id == -found_decoder has not been found - */ - int found_decoder; - - int64_t last_duration; - - /** - * Those are used for average framerate estimation. - */ - int64_t fps_first_dts; - int fps_first_dts_idx; - int64_t fps_last_dts; - int fps_last_dts_idx; -} FFStreamInfo; - /** * Returned by demuxers to indicate that data was consumed but discarded * (ignored streams or junk data). The framework will re-call the demuxer. diff --git a/libavformat/internal.h b/libavformat/internal.h index 7702986c9c..9996b7a770 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -26,6 +26,7 @@ #include "libavcodec/packet_internal.h" #include "avformat.h" +#include "stream.h" #define MAX_URL_SIZE 4096 @@ -55,18 +56,6 @@ typedef struct CodecMime{ enum AVCodecID id; } CodecMime; -/*************************************************/ -/* fractional numbers for exact pts handling */ - -/** - * The exact value of the fractional number is: 'val + num / den'. - * num is assumed to be 0 <= num < den. - */ -typedef struct FFFrac { - int64_t val, num, den; -} FFFrac; - - typedef struct FFFormatContext { /** * The public context. @@ -196,237 +185,6 @@ static av_always_inline FFFormatContext *ffformatcontext(AVFormatContext *s) return (FFFormatContext*)s; } -typedef struct FFStream { - /** - * The public context. - */ - AVStream pub; - - /** - * Set to 1 if the codec allows reordering, so pts can be different - * from dts. - */ - int reorder; - - /** - * bitstream filter to run on stream - * - encoding: Set by muxer using ff_stream_add_bitstream_filter - * - decoding: unused - */ - struct AVBSFContext *bsfc; - - /** - * Whether or not check_bitstream should still be run on each packet - */ - int bitstream_checked; - - /** - * The codec context used by avformat_find_stream_info, the parser, etc. - */ - struct AVCodecContext *avctx; - /** - * 1 if avctx has been initialized with the values from the codec parameters - */ - int avctx_inited; - - /* the context for extracting extradata in find_stream_info() - * inited=1/bsf=NULL signals that extracting is not possible (codec not - * supported) */ - struct { - struct AVBSFContext *bsf; - int inited; - } extract_extradata; - - /** - * Whether the internal avctx needs to be updated from codecpar (after a late change to codecpar) - */ - int need_context_update; - - int is_intra_only; - - FFFrac *priv_pts; - - /** - * Stream information used internally by avformat_find_stream_info() - */ - struct FFStreamInfo *info; - - AVIndexEntry *index_entries; /**< Only used if the format does not - support seeking natively. */ - int nb_index_entries; - unsigned int index_entries_allocated_size; - - int64_t interleaver_chunk_size; - int64_t interleaver_chunk_duration; - - /** - * stream probing state - * -1 -> probing finished - * 0 -> no probing requested - * rest -> perform probing with request_probe being the minimum score to accept. - */ - int request_probe; - /** - * Indicates that everything up to the next keyframe - * should be discarded. - */ - int skip_to_keyframe; - - /** - * Number of samples to skip at the start of the frame decoded from the next packet. - */ - int skip_samples; - - /** - * If not 0, the number of samples that should be skipped from the start of - * the stream (the samples are removed from packets with pts==0, which also - * assumes negative timestamps do not happen). - * Intended for use with formats such as mp3 with ad-hoc gapless audio - * support. - */ - int64_t start_skip_samples; - - /** - * If not 0, the first audio sample that should be discarded from the stream. - * This is broken by design (needs global sample count), but can't be - * avoided for broken by design formats such as mp3 with ad-hoc gapless - * audio support. - */ - int64_t first_discard_sample; - - /** - * The sample after last sample that is intended to be discarded after - * first_discard_sample. Works on frame boundaries only. Used to prevent - * early EOF if the gapless info is broken (considered concatenated mp3s). - */ - int64_t last_discard_sample; - - /** - * Number of internally decoded frames, used internally in libavformat, do not access - * its lifetime differs from info which is why it is not in that structure. - */ - int nb_decoded_frames; - - /** - * Timestamp offset added to timestamps before muxing - */ - int64_t mux_ts_offset; - - /** - * This is the lowest ts allowed in this track; it may be set by the muxer - * during init or write_header and influences the automatic timestamp - * shifting code. - */ - int64_t lowest_ts_allowed; - - /** - * Internal data to check for wrapping of the time stamp - */ - int64_t pts_wrap_reference; - - /** - * Options for behavior, when a wrap is detected. - * - * Defined by AV_PTS_WRAP_ values. - * - * If correction is enabled, there are two possibilities: - * If the first time stamp is near the wrap point, the wrap offset - * will be subtracted, which will create negative time stamps. - * Otherwise the offset will be added. - */ - int pts_wrap_behavior; - - /** - * Internal data to prevent doing update_initial_durations() twice - */ - int update_initial_durations_done; - -#define MAX_REORDER_DELAY 16 - - /** - * Internal data to generate dts from pts - */ - int64_t pts_reorder_error[MAX_REORDER_DELAY+1]; - uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1]; - - int64_t pts_buffer[MAX_REORDER_DELAY+1]; - - /** - * Internal data to analyze DTS and detect faulty mpeg streams - */ - int64_t last_dts_for_order_check; - uint8_t dts_ordered; - uint8_t dts_misordered; - -#if FF_API_AVSTREAM_SIDE_DATA - /** - * Internal data to inject global side data - */ - int inject_global_side_data; -#endif - - /** - * display aspect ratio (0 if unknown) - * - encoding: unused - * - decoding: Set by libavformat to calculate sample_aspect_ratio internally - */ - AVRational display_aspect_ratio; - - AVProbeData probe_data; - - /** - * last packet in packet_buffer for this stream when muxing. - */ - PacketListEntry *last_in_packet_buffer; - - int64_t last_IP_pts; - int last_IP_duration; - - /** - * Number of packets to buffer for codec probing - */ - int probe_packets; - - /* av_read_frame() support */ - enum AVStreamParseType need_parsing; - struct AVCodecParserContext *parser; - - /** - * Number of frames that have been demuxed during avformat_find_stream_info() - */ - int codec_info_nb_frames; - - /** - * Stream Identifier - * This is the MPEG-TS stream identifier +1 - * 0 means unknown - */ - int stream_identifier; - - // Timestamp generation support: - /** - * Timestamp corresponding to the last dts sync point. - * - * Initialized when AVCodecParserContext.dts_sync_point >= 0 and - * a DTS is received from the underlying container. Otherwise set to - * AV_NOPTS_VALUE by default. - */ - int64_t first_dts; - int64_t cur_dts; - - const struct AVCodecDescriptor *codec_desc; -} FFStream; - -static av_always_inline FFStream *ffstream(AVStream *st) -{ - return (FFStream*)st; -} - -static av_always_inline const FFStream *cffstream(const AVStream *st) -{ - return (const FFStream*)st; -} - #ifdef __GNUC__ #define dynarray_add(tab, nb_ptr, elem)\ do {\ @@ -575,39 +333,12 @@ enum AVCodecID ff_guess_image2_codec(const char *filename); const struct AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st, enum AVCodecID codec_id); -/** - * Set the time base and wrapping info for a given stream. This will be used - * to interpret the stream's timestamps. If the new time base is invalid - * (numerator or denominator are non-positive), it leaves the stream - * unchanged. - * - * @param st stream - * @param pts_wrap_bits number of bits effectively used by the pts - * (used for wrap control) - * @param pts_num time base numerator - * @param pts_den time base denominator - */ -void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, - unsigned int pts_num, unsigned int pts_den); - /** * Set the timebase for each stream from the corresponding codec timebase and * print it. */ int ff_framehash_write_header(AVFormatContext *s); -/** - * Frees a stream without modifying the corresponding AVFormatContext. - * Must only be called if the latter doesn't matter or if the stream - * is not yet attached to an AVFormatContext. - */ -void ff_free_stream(AVStream **st); -/** - * Remove a stream from its AVFormatContext and free it. - * The stream must be the last stream of the AVFormatContext. - */ -void ff_remove_stream(AVFormatContext *s, AVStream *st); - unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id); enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag); @@ -629,26 +360,6 @@ int ff_is_intra_only(enum AVCodecID id); */ enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags); -/** - * Copy side data from source to destination stream - * - * @param dst pointer to destination AVStream - * @param src pointer to source AVStream - * @return >=0 on success, AVERROR code on error - */ -int ff_stream_side_data_copy(AVStream *dst, const AVStream *src); - -/** - * Create a new stream and copy to it all parameters from a source stream, with - * the exception of the index field, which is set when the new stream is - * created. - * - * @param dst_ctx pointer to the context in which the new stream is created - * @param src pointer to source AVStream - * @return pointer to the new stream or NULL on error - */ -AVStream *ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src); - /** * Wrap ffurl_move() and log if error happens. * diff --git a/libavformat/stream.c b/libavformat/stream.c new file mode 100644 index 0000000000..79ade33b74 --- /dev/null +++ b/libavformat/stream.c @@ -0,0 +1,243 @@ +/* + * AVStream related functions and structs + * + * 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 + +#include "libavutil/avassert.h" + +#include "libavcodec/bsf.h" +#include "libavcodec/parser.h" + +#include "avformat.h" +#include "stream.h" + +void ff_free_stream(AVStream **pst) +{ + AVStream *st = *pst; + FFStream *const sti = ffstream(st); + + if (!st) + return; + +#if FF_API_AVSTREAM_SIDE_DATA +FF_DISABLE_DEPRECATION_WARNINGS + for (int i = 0; i < st->nb_side_data; i++) + av_freep(&st->side_data[i].data); + av_freep(&st->side_data); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (st->attached_pic.data) + av_packet_unref(&st->attached_pic); + + av_parser_close(sti->parser); + avcodec_free_context(&sti->avctx); + av_bsf_free(&sti->bsfc); + av_freep(&sti->priv_pts); + av_freep(&sti->index_entries); + av_freep(&sti->probe_data.buf); + + av_bsf_free(&sti->extract_extradata.bsf); + + if (sti->info) { + av_freep(&sti->info->duration_error); + av_freep(&sti->info); + } + + av_dict_free(&st->metadata); + avcodec_parameters_free(&st->codecpar); + av_freep(&st->priv_data); + + av_freep(pst); +} + +void ff_remove_stream(AVFormatContext *s, AVStream *st) +{ + av_assert0(s->nb_streams>0); + av_assert0(s->streams[ s->nb_streams - 1 ] == st); + + ff_free_stream(&s->streams[ --s->nb_streams ]); +} + +#if FF_API_AVSTREAM_SIDE_DATA +FF_DISABLE_DEPRECATION_WARNINGS +uint8_t *av_stream_get_side_data(const AVStream *st, + enum AVPacketSideDataType type, size_t *size) +{ + for (int i = 0; i < st->nb_side_data; i++) { + if (st->side_data[i].type == type) { + if (size) + *size = st->side_data[i].size; + return st->side_data[i].data; + } + } + if (size) + *size = 0; + return NULL; +} + +int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, + uint8_t *data, size_t size) +{ + AVPacketSideData *sd, *tmp; + + for (int i = 0; i < st->nb_side_data; i++) { + sd = &st->side_data[i]; + + if (sd->type == type) { + av_freep(&sd->data); + sd->data = data; + sd->size = size; + return 0; + } + } + + if (st->nb_side_data + 1U > FFMIN(INT_MAX, SIZE_MAX / sizeof(*tmp))) + return AVERROR(ERANGE); + + tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); + if (!tmp) { + return AVERROR(ENOMEM); + } + + st->side_data = tmp; + st->nb_side_data++; + + sd = &st->side_data[st->nb_side_data - 1]; + sd->type = type; + sd->data = data; + sd->size = size; + + return 0; +} + +uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, + size_t size) +{ + int ret; + uint8_t *data = av_malloc(size); + + if (!data) + return NULL; + + ret = av_stream_add_side_data(st, type, data, size); + if (ret < 0) { + av_freep(&data); + return NULL; + } + + return data; +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +/** + * Copy all stream parameters from source to destination stream, with the + * exception of the index field, which is usually set by avformat_new_stream(). + * + * @param dst pointer to destination AVStream + * @param src pointer to source AVStream + * @return >=0 on success, AVERROR code on error + */ +static int stream_params_copy(AVStream *dst, const AVStream *src) +{ + int ret; + + dst->id = src->id; + dst->time_base = src->time_base; + dst->start_time = src->start_time; + dst->duration = src->duration; + dst->nb_frames = src->nb_frames; + dst->disposition = src->disposition; + dst->discard = src->discard; + dst->sample_aspect_ratio = src->sample_aspect_ratio; + dst->avg_frame_rate = src->avg_frame_rate; + dst->event_flags = src->event_flags; + dst->r_frame_rate = src->r_frame_rate; + dst->pts_wrap_bits = src->pts_wrap_bits; + + av_dict_free(&dst->metadata); + ret = av_dict_copy(&dst->metadata, src->metadata, 0); + if (ret < 0) + return ret; + + ret = avcodec_parameters_copy(dst->codecpar, src->codecpar); + if (ret < 0) + return ret; + + av_packet_unref(&dst->attached_pic); + if (src->attached_pic.data) { + ret = av_packet_ref(&dst->attached_pic, &src->attached_pic); + if (ret < 0) + return ret; + } + + return 0; +} + +AVStream *ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src) +{ + AVStream *st; + int ret; + + st = avformat_new_stream(dst_ctx, NULL); + if (!st) + return NULL; + + ret = stream_params_copy(st, src); + if (ret < 0) { + ff_remove_stream(dst_ctx, st); + return NULL; + } + + return st; +} + +AVRational av_stream_get_codec_timebase(const AVStream *st) +{ + // See avformat_transfer_internal_stream_timing_info() TODO. + return cffstream(st)->avctx->time_base; +} + +void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, + unsigned int pts_num, unsigned int pts_den) +{ + FFStream *const sti = ffstream(st); + AVRational new_tb; + if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) { + if (new_tb.num != pts_num) + av_log(NULL, AV_LOG_DEBUG, + "st:%d removing common factor %d from timebase\n", + st->index, pts_num / new_tb.num); + } else + av_log(NULL, AV_LOG_WARNING, + "st:%d has too large timebase, reducing\n", st->index); + + if (new_tb.num <= 0 || new_tb.den <= 0) { + av_log(NULL, AV_LOG_ERROR, + "Ignoring attempt to set invalid timebase %d/%d for st:%d\n", + new_tb.num, new_tb.den, + st->index); + return; + } + st->time_base = new_tb; + sti->avctx->pkt_timebase = new_tb; + st->pts_wrap_bits = pts_wrap_bits; +} diff --git a/libavformat/stream.h b/libavformat/stream.h new file mode 100644 index 0000000000..d3ca8d626c --- /dev/null +++ b/libavformat/stream.h @@ -0,0 +1,338 @@ +/* + * AVStream related functions and structs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_STREAM_H +#define AVFORMAT_STREAM_H + +#include + +#include "libavcodec/packet_internal.h" + +#include "avformat.h" + +/** + * Fractional numbers for exact pts handling + * + * The exact value of the fractional number is: 'val + num / den'. + * num is assumed to be 0 <= num < den. + */ +typedef struct FFFrac { + int64_t val, num, den; +} FFFrac; + +#define MAX_STD_TIMEBASES (30*12+30+3+6) +typedef struct FFStreamInfo { + int64_t last_dts; + int64_t duration_gcd; + int duration_count; + int64_t rfps_duration_sum; + double (*duration_error)[2][MAX_STD_TIMEBASES]; + int64_t codec_info_duration; + int64_t codec_info_duration_fields; + int frame_delay_evidence; + + /** + * 0 -> decoder has not been searched for yet. + * >0 -> decoder found + * <0 -> decoder with codec_id == -found_decoder has not been found + */ + int found_decoder; + + int64_t last_duration; + + /** + * Those are used for average framerate estimation. + */ + int64_t fps_first_dts; + int fps_first_dts_idx; + int64_t fps_last_dts; + int fps_last_dts_idx; +} FFStreamInfo; + +typedef struct FFStream { + /** + * The public context. + */ + AVStream pub; + + /** + * Set to 1 if the codec allows reordering, so pts can be different + * from dts. + */ + int reorder; + + /** + * bitstream filter to run on stream + * - encoding: Set by muxer using ff_stream_add_bitstream_filter + * - decoding: unused + */ + struct AVBSFContext *bsfc; + + /** + * Whether or not check_bitstream should still be run on each packet + */ + int bitstream_checked; + + /** + * The codec context used by avformat_find_stream_info, the parser, etc. + */ + struct AVCodecContext *avctx; + /** + * 1 if avctx has been initialized with the values from the codec parameters + */ + int avctx_inited; + + /* the context for extracting extradata in find_stream_info() + * inited=1/bsf=NULL signals that extracting is not possible (codec not + * supported) */ + struct { + struct AVBSFContext *bsf; + int inited; + } extract_extradata; + + /** + * Whether the internal avctx needs to be updated from codecpar (after a late change to codecpar) + */ + int need_context_update; + + int is_intra_only; + + FFFrac *priv_pts; + + /** + * Stream information used internally by avformat_find_stream_info() + */ + struct FFStreamInfo *info; + + AVIndexEntry *index_entries; /**< Only used if the format does not + support seeking natively. */ + int nb_index_entries; + unsigned int index_entries_allocated_size; + + int64_t interleaver_chunk_size; + int64_t interleaver_chunk_duration; + + /** + * stream probing state + * -1 -> probing finished + * 0 -> no probing requested + * rest -> perform probing with request_probe being the minimum score to accept. + */ + int request_probe; + /** + * Indicates that everything up to the next keyframe + * should be discarded. + */ + int skip_to_keyframe; + + /** + * Number of samples to skip at the start of the frame decoded from the next packet. + */ + int skip_samples; + + /** + * If not 0, the number of samples that should be skipped from the start of + * the stream (the samples are removed from packets with pts==0, which also + * assumes negative timestamps do not happen). + * Intended for use with formats such as mp3 with ad-hoc gapless audio + * support. + */ + int64_t start_skip_samples; + + /** + * If not 0, the first audio sample that should be discarded from the stream. + * This is broken by design (needs global sample count), but can't be + * avoided for broken by design formats such as mp3 with ad-hoc gapless + * audio support. + */ + int64_t first_discard_sample; + + /** + * The sample after last sample that is intended to be discarded after + * first_discard_sample. Works on frame boundaries only. Used to prevent + * early EOF if the gapless info is broken (considered concatenated mp3s). + */ + int64_t last_discard_sample; + + /** + * Number of internally decoded frames, used internally in libavformat, do not access + * its lifetime differs from info which is why it is not in that structure. + */ + int nb_decoded_frames; + + /** + * Timestamp offset added to timestamps before muxing + */ + int64_t mux_ts_offset; + + /** + * This is the lowest ts allowed in this track; it may be set by the muxer + * during init or write_header and influences the automatic timestamp + * shifting code. + */ + int64_t lowest_ts_allowed; + + /** + * Internal data to check for wrapping of the time stamp + */ + int64_t pts_wrap_reference; + + /** + * Options for behavior, when a wrap is detected. + * + * Defined by AV_PTS_WRAP_ values. + * + * If correction is enabled, there are two possibilities: + * If the first time stamp is near the wrap point, the wrap offset + * will be subtracted, which will create negative time stamps. + * Otherwise the offset will be added. + */ + int pts_wrap_behavior; + + /** + * Internal data to prevent doing update_initial_durations() twice + */ + int update_initial_durations_done; + +#define MAX_REORDER_DELAY 16 + + /** + * Internal data to generate dts from pts + */ + int64_t pts_reorder_error[MAX_REORDER_DELAY+1]; + uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1]; + + int64_t pts_buffer[MAX_REORDER_DELAY+1]; + + /** + * Internal data to analyze DTS and detect faulty mpeg streams + */ + int64_t last_dts_for_order_check; + uint8_t dts_ordered; + uint8_t dts_misordered; + +#if FF_API_AVSTREAM_SIDE_DATA + /** + * Internal data to inject global side data + */ + int inject_global_side_data; +#endif + + /** + * display aspect ratio (0 if unknown) + * - encoding: unused + * - decoding: Set by libavformat to calculate sample_aspect_ratio internally + */ + AVRational display_aspect_ratio; + + AVProbeData probe_data; + + /** + * last packet in packet_buffer for this stream when muxing. + */ + PacketListEntry *last_in_packet_buffer; + + int64_t last_IP_pts; + int last_IP_duration; + + /** + * Number of packets to buffer for codec probing + */ + int probe_packets; + + /* av_read_frame() support */ + enum AVStreamParseType need_parsing; + struct AVCodecParserContext *parser; + + /** + * Number of frames that have been demuxed during avformat_find_stream_info() + */ + int codec_info_nb_frames; + + /** + * Stream Identifier + * This is the MPEG-TS stream identifier +1 + * 0 means unknown + */ + int stream_identifier; + + // Timestamp generation support: + /** + * Timestamp corresponding to the last dts sync point. + * + * Initialized when AVCodecParserContext.dts_sync_point >= 0 and + * a DTS is received from the underlying container. Otherwise set to + * AV_NOPTS_VALUE by default. + */ + int64_t first_dts; + int64_t cur_dts; + + const struct AVCodecDescriptor *codec_desc; +} FFStream; + +static av_always_inline FFStream *ffstream(AVStream *st) +{ + return (FFStream*)st; +} + +static av_always_inline const FFStream *cffstream(const AVStream *st) +{ + return (const FFStream*)st; +} + +/** + * Set the time base and wrapping info for a given stream. This will be used + * to interpret the stream's timestamps. If the new time base is invalid + * (numerator or denominator are non-positive), it leaves the stream + * unchanged. + * + * @param st stream + * @param pts_wrap_bits number of bits effectively used by the pts + * (used for wrap control) + * @param pts_num time base numerator + * @param pts_den time base denominator + */ +void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, + unsigned int pts_num, unsigned int pts_den); + +/** + * Frees a stream without modifying the corresponding AVFormatContext. + * Must only be called if the latter doesn't matter or if the stream + * is not yet attached to an AVFormatContext. + */ +void ff_free_stream(AVStream **st); +/** + * Remove a stream from its AVFormatContext and free it. + * The stream must be the last stream of the AVFormatContext. + */ +void ff_remove_stream(AVFormatContext *s, AVStream *st); + +/** + * Create a new stream and copy to it all parameters from a source stream, with + * the exception of the index field, which is set when the new stream is + * created. + * + * @param dst_ctx pointer to the context in which the new stream is created + * @param src pointer to source AVStream + * @return pointer to the new stream or NULL on error + */ +AVStream *ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src); + +#endif /* AVFORMAT_STREAM_H */ -- 2.42.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".