[FFmpeg-devel] [PATCH] avformat: move internal AVStream related functions and structs to a separate header
James Almer
jamrial at gmail.com
Mon Nov 6 17:04:49 EET 2023
Signed-off-by: James Almer <jamrial at gmail.com>
---
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 <stdint.h>
+
+#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 <stdint.h>
+
+#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
More information about the ffmpeg-devel
mailing list