This source file includes following definitions.
- avformat_version
- avformat_configuration
- avformat_license
- ff_lock_avformat
- ff_unlock_avformat
- is_relative
- wrap_timestamp
- MAKE_ACCESSORS
- av_stream_get_parser
- av_format_inject_global_side_data
- ff_copy_whiteblacklists
- find_decoder
- find_probe_decoder
- av_format_get_probe_score
- ffio_limit
- append_packet_chunked
- av_get_packet
- av_append_packet
- av_filename_number_test
- set_codec_from_probe_data
- av_demuxer_open
- init_input
- ff_packet_list_put
- avformat_queue_attached_pictures
- update_stream_avctx
- avformat_open_input
- force_codec_ids
- probe_codec
- update_wrap_reference
- ff_read_packet
- determinable_frame_size
- ff_compute_frame_duration
- ff_is_intra_only
- has_decode_delay_been_guessed
- get_next_pkt
- select_from_pts_buffer
- update_dts_from_pts
- update_initial_timestamps
- update_initial_durations
- compute_pkt_fields
- ff_packet_list_free
- parse_packet
- ff_packet_list_get
- ts_to_samples
- read_frame_internal
- av_read_frame
- flush_packet_queue
- av_find_default_stream_index
- ff_read_frame_flush
- ff_update_cur_dts
- ff_reduce_index
- ff_add_index_entry
- av_add_index_entry
- ff_index_search_timestamp
- ff_configure_buffers_for_index
- av_index_search_timestamp
- ff_read_timestamp
- ff_seek_frame_binary
- ff_find_last_ts
- ff_gen_search
- seek_frame_byte
- seek_frame_generic
- seek_frame_internal
- av_seek_frame
- avformat_seek_file
- avformat_flush
- has_duration
- update_stream_timings
- fill_all_stream_timings
- estimate_timings_from_bit_rate
- estimate_timings_from_pts
- duration_estimate_name
- estimate_timings
- has_codec_parameters
- try_decode_frame
- ff_codec_get_tag
- ff_codec_get_id
- ff_get_pcm_codec_id
- av_codec_get_tag
- av_codec_get_tag2
- av_codec_get_id
- compute_chapters_end
- get_std_framerate
- tb_unreliable
- ff_alloc_extradata
- ff_get_extradata
- ff_rfps_add_frame
- ff_rfps_calculate
- extract_extradata_check
- extract_extradata_init
- extract_extradata
- add_coded_side_data
- avformat_find_stream_info
- av_find_program_from_stream
- av_find_best_stream
- av_read_play
- av_read_pause
- ff_stream_encode_params_copy
- free_stream
- ff_free_stream
- avformat_free_context
- avformat_close_input
- avformat_new_stream
- av_new_program
- avpriv_new_chapter
- av_program_add_stream_index
- ff_ntp_time
- ff_get_formatted_ntp_time
- av_get_frame_filename2
- av_get_frame_filename
- av_url_split
- ff_mkdir_p
- ff_data_to_hex
- ff_hex_to_data
- avpriv_set_pts_info
- ff_parse_key_value
- ff_find_stream_index
- avformat_query_codec
- avformat_network_init
- avformat_network_deinit
- ff_add_param_change
- av_guess_sample_aspect_ratio
- av_guess_frame_rate
- match_stream_specifier
- avformat_match_stream_specifier
- ff_generate_avci_extradata
- av_stream_get_side_data
- av_stream_add_side_data
- av_stream_new_side_data
- ff_stream_add_bitstream_filter
- av_apply_bitstream_filters
- ff_format_output_open
- ff_format_io_close
- ff_is_http_proto
- ff_parse_creation_time_metadata
- ff_standardize_creation_time
- ff_get_packet_palette
- ff_bprint_to_codecpar_extradata
- avformat_transfer_internal_stream_timing_info
- av_stream_get_codec_timebase
- ff_format_set_url
#include <stdint.h>
#include "config.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/dict.h"
#include "libavutil/internal.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "libavutil/pixfmt.h"
#include "libavutil/thread.h"
#include "libavutil/time.h"
#include "libavutil/timestamp.h"
#include "libavcodec/bytestream.h"
#include "libavcodec/internal.h"
#include "libavcodec/raw.h"
#include "avformat.h"
#include "avio_internal.h"
#include "id3v2.h"
#include "internal.h"
#if CONFIG_NETWORK
#include "network.h"
#endif
#include "url.h"
#include "libavutil/ffversion.h"
const char av_format_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
static AVMutex avformat_mutex = AV_MUTEX_INITIALIZER;
unsigned avformat_version(void)
{
av_assert0(LIBAVFORMAT_VERSION_MICRO >= 100);
return LIBAVFORMAT_VERSION_INT;
}
const char *avformat_configuration(void)
{
return FFMPEG_CONFIGURATION;
}
const char *avformat_license(void)
{
#define LICENSE_PREFIX "libavformat license: "
return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1];
}
int ff_lock_avformat(void)
{
return ff_mutex_lock(&avformat_mutex) ? -1 : 0;
}
int ff_unlock_avformat(void)
{
return ff_mutex_unlock(&avformat_mutex) ? -1 : 0;
}
#define RELATIVE_TS_BASE (INT64_MAX - (1LL<<48))
static int is_relative(int64_t ts) {
return ts > (RELATIVE_TS_BASE - (1LL<<48));
}
static int64_t wrap_timestamp(const AVStream *st, int64_t timestamp)
{
if (st->pts_wrap_behavior != AV_PTS_WRAP_IGNORE &&
st->pts_wrap_reference != AV_NOPTS_VALUE && timestamp != AV_NOPTS_VALUE) {
if (st->pts_wrap_behavior == AV_PTS_WRAP_ADD_OFFSET &&
timestamp < st->pts_wrap_reference)
return timestamp + (1ULL << st->pts_wrap_bits);
else if (st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET &&
timestamp >= st->pts_wrap_reference)
return timestamp - (1ULL << st->pts_wrap_bits);
}
return timestamp;
}
#if FF_API_FORMAT_GET_SET
MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate)
#if FF_API_LAVF_FFSERVER
FF_DISABLE_DEPRECATION_WARNINGS
MAKE_ACCESSORS(AVStream, stream, char *, recommended_encoder_configuration)
FF_ENABLE_DEPRECATION_WARNINGS
#endif
MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec)
MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, audio_codec)
MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, subtitle_codec)
MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, data_codec)
MAKE_ACCESSORS(AVFormatContext, format, int, metadata_header_padding)
MAKE_ACCESSORS(AVFormatContext, format, void *, opaque)
MAKE_ACCESSORS(AVFormatContext, format, av_format_control_message, control_message_cb)
#if FF_API_OLD_OPEN_CALLBACKS
FF_DISABLE_DEPRECATION_WARNINGS
MAKE_ACCESSORS(AVFormatContext, format, AVOpenCallback, open_cb)
FF_ENABLE_DEPRECATION_WARNINGS
#endif
#endif
int64_t av_stream_get_end_pts(const AVStream *st)
{
if (st->internal->priv_pts) {
return st->internal->priv_pts->val;
} else
return AV_NOPTS_VALUE;
}
struct AVCodecParserContext *av_stream_get_parser(const AVStream *st)
{
return st->parser;
}
void av_format_inject_global_side_data(AVFormatContext *s)
{
int i;
s->internal->inject_global_side_data = 1;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
st->inject_global_side_data = 1;
}
}
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
{
av_assert0(!dst->codec_whitelist &&
!dst->format_whitelist &&
!dst->protocol_whitelist &&
!dst->protocol_blacklist);
dst-> codec_whitelist = av_strdup(src->codec_whitelist);
dst->format_whitelist = av_strdup(src->format_whitelist);
dst->protocol_whitelist = av_strdup(src->protocol_whitelist);
dst->protocol_blacklist = av_strdup(src->protocol_blacklist);
if ( (src-> codec_whitelist && !dst-> codec_whitelist)
|| (src-> format_whitelist && !dst-> format_whitelist)
|| (src->protocol_whitelist && !dst->protocol_whitelist)
|| (src->protocol_blacklist && !dst->protocol_blacklist)) {
av_log(dst, AV_LOG_ERROR, "Failed to duplicate black/whitelist\n");
return AVERROR(ENOMEM);
}
return 0;
}
static const AVCodec *find_decoder(AVFormatContext *s, const AVStream *st, enum AVCodecID codec_id)
{
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
if (st->codec->codec)
return st->codec->codec;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (s->video_codec) return s->video_codec;
break;
case AVMEDIA_TYPE_AUDIO:
if (s->audio_codec) return s->audio_codec;
break;
case AVMEDIA_TYPE_SUBTITLE:
if (s->subtitle_codec) return s->subtitle_codec;
break;
}
return avcodec_find_decoder(codec_id);
}
static const AVCodec *find_probe_decoder(AVFormatContext *s, const AVStream *st, enum AVCodecID codec_id)
{
const AVCodec *codec;
#if CONFIG_H264_DECODER
if (codec_id == AV_CODEC_ID_H264)
return avcodec_find_decoder_by_name("h264");
#endif
codec = find_decoder(s, st, codec_id);
if (!codec)
return NULL;
if (codec->capabilities & AV_CODEC_CAP_AVOID_PROBING) {
const AVCodec *probe_codec = NULL;
void *iter = NULL;
while ((probe_codec = av_codec_iterate(&iter))) {
if (probe_codec->id == codec->id &&
av_codec_is_decoder(probe_codec) &&
!(probe_codec->capabilities & (AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_EXPERIMENTAL))) {
return probe_codec;
}
}
}
return codec;
}
#if FF_API_FORMAT_GET_SET
int av_format_get_probe_score(const AVFormatContext *s)
{
return s->probe_score;
}
#endif
#define SANE_CHUNK_SIZE (50000000)
int ffio_limit(AVIOContext *s, int size)
{
if (s->maxsize>= 0) {
int64_t remaining= s->maxsize - avio_tell(s);
if (remaining < size) {
int64_t newsize = avio_size(s);
if (!s->maxsize || s->maxsize<newsize)
s->maxsize = newsize - !newsize;
remaining= s->maxsize - avio_tell(s);
remaining= FFMAX(remaining, 0);
}
if (s->maxsize>= 0 && remaining+1 < size) {
av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG, "Truncating packet of size %d to %"PRId64"\n", size, remaining+1);
size = remaining+1;
}
}
return size;
}
static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
{
int orig_size = pkt->size;
int ret;
do {
int prev_size = pkt->size;
int read_size;
read_size = size;
if (read_size > SANE_CHUNK_SIZE/10) {
read_size = ffio_limit(s, read_size);
if (s->maxsize < 0)
read_size = FFMIN(read_size, SANE_CHUNK_SIZE);
}
ret = av_grow_packet(pkt, read_size);
if (ret < 0)
break;
ret = avio_read(s, pkt->data + prev_size, read_size);
if (ret != read_size) {
av_shrink_packet(pkt, prev_size + FFMAX(ret, 0));
break;
}
size -= read_size;
} while (size > 0);
if (size > 0)
pkt->flags |= AV_PKT_FLAG_CORRUPT;
if (!pkt->size)
av_packet_unref(pkt);
return pkt->size > orig_size ? pkt->size - orig_size : ret;
}
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
{
av_init_packet(pkt);
pkt->data = NULL;
pkt->size = 0;
pkt->pos = avio_tell(s);
return append_packet_chunked(s, pkt, size);
}
int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
{
if (!pkt->size)
return av_get_packet(s, pkt, size);
return append_packet_chunked(s, pkt, size);
}
int av_filename_number_test(const char *filename)
{
char buf[1024];
return filename &&
(av_get_frame_filename(buf, sizeof(buf), filename, 1) >= 0);
}
static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st,
AVProbeData *pd)
{
static const struct {
const char *name;
enum AVCodecID id;
enum AVMediaType type;
} fmt_id_type[] = {
{ "aac", AV_CODEC_ID_AAC, AVMEDIA_TYPE_AUDIO },
{ "ac3", AV_CODEC_ID_AC3, AVMEDIA_TYPE_AUDIO },
{ "aptx", AV_CODEC_ID_APTX, AVMEDIA_TYPE_AUDIO },
{ "dts", AV_CODEC_ID_DTS, AVMEDIA_TYPE_AUDIO },
{ "dvbsub", AV_CODEC_ID_DVB_SUBTITLE,AVMEDIA_TYPE_SUBTITLE },
{ "dvbtxt", AV_CODEC_ID_DVB_TELETEXT,AVMEDIA_TYPE_SUBTITLE },
{ "eac3", AV_CODEC_ID_EAC3, AVMEDIA_TYPE_AUDIO },
{ "h264", AV_CODEC_ID_H264, AVMEDIA_TYPE_VIDEO },
{ "hevc", AV_CODEC_ID_HEVC, AVMEDIA_TYPE_VIDEO },
{ "loas", AV_CODEC_ID_AAC_LATM, AVMEDIA_TYPE_AUDIO },
{ "m4v", AV_CODEC_ID_MPEG4, AVMEDIA_TYPE_VIDEO },
{ "mjpeg_2000",AV_CODEC_ID_JPEG2000, AVMEDIA_TYPE_VIDEO },
{ "mp3", AV_CODEC_ID_MP3, AVMEDIA_TYPE_AUDIO },
{ "mpegvideo", AV_CODEC_ID_MPEG2VIDEO, AVMEDIA_TYPE_VIDEO },
{ "truehd", AV_CODEC_ID_TRUEHD, AVMEDIA_TYPE_AUDIO },
{ 0 }
};
int score;
const AVInputFormat *fmt = av_probe_input_format3(pd, 1, &score);
if (fmt) {
int i;
av_log(s, AV_LOG_DEBUG,
"Probe with size=%d, packets=%d detected %s with score=%d\n",
pd->buf_size, s->max_probe_packets - st->probe_packets,
fmt->name, score);
for (i = 0; fmt_id_type[i].name; i++) {
if (!strcmp(fmt->name, fmt_id_type[i].name)) {
if (fmt_id_type[i].type != AVMEDIA_TYPE_AUDIO &&
st->codecpar->sample_rate)
continue;
if (st->request_probe > score &&
st->codecpar->codec_id != fmt_id_type[i].id)
continue;
st->codecpar->codec_id = fmt_id_type[i].id;
st->codecpar->codec_type = fmt_id_type[i].type;
st->internal->need_context_update = 1;
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
st->codec->codec_type = st->codecpar->codec_type;
st->codec->codec_id = st->codecpar->codec_id;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
return score;
}
}
}
return 0;
}
int av_demuxer_open(AVFormatContext *ic) {
int err;
if (ic->format_whitelist && av_match_list(ic->iformat->name, ic->format_whitelist, ',') <= 0) {
av_log(ic, AV_LOG_ERROR, "Format not on whitelist \'%s\'\n", ic->format_whitelist);
return AVERROR(EINVAL);
}
if (ic->iformat->read_header) {
err = ic->iformat->read_header(ic);
if (err < 0)
return err;
}
if (ic->pb && !ic->internal->data_offset)
ic->internal->data_offset = avio_tell(ic->pb);
return 0;
}
static int init_input(AVFormatContext *s, const char *filename,
AVDictionary **options)
{
int ret;
AVProbeData pd = { filename, NULL, 0 };
int score = AVPROBE_SCORE_RETRY;
if (s->pb) {
s->flags |= AVFMT_FLAG_CUSTOM_IO;
if (!s->iformat)
return av_probe_input_buffer2(s->pb, &s->iformat, filename,
s, 0, s->format_probesize);
else if (s->iformat->flags & AVFMT_NOFILE)
av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and "
"will be ignored with AVFMT_NOFILE format.\n");
return 0;
}
if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
(!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
return score;
if ((ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0)
return ret;
if (s->iformat)
return 0;
return av_probe_input_buffer2(s->pb, &s->iformat, filename,
s, 0, s->format_probesize);
}
int ff_packet_list_put(AVPacketList **packet_buffer,
AVPacketList **plast_pktl,
AVPacket *pkt, int flags)
{
AVPacketList *pktl = av_mallocz(sizeof(AVPacketList));
int ret;
if (!pktl)
return AVERROR(ENOMEM);
if (flags & FF_PACKETLIST_FLAG_REF_PACKET) {
if ((ret = av_packet_ref(&pktl->pkt, pkt)) < 0) {
av_free(pktl);
return ret;
}
} else {
ret = av_packet_make_refcounted(pkt);
if (ret < 0) {
av_free(pktl);
return ret;
}
av_packet_move_ref(&pktl->pkt, pkt);
}
if (*packet_buffer)
(*plast_pktl)->next = pktl;
else
*packet_buffer = pktl;
*plast_pktl = pktl;
return 0;
}
int avformat_queue_attached_pictures(AVFormatContext *s)
{
int i, ret;
for (i = 0; i < s->nb_streams; i++)
if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC &&
s->streams[i]->discard < AVDISCARD_ALL) {
if (s->streams[i]->attached_pic.size <= 0) {
av_log(s, AV_LOG_WARNING,
"Attached picture on stream %d has invalid size, "
"ignoring\n", i);
continue;
}
ret = ff_packet_list_put(&s->internal->raw_packet_buffer,
&s->internal->raw_packet_buffer_end,
&s->streams[i]->attached_pic,
FF_PACKETLIST_FLAG_REF_PACKET);
if (ret < 0)
return ret;
}
return 0;
}
static int update_stream_avctx(AVFormatContext *s)
{
int i, ret;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
if (!st->internal->need_context_update)
continue;
if (st->parser && st->internal->avctx->codec_id != st->codecpar->codec_id) {
av_parser_close(st->parser);
st->parser = NULL;
}
ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
if (ret < 0)
return ret;
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
ret = avcodec_parameters_to_context(st->codec, st->codecpar);
if (ret < 0)
return ret;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
st->internal->need_context_update = 0;
}
return 0;
}
int avformat_open_input(AVFormatContext **ps, const char *filename,
ff_const59 AVInputFormat *fmt, AVDictionary **options)
{
AVFormatContext *s = *ps;
int i, ret = 0;
AVDictionary *tmp = NULL;
ID3v2ExtraMeta *id3v2_extra_meta = NULL;
if (!s && !(s = avformat_alloc_context()))
return AVERROR(ENOMEM);
if (!s->av_class) {
av_log(NULL, AV_LOG_ERROR, "Input context has not been properly allocated by avformat_alloc_context() and is not NULL either\n");
return AVERROR(EINVAL);
}
if (fmt)
s->iformat = fmt;
if (options)
av_dict_copy(&tmp, *options, 0);
if (s->pb)
s->flags |= AVFMT_FLAG_CUSTOM_IO;
if ((ret = av_opt_set_dict(s, &tmp)) < 0)
goto fail;
if (!(s->url = av_strdup(filename ? filename : ""))) {
ret = AVERROR(ENOMEM);
goto fail;
}
#if FF_API_FORMAT_FILENAME
FF_DISABLE_DEPRECATION_WARNINGS
av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename));
FF_ENABLE_DEPRECATION_WARNINGS
#endif
if ((ret = init_input(s, filename, &tmp)) < 0)
goto fail;
s->probe_score = ret;
if (!s->protocol_whitelist && s->pb && s->pb->protocol_whitelist) {
s->protocol_whitelist = av_strdup(s->pb->protocol_whitelist);
if (!s->protocol_whitelist) {
ret = AVERROR(ENOMEM);
goto fail;
}
}
if (!s->protocol_blacklist && s->pb && s->pb->protocol_blacklist) {
s->protocol_blacklist = av_strdup(s->pb->protocol_blacklist);
if (!s->protocol_blacklist) {
ret = AVERROR(ENOMEM);
goto fail;
}
}
if (s->format_whitelist && av_match_list(s->iformat->name, s->format_whitelist, ',') <= 0) {
av_log(s, AV_LOG_ERROR, "Format not on whitelist \'%s\'\n", s->format_whitelist);
ret = AVERROR(EINVAL);
goto fail;
}
avio_skip(s->pb, s->skip_initial_bytes);
if (s->iformat->flags & AVFMT_NEEDNUMBER) {
if (!av_filename_number_test(filename)) {
ret = AVERROR(EINVAL);
goto fail;
}
}
s->duration = s->start_time = AV_NOPTS_VALUE;
if (s->iformat->priv_data_size > 0) {
if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) {
ret = AVERROR(ENOMEM);
goto fail;
}
if (s->iformat->priv_class) {
*(const AVClass **) s->priv_data = s->iformat->priv_class;
av_opt_set_defaults(s->priv_data);
if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)
goto fail;
}
}
if (s->pb)
ff_id3v2_read_dict(s->pb, &s->internal->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
if ((ret = s->iformat->read_header(s)) < 0)
goto fail;
if (!s->metadata) {
s->metadata = s->internal->id3v2_meta;
s->internal->id3v2_meta = NULL;
} else if (s->internal->id3v2_meta) {
av_log(s, AV_LOG_WARNING, "Discarding ID3 tags because more suitable tags were found.\n");
av_dict_free(&s->internal->id3v2_meta);
}
if (id3v2_extra_meta) {
if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") ||
!strcmp(s->iformat->name, "tta") || !strcmp(s->iformat->name, "wav")) {
if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0)
goto close;
if ((ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0)
goto close;
if ((ret = ff_id3v2_parse_priv(s, id3v2_extra_meta)) < 0)
goto close;
} else
av_log(s, AV_LOG_DEBUG, "demuxer does not support additional id3 data, skipping\n");
}
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
if ((ret = avformat_queue_attached_pictures(s)) < 0)
goto close;
if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->internal->data_offset)
s->internal->data_offset = avio_tell(s->pb);
s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
update_stream_avctx(s);
for (i = 0; i < s->nb_streams; i++)
s->streams[i]->internal->orig_codec_id = s->streams[i]->codecpar->codec_id;
if (options) {
av_dict_free(options);
*options = tmp;
}
*ps = s;
return 0;
close:
if (s->iformat->read_close)
s->iformat->read_close(s);
fail:
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
av_dict_free(&tmp);
if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO))
avio_closep(&s->pb);
avformat_free_context(s);
*ps = NULL;
return ret;
}
static void force_codec_ids(AVFormatContext *s, AVStream *st)
{
switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (s->video_codec_id)
st->codecpar->codec_id = s->video_codec_id;
break;
case AVMEDIA_TYPE_AUDIO:
if (s->audio_codec_id)
st->codecpar->codec_id = s->audio_codec_id;
break;
case AVMEDIA_TYPE_SUBTITLE:
if (s->subtitle_codec_id)
st->codecpar->codec_id = s->subtitle_codec_id;
break;
case AVMEDIA_TYPE_DATA:
if (s->data_codec_id)
st->codecpar->codec_id = s->data_codec_id;
break;
}
}
static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
{
if (st->request_probe>0) {
AVProbeData *pd = &st->probe_data;
int end;
av_log(s, AV_LOG_DEBUG, "probing stream %d pp:%d\n", st->index, st->probe_packets);
--st->probe_packets;
if (pkt) {
uint8_t *new_buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
if (!new_buf) {
av_log(s, AV_LOG_WARNING,
"Failed to reallocate probe buffer for stream %d\n",
st->index);
goto no_packet;
}
pd->buf = new_buf;
memcpy(pd->buf + pd->buf_size, pkt->data, pkt->size);
pd->buf_size += pkt->size;
memset(pd->buf + pd->buf_size, 0, AVPROBE_PADDING_SIZE);
} else {
no_packet:
st->probe_packets = 0;
if (!pd->buf_size) {
av_log(s, AV_LOG_WARNING,
"nothing to probe for stream %d\n", st->index);
}
}
end= s->internal->raw_packet_buffer_remaining_size <= 0
|| st->probe_packets<= 0;
if (end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) {
int score = set_codec_from_probe_data(s, st, pd);
if ( (st->codecpar->codec_id != AV_CODEC_ID_NONE && score > AVPROBE_SCORE_STREAM_RETRY)
|| end) {
pd->buf_size = 0;
av_freep(&pd->buf);
st->request_probe = -1;
if (st->codecpar->codec_id != AV_CODEC_ID_NONE) {
av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index);
} else
av_log(s, AV_LOG_WARNING, "probed stream %d failed\n", st->index);
}
force_codec_ids(s, st);
}
}
return 0;
}
static int update_wrap_reference(AVFormatContext *s, AVStream *st, int stream_index, AVPacket *pkt)
{
int64_t ref = pkt->dts;
int i, pts_wrap_behavior;
int64_t pts_wrap_reference;
AVProgram *first_program;
if (ref == AV_NOPTS_VALUE)
ref = pkt->pts;
if (st->pts_wrap_reference != AV_NOPTS_VALUE || st->pts_wrap_bits >= 63 || ref == AV_NOPTS_VALUE || !s->correct_ts_overflow)
return 0;
ref &= (1LL << st->pts_wrap_bits)-1;
pts_wrap_reference = ref - av_rescale(60, st->time_base.den, st->time_base.num);
pts_wrap_behavior = (ref < (1LL << st->pts_wrap_bits) - (1LL << st->pts_wrap_bits-3)) ||
(ref < (1LL << st->pts_wrap_bits) - av_rescale(60, st->time_base.den, st->time_base.num)) ?
AV_PTS_WRAP_ADD_OFFSET : AV_PTS_WRAP_SUB_OFFSET;
first_program = av_find_program_from_stream(s, NULL, stream_index);
if (!first_program) {
int default_stream_index = av_find_default_stream_index(s);
if (s->streams[default_stream_index]->pts_wrap_reference == AV_NOPTS_VALUE) {
for (i = 0; i < s->nb_streams; i++) {
if (av_find_program_from_stream(s, NULL, i))
continue;
s->streams[i]->pts_wrap_reference = pts_wrap_reference;
s->streams[i]->pts_wrap_behavior = pts_wrap_behavior;
}
}
else {
st->pts_wrap_reference = s->streams[default_stream_index]->pts_wrap_reference;
st->pts_wrap_behavior = s->streams[default_stream_index]->pts_wrap_behavior;
}
}
else {
AVProgram *program = first_program;
while (program) {
if (program->pts_wrap_reference != AV_NOPTS_VALUE) {
pts_wrap_reference = program->pts_wrap_reference;
pts_wrap_behavior = program->pts_wrap_behavior;
break;
}
program = av_find_program_from_stream(s, program, stream_index);
}
program = first_program;
while (program) {
if (program->pts_wrap_reference != pts_wrap_reference) {
for (i = 0; i<program->nb_stream_indexes; i++) {
s->streams[program->stream_index[i]]->pts_wrap_reference = pts_wrap_reference;
s->streams[program->stream_index[i]]->pts_wrap_behavior = pts_wrap_behavior;
}
program->pts_wrap_reference = pts_wrap_reference;
program->pts_wrap_behavior = pts_wrap_behavior;
}
program = av_find_program_from_stream(s, program, stream_index);
}
}
return 1;
}
int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, i, err;
AVStream *st;
pkt->data = NULL;
pkt->size = 0;
av_init_packet(pkt);
for (;;) {
AVPacketList *pktl = s->internal->raw_packet_buffer;
const AVPacket *pkt1;
if (pktl) {
st = s->streams[pktl->pkt.stream_index];
if (s->internal->raw_packet_buffer_remaining_size <= 0)
if ((err = probe_codec(s, st, NULL)) < 0)
return err;
if (st->request_probe <= 0) {
ff_packet_list_get(&s->internal->raw_packet_buffer,
&s->internal->raw_packet_buffer_end, pkt);
s->internal->raw_packet_buffer_remaining_size += pkt->size;
return 0;
}
}
ret = s->iformat->read_packet(s, pkt);
if (ret < 0) {
av_packet_unref(pkt);
if (ret == FFERROR_REDO)
continue;
if (!pktl || ret == AVERROR(EAGAIN))
return ret;
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->probe_packets || st->request_probe > 0)
if ((err = probe_codec(s, st, NULL)) < 0)
return err;
av_assert0(st->request_probe <= 0);
}
continue;
}
err = av_packet_make_refcounted(pkt);
if (err < 0) {
av_packet_unref(pkt);
return err;
}
if (pkt->flags & AV_PKT_FLAG_CORRUPT) {
av_log(s, AV_LOG_WARNING,
"Packet corrupt (stream = %d, dts = %s)",
pkt->stream_index, av_ts2str(pkt->dts));
if (s->flags & AVFMT_FLAG_DISCARD_CORRUPT) {
av_log(s, AV_LOG_WARNING, ", dropping it.\n");
av_packet_unref(pkt);
continue;
}
av_log(s, AV_LOG_WARNING, ".\n");
}
av_assert0(pkt->stream_index < (unsigned)s->nb_streams &&
"Invalid stream index.\n");
st = s->streams[pkt->stream_index];
if (update_wrap_reference(s, st, pkt->stream_index, pkt) && st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) {
if (!is_relative(st->first_dts))
st->first_dts = wrap_timestamp(st, st->first_dts);
if (!is_relative(st->start_time))
st->start_time = wrap_timestamp(st, st->start_time);
if (!is_relative(st->cur_dts))
st->cur_dts = wrap_timestamp(st, st->cur_dts);
}
pkt->dts = wrap_timestamp(st, pkt->dts);
pkt->pts = wrap_timestamp(st, pkt->pts);
force_codec_ids(s, st);
if (s->use_wallclock_as_timestamps)
pkt->dts = pkt->pts = av_rescale_q(av_gettime(), AV_TIME_BASE_Q, st->time_base);
if (!pktl && st->request_probe <= 0)
return ret;
err = ff_packet_list_put(&s->internal->raw_packet_buffer,
&s->internal->raw_packet_buffer_end,
pkt, 0);
if (err < 0) {
av_packet_unref(pkt);
return err;
}
pkt1 = &s->internal->raw_packet_buffer_end->pkt;
s->internal->raw_packet_buffer_remaining_size -= pkt1->size;
if ((err = probe_codec(s, st, pkt1)) < 0)
return err;
}
}
static int determinable_frame_size(AVCodecContext *avctx)
{
switch(avctx->codec_id) {
case AV_CODEC_ID_MP1:
case AV_CODEC_ID_MP2:
case AV_CODEC_ID_MP3:
case AV_CODEC_ID_CODEC2:
return 1;
}
return 0;
}
void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStream *st,
AVCodecParserContext *pc, AVPacket *pkt)
{
AVRational codec_framerate = s->iformat ? st->internal->avctx->framerate :
av_mul_q(av_inv_q(st->internal->avctx->time_base), (AVRational){1, st->internal->avctx->ticks_per_frame});
int frame_size, sample_rate;
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
if ((!codec_framerate.den || !codec_framerate.num) && st->codec->time_base.den && st->codec->time_base.num)
codec_framerate = av_mul_q(av_inv_q(st->codec->time_base), (AVRational){1, st->codec->ticks_per_frame});
FF_ENABLE_DEPRECATION_WARNINGS
#endif
*pnum = 0;
*pden = 0;
switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (st->r_frame_rate.num && !pc && s->iformat) {
*pnum = st->r_frame_rate.den;
*pden = st->r_frame_rate.num;
} else if (st->time_base.num * 1000LL > st->time_base.den) {
*pnum = st->time_base.num;
*pden = st->time_base.den;
} else if (codec_framerate.den * 1000LL > codec_framerate.num) {
av_assert0(st->internal->avctx->ticks_per_frame);
av_reduce(pnum, pden,
codec_framerate.den,
codec_framerate.num * (int64_t)st->internal->avctx->ticks_per_frame,
INT_MAX);
if (pc && pc->repeat_pict) {
av_assert0(s->iformat);
av_reduce(pnum, pden,
(*pnum) * (1LL + pc->repeat_pict),
(*pden),
INT_MAX);
}
if (st->internal->avctx->ticks_per_frame > 1 && !pc)
*pnum = *pden = 0;
}
break;
case AVMEDIA_TYPE_AUDIO:
if (st->internal->avctx_inited) {
frame_size = av_get_audio_frame_duration(st->internal->avctx, pkt->size);
sample_rate = st->internal->avctx->sample_rate;
} else {
frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size);
sample_rate = st->codecpar->sample_rate;
}
if (frame_size <= 0 || sample_rate <= 0)
break;
*pnum = frame_size;
*pden = sample_rate;
break;
default:
break;
}
}
int ff_is_intra_only(enum AVCodecID id)
{
const AVCodecDescriptor *d = avcodec_descriptor_get(id);
if (!d)
return 0;
if ((d->type == AVMEDIA_TYPE_VIDEO || d->type == AVMEDIA_TYPE_AUDIO) &&
!(d->props & AV_CODEC_PROP_INTRA_ONLY))
return 0;
return 1;
}
static int has_decode_delay_been_guessed(AVStream *st)
{
if (st->codecpar->codec_id != AV_CODEC_ID_H264) return 1;
if (!st->info)
return 1;
#if CONFIG_H264_DECODER
if (st->internal->avctx->has_b_frames &&
avpriv_h264_has_num_reorder_frames(st->internal->avctx) == st->internal->avctx->has_b_frames)
return 1;
#endif
if (st->internal->avctx->has_b_frames<3)
return st->nb_decoded_frames >= 7;
else if (st->internal->avctx->has_b_frames<4)
return st->nb_decoded_frames >= 18;
else
return st->nb_decoded_frames >= 20;
}
static AVPacketList *get_next_pkt(AVFormatContext *s, AVStream *st, AVPacketList *pktl)
{
if (pktl->next)
return pktl->next;
if (pktl == s->internal->packet_buffer_end)
return s->internal->parse_queue;
return NULL;
}
static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t dts) {
int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 &&
st->codecpar->codec_id != AV_CODEC_ID_HEVC;
if(!onein_oneout) {
int delay = st->internal->avctx->has_b_frames;
int i;
if (dts == AV_NOPTS_VALUE) {
int64_t best_score = INT64_MAX;
for (i = 0; i<delay; i++) {
if (st->pts_reorder_error_count[i]) {
int64_t score = st->pts_reorder_error[i] / st->pts_reorder_error_count[i];
if (score < best_score) {
best_score = score;
dts = pts_buffer[i];
}
}
}
} else {
for (i = 0; i<delay; i++) {
if (pts_buffer[i] != AV_NOPTS_VALUE) {
int64_t diff = FFABS(pts_buffer[i] - dts)
+ (uint64_t)st->pts_reorder_error[i];
diff = FFMAX(diff, st->pts_reorder_error[i]);
st->pts_reorder_error[i] = diff;
st->pts_reorder_error_count[i]++;
if (st->pts_reorder_error_count[i] > 250) {
st->pts_reorder_error[i] >>= 1;
st->pts_reorder_error_count[i] >>= 1;
}
}
}
}
}
if (dts == AV_NOPTS_VALUE)
dts = pts_buffer[0];
return dts;
}
static void update_dts_from_pts(AVFormatContext *s, int stream_index,
AVPacketList *pkt_buffer)
{
AVStream *st = s->streams[stream_index];
int delay = st->internal->avctx->has_b_frames;
int i;
int64_t pts_buffer[MAX_REORDER_DELAY+1];
for (i = 0; i<MAX_REORDER_DELAY+1; i++)
pts_buffer[i] = AV_NOPTS_VALUE;
for (; pkt_buffer; pkt_buffer = get_next_pkt(s, st, pkt_buffer)) {
if (pkt_buffer->pkt.stream_index != stream_index)
continue;
if (pkt_buffer->pkt.pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY) {
pts_buffer[0] = pkt_buffer->pkt.pts;
for (i = 0; i<delay && pts_buffer[i] > pts_buffer[i + 1]; i++)
FFSWAP(int64_t, pts_buffer[i], pts_buffer[i + 1]);
pkt_buffer->pkt.dts = select_from_pts_buffer(st, pts_buffer, pkt_buffer->pkt.dts);
}
}
}
static void update_initial_timestamps(AVFormatContext *s, int stream_index,
int64_t dts, int64_t pts, AVPacket *pkt)
{
AVStream *st = s->streams[stream_index];
AVPacketList *pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue;
AVPacketList *pktl_it;
uint64_t shift;
if (st->first_dts != AV_NOPTS_VALUE ||
dts == AV_NOPTS_VALUE ||
st->cur_dts == AV_NOPTS_VALUE ||
st->cur_dts < INT_MIN + RELATIVE_TS_BASE ||
is_relative(dts))
return;
st->first_dts = dts - (st->cur_dts - RELATIVE_TS_BASE);
st->cur_dts = dts;
shift = (uint64_t)st->first_dts - RELATIVE_TS_BASE;
if (is_relative(pts))
pts += shift;
for (pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) {
if (pktl_it->pkt.stream_index != stream_index)
continue;
if (is_relative(pktl_it->pkt.pts))
pktl_it->pkt.pts += shift;
if (is_relative(pktl_it->pkt.dts))
pktl_it->pkt.dts += shift;
if (st->start_time == AV_NOPTS_VALUE && pktl_it->pkt.pts != AV_NOPTS_VALUE) {
st->start_time = pktl_it->pkt.pts;
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate)
st->start_time = av_sat_add64(st->start_time, av_rescale_q(st->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base));
}
}
if (has_decode_delay_been_guessed(st)) {
update_dts_from_pts(s, stream_index, pktl);
}
if (st->start_time == AV_NOPTS_VALUE) {
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || !(pkt->flags & AV_PKT_FLAG_DISCARD)) {
st->start_time = pts;
}
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate)
st->start_time = av_sat_add64(st->start_time, av_rescale_q(st->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base));
}
}
static void update_initial_durations(AVFormatContext *s, AVStream *st,
int stream_index, int64_t duration)
{
AVPacketList *pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue;
int64_t cur_dts = RELATIVE_TS_BASE;
if (st->first_dts != AV_NOPTS_VALUE) {
if (st->update_initial_durations_done)
return;
st->update_initial_durations_done = 1;
cur_dts = st->first_dts;
for (; pktl; pktl = get_next_pkt(s, st, pktl)) {
if (pktl->pkt.stream_index == stream_index) {
if (pktl->pkt.pts != pktl->pkt.dts ||
pktl->pkt.dts != AV_NOPTS_VALUE ||
pktl->pkt.duration)
break;
cur_dts -= duration;
}
}
if (pktl && pktl->pkt.dts != st->first_dts) {
av_log(s, AV_LOG_DEBUG, "first_dts %s not matching first dts %s (pts %s, duration %"PRId64") in the queue\n",
av_ts2str(st->first_dts), av_ts2str(pktl->pkt.dts), av_ts2str(pktl->pkt.pts), pktl->pkt.duration);
return;
}
if (!pktl) {
av_log(s, AV_LOG_DEBUG, "first_dts %s but no packet with dts in the queue\n", av_ts2str(st->first_dts));
return;
}
pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue;
st->first_dts = cur_dts;
} else if (st->cur_dts != RELATIVE_TS_BASE)
return;
for (; pktl; pktl = get_next_pkt(s, st, pktl)) {
if (pktl->pkt.stream_index != stream_index)
continue;
if ((pktl->pkt.pts == pktl->pkt.dts ||
pktl->pkt.pts == AV_NOPTS_VALUE) &&
(pktl->pkt.dts == AV_NOPTS_VALUE ||
pktl->pkt.dts == st->first_dts ||
pktl->pkt.dts == RELATIVE_TS_BASE) &&
!pktl->pkt.duration) {
pktl->pkt.dts = cur_dts;
if (!st->internal->avctx->has_b_frames)
pktl->pkt.pts = cur_dts;
pktl->pkt.duration = duration;
} else
break;
cur_dts = pktl->pkt.dts + pktl->pkt.duration;
}
if (!pktl)
st->cur_dts = cur_dts;
}
static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
AVCodecParserContext *pc, AVPacket *pkt,
int64_t next_dts, int64_t next_pts)
{
int num, den, presentation_delayed, delay, i;
int64_t offset;
AVRational duration;
int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 &&
st->codecpar->codec_id != AV_CODEC_ID_HEVC;
if (s->flags & AVFMT_FLAG_NOFILLIN)
return;
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pkt->dts != AV_NOPTS_VALUE) {
if (pkt->dts == pkt->pts && st->last_dts_for_order_check != AV_NOPTS_VALUE) {
if (st->last_dts_for_order_check <= pkt->dts) {
st->dts_ordered++;
} else {
av_log(s, st->dts_misordered ? AV_LOG_DEBUG : AV_LOG_WARNING,
"DTS %"PRIi64" < %"PRIi64" out of order\n",
pkt->dts,
st->last_dts_for_order_check);
st->dts_misordered++;
}
if (st->dts_ordered + st->dts_misordered > 250) {
st->dts_ordered >>= 1;
st->dts_misordered >>= 1;
}
}
st->last_dts_for_order_check = pkt->dts;
if (st->dts_ordered < 8*st->dts_misordered && pkt->dts == pkt->pts)
pkt->dts = AV_NOPTS_VALUE;
}
if ((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE)
pkt->dts = AV_NOPTS_VALUE;
if (pc && pc->pict_type == AV_PICTURE_TYPE_B
&& !st->internal->avctx->has_b_frames)
st->internal->avctx->has_b_frames = 1;
delay = st->internal->avctx->has_b_frames;
presentation_delayed = 0;
if (delay &&
pc && pc->pict_type != AV_PICTURE_TYPE_B)
presentation_delayed = 1;
if (pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE &&
st->pts_wrap_bits < 63 &&
pkt->dts - (1LL << (st->pts_wrap_bits - 1)) > pkt->pts) {
if (is_relative(st->cur_dts) || pkt->dts - (1LL<<(st->pts_wrap_bits - 1)) > st->cur_dts) {
pkt->dts -= 1LL << st->pts_wrap_bits;
} else
pkt->pts += 1LL << st->pts_wrap_bits;
}
if (delay == 1 && pkt->dts == pkt->pts &&
pkt->dts != AV_NOPTS_VALUE && presentation_delayed) {
av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination %"PRIi64"\n", pkt->dts);
if ( strcmp(s->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2")
&& strcmp(s->iformat->name, "flv"))
pkt->dts = AV_NOPTS_VALUE;
}
duration = av_mul_q((AVRational) {pkt->duration, 1}, st->time_base);
if (pkt->duration <= 0) {
ff_compute_frame_duration(s, &num, &den, st, pc, pkt);
if (den && num) {
duration = (AVRational) {num, den};
pkt->duration = av_rescale_rnd(1,
num * (int64_t) st->time_base.den,
den * (int64_t) st->time_base.num,
AV_ROUND_DOWN);
}
}
if (pkt->duration > 0 && (s->internal->packet_buffer || s->internal->parse_queue))
update_initial_durations(s, st, pkt->stream_index, pkt->duration);
if (pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size) {
offset = av_rescale(pc->offset, pkt->duration, pkt->size);
if (pkt->pts != AV_NOPTS_VALUE)
pkt->pts += offset;
if (pkt->dts != AV_NOPTS_VALUE)
pkt->dts += offset;
}
if (pkt->dts != AV_NOPTS_VALUE &&
pkt->pts != AV_NOPTS_VALUE &&
pkt->pts > pkt->dts)
presentation_delayed = 1;
if (s->debug & FF_FDEBUG_TS)
av_log(s, AV_LOG_DEBUG,
"IN delayed:%d pts:%s, dts:%s cur_dts:%s st:%d pc:%p duration:%"PRId64" delay:%d onein_oneout:%d\n",
presentation_delayed, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts),
pkt->stream_index, pc, pkt->duration, delay, onein_oneout);
if ((delay == 0 || (delay == 1 && pc)) &&
onein_oneout) {
if (presentation_delayed) {
if (pkt->dts == AV_NOPTS_VALUE)
pkt->dts = st->last_IP_pts;
update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts, pkt);
if (pkt->dts == AV_NOPTS_VALUE)
pkt->dts = st->cur_dts;
if (st->last_IP_duration == 0 && (uint64_t)pkt->duration <= INT32_MAX)
st->last_IP_duration = pkt->duration;
if (pkt->dts != AV_NOPTS_VALUE)
st->cur_dts = av_sat_add64(pkt->dts, st->last_IP_duration);
if (pkt->dts != AV_NOPTS_VALUE &&
pkt->pts == AV_NOPTS_VALUE &&
st->last_IP_duration > 0 &&
((uint64_t)st->cur_dts - (uint64_t)next_dts + 1) <= 2 &&
next_dts != next_pts &&
next_pts != AV_NOPTS_VALUE)
pkt->pts = next_dts;
if ((uint64_t)pkt->duration <= INT32_MAX)
st->last_IP_duration = pkt->duration;
st->last_IP_pts = pkt->pts;
} else if (pkt->pts != AV_NOPTS_VALUE ||
pkt->dts != AV_NOPTS_VALUE ||
pkt->duration > 0 ) {
if (pkt->pts == AV_NOPTS_VALUE)
pkt->pts = pkt->dts;
update_initial_timestamps(s, pkt->stream_index, pkt->pts,
pkt->pts, pkt);
if (pkt->pts == AV_NOPTS_VALUE)
pkt->pts = st->cur_dts;
pkt->dts = pkt->pts;
if (pkt->pts != AV_NOPTS_VALUE && duration.num >= 0)
st->cur_dts = av_add_stable(st->time_base, pkt->pts, duration, 1);
}
}
if (pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY) {
st->pts_buffer[0] = pkt->pts;
for (i = 0; i<delay && st->pts_buffer[i] > st->pts_buffer[i + 1]; i++)
FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i + 1]);
if(has_decode_delay_been_guessed(st))
pkt->dts = select_from_pts_buffer(st, st->pts_buffer, pkt->dts);
}
if (!onein_oneout)
update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts, pkt);
if (pkt->dts > st->cur_dts)
st->cur_dts = pkt->dts;
if (s->debug & FF_FDEBUG_TS)
av_log(s, AV_LOG_DEBUG, "OUTdelayed:%d/%d pts:%s, dts:%s cur_dts:%s st:%d (%d)\n",
presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), st->index, st->id);
if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA || ff_is_intra_only(st->codecpar->codec_id))
pkt->flags |= AV_PKT_FLAG_KEY;
#if FF_API_CONVERGENCE_DURATION
FF_DISABLE_DEPRECATION_WARNINGS
if (pc)
pkt->convergence_duration = pc->convergence_duration;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
}
void ff_packet_list_free(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end)
{
AVPacketList *tmp = *pkt_buf;
while (tmp) {
AVPacketList *pktl = tmp;
tmp = pktl->next;
av_packet_unref(&pktl->pkt);
av_freep(&pktl);
}
*pkt_buf = NULL;
*pkt_buf_end = NULL;
}
static int parse_packet(AVFormatContext *s, AVPacket *pkt,
int stream_index, int flush)
{
AVPacket out_pkt;
AVStream *st = s->streams[stream_index];
uint8_t *data = pkt->data;
int size = pkt->size;
int ret = 0, got_output = flush;
if (size || flush) {
av_init_packet(&out_pkt);
} else if (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) {
compute_pkt_fields(s, st, st->parser, pkt, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
}
while (size > 0 || (flush && got_output)) {
int len;
int64_t next_pts = pkt->pts;
int64_t next_dts = pkt->dts;
len = av_parser_parse2(st->parser, st->internal->avctx,
&out_pkt.data, &out_pkt.size, data, size,
pkt->pts, pkt->dts, pkt->pos);
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
pkt->pos = -1;
data += len;
size -= len;
got_output = !!out_pkt.size;
if (!out_pkt.size)
continue;
if (pkt->buf && out_pkt.data == pkt->data) {
out_pkt.buf = av_buffer_ref(pkt->buf);
if (!out_pkt.buf) {
ret = AVERROR(ENOMEM);
goto fail;
}
} else {
ret = av_packet_make_refcounted(&out_pkt);
if (ret < 0)
goto fail;
}
if (pkt->side_data) {
out_pkt.side_data = pkt->side_data;
out_pkt.side_data_elems = pkt->side_data_elems;
pkt->side_data = NULL;
pkt->side_data_elems = 0;
}
out_pkt.duration = (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) ? pkt->duration : 0;
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
if (st->internal->avctx->sample_rate > 0) {
out_pkt.duration =
av_rescale_q_rnd(st->parser->duration,
(AVRational) { 1, st->internal->avctx->sample_rate },
st->time_base,
AV_ROUND_DOWN);
}
}
out_pkt.stream_index = st->index;
out_pkt.pts = st->parser->pts;
out_pkt.dts = st->parser->dts;
out_pkt.pos = st->parser->pos;
out_pkt.flags |= pkt->flags & AV_PKT_FLAG_DISCARD;
if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW)
out_pkt.pos = st->parser->frame_offset;
if (st->parser->key_frame == 1 ||
(st->parser->key_frame == -1 &&
st->parser->pict_type == AV_PICTURE_TYPE_I))
out_pkt.flags |= AV_PKT_FLAG_KEY;
if (st->parser->key_frame == -1 && st->parser->pict_type ==AV_PICTURE_TYPE_NONE && (pkt->flags&AV_PKT_FLAG_KEY))
out_pkt.flags |= AV_PKT_FLAG_KEY;
compute_pkt_fields(s, st, st->parser, &out_pkt, next_dts, next_pts);
ret = ff_packet_list_put(&s->internal->parse_queue,
&s->internal->parse_queue_end,
&out_pkt, 0);
if (ret < 0) {
av_packet_unref(&out_pkt);
goto fail;
}
}
if (flush) {
av_parser_close(st->parser);
st->parser = NULL;
}
fail:
av_packet_unref(pkt);
return ret;
}
int ff_packet_list_get(AVPacketList **pkt_buffer,
AVPacketList **pkt_buffer_end,
AVPacket *pkt)
{
AVPacketList *pktl;
av_assert0(*pkt_buffer);
pktl = *pkt_buffer;
*pkt = pktl->pkt;
*pkt_buffer = pktl->next;
if (!pktl->next)
*pkt_buffer_end = NULL;
av_freep(&pktl);
return 0;
}
static int64_t ts_to_samples(AVStream *st, int64_t ts)
{
return av_rescale(ts, st->time_base.num * st->codecpar->sample_rate, st->time_base.den);
}
static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
{
int ret, i, got_packet = 0;
AVDictionary *metadata = NULL;
while (!got_packet && !s->internal->parse_queue) {
AVStream *st;
ret = ff_read_packet(s, pkt);
if (ret < 0) {
if (ret == AVERROR(EAGAIN))
return ret;
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->parser && st->need_parsing)
parse_packet(s, pkt, st->index, 1);
}
break;
}
ret = 0;
st = s->streams[pkt->stream_index];
if (st->internal->need_context_update) {
if (avcodec_is_open(st->internal->avctx)) {
av_log(s, AV_LOG_DEBUG, "Demuxer context update while decoder is open, closing and trying to re-open\n");
avcodec_close(st->internal->avctx);
st->info->found_decoder = 0;
}
if (st->parser && st->internal->avctx->codec_id != st->codecpar->codec_id) {
av_parser_close(st->parser);
st->parser = NULL;
}
ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
if (ret < 0) {
av_packet_unref(pkt);
return ret;
}
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
ret = avcodec_parameters_to_context(st->codec, st->codecpar);
if (ret < 0) {
av_packet_unref(pkt);
return ret;
}
FF_ENABLE_DEPRECATION_WARNINGS
#endif
st->internal->need_context_update = 0;
}
if (pkt->pts != AV_NOPTS_VALUE &&
pkt->dts != AV_NOPTS_VALUE &&
pkt->pts < pkt->dts) {
av_log(s, AV_LOG_WARNING,
"Invalid timestamps stream=%d, pts=%s, dts=%s, size=%d\n",
pkt->stream_index,
av_ts2str(pkt->pts),
av_ts2str(pkt->dts),
pkt->size);
}
if (s->debug & FF_FDEBUG_TS)
av_log(s, AV_LOG_DEBUG,
"ff_read_packet stream=%d, pts=%s, dts=%s, size=%d, duration=%"PRId64", flags=%d\n",
pkt->stream_index,
av_ts2str(pkt->pts),
av_ts2str(pkt->dts),
pkt->size, pkt->duration, pkt->flags);
if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) {
st->parser = av_parser_init(st->codecpar->codec_id);
if (!st->parser) {
av_log(s, AV_LOG_VERBOSE, "parser not found for codec "
"%s, packets or times may be invalid.\n",
avcodec_get_name(st->codecpar->codec_id));
st->need_parsing = AVSTREAM_PARSE_NONE;
} else if (st->need_parsing == AVSTREAM_PARSE_HEADERS)
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
else if (st->need_parsing == AVSTREAM_PARSE_FULL_ONCE)
st->parser->flags |= PARSER_FLAG_ONCE;
else if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW)
st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
}
if (!st->need_parsing || !st->parser) {
compute_pkt_fields(s, st, NULL, pkt, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
if ((s->iformat->flags & AVFMT_GENERIC_INDEX) &&
(pkt->flags & AV_PKT_FLAG_KEY) && pkt->dts != AV_NOPTS_VALUE) {
ff_reduce_index(s, st->index);
av_add_index_entry(st, pkt->pos, pkt->dts,
0, 0, AVINDEX_KEYFRAME);
}
got_packet = 1;
} else if (st->discard < AVDISCARD_ALL) {
if ((ret = parse_packet(s, pkt, pkt->stream_index, 0)) < 0)
return ret;
st->codecpar->sample_rate = st->internal->avctx->sample_rate;
st->codecpar->bit_rate = st->internal->avctx->bit_rate;
st->codecpar->channels = st->internal->avctx->channels;
st->codecpar->channel_layout = st->internal->avctx->channel_layout;
st->codecpar->codec_id = st->internal->avctx->codec_id;
} else {
av_packet_unref(pkt);
}
if (pkt->flags & AV_PKT_FLAG_KEY)
st->skip_to_keyframe = 0;
if (st->skip_to_keyframe) {
av_packet_unref(pkt);
got_packet = 0;
}
}
if (!got_packet && s->internal->parse_queue)
ret = ff_packet_list_get(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt);
if (ret >= 0) {
AVStream *st = s->streams[pkt->stream_index];
int discard_padding = 0;
if (st->first_discard_sample && pkt->pts != AV_NOPTS_VALUE) {
int64_t pts = pkt->pts - (is_relative(pkt->pts) ? RELATIVE_TS_BASE : 0);
int64_t sample = ts_to_samples(st, pts);
int duration = ts_to_samples(st, pkt->duration);
int64_t end_sample = sample + duration;
if (duration > 0 && end_sample >= st->first_discard_sample &&
sample < st->last_discard_sample)
discard_padding = FFMIN(end_sample - st->first_discard_sample, duration);
}
if (st->start_skip_samples && (pkt->pts == 0 || pkt->pts == RELATIVE_TS_BASE))
st->skip_samples = st->start_skip_samples;
if (st->skip_samples || discard_padding) {
uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (p) {
AV_WL32(p, st->skip_samples);
AV_WL32(p + 4, discard_padding);
av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d / discard %d\n", st->skip_samples, discard_padding);
}
st->skip_samples = 0;
}
if (st->inject_global_side_data) {
for (i = 0; i < st->nb_side_data; i++) {
AVPacketSideData *src_sd = &st->side_data[i];
uint8_t *dst_data;
if (av_packet_get_side_data(pkt, src_sd->type, NULL))
continue;
dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size);
if (!dst_data) {
av_log(s, AV_LOG_WARNING, "Could not inject global side data\n");
continue;
}
memcpy(dst_data, src_sd->data, src_sd->size);
}
st->inject_global_side_data = 0;
}
}
av_opt_get_dict_val(s, "metadata", AV_OPT_SEARCH_CHILDREN, &metadata);
if (metadata) {
s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
av_dict_copy(&s->metadata, metadata, 0);
av_dict_free(&metadata);
av_opt_set_dict_val(s, "metadata", NULL, AV_OPT_SEARCH_CHILDREN);
}
#if FF_API_LAVF_AVCTX
update_stream_avctx(s);
#endif
if (s->debug & FF_FDEBUG_TS)
av_log(s, AV_LOG_DEBUG,
"read_frame_internal stream=%d, pts=%s, dts=%s, "
"size=%d, duration=%"PRId64", flags=%d\n",
pkt->stream_index,
av_ts2str(pkt->pts),
av_ts2str(pkt->dts),
pkt->size, pkt->duration, pkt->flags);
if (ret == AVERROR_EOF && s->pb && s->pb->error < 0 && s->pb->error != AVERROR(EAGAIN))
ret = s->pb->error;
return ret;
}
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{
const int genpts = s->flags & AVFMT_FLAG_GENPTS;
int eof = 0;
int ret;
AVStream *st;
if (!genpts) {
ret = s->internal->packet_buffer
? ff_packet_list_get(&s->internal->packet_buffer,
&s->internal->packet_buffer_end, pkt)
: read_frame_internal(s, pkt);
if (ret < 0)
return ret;
goto return_packet;
}
for (;;) {
AVPacketList *pktl = s->internal->packet_buffer;
if (pktl) {
AVPacket *next_pkt = &pktl->pkt;
if (next_pkt->dts != AV_NOPTS_VALUE) {
int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits;
int64_t last_dts = next_pkt->dts;
av_assert2(wrap_bits <= 64);
while (pktl && next_pkt->pts == AV_NOPTS_VALUE) {
if (pktl->pkt.stream_index == next_pkt->stream_index &&
av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2ULL << (wrap_bits - 1)) < 0) {
if (av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2ULL << (wrap_bits - 1))) {
next_pkt->pts = pktl->pkt.dts;
}
if (last_dts != AV_NOPTS_VALUE) {
last_dts = pktl->pkt.dts;
}
}
pktl = pktl->next;
}
if (eof && next_pkt->pts == AV_NOPTS_VALUE && last_dts != AV_NOPTS_VALUE) {
next_pkt->pts = last_dts + next_pkt->duration;
}
pktl = s->internal->packet_buffer;
}
st = s->streams[next_pkt->stream_index];
if (!(next_pkt->pts == AV_NOPTS_VALUE && st->discard < AVDISCARD_ALL &&
next_pkt->dts != AV_NOPTS_VALUE && !eof)) {
ret = ff_packet_list_get(&s->internal->packet_buffer,
&s->internal->packet_buffer_end, pkt);
goto return_packet;
}
}
ret = read_frame_internal(s, pkt);
if (ret < 0) {
if (pktl && ret != AVERROR(EAGAIN)) {
eof = 1;
continue;
} else
return ret;
}
ret = ff_packet_list_put(&s->internal->packet_buffer,
&s->internal->packet_buffer_end,
pkt, 0);
if (ret < 0) {
av_packet_unref(pkt);
return ret;
}
}
return_packet:
st = s->streams[pkt->stream_index];
if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & AV_PKT_FLAG_KEY) {
ff_reduce_index(s, st->index);
av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME);
}
if (is_relative(pkt->dts))
pkt->dts -= RELATIVE_TS_BASE;
if (is_relative(pkt->pts))
pkt->pts -= RELATIVE_TS_BASE;
return ret;
}
static void flush_packet_queue(AVFormatContext *s)
{
if (!s->internal)
return;
ff_packet_list_free(&s->internal->parse_queue, &s->internal->parse_queue_end);
ff_packet_list_free(&s->internal->packet_buffer, &s->internal->packet_buffer_end);
ff_packet_list_free(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end);
s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
}
int av_find_default_stream_index(AVFormatContext *s)
{
int i;
AVStream *st;
int best_stream = 0;
int best_score = INT_MIN;
if (s->nb_streams <= 0)
return -1;
for (i = 0; i < s->nb_streams; i++) {
int score = 0;
st = s->streams[i];
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
score -= 400;
if (st->codecpar->width && st->codecpar->height)
score += 50;
score+= 25;
}
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
if (st->codecpar->sample_rate)
score += 50;
}
if (st->codec_info_nb_frames)
score += 12;
if (st->discard != AVDISCARD_ALL)
score += 200;
if (score > best_score) {
best_score = score;
best_stream = i;
}
}
return best_stream;
}
void ff_read_frame_flush(AVFormatContext *s)
{
AVStream *st;
int i, j;
flush_packet_queue(s);
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->parser) {
av_parser_close(st->parser);
st->parser = NULL;
}
st->last_IP_pts = AV_NOPTS_VALUE;
st->last_dts_for_order_check = AV_NOPTS_VALUE;
if (st->first_dts == AV_NOPTS_VALUE)
st->cur_dts = RELATIVE_TS_BASE;
else
st->cur_dts = AV_NOPTS_VALUE;
st->probe_packets = s->max_probe_packets;
for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
st->pts_buffer[j] = AV_NOPTS_VALUE;
if (s->internal->inject_global_side_data)
st->inject_global_side_data = 1;
st->skip_samples = 0;
}
}
void ff_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
{
int i;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
st->cur_dts =
av_rescale(timestamp,
st->time_base.den * (int64_t) ref_st->time_base.num,
st->time_base.num * (int64_t) ref_st->time_base.den);
}
}
void ff_reduce_index(AVFormatContext *s, int stream_index)
{
AVStream *st = s->streams[stream_index];
unsigned int max_entries = s->max_index_size / sizeof(AVIndexEntry);
if ((unsigned) st->nb_index_entries >= max_entries) {
int i;
for (i = 0; 2 * i < st->nb_index_entries; i++)
st->index_entries[i] = st->index_entries[2 * i];
st->nb_index_entries = i;
}
}
int ff_add_index_entry(AVIndexEntry **index_entries,
int *nb_index_entries,
unsigned int *index_entries_allocated_size,
int64_t pos, int64_t timestamp,
int size, int distance, int flags)
{
AVIndexEntry *entries, *ie;
int index;
if ((unsigned) *nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
return -1;
if (timestamp == AV_NOPTS_VALUE)
return AVERROR(EINVAL);
if (size < 0 || size > 0x3FFFFFFF)
return AVERROR(EINVAL);
if (is_relative(timestamp))
timestamp -= RELATIVE_TS_BASE;
entries = av_fast_realloc(*index_entries,
index_entries_allocated_size,
(*nb_index_entries + 1) *
sizeof(AVIndexEntry));
if (!entries)
return -1;
*index_entries = entries;
index = ff_index_search_timestamp(*index_entries, *nb_index_entries,
timestamp, AVSEEK_FLAG_ANY);
if (index < 0) {
index = (*nb_index_entries)++;
ie = &entries[index];
av_assert0(index == 0 || ie[-1].timestamp < timestamp);
} else {
ie = &entries[index];
if (ie->timestamp != timestamp) {
if (ie->timestamp <= timestamp)
return -1;
memmove(entries + index + 1, entries + index,
sizeof(AVIndexEntry) * (*nb_index_entries - index));
(*nb_index_entries)++;
} else if (ie->pos == pos && distance < ie->min_distance)
distance = ie->min_distance;
}
ie->pos = pos;
ie->timestamp = timestamp;
ie->min_distance = distance;
ie->size = size;
ie->flags = flags;
return index;
}
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
int size, int distance, int flags)
{
timestamp = wrap_timestamp(st, timestamp);
return ff_add_index_entry(&st->index_entries, &st->nb_index_entries,
&st->index_entries_allocated_size, pos,
timestamp, size, distance, flags);
}
int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries,
int64_t wanted_timestamp, int flags)
{
int a, b, m;
int64_t timestamp;
a = -1;
b = nb_entries;
if (b && entries[b - 1].timestamp < wanted_timestamp)
a = b - 1;
while (b - a > 1) {
m = (a + b) >> 1;
while ((entries[m].flags & AVINDEX_DISCARD_FRAME) && m < b && m < nb_entries - 1) {
m++;
if (m == b && entries[m].timestamp >= wanted_timestamp) {
m = b - 1;
break;
}
}
timestamp = entries[m].timestamp;
if (timestamp >= wanted_timestamp)
b = m;
if (timestamp <= wanted_timestamp)
a = m;
}
m = (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
if (!(flags & AVSEEK_FLAG_ANY))
while (m >= 0 && m < nb_entries &&
!(entries[m].flags & AVINDEX_KEYFRAME))
m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;
if (m == nb_entries)
return -1;
return m;
}
void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
{
int ist1, ist2;
int64_t pos_delta = 0;
int64_t skip = 0;
const char *proto = avio_find_protocol_name(s->url);
av_assert0(time_tolerance >= 0);
if (!proto) {
av_log(s, AV_LOG_INFO,
"Protocol name not provided, cannot determine if input is local or "
"a network protocol, buffers and access patterns cannot be configured "
"optimally without knowing the protocol\n");
}
if (proto && !(strcmp(proto, "file") && strcmp(proto, "pipe") && strcmp(proto, "cache")))
return;
for (ist1 = 0; ist1 < s->nb_streams; ist1++) {
AVStream *st1 = s->streams[ist1];
for (ist2 = 0; ist2 < s->nb_streams; ist2++) {
AVStream *st2 = s->streams[ist2];
int i1, i2;
if (ist1 == ist2)
continue;
for (i1 = i2 = 0; i1 < st1->nb_index_entries; i1++) {
AVIndexEntry *e1 = &st1->index_entries[i1];
int64_t e1_pts = av_rescale_q(e1->timestamp, st1->time_base, AV_TIME_BASE_Q);
skip = FFMAX(skip, e1->size);
for (; i2 < st2->nb_index_entries; i2++) {
AVIndexEntry *e2 = &st2->index_entries[i2];
int64_t e2_pts = av_rescale_q(e2->timestamp, st2->time_base, AV_TIME_BASE_Q);
if (e2_pts < e1_pts || e2_pts - (uint64_t)e1_pts < time_tolerance)
continue;
pos_delta = FFMAX(pos_delta, e1->pos - e2->pos);
break;
}
}
}
}
pos_delta *= 2;
if (s->pb->buffer_size < pos_delta && pos_delta < (1<<24)) {
av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta);
if (ffio_realloc_buf(s->pb, pos_delta)) {
av_log(s, AV_LOG_ERROR, "Realloc buffer fail.\n");
return;
}
s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, pos_delta/2);
}
if (skip < (1<<23)) {
s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, skip);
}
}
int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
{
return ff_index_search_timestamp(st->index_entries, st->nb_index_entries,
wanted_timestamp, flags);
}
static int64_t ff_read_timestamp(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit,
int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ))
{
int64_t ts = read_timestamp(s, stream_index, ppos, pos_limit);
if (stream_index >= 0)
ts = wrap_timestamp(s->streams[stream_index], ts);
return ts;
}
int ff_seek_frame_binary(AVFormatContext *s, int stream_index,
int64_t target_ts, int flags)
{
const AVInputFormat *avif = s->iformat;
int64_t av_uninit(pos_min), av_uninit(pos_max), pos, pos_limit;
int64_t ts_min, ts_max, ts;
int index;
int64_t ret;
AVStream *st;
if (stream_index < 0)
return -1;
av_log(s, AV_LOG_TRACE, "read_seek: %d %s\n", stream_index, av_ts2str(target_ts));
ts_max =
ts_min = AV_NOPTS_VALUE;
pos_limit = -1;
st = s->streams[stream_index];
if (st->index_entries) {
AVIndexEntry *e;
index = av_index_search_timestamp(st, target_ts,
flags | AVSEEK_FLAG_BACKWARD);
index = FFMAX(index, 0);
e = &st->index_entries[index];
if (e->timestamp <= target_ts || e->pos == e->min_distance) {
pos_min = e->pos;
ts_min = e->timestamp;
av_log(s, AV_LOG_TRACE, "using cached pos_min=0x%"PRIx64" dts_min=%s\n",
pos_min, av_ts2str(ts_min));
} else {
av_assert1(index == 0);
}
index = av_index_search_timestamp(st, target_ts,
flags & ~AVSEEK_FLAG_BACKWARD);
av_assert0(index < st->nb_index_entries);
if (index >= 0) {
e = &st->index_entries[index];
av_assert1(e->timestamp >= target_ts);
pos_max = e->pos;
ts_max = e->timestamp;
pos_limit = pos_max - e->min_distance;
av_log(s, AV_LOG_TRACE, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64
" dts_max=%s\n", pos_max, pos_limit, av_ts2str(ts_max));
}
}
pos = ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit,
ts_min, ts_max, flags, &ts, avif->read_timestamp);
if (pos < 0)
return -1;
if ((ret = avio_seek(s->pb, pos, SEEK_SET)) < 0)
return ret;
ff_read_frame_flush(s);
ff_update_cur_dts(s, st, ts);
return 0;
}
int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos,
int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ))
{
int64_t step = 1024;
int64_t limit, ts_max;
int64_t filesize = avio_size(s->pb);
int64_t pos_max = filesize - 1;
do {
limit = pos_max;
pos_max = FFMAX(0, (pos_max) - step);
ts_max = ff_read_timestamp(s, stream_index,
&pos_max, limit, read_timestamp);
step += step;
} while (ts_max == AV_NOPTS_VALUE && 2*limit > step);
if (ts_max == AV_NOPTS_VALUE)
return -1;
for (;;) {
int64_t tmp_pos = pos_max + 1;
int64_t tmp_ts = ff_read_timestamp(s, stream_index,
&tmp_pos, INT64_MAX, read_timestamp);
if (tmp_ts == AV_NOPTS_VALUE)
break;
av_assert0(tmp_pos > pos_max);
ts_max = tmp_ts;
pos_max = tmp_pos;
if (tmp_pos >= filesize)
break;
}
if (ts)
*ts = ts_max;
if (pos)
*pos = pos_max;
return 0;
}
int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
int64_t pos_min, int64_t pos_max, int64_t pos_limit,
int64_t ts_min, int64_t ts_max,
int flags, int64_t *ts_ret,
int64_t (*read_timestamp)(struct AVFormatContext *, int,
int64_t *, int64_t))
{
int64_t pos, ts;
int64_t start_pos;
int no_change;
int ret;
av_log(s, AV_LOG_TRACE, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts));
if (ts_min == AV_NOPTS_VALUE) {
pos_min = s->internal->data_offset;
ts_min = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
if (ts_min == AV_NOPTS_VALUE)
return -1;
}
if (ts_min >= target_ts) {
*ts_ret = ts_min;
return pos_min;
}
if (ts_max == AV_NOPTS_VALUE) {
if ((ret = ff_find_last_ts(s, stream_index, &ts_max, &pos_max, read_timestamp)) < 0)
return ret;
pos_limit = pos_max;
}
if (ts_max <= target_ts) {
*ts_ret = ts_max;
return pos_max;
}
av_assert0(ts_min < ts_max);
no_change = 0;
while (pos_min < pos_limit) {
av_log(s, AV_LOG_TRACE,
"pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
pos_min, pos_max, av_ts2str(ts_min), av_ts2str(ts_max));
av_assert0(pos_limit <= pos_max);
if (no_change == 0) {
int64_t approximate_keyframe_distance = pos_max - pos_limit;
pos = av_rescale(target_ts - ts_min, pos_max - pos_min,
ts_max - ts_min) +
pos_min - approximate_keyframe_distance;
} else if (no_change == 1) {
pos = (pos_min + pos_limit) >> 1;
} else {
pos = pos_min;
}
if (pos <= pos_min)
pos = pos_min + 1;
else if (pos > pos_limit)
pos = pos_limit;
start_pos = pos;
ts = ff_read_timestamp(s, stream_index, &pos, INT64_MAX, read_timestamp);
if (pos == pos_max)
no_change++;
else
no_change = 0;
av_log(s, AV_LOG_TRACE, "%"PRId64" %"PRId64" %"PRId64" / %s %s %s"
" target:%s limit:%"PRId64" start:%"PRId64" noc:%d\n",
pos_min, pos, pos_max,
av_ts2str(ts_min), av_ts2str(ts), av_ts2str(ts_max), av_ts2str(target_ts),
pos_limit, start_pos, no_change);
if (ts == AV_NOPTS_VALUE) {
av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n");
return -1;
}
if (target_ts <= ts) {
pos_limit = start_pos - 1;
pos_max = pos;
ts_max = ts;
}
if (target_ts >= ts) {
pos_min = pos;
ts_min = ts;
}
}
pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
#if 0
pos_min = pos;
ts_min = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
pos_min++;
ts_max = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" %s<=%s<=%s\n",
pos, av_ts2str(ts_min), av_ts2str(target_ts), av_ts2str(ts_max));
#endif
*ts_ret = ts;
return pos;
}
static int seek_frame_byte(AVFormatContext *s, int stream_index,
int64_t pos, int flags)
{
int64_t pos_min, pos_max;
pos_min = s->internal->data_offset;
pos_max = avio_size(s->pb) - 1;
if (pos < pos_min)
pos = pos_min;
else if (pos > pos_max)
pos = pos_max;
avio_seek(s->pb, pos, SEEK_SET);
s->io_repositioned = 1;
return 0;
}
static int seek_frame_generic(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
int index;
int64_t ret;
AVStream *st;
AVIndexEntry *ie;
st = s->streams[stream_index];
index = av_index_search_timestamp(st, timestamp, flags);
if (index < 0 && st->nb_index_entries &&
timestamp < st->index_entries[0].timestamp)
return -1;
if (index < 0 || index == st->nb_index_entries - 1) {
AVPacket pkt;
int nonkey = 0;
if (st->nb_index_entries) {
av_assert0(st->index_entries);
ie = &st->index_entries[st->nb_index_entries - 1];
if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
return ret;
ff_update_cur_dts(s, st, ie->timestamp);
} else {
if ((ret = avio_seek(s->pb, s->internal->data_offset, SEEK_SET)) < 0)
return ret;
}
for (;;) {
int read_status;
do {
read_status = av_read_frame(s, &pkt);
} while (read_status == AVERROR(EAGAIN));
if (read_status < 0)
break;
if (stream_index == pkt.stream_index && pkt.dts > timestamp) {
if (pkt.flags & AV_PKT_FLAG_KEY) {
av_packet_unref(&pkt);
break;
}
if (nonkey++ > 1000 && st->codecpar->codec_id != AV_CODEC_ID_CDGRAPHICS) {
av_log(s, AV_LOG_ERROR,"seek_frame_generic failed as this stream seems to contain no keyframes after the target timestamp, %d non keyframes found\n", nonkey);
av_packet_unref(&pkt);
break;
}
}
av_packet_unref(&pkt);
}
index = av_index_search_timestamp(st, timestamp, flags);
}
if (index < 0)
return -1;
ff_read_frame_flush(s);
if (s->iformat->read_seek)
if (s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0)
return 0;
ie = &st->index_entries[index];
if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
return ret;
ff_update_cur_dts(s, st, ie->timestamp);
return 0;
}
static int seek_frame_internal(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
int ret;
AVStream *st;
if (flags & AVSEEK_FLAG_BYTE) {
if (s->iformat->flags & AVFMT_NO_BYTE_SEEK)
return -1;
ff_read_frame_flush(s);
return seek_frame_byte(s, stream_index, timestamp, flags);
}
if (stream_index < 0) {
stream_index = av_find_default_stream_index(s);
if (stream_index < 0)
return -1;
st = s->streams[stream_index];
timestamp = av_rescale(timestamp, st->time_base.den,
AV_TIME_BASE * (int64_t) st->time_base.num);
}
if (s->iformat->read_seek) {
ff_read_frame_flush(s);
ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
} else
ret = -1;
if (ret >= 0)
return 0;
if (s->iformat->read_timestamp &&
!(s->iformat->flags & AVFMT_NOBINSEARCH)) {
ff_read_frame_flush(s);
return ff_seek_frame_binary(s, stream_index, timestamp, flags);
} else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) {
ff_read_frame_flush(s);
return seek_frame_generic(s, stream_index, timestamp, flags);
} else
return -1;
}
int av_seek_frame(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
int ret;
if (s->iformat->read_seek2 && !s->iformat->read_seek) {
int64_t min_ts = INT64_MIN, max_ts = INT64_MAX;
if ((flags & AVSEEK_FLAG_BACKWARD))
max_ts = timestamp;
else
min_ts = timestamp;
return avformat_seek_file(s, stream_index, min_ts, timestamp, max_ts,
flags & ~AVSEEK_FLAG_BACKWARD);
}
ret = seek_frame_internal(s, stream_index, timestamp, flags);
if (ret >= 0)
ret = avformat_queue_attached_pictures(s);
return ret;
}
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts,
int64_t ts, int64_t max_ts, int flags)
{
if (min_ts > ts || max_ts < ts)
return -1;
if (stream_index < -1 || stream_index >= (int)s->nb_streams)
return AVERROR(EINVAL);
if (s->seek2any>0)
flags |= AVSEEK_FLAG_ANY;
flags &= ~AVSEEK_FLAG_BACKWARD;
if (s->iformat->read_seek2) {
int ret;
ff_read_frame_flush(s);
if (stream_index == -1 && s->nb_streams == 1) {
AVRational time_base = s->streams[0]->time_base;
ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base);
min_ts = av_rescale_rnd(min_ts, time_base.den,
time_base.num * (int64_t)AV_TIME_BASE,
AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
max_ts = av_rescale_rnd(max_ts, time_base.den,
time_base.num * (int64_t)AV_TIME_BASE,
AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
stream_index = 0;
}
ret = s->iformat->read_seek2(s, stream_index, min_ts,
ts, max_ts, flags);
if (ret >= 0)
ret = avformat_queue_attached_pictures(s);
return ret;
}
if (s->iformat->read_timestamp) {
}
if (s->iformat->read_seek || 1) {
int dir = (ts - (uint64_t)min_ts > (uint64_t)max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0);
int ret = av_seek_frame(s, stream_index, ts, flags | dir);
if (ret<0 && ts != min_ts && max_ts != ts) {
ret = av_seek_frame(s, stream_index, dir ? max_ts : min_ts, flags | dir);
if (ret >= 0)
ret = av_seek_frame(s, stream_index, ts, flags | (dir^AVSEEK_FLAG_BACKWARD));
}
return ret;
}
return -1;
}
int avformat_flush(AVFormatContext *s)
{
ff_read_frame_flush(s);
return 0;
}
static int has_duration(AVFormatContext *ic)
{
int i;
AVStream *st;
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->duration != AV_NOPTS_VALUE)
return 1;
}
if (ic->duration != AV_NOPTS_VALUE)
return 1;
return 0;
}
static void update_stream_timings(AVFormatContext *ic)
{
int64_t start_time, start_time1, start_time_text, end_time, end_time1, end_time_text;
int64_t duration, duration1, duration_text, filesize;
int i;
AVProgram *p;
start_time = INT64_MAX;
start_time_text = INT64_MAX;
end_time = INT64_MIN;
end_time_text = INT64_MIN;
duration = INT64_MIN;
duration_text = INT64_MIN;
for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
int is_text = st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ||
st->codecpar->codec_type == AVMEDIA_TYPE_DATA;
if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
start_time1 = av_rescale_q(st->start_time, st->time_base,
AV_TIME_BASE_Q);
if (is_text)
start_time_text = FFMIN(start_time_text, start_time1);
else
start_time = FFMIN(start_time, start_time1);
end_time1 = av_rescale_q_rnd(st->duration, st->time_base,
AV_TIME_BASE_Q,
AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
if (end_time1 != AV_NOPTS_VALUE && (end_time1 > 0 ? start_time1 <= INT64_MAX - end_time1 : start_time1 >= INT64_MIN - end_time1)) {
end_time1 += start_time1;
if (is_text)
end_time_text = FFMAX(end_time_text, end_time1);
else
end_time = FFMAX(end_time, end_time1);
}
for (p = NULL; (p = av_find_program_from_stream(ic, p, i)); ) {
if (p->start_time == AV_NOPTS_VALUE || p->start_time > start_time1)
p->start_time = start_time1;
if (p->end_time < end_time1)
p->end_time = end_time1;
}
}
if (st->duration != AV_NOPTS_VALUE) {
duration1 = av_rescale_q(st->duration, st->time_base,
AV_TIME_BASE_Q);
if (is_text)
duration_text = FFMAX(duration_text, duration1);
else
duration = FFMAX(duration, duration1);
}
}
if (start_time == INT64_MAX || (start_time > start_time_text && start_time - (uint64_t)start_time_text < AV_TIME_BASE))
start_time = start_time_text;
else if (start_time > start_time_text)
av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream starttime %f\n", start_time_text / (float)AV_TIME_BASE);
if (end_time == INT64_MIN || (end_time < end_time_text && end_time_text - (uint64_t)end_time < AV_TIME_BASE))
end_time = end_time_text;
else if (end_time < end_time_text)
av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream endtime %f\n", end_time_text / (float)AV_TIME_BASE);
if (duration == INT64_MIN || (duration < duration_text && duration_text - duration < AV_TIME_BASE))
duration = duration_text;
else if (duration < duration_text)
av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream duration %f\n", duration_text / (float)AV_TIME_BASE);
if (start_time != INT64_MAX) {
ic->start_time = start_time;
if (end_time != INT64_MIN) {
if (ic->nb_programs > 1) {
for (i = 0; i < ic->nb_programs; i++) {
p = ic->programs[i];
if (p->start_time != AV_NOPTS_VALUE &&
p->end_time > p->start_time &&
p->end_time - (uint64_t)p->start_time <= INT64_MAX)
duration = FFMAX(duration, p->end_time - p->start_time);
}
} else if (end_time >= start_time && end_time - (uint64_t)start_time <= INT64_MAX) {
duration = FFMAX(duration, end_time - start_time);
}
}
}
if (duration != INT64_MIN && duration > 0 && ic->duration == AV_NOPTS_VALUE) {
ic->duration = duration;
}
if (ic->pb && (filesize = avio_size(ic->pb)) > 0 && ic->duration > 0) {
double bitrate = (double) filesize * 8.0 * AV_TIME_BASE /
(double) ic->duration;
if (bitrate >= 0 && bitrate <= INT64_MAX)
ic->bit_rate = bitrate;
}
}
static void fill_all_stream_timings(AVFormatContext *ic)
{
int i;
AVStream *st;
update_stream_timings(ic);
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->start_time == AV_NOPTS_VALUE) {
if (ic->start_time != AV_NOPTS_VALUE)
st->start_time = av_rescale_q(ic->start_time, AV_TIME_BASE_Q,
st->time_base);
if (ic->duration != AV_NOPTS_VALUE)
st->duration = av_rescale_q(ic->duration, AV_TIME_BASE_Q,
st->time_base);
}
}
}
static void estimate_timings_from_bit_rate(AVFormatContext *ic)
{
int64_t filesize, duration;
int i, show_warning = 0;
AVStream *st;
if (ic->bit_rate <= 0) {
int64_t bit_rate = 0;
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->codecpar->bit_rate <= 0 && st->internal->avctx->bit_rate > 0)
st->codecpar->bit_rate = st->internal->avctx->bit_rate;
if (st->codecpar->bit_rate > 0) {
if (INT64_MAX - st->codecpar->bit_rate < bit_rate) {
bit_rate = 0;
break;
}
bit_rate += st->codecpar->bit_rate;
} else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->codec_info_nb_frames > 1) {
bit_rate = 0;
break;
}
}
ic->bit_rate = bit_rate;
}
if (ic->duration == AV_NOPTS_VALUE &&
ic->bit_rate != 0) {
filesize = ic->pb ? avio_size(ic->pb) : 0;
if (filesize > ic->internal->data_offset) {
filesize -= ic->internal->data_offset;
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if ( st->time_base.num <= INT64_MAX / ic->bit_rate
&& st->duration == AV_NOPTS_VALUE) {
duration = av_rescale(filesize, 8LL * st->time_base.den,
ic->bit_rate *
(int64_t) st->time_base.num);
st->duration = duration;
show_warning = 1;
}
}
}
}
if (show_warning)
av_log(ic, AV_LOG_WARNING,
"Estimating duration from bitrate, this may be inaccurate\n");
}
#define DURATION_MAX_READ_SIZE 250000LL
#define DURATION_MAX_RETRY 6
static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
{
AVPacket pkt1, *pkt = &pkt1;
AVStream *st;
int num, den, read_size, i, ret;
int found_duration = 0;
int is_end;
int64_t filesize, offset, duration;
int retry = 0;
flush_packet_queue(ic);
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->start_time == AV_NOPTS_VALUE &&
st->first_dts == AV_NOPTS_VALUE &&
st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN)
av_log(ic, AV_LOG_WARNING,
"start time for stream %d is not set in estimate_timings_from_pts\n", i);
if (st->parser) {
av_parser_close(st->parser);
st->parser = NULL;
}
}
if (ic->skip_estimate_duration_from_pts) {
av_log(ic, AV_LOG_INFO, "Skipping duration calculation in estimate_timings_from_pts\n");
goto skip_duration_calc;
}
av_opt_set(ic, "skip_changes", "1", AV_OPT_SEARCH_CHILDREN);
filesize = ic->pb ? avio_size(ic->pb) : 0;
do {
is_end = found_duration;
offset = filesize - (DURATION_MAX_READ_SIZE << retry);
if (offset < 0)
offset = 0;
avio_seek(ic->pb, offset, SEEK_SET);
read_size = 0;
for (;;) {
if (read_size >= DURATION_MAX_READ_SIZE << (FFMAX(retry - 1, 0)))
break;
do {
ret = ff_read_packet(ic, pkt);
} while (ret == AVERROR(EAGAIN));
if (ret != 0)
break;
read_size += pkt->size;
st = ic->streams[pkt->stream_index];
if (pkt->pts != AV_NOPTS_VALUE &&
(st->start_time != AV_NOPTS_VALUE ||
st->first_dts != AV_NOPTS_VALUE)) {
if (pkt->duration == 0) {
ff_compute_frame_duration(ic, &num, &den, st, st->parser, pkt);
if (den && num) {
pkt->duration = av_rescale_rnd(1,
num * (int64_t) st->time_base.den,
den * (int64_t) st->time_base.num,
AV_ROUND_DOWN);
}
}
duration = pkt->pts + pkt->duration;
found_duration = 1;
if (st->start_time != AV_NOPTS_VALUE)
duration -= st->start_time;
else
duration -= st->first_dts;
if (duration > 0) {
if (st->duration == AV_NOPTS_VALUE || st->info->last_duration<= 0 ||
(st->duration < duration && FFABS(duration - st->info->last_duration) < 60LL*st->time_base.den / st->time_base.num))
st->duration = duration;
st->info->last_duration = duration;
}
}
av_packet_unref(pkt);
}
if (!is_end) {
is_end = 1;
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
case AVMEDIA_TYPE_AUDIO:
if (st->duration == AV_NOPTS_VALUE)
is_end = 0;
}
}
}
} while (!is_end &&
offset &&
++retry <= DURATION_MAX_RETRY);
av_opt_set(ic, "skip_changes", "0", AV_OPT_SEARCH_CHILDREN);
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->duration == AV_NOPTS_VALUE) {
switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
case AVMEDIA_TYPE_AUDIO:
if (st->start_time != AV_NOPTS_VALUE || st->first_dts != AV_NOPTS_VALUE) {
av_log(ic, AV_LOG_WARNING, "stream %d : no PTS found at end of file, duration not set\n", i);
} else
av_log(ic, AV_LOG_WARNING, "stream %d : no TS found at start of file, duration not set\n", i);
}
}
}
skip_duration_calc:
fill_all_stream_timings(ic);
avio_seek(ic->pb, old_offset, SEEK_SET);
for (i = 0; i < ic->nb_streams; i++) {
int j;
st = ic->streams[i];
st->cur_dts = st->first_dts;
st->last_IP_pts = AV_NOPTS_VALUE;
st->last_dts_for_order_check = AV_NOPTS_VALUE;
for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
st->pts_buffer[j] = AV_NOPTS_VALUE;
}
}
static const char *duration_name[] = {
[AVFMT_DURATION_FROM_PTS] = "pts",
[AVFMT_DURATION_FROM_STREAM] = "stream",
[AVFMT_DURATION_FROM_BITRATE] = "bit rate",
};
static const char *duration_estimate_name(enum AVDurationEstimationMethod method)
{
return duration_name[method];
}
static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
{
int64_t file_size;
if (ic->iformat->flags & AVFMT_NOFILE) {
file_size = 0;
} else {
file_size = avio_size(ic->pb);
file_size = FFMAX(0, file_size);
}
if ((!strcmp(ic->iformat->name, "mpeg") ||
!strcmp(ic->iformat->name, "mpegts")) &&
file_size && (ic->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
estimate_timings_from_pts(ic, old_offset);
ic->duration_estimation_method = AVFMT_DURATION_FROM_PTS;
} else if (has_duration(ic)) {
fill_all_stream_timings(ic);
if(!strcmp(ic->iformat->name, "nut"))
ic->duration_estimation_method = AVFMT_DURATION_FROM_PTS;
else
ic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM;
} else {
estimate_timings_from_bit_rate(ic);
ic->duration_estimation_method = AVFMT_DURATION_FROM_BITRATE;
}
update_stream_timings(ic);
{
int i;
AVStream av_unused *st;
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->time_base.den)
av_log(ic, AV_LOG_TRACE, "stream %d: start_time: %s duration: %s\n", i,
av_ts2timestr(st->start_time, &st->time_base),
av_ts2timestr(st->duration, &st->time_base));
}
av_log(ic, AV_LOG_TRACE,
"format: start_time: %s duration: %s (estimate from %s) bitrate=%"PRId64" kb/s\n",
av_ts2timestr(ic->start_time, &AV_TIME_BASE_Q),
av_ts2timestr(ic->duration, &AV_TIME_BASE_Q),
duration_estimate_name(ic->duration_estimation_method),
(int64_t)ic->bit_rate / 1000);
}
}
static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
{
AVCodecContext *avctx = st->internal->avctx;
#define FAIL(errmsg) do { \
if (errmsg_ptr) \
*errmsg_ptr = errmsg; \
return 0; \
} while (0)
if ( avctx->codec_id == AV_CODEC_ID_NONE
&& avctx->codec_type != AVMEDIA_TYPE_DATA)
FAIL("unknown codec");
switch (avctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
if (!avctx->frame_size && determinable_frame_size(avctx))
FAIL("unspecified frame size");
if (st->info->found_decoder >= 0 &&
avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
FAIL("unspecified sample format");
if (!avctx->sample_rate)
FAIL("unspecified sample rate");
if (!avctx->channels)
FAIL("unspecified number of channels");
if (st->info->found_decoder >= 0 && !st->nb_decoded_frames && avctx->codec_id == AV_CODEC_ID_DTS)
FAIL("no decodable DTS frames");
break;
case AVMEDIA_TYPE_VIDEO:
if (!avctx->width)
FAIL("unspecified size");
if (st->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE)
FAIL("unspecified pixel format");
if (st->codecpar->codec_id == AV_CODEC_ID_RV30 || st->codecpar->codec_id == AV_CODEC_ID_RV40)
if (!st->sample_aspect_ratio.num && !st->codecpar->sample_aspect_ratio.num && !st->codec_info_nb_frames)
FAIL("no frame in rv30/40 and no sar");
break;
case AVMEDIA_TYPE_SUBTITLE:
if (avctx->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE && !avctx->width)
FAIL("unspecified size");
break;
case AVMEDIA_TYPE_DATA:
if (avctx->codec_id == AV_CODEC_ID_NONE) return 1;
}
return 1;
}
static int try_decode_frame(AVFormatContext *s, AVStream *st,
const AVPacket *avpkt, AVDictionary **options)
{
AVCodecContext *avctx = st->internal->avctx;
const AVCodec *codec;
int got_picture = 1, ret = 0;
AVFrame *frame = av_frame_alloc();
AVSubtitle subtitle;
AVPacket pkt = *avpkt;
int do_skip_frame = 0;
enum AVDiscard skip_frame;
if (!frame)
return AVERROR(ENOMEM);
if (!avcodec_is_open(avctx) &&
st->info->found_decoder <= 0 &&
(st->codecpar->codec_id != -st->info->found_decoder || !st->codecpar->codec_id)) {
AVDictionary *thread_opt = NULL;
codec = find_probe_decoder(s, st, st->codecpar->codec_id);
if (!codec) {
st->info->found_decoder = -st->codecpar->codec_id;
ret = -1;
goto fail;
}
av_dict_set(options ? options : &thread_opt, "threads", "1", 0);
if (s->codec_whitelist)
av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0);
ret = avcodec_open2(avctx, codec, options ? options : &thread_opt);
if (!options)
av_dict_free(&thread_opt);
if (ret < 0) {
st->info->found_decoder = -avctx->codec_id;
goto fail;
}
st->info->found_decoder = 1;
} else if (!st->info->found_decoder)
st->info->found_decoder = 1;
if (st->info->found_decoder < 0) {
ret = -1;
goto fail;
}
if (avpriv_codec_get_cap_skip_frame_fill_param(avctx->codec)) {
do_skip_frame = 1;
skip_frame = avctx->skip_frame;
avctx->skip_frame = AVDISCARD_ALL;
}
while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
ret >= 0 &&
(!has_codec_parameters(st, NULL) || !has_decode_delay_been_guessed(st) ||
(!st->codec_info_nb_frames &&
(avctx->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) {
got_picture = 0;
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO ||
avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
ret = avcodec_send_packet(avctx, &pkt);
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
break;
if (ret >= 0)
pkt.size = 0;
ret = avcodec_receive_frame(avctx, frame);
if (ret >= 0)
got_picture = 1;
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
ret = 0;
} else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
ret = avcodec_decode_subtitle2(avctx, &subtitle,
&got_picture, &pkt);
if (got_picture)
avsubtitle_free(&subtitle);
if (ret >= 0)
pkt.size = 0;
}
if (ret >= 0) {
if (got_picture)
st->nb_decoded_frames++;
ret = got_picture;
}
}
if (!pkt.data && !got_picture)
ret = -1;
fail:
if (do_skip_frame) {
avctx->skip_frame = skip_frame;
}
av_frame_free(&frame);
return ret;
}
unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id)
{
while (tags->id != AV_CODEC_ID_NONE) {
if (tags->id == id)
return tags->tag;
tags++;
}
return 0;
}
enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag)
{
int i;
for (i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
if (tag == tags[i].tag)
return tags[i].id;
for (i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
if (avpriv_toupper4(tag) == avpriv_toupper4(tags[i].tag))
return tags[i].id;
return AV_CODEC_ID_NONE;
}
enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags)
{
if (bps <= 0 || bps > 64)
return AV_CODEC_ID_NONE;
if (flt) {
switch (bps) {
case 32:
return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
case 64:
return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE;
default:
return AV_CODEC_ID_NONE;
}
} else {
bps += 7;
bps >>= 3;
if (sflags & (1 << (bps - 1))) {
switch (bps) {
case 1:
return AV_CODEC_ID_PCM_S8;
case 2:
return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
case 3:
return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
case 4:
return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
case 8:
return be ? AV_CODEC_ID_PCM_S64BE : AV_CODEC_ID_PCM_S64LE;
default:
return AV_CODEC_ID_NONE;
}
} else {
switch (bps) {
case 1:
return AV_CODEC_ID_PCM_U8;
case 2:
return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE;
case 3:
return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE;
case 4:
return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE;
default:
return AV_CODEC_ID_NONE;
}
}
}
}
unsigned int av_codec_get_tag(const AVCodecTag *const *tags, enum AVCodecID id)
{
unsigned int tag;
if (!av_codec_get_tag2(tags, id, &tag))
return 0;
return tag;
}
int av_codec_get_tag2(const AVCodecTag * const *tags, enum AVCodecID id,
unsigned int *tag)
{
int i;
for (i = 0; tags && tags[i]; i++) {
const AVCodecTag *codec_tags = tags[i];
while (codec_tags->id != AV_CODEC_ID_NONE) {
if (codec_tags->id == id) {
*tag = codec_tags->tag;
return 1;
}
codec_tags++;
}
}
return 0;
}
enum AVCodecID av_codec_get_id(const AVCodecTag *const *tags, unsigned int tag)
{
int i;
for (i = 0; tags && tags[i]; i++) {
enum AVCodecID id = ff_codec_get_id(tags[i], tag);
if (id != AV_CODEC_ID_NONE)
return id;
}
return AV_CODEC_ID_NONE;
}
static void compute_chapters_end(AVFormatContext *s)
{
unsigned int i, j;
int64_t max_time = 0;
if (s->duration > 0 && s->start_time < INT64_MAX - s->duration)
max_time = s->duration +
((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time);
for (i = 0; i < s->nb_chapters; i++)
if (s->chapters[i]->end == AV_NOPTS_VALUE) {
AVChapter *ch = s->chapters[i];
int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q,
ch->time_base)
: INT64_MAX;
for (j = 0; j < s->nb_chapters; j++) {
AVChapter *ch1 = s->chapters[j];
int64_t next_start = av_rescale_q(ch1->start, ch1->time_base,
ch->time_base);
if (j != i && next_start > ch->start && next_start < end)
end = next_start;
}
ch->end = (end == INT64_MAX || end < ch->start) ? ch->start : end;
}
}
static int get_std_framerate(int i)
{
if (i < 30*12)
return (i + 1) * 1001;
i -= 30*12;
if (i < 30)
return (i + 31) * 1001 * 12;
i -= 30;
if (i < 3)
return ((const int[]) { 80, 120, 240})[i] * 1001 * 12;
i -= 3;
return ((const int[]) { 24, 30, 60, 12, 15, 48 })[i] * 1000 * 12;
}
static int tb_unreliable(AVCodecContext *c)
{
if (c->time_base.den >= 101LL * c->time_base.num ||
c->time_base.den < 5LL * c->time_base.num ||
c->codec_tag == AV_RL32("mp4v") ||
c->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
c->codec_id == AV_CODEC_ID_GIF ||
c->codec_id == AV_CODEC_ID_HEVC ||
c->codec_id == AV_CODEC_ID_H264)
return 1;
return 0;
}
int ff_alloc_extradata(AVCodecParameters *par, int size)
{
av_freep(&par->extradata);
par->extradata_size = 0;
if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
return AVERROR(EINVAL);
par->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!par->extradata)
return AVERROR(ENOMEM);
memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
par->extradata_size = size;
return 0;
}
int ff_get_extradata(AVFormatContext *s, AVCodecParameters *par, AVIOContext *pb, int size)
{
int ret = ff_alloc_extradata(par, size);
if (ret < 0)
return ret;
ret = avio_read(pb, par->extradata, size);
if (ret != size) {
av_freep(&par->extradata);
par->extradata_size = 0;
av_log(s, AV_LOG_ERROR, "Failed to read extradata of size %d\n", size);
return ret < 0 ? ret : AVERROR_INVALIDDATA;
}
return ret;
}
int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t ts)
{
int i, j;
int64_t last = st->info->last_dts;
if ( ts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && ts > last
&& ts - (uint64_t)last < INT64_MAX) {
double dts = (is_relative(ts) ? ts - RELATIVE_TS_BASE : ts) * av_q2d(st->time_base);
int64_t duration = ts - last;
if (!st->info->duration_error)
st->info->duration_error = av_mallocz(sizeof(st->info->duration_error[0])*2);
if (!st->info->duration_error)
return AVERROR(ENOMEM);
for (i = 0; i<MAX_STD_TIMEBASES; i++) {
if (st->info->duration_error[0][1][i] < 1e10) {
int framerate = get_std_framerate(i);
double sdts = dts*framerate/(1001*12);
for (j= 0; j<2; j++) {
int64_t ticks = llrint(sdts+j*0.5);
double error= sdts - ticks + j*0.5;
st->info->duration_error[j][0][i] += error;
st->info->duration_error[j][1][i] += error*error;
}
}
}
if (st->info->rfps_duration_sum <= INT64_MAX - duration) {
st->info->duration_count++;
st->info->rfps_duration_sum += duration;
}
if (st->info->duration_count % 10 == 0) {
int n = st->info->duration_count;
for (i = 0; i<MAX_STD_TIMEBASES; i++) {
if (st->info->duration_error[0][1][i] < 1e10) {
double a0 = st->info->duration_error[0][0][i] / n;
double error0 = st->info->duration_error[0][1][i] / n - a0*a0;
double a1 = st->info->duration_error[1][0][i] / n;
double error1 = st->info->duration_error[1][1][i] / n - a1*a1;
if (error0 > 0.04 && error1 > 0.04) {
st->info->duration_error[0][1][i] = 2e10;
st->info->duration_error[1][1][i] = 2e10;
}
}
}
}
if (st->info->duration_count > 3 && is_relative(ts) == is_relative(last))
st->info->duration_gcd = av_gcd(st->info->duration_gcd, duration);
}
if (ts != AV_NOPTS_VALUE)
st->info->last_dts = ts;
return 0;
}
void ff_rfps_calculate(AVFormatContext *ic)
{
int i, j;
for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
continue;
if (tb_unreliable(st->internal->avctx) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num)
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX);
if (st->info->duration_count>1 && !st->r_frame_rate.num
&& tb_unreliable(st->internal->avctx)) {
int num = 0;
double best_error= 0.01;
AVRational ref_rate = st->r_frame_rate.num ? st->r_frame_rate : av_inv_q(st->time_base);
for (j= 0; j<MAX_STD_TIMEBASES; j++) {
int k;
if (st->info->codec_info_duration &&
st->info->codec_info_duration*av_q2d(st->time_base) < (1001*11.5)/get_std_framerate(j))
continue;
if (!st->info->codec_info_duration && get_std_framerate(j) < 1001*12)
continue;
if (av_q2d(st->time_base) * st->info->rfps_duration_sum / st->info->duration_count < (1001*12.0 * 0.8)/get_std_framerate(j))
continue;
for (k= 0; k<2; k++) {
int n = st->info->duration_count;
double a= st->info->duration_error[k][0][j] / n;
double error= st->info->duration_error[k][1][j]/n - a*a;
if (error < best_error && best_error> 0.000000001) {
best_error= error;
num = get_std_framerate(j);
}
if (error < 0.02)
av_log(ic, AV_LOG_DEBUG, "rfps: %f %f\n", get_std_framerate(j) / 12.0/1001, error);
}
}
if (num && (!ref_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(ref_rate)))
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
}
if ( !st->avg_frame_rate.num
&& st->r_frame_rate.num && st->info->rfps_duration_sum
&& st->info->codec_info_duration <= 0
&& st->info->duration_count > 2
&& fabs(1.0 / (av_q2d(st->r_frame_rate) * av_q2d(st->time_base)) - st->info->rfps_duration_sum / (double)st->info->duration_count) <= 1.0
) {
av_log(ic, AV_LOG_DEBUG, "Setting avg frame rate based on r frame rate\n");
st->avg_frame_rate = st->r_frame_rate;
}
av_freep(&st->info->duration_error);
st->info->last_dts = AV_NOPTS_VALUE;
st->info->duration_count = 0;
st->info->rfps_duration_sum = 0;
}
}
static int extract_extradata_check(AVStream *st)
{
const AVBitStreamFilter *f;
f = av_bsf_get_by_name("extract_extradata");
if (!f)
return 0;
if (f->codec_ids) {
const enum AVCodecID *ids;
for (ids = f->codec_ids; *ids != AV_CODEC_ID_NONE; ids++)
if (*ids == st->codecpar->codec_id)
return 1;
}
return 0;
}
static int extract_extradata_init(AVStream *st)
{
AVStreamInternal *sti = st->internal;
const AVBitStreamFilter *f;
int ret;
f = av_bsf_get_by_name("extract_extradata");
if (!f)
goto finish;
ret = extract_extradata_check(st);
if (!ret)
goto finish;
sti->extract_extradata.pkt = av_packet_alloc();
if (!sti->extract_extradata.pkt)
return AVERROR(ENOMEM);
ret = av_bsf_alloc(f, &sti->extract_extradata.bsf);
if (ret < 0)
goto fail;
ret = avcodec_parameters_copy(sti->extract_extradata.bsf->par_in,
st->codecpar);
if (ret < 0)
goto fail;
sti->extract_extradata.bsf->time_base_in = st->time_base;
ret = av_bsf_init(sti->extract_extradata.bsf);
if (ret < 0)
goto fail;
finish:
sti->extract_extradata.inited = 1;
return 0;
fail:
av_bsf_free(&sti->extract_extradata.bsf);
av_packet_free(&sti->extract_extradata.pkt);
return ret;
}
static int extract_extradata(AVStream *st, const AVPacket *pkt)
{
AVStreamInternal *sti = st->internal;
AVPacket *pkt_ref;
int ret;
if (!sti->extract_extradata.inited) {
ret = extract_extradata_init(st);
if (ret < 0)
return ret;
}
if (sti->extract_extradata.inited && !sti->extract_extradata.bsf)
return 0;
pkt_ref = sti->extract_extradata.pkt;
ret = av_packet_ref(pkt_ref, pkt);
if (ret < 0)
return ret;
ret = av_bsf_send_packet(sti->extract_extradata.bsf, pkt_ref);
if (ret < 0) {
av_packet_unref(pkt_ref);
return ret;
}
while (ret >= 0 && !sti->avctx->extradata) {
int extradata_size;
uint8_t *extradata;
ret = av_bsf_receive_packet(sti->extract_extradata.bsf, pkt_ref);
if (ret < 0) {
if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
return ret;
continue;
}
extradata = av_packet_get_side_data(pkt_ref, AV_PKT_DATA_NEW_EXTRADATA,
&extradata_size);
if (extradata) {
av_assert0(!sti->avctx->extradata);
if ((unsigned)extradata_size < FF_MAX_EXTRADATA_SIZE)
sti->avctx->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!sti->avctx->extradata) {
av_packet_unref(pkt_ref);
return AVERROR(ENOMEM);
}
memcpy(sti->avctx->extradata, extradata, extradata_size);
sti->avctx->extradata_size = extradata_size;
}
av_packet_unref(pkt_ref);
}
return 0;
}
static int add_coded_side_data(AVStream *st, AVCodecContext *avctx)
{
int i;
for (i = 0; i < avctx->nb_coded_side_data; i++) {
const AVPacketSideData *sd_src = &avctx->coded_side_data[i];
uint8_t *dst_data;
dst_data = av_stream_new_side_data(st, sd_src->type, sd_src->size);
if (!dst_data)
return AVERROR(ENOMEM);
memcpy(dst_data, sd_src->data, sd_src->size);
}
return 0;
}
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
{
int i, count = 0, ret = 0, j;
int64_t read_size;
AVStream *st;
AVCodecContext *avctx;
AVPacket pkt1;
int64_t old_offset = avio_tell(ic->pb);
int orig_nb_streams = ic->nb_streams;
int flush_codecs;
int64_t max_analyze_duration = ic->max_analyze_duration;
int64_t max_stream_analyze_duration;
int64_t max_subtitle_analyze_duration;
int64_t probesize = ic->probesize;
int eof_reached = 0;
int *missing_streams = av_opt_ptr(ic->iformat->priv_class, ic->priv_data, "missing_streams");
flush_codecs = probesize > 0;
av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN);
max_stream_analyze_duration = max_analyze_duration;
max_subtitle_analyze_duration = max_analyze_duration;
if (!max_analyze_duration) {
max_stream_analyze_duration =
max_analyze_duration = 5*AV_TIME_BASE;
max_subtitle_analyze_duration = 30*AV_TIME_BASE;
if (!strcmp(ic->iformat->name, "flv"))
max_stream_analyze_duration = 90*AV_TIME_BASE;
if (!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts"))
max_stream_analyze_duration = 7*AV_TIME_BASE;
}
if (ic->pb)
av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d nb_streams:%d\n",
avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, ic->nb_streams);
for (i = 0; i < ic->nb_streams; i++) {
const AVCodec *codec;
AVDictionary *thread_opt = NULL;
st = ic->streams[i];
avctx = st->internal->avctx;
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
if (!avctx->time_base.num)
avctx->time_base = st->time_base;
}
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
if (st->codec->codec_id != st->internal->orig_codec_id) {
st->codecpar->codec_id = st->codec->codec_id;
st->codecpar->codec_type = st->codec->codec_type;
st->internal->orig_codec_id = st->codec->codec_id;
}
FF_ENABLE_DEPRECATION_WARNINGS
#endif
if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE) && st->request_probe <= 0) {
st->parser = av_parser_init(st->codecpar->codec_id);
if (st->parser) {
if (st->need_parsing == AVSTREAM_PARSE_HEADERS) {
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
} else if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW) {
st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
}
} else if (st->need_parsing) {
av_log(ic, AV_LOG_VERBOSE, "parser not found for codec "
"%s, packets or times may be invalid.\n",
avcodec_get_name(st->codecpar->codec_id));
}
}
if (st->codecpar->codec_id != st->internal->orig_codec_id)
st->internal->orig_codec_id = st->codecpar->codec_id;
ret = avcodec_parameters_to_context(avctx, st->codecpar);
if (ret < 0)
goto find_stream_info_err;
if (st->request_probe <= 0)
st->internal->avctx_inited = 1;
codec = find_probe_decoder(ic, st, st->codecpar->codec_id);
av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0);
if (ic->codec_whitelist)
av_dict_set(options ? &options[i] : &thread_opt, "codec_whitelist", ic->codec_whitelist, 0);
if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE
&& codec && !avctx->codec) {
if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0)
av_log(ic, AV_LOG_WARNING,
"Failed to open codec in %s\n",__FUNCTION__);
}
if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) {
if (codec && !avctx->codec)
if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0)
av_log(ic, AV_LOG_WARNING,
"Failed to open codec in %s\n",__FUNCTION__);
}
if (!options)
av_dict_free(&thread_opt);
}
for (i = 0; i < ic->nb_streams; i++) {
#if FF_API_R_FRAME_RATE
ic->streams[i]->info->last_dts = AV_NOPTS_VALUE;
#endif
ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE;
ic->streams[i]->info->fps_last_dts = AV_NOPTS_VALUE;
}
read_size = 0;
for (;;) {
const AVPacket *pkt;
int analyzed_all_streams;
if (ff_check_interrupt(&ic->interrupt_callback)) {
ret = AVERROR_EXIT;
av_log(ic, AV_LOG_DEBUG, "interrupted\n");
break;
}
for (i = 0; i < ic->nb_streams; i++) {
int fps_analyze_framecount = 20;
int count;
st = ic->streams[i];
if (!has_codec_parameters(st, NULL))
break;
if (av_q2d(st->time_base) > 0.0005)
fps_analyze_framecount *= 2;
if (!tb_unreliable(st->internal->avctx))
fps_analyze_framecount = 0;
if (ic->fps_probe_size >= 0)
fps_analyze_framecount = ic->fps_probe_size;
if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
fps_analyze_framecount = 0;
count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ?
st->info->codec_info_duration_fields/2 :
st->info->duration_count;
if (!(st->r_frame_rate.num && st->avg_frame_rate.num) &&
st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (count < fps_analyze_framecount)
break;
}
if (st->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0)
break;
if (!st->internal->avctx->extradata &&
(!st->internal->extract_extradata.inited ||
st->internal->extract_extradata.bsf) &&
extract_extradata_check(st))
break;
if (st->first_dts == AV_NOPTS_VALUE &&
!(ic->iformat->flags & AVFMT_NOTIMESTAMPS) &&
st->codec_info_nb_frames < ((st->disposition & AV_DISPOSITION_ATTACHED_PIC) ? 1 : ic->max_ts_probe) &&
(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))
break;
}
analyzed_all_streams = 0;
if (!missing_streams || !*missing_streams)
if (i == ic->nb_streams) {
analyzed_all_streams = 1;
if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {
ret = count;
av_log(ic, AV_LOG_DEBUG, "All info found\n");
flush_codecs = 0;
break;
}
}
if (read_size >= probesize) {
ret = count;
av_log(ic, AV_LOG_DEBUG,
"Probe buffer size limit of %"PRId64" bytes reached\n", probesize);
for (i = 0; i < ic->nb_streams; i++)
if (!ic->streams[i]->r_frame_rate.num &&
ic->streams[i]->info->duration_count <= 1 &&
ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
strcmp(ic->iformat->name, "image2"))
av_log(ic, AV_LOG_WARNING,
"Stream #%d: not enough frames to estimate rate; "
"consider increasing probesize\n", i);
break;
}
ret = read_frame_internal(ic, &pkt1);
if (ret == AVERROR(EAGAIN))
continue;
if (ret < 0) {
eof_reached = 1;
break;
}
if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) {
ret = ff_packet_list_put(&ic->internal->packet_buffer,
&ic->internal->packet_buffer_end,
&pkt1, 0);
if (ret < 0)
goto unref_then_goto_end;
pkt = &ic->internal->packet_buffer_end->pkt;
} else {
pkt = &pkt1;
}
st = ic->streams[pkt->stream_index];
if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC))
read_size += pkt->size;
avctx = st->internal->avctx;
if (!st->internal->avctx_inited) {
ret = avcodec_parameters_to_context(avctx, st->codecpar);
if (ret < 0)
goto unref_then_goto_end;
st->internal->avctx_inited = 1;
}
if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {
if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
st->info->fps_last_dts >= pkt->dts) {
av_log(ic, AV_LOG_DEBUG,
"Non-increasing DTS in stream %d: packet %d with DTS "
"%"PRId64", packet %d with DTS %"PRId64"\n",
st->index, st->info->fps_last_dts_idx,
st->info->fps_last_dts, st->codec_info_nb_frames,
pkt->dts);
st->info->fps_first_dts =
st->info->fps_last_dts = AV_NOPTS_VALUE;
}
if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
st->info->fps_last_dts_idx > st->info->fps_first_dts_idx &&
(pkt->dts - (uint64_t)st->info->fps_last_dts) / 1000 >
(st->info->fps_last_dts - (uint64_t)st->info->fps_first_dts) /
(st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) {
av_log(ic, AV_LOG_WARNING,
"DTS discontinuity in stream %d: packet %d with DTS "
"%"PRId64", packet %d with DTS %"PRId64"\n",
st->index, st->info->fps_last_dts_idx,
st->info->fps_last_dts, st->codec_info_nb_frames,
pkt->dts);
st->info->fps_first_dts =
st->info->fps_last_dts = AV_NOPTS_VALUE;
}
if (st->info->fps_first_dts == AV_NOPTS_VALUE) {
st->info->fps_first_dts = pkt->dts;
st->info->fps_first_dts_idx = st->codec_info_nb_frames;
}
st->info->fps_last_dts = pkt->dts;
st->info->fps_last_dts_idx = st->codec_info_nb_frames;
}
if (st->codec_info_nb_frames>1) {
int64_t t = 0;
int64_t limit;
if (st->time_base.den > 0)
t = av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q);
if (st->avg_frame_rate.num > 0)
t = FFMAX(t, av_rescale_q(st->codec_info_nb_frames, av_inv_q(st->avg_frame_rate), AV_TIME_BASE_Q));
if ( t == 0
&& st->codec_info_nb_frames>30
&& st->info->fps_first_dts != AV_NOPTS_VALUE
&& st->info->fps_last_dts != AV_NOPTS_VALUE)
t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q));
if (analyzed_all_streams) limit = max_analyze_duration;
else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) limit = max_subtitle_analyze_duration;
else limit = max_stream_analyze_duration;
if (t >= limit) {
av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %"PRId64" reached at %"PRId64" microseconds st:%d\n",
limit,
t, pkt->stream_index);
if (ic->flags & AVFMT_FLAG_NOBUFFER)
av_packet_unref(&pkt1);
break;
}
if (pkt->duration) {
if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE && pkt->pts != AV_NOPTS_VALUE && st->start_time != AV_NOPTS_VALUE && pkt->pts >= st->start_time) {
st->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, st->info->codec_info_duration + pkt->duration);
} else
st->info->codec_info_duration += pkt->duration;
st->info->codec_info_duration_fields += st->parser && st->need_parsing && avctx->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2;
}
}
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
#if FF_API_R_FRAME_RATE
ff_rfps_add_frame(ic, st, pkt->dts);
#endif
if (pkt->dts != pkt->pts && pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE)
st->info->frame_delay_evidence = 1;
}
if (!st->internal->avctx->extradata) {
ret = extract_extradata(st, pkt);
if (ret < 0)
goto unref_then_goto_end;
}
try_decode_frame(ic, st, pkt,
(options && i < orig_nb_streams) ? &options[i] : NULL);
if (ic->flags & AVFMT_FLAG_NOBUFFER)
av_packet_unref(&pkt1);
st->codec_info_nb_frames++;
count++;
}
if (eof_reached) {
int stream_index;
for (stream_index = 0; stream_index < ic->nb_streams; stream_index++) {
st = ic->streams[stream_index];
avctx = st->internal->avctx;
if (!has_codec_parameters(st, NULL)) {
const AVCodec *codec = find_probe_decoder(ic, st, st->codecpar->codec_id);
if (codec && !avctx->codec) {
AVDictionary *opts = NULL;
if (ic->codec_whitelist)
av_dict_set(&opts, "codec_whitelist", ic->codec_whitelist, 0);
if (avcodec_open2(avctx, codec, (options && stream_index < orig_nb_streams) ? &options[stream_index] : &opts) < 0)
av_log(ic, AV_LOG_WARNING,
"Failed to open codec in %s\n",__FUNCTION__);
av_dict_free(&opts);
}
}
if (ic->internal->packet_buffer && !has_decode_delay_been_guessed(st)) {
update_dts_from_pts(ic, stream_index, ic->internal->packet_buffer);
}
}
}
if (flush_codecs) {
AVPacket empty_pkt = { 0 };
int err = 0;
av_init_packet(&empty_pkt);
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->info->found_decoder == 1) {
do {
err = try_decode_frame(ic, st, &empty_pkt,
(options && i < orig_nb_streams)
? &options[i] : NULL);
} while (err > 0 && !has_codec_parameters(st, NULL));
if (err < 0) {
av_log(ic, AV_LOG_INFO,
"decoding for stream %d failed\n", st->index);
}
}
}
}
ff_rfps_calculate(ic);
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
avctx = st->internal->avctx;
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
if (avctx->codec_id == AV_CODEC_ID_RAWVIDEO && !avctx->codec_tag && !avctx->bits_per_coded_sample) {
uint32_t tag= avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt);
if (avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), tag) == avctx->pix_fmt)
avctx->codec_tag= tag;
}
if (st->info->codec_info_duration_fields &&
!st->avg_frame_rate.num &&
st->info->codec_info_duration) {
int best_fps = 0;
double best_error = 0.01;
AVRational codec_frame_rate = avctx->framerate;
if (st->info->codec_info_duration >= INT64_MAX / st->time_base.num / 2||
st->info->codec_info_duration_fields >= INT64_MAX / st->time_base.den ||
st->info->codec_info_duration < 0)
continue;
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
st->info->codec_info_duration_fields * (int64_t) st->time_base.den,
st->info->codec_info_duration * 2 * (int64_t) st->time_base.num, 60000);
for (j = 0; j < MAX_STD_TIMEBASES; j++) {
AVRational std_fps = { get_std_framerate(j), 12 * 1001 };
double error = fabs(av_q2d(st->avg_frame_rate) /
av_q2d(std_fps) - 1);
if (error < best_error) {
best_error = error;
best_fps = std_fps.num;
}
if (ic->internal->prefer_codec_framerate && codec_frame_rate.num > 0 && codec_frame_rate.den > 0) {
error = fabs(av_q2d(codec_frame_rate) /
av_q2d(std_fps) - 1);
if (error < best_error) {
best_error = error;
best_fps = std_fps.num;
}
}
}
if (best_fps)
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
best_fps, 12 * 1001, INT_MAX);
}
if (!st->r_frame_rate.num) {
if ( avctx->time_base.den * (int64_t) st->time_base.num
<= avctx->time_base.num * avctx->ticks_per_frame * (uint64_t) st->time_base.den) {
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
avctx->time_base.den, (int64_t)avctx->time_base.num * avctx->ticks_per_frame, INT_MAX);
} else {
st->r_frame_rate.num = st->time_base.den;
st->r_frame_rate.den = st->time_base.num;
}
}
if (st->display_aspect_ratio.num && st->display_aspect_ratio.den) {
AVRational hw_ratio = { avctx->height, avctx->width };
st->sample_aspect_ratio = av_mul_q(st->display_aspect_ratio,
hw_ratio);
}
} else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
if (!avctx->bits_per_coded_sample)
avctx->bits_per_coded_sample =
av_get_bits_per_sample(avctx->codec_id);
switch (avctx->audio_service_type) {
case AV_AUDIO_SERVICE_TYPE_EFFECTS:
st->disposition = AV_DISPOSITION_CLEAN_EFFECTS;
break;
case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED:
st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED;
break;
case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED:
st->disposition = AV_DISPOSITION_HEARING_IMPAIRED;
break;
case AV_AUDIO_SERVICE_TYPE_COMMENTARY:
st->disposition = AV_DISPOSITION_COMMENT;
break;
case AV_AUDIO_SERVICE_TYPE_KARAOKE:
st->disposition = AV_DISPOSITION_KARAOKE;
break;
}
}
}
if (probesize)
estimate_timings(ic, old_offset);
av_opt_set(ic, "skip_clear", "0", AV_OPT_SEARCH_CHILDREN);
if (ret >= 0 && ic->nb_streams)
ret = -1;
for (i = 0; i < ic->nb_streams; i++) {
const char *errmsg;
st = ic->streams[i];
if (!st->internal->avctx_inited) {
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
st->codecpar->format == AV_SAMPLE_FMT_NONE)
st->codecpar->format = st->internal->avctx->sample_fmt;
ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
if (ret < 0)
goto find_stream_info_err;
}
if (!has_codec_parameters(st, &errmsg)) {
char buf[256];
avcodec_string(buf, sizeof(buf), st->internal->avctx, 0);
av_log(ic, AV_LOG_WARNING,
"Could not find codec parameters for stream %d (%s): %s\n"
"Consider increasing the value for the 'analyzeduration' and 'probesize' options\n",
i, buf, errmsg);
} else {
ret = 0;
}
}
compute_chapters_end(ic);
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->internal->avctx_inited) {
int orig_w = st->codecpar->width;
int orig_h = st->codecpar->height;
ret = avcodec_parameters_from_context(st->codecpar, st->internal->avctx);
if (ret < 0)
goto find_stream_info_err;
ret = add_coded_side_data(st, st->internal->avctx);
if (ret < 0)
goto find_stream_info_err;
#if FF_API_LOWRES
if (st->internal->avctx->lowres && orig_w) {
st->codecpar->width = orig_w;
st->codecpar->height = orig_h;
}
#endif
}
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
ret = avcodec_parameters_to_context(st->codec, st->codecpar);
if (ret < 0)
goto find_stream_info_err;
#if FF_API_LOWRES
if (st->internal->avctx->lowres && st->internal->avctx->width) {
st->codec->lowres = st->internal->avctx->lowres;
st->codec->width = st->internal->avctx->width;
st->codec->height = st->internal->avctx->height;
}
#endif
if (st->codec->codec_tag != MKTAG('t','m','c','d')) {
st->codec->time_base = st->internal->avctx->time_base;
st->codec->ticks_per_frame = st->internal->avctx->ticks_per_frame;
}
st->codec->framerate = st->avg_frame_rate;
if (st->internal->avctx->subtitle_header) {
st->codec->subtitle_header = av_malloc(st->internal->avctx->subtitle_header_size);
if (!st->codec->subtitle_header)
goto find_stream_info_err;
st->codec->subtitle_header_size = st->internal->avctx->subtitle_header_size;
memcpy(st->codec->subtitle_header, st->internal->avctx->subtitle_header,
st->codec->subtitle_header_size);
}
st->codec->coded_width = st->internal->avctx->coded_width;
st->codec->coded_height = st->internal->avctx->coded_height;
st->codec->properties = st->internal->avctx->properties;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
st->internal->avctx_inited = 0;
}
find_stream_info_err:
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->info)
av_freep(&st->info->duration_error);
avcodec_close(ic->streams[i]->internal->avctx);
av_freep(&ic->streams[i]->info);
av_bsf_free(&ic->streams[i]->internal->extract_extradata.bsf);
av_packet_free(&ic->streams[i]->internal->extract_extradata.pkt);
}
if (ic->pb)
av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n",
avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, count);
return ret;
unref_then_goto_end:
av_packet_unref(&pkt1);
goto find_stream_info_err;
}
AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s)
{
int i, j;
for (i = 0; i < ic->nb_programs; i++) {
if (ic->programs[i] == last) {
last = NULL;
} else {
if (!last)
for (j = 0; j < ic->programs[i]->nb_stream_indexes; j++)
if (ic->programs[i]->stream_index[j] == s)
return ic->programs[i];
}
}
return NULL;
}
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
int wanted_stream_nb, int related_stream,
AVCodec **decoder_ret, int flags)
{
int i, nb_streams = ic->nb_streams;
int ret = AVERROR_STREAM_NOT_FOUND;
int best_count = -1, best_multiframe = -1, best_disposition = -1;
int count, multiframe, disposition;
int64_t best_bitrate = -1;
int64_t bitrate;
unsigned *program = NULL;
const AVCodec *decoder = NULL, *best_decoder = NULL;
if (related_stream >= 0 && wanted_stream_nb < 0) {
AVProgram *p = av_find_program_from_stream(ic, NULL, related_stream);
if (p) {
program = p->stream_index;
nb_streams = p->nb_stream_indexes;
}
}
for (i = 0; i < nb_streams; i++) {
int real_stream_index = program ? program[i] : i;
AVStream *st = ic->streams[real_stream_index];
AVCodecParameters *par = st->codecpar;
if (par->codec_type != type)
continue;
if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb)
continue;
if (type == AVMEDIA_TYPE_AUDIO && !(par->channels && par->sample_rate))
continue;
if (decoder_ret) {
decoder = find_decoder(ic, st, par->codec_id);
if (!decoder) {
if (ret < 0)
ret = AVERROR_DECODER_NOT_FOUND;
continue;
}
}
disposition = !(st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED | AV_DISPOSITION_VISUAL_IMPAIRED))
+ !! (st->disposition & AV_DISPOSITION_DEFAULT);
count = st->codec_info_nb_frames;
bitrate = par->bit_rate;
multiframe = FFMIN(5, count);
if ((best_disposition > disposition) ||
(best_disposition == disposition && best_multiframe > multiframe) ||
(best_disposition == disposition && best_multiframe == multiframe && best_bitrate > bitrate) ||
(best_disposition == disposition && best_multiframe == multiframe && best_bitrate == bitrate && best_count >= count))
continue;
best_disposition = disposition;
best_count = count;
best_bitrate = bitrate;
best_multiframe = multiframe;
ret = real_stream_index;
best_decoder = decoder;
if (program && i == nb_streams - 1 && ret < 0) {
program = NULL;
nb_streams = ic->nb_streams;
i = 0;
}
}
if (decoder_ret)
*decoder_ret = (AVCodec*)best_decoder;
return ret;
}
int av_read_play(AVFormatContext *s)
{
if (s->iformat->read_play)
return s->iformat->read_play(s);
if (s->pb)
return avio_pause(s->pb, 0);
return AVERROR(ENOSYS);
}
int av_read_pause(AVFormatContext *s)
{
if (s->iformat->read_pause)
return s->iformat->read_pause(s);
if (s->pb)
return avio_pause(s->pb, 1);
return AVERROR(ENOSYS);
}
int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src)
{
int ret, i;
dst->id = src->id;
dst->time_base = src->time_base;
dst->nb_frames = src->nb_frames;
dst->disposition = src->disposition;
dst->sample_aspect_ratio = src->sample_aspect_ratio;
dst->avg_frame_rate = src->avg_frame_rate;
dst->r_frame_rate = src->r_frame_rate;
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;
for (i = 0; i < dst->nb_side_data; i++)
av_free(dst->side_data[i].data);
av_freep(&dst->side_data);
dst->nb_side_data = 0;
if (src->nb_side_data) {
dst->side_data = av_mallocz_array(src->nb_side_data,
sizeof(AVPacketSideData));
if (!dst->side_data)
return AVERROR(ENOMEM);
dst->nb_side_data = src->nb_side_data;
for (i = 0; i < src->nb_side_data; i++) {
uint8_t *data = av_memdup(src->side_data[i].data,
src->side_data[i].size);
if (!data)
return AVERROR(ENOMEM);
dst->side_data[i].type = src->side_data[i].type;
dst->side_data[i].size = src->side_data[i].size;
dst->side_data[i].data = data;
}
}
#if FF_API_LAVF_FFSERVER
FF_DISABLE_DEPRECATION_WARNINGS
av_freep(&dst->recommended_encoder_configuration);
if (src->recommended_encoder_configuration) {
const char *conf_str = src->recommended_encoder_configuration;
dst->recommended_encoder_configuration = av_strdup(conf_str);
if (!dst->recommended_encoder_configuration)
return AVERROR(ENOMEM);
}
FF_ENABLE_DEPRECATION_WARNINGS
#endif
return 0;
}
static void free_stream(AVStream **pst)
{
AVStream *st = *pst;
int i;
if (!st)
return;
for (i = 0; i < st->nb_side_data; i++)
av_freep(&st->side_data[i].data);
av_freep(&st->side_data);
if (st->parser)
av_parser_close(st->parser);
if (st->attached_pic.data)
av_packet_unref(&st->attached_pic);
if (st->internal) {
avcodec_free_context(&st->internal->avctx);
av_bsf_free(&st->internal->bsfc);
av_freep(&st->internal->priv_pts);
av_bsf_free(&st->internal->extract_extradata.bsf);
av_packet_free(&st->internal->extract_extradata.pkt);
}
av_freep(&st->internal);
av_dict_free(&st->metadata);
avcodec_parameters_free(&st->codecpar);
av_freep(&st->probe_data.buf);
av_freep(&st->index_entries);
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
avcodec_free_context(&st->codec);
FF_ENABLE_DEPRECATION_WARNINGS
#endif
av_freep(&st->priv_data);
if (st->info)
av_freep(&st->info->duration_error);
av_freep(&st->info);
#if FF_API_LAVF_FFSERVER
FF_DISABLE_DEPRECATION_WARNINGS
av_freep(&st->recommended_encoder_configuration);
FF_ENABLE_DEPRECATION_WARNINGS
#endif
av_freep(pst);
}
void ff_free_stream(AVFormatContext *s, AVStream *st)
{
av_assert0(s->nb_streams>0);
av_assert0(s->streams[ s->nb_streams - 1 ] == st);
free_stream(&s->streams[ --s->nb_streams ]);
}
void avformat_free_context(AVFormatContext *s)
{
int i;
if (!s)
return;
if (s->oformat && s->oformat->deinit && s->internal->initialized)
s->oformat->deinit(s);
av_opt_free(s);
if (s->iformat && s->iformat->priv_class && s->priv_data)
av_opt_free(s->priv_data);
if (s->oformat && s->oformat->priv_class && s->priv_data)
av_opt_free(s->priv_data);
for (i = 0; i < s->nb_streams; i++)
free_stream(&s->streams[i]);
s->nb_streams = 0;
for (i = 0; i < s->nb_programs; i++) {
av_dict_free(&s->programs[i]->metadata);
av_freep(&s->programs[i]->stream_index);
av_freep(&s->programs[i]);
}
s->nb_programs = 0;
av_freep(&s->programs);
av_freep(&s->priv_data);
while (s->nb_chapters--) {
av_dict_free(&s->chapters[s->nb_chapters]->metadata);
av_freep(&s->chapters[s->nb_chapters]);
}
av_freep(&s->chapters);
av_dict_free(&s->metadata);
av_dict_free(&s->internal->id3v2_meta);
av_freep(&s->streams);
flush_packet_queue(s);
av_freep(&s->internal);
av_freep(&s->url);
av_free(s);
}
void avformat_close_input(AVFormatContext **ps)
{
AVFormatContext *s;
AVIOContext *pb;
if (!ps || !*ps)
return;
s = *ps;
pb = s->pb;
if ((s->iformat && strcmp(s->iformat->name, "image2") && s->iformat->flags & AVFMT_NOFILE) ||
(s->flags & AVFMT_FLAG_CUSTOM_IO))
pb = NULL;
flush_packet_queue(s);
if (s->iformat)
if (s->iformat->read_close)
s->iformat->read_close(s);
avformat_free_context(s);
*ps = NULL;
avio_close(pb);
}
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
{
AVStream *st;
int i;
AVStream **streams;
if (s->nb_streams >= FFMIN(s->max_streams, INT_MAX/sizeof(*streams))) {
if (s->max_streams < INT_MAX/sizeof(*streams))
av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter (%d), see the documentation if you wish to increase it\n", s->max_streams);
return NULL;
}
streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));
if (!streams)
return NULL;
s->streams = streams;
st = av_mallocz(sizeof(AVStream));
if (!st)
return NULL;
if (!(st->info = av_mallocz(sizeof(*st->info)))) {
av_free(st);
return NULL;
}
st->info->last_dts = AV_NOPTS_VALUE;
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
st->codec = avcodec_alloc_context3(c);
if (!st->codec) {
av_free(st->info);
av_free(st);
return NULL;
}
FF_ENABLE_DEPRECATION_WARNINGS
#endif
st->internal = av_mallocz(sizeof(*st->internal));
if (!st->internal)
goto fail;
st->codecpar = avcodec_parameters_alloc();
if (!st->codecpar)
goto fail;
st->internal->avctx = avcodec_alloc_context3(NULL);
if (!st->internal->avctx)
goto fail;
if (s->iformat) {
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
st->codec->bit_rate = 0;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
avpriv_set_pts_info(st, 33, 1, 90000);
st->cur_dts = RELATIVE_TS_BASE;
} else {
st->cur_dts = AV_NOPTS_VALUE;
}
st->index = s->nb_streams;
st->start_time = AV_NOPTS_VALUE;
st->duration = AV_NOPTS_VALUE;
st->first_dts = AV_NOPTS_VALUE;
st->probe_packets = s->max_probe_packets;
st->pts_wrap_reference = AV_NOPTS_VALUE;
st->pts_wrap_behavior = AV_PTS_WRAP_IGNORE;
st->last_IP_pts = AV_NOPTS_VALUE;
st->last_dts_for_order_check = AV_NOPTS_VALUE;
for (i = 0; i < MAX_REORDER_DELAY + 1; i++)
st->pts_buffer[i] = AV_NOPTS_VALUE;
st->sample_aspect_ratio = (AVRational) { 0, 1 };
#if FF_API_R_FRAME_RATE
st->info->last_dts = AV_NOPTS_VALUE;
#endif
st->info->fps_first_dts = AV_NOPTS_VALUE;
st->info->fps_last_dts = AV_NOPTS_VALUE;
st->inject_global_side_data = s->internal->inject_global_side_data;
st->internal->need_context_update = 1;
s->streams[s->nb_streams++] = st;
return st;
fail:
free_stream(&st);
return NULL;
}
AVProgram *av_new_program(AVFormatContext *ac, int id)
{
AVProgram *program = NULL;
int i;
av_log(ac, AV_LOG_TRACE, "new_program: id=0x%04x\n", id);
for (i = 0; i < ac->nb_programs; i++)
if (ac->programs[i]->id == id)
program = ac->programs[i];
if (!program) {
program = av_mallocz(sizeof(AVProgram));
if (!program)
return NULL;
dynarray_add(&ac->programs, &ac->nb_programs, program);
program->discard = AVDISCARD_NONE;
program->pmt_version = -1;
}
program->id = id;
program->pts_wrap_reference = AV_NOPTS_VALUE;
program->pts_wrap_behavior = AV_PTS_WRAP_IGNORE;
program->start_time =
program->end_time = AV_NOPTS_VALUE;
return program;
}
AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base,
int64_t start, int64_t end, const char *title)
{
AVChapter *chapter = NULL;
int i;
if (end != AV_NOPTS_VALUE && start > end) {
av_log(s, AV_LOG_ERROR, "Chapter end time %"PRId64" before start %"PRId64"\n", end, start);
return NULL;
}
for (i = 0; i < s->nb_chapters; i++)
if (s->chapters[i]->id == id)
chapter = s->chapters[i];
if (!chapter) {
chapter = av_mallocz(sizeof(AVChapter));
if (!chapter)
return NULL;
dynarray_add(&s->chapters, &s->nb_chapters, chapter);
}
av_dict_set(&chapter->metadata, "title", title, 0);
chapter->id = id;
chapter->time_base = time_base;
chapter->start = start;
chapter->end = end;
return chapter;
}
void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned idx)
{
int i, j;
AVProgram *program = NULL;
void *tmp;
if (idx >= ac->nb_streams) {
av_log(ac, AV_LOG_ERROR, "stream index %d is not valid\n", idx);
return;
}
for (i = 0; i < ac->nb_programs; i++) {
if (ac->programs[i]->id != progid)
continue;
program = ac->programs[i];
for (j = 0; j < program->nb_stream_indexes; j++)
if (program->stream_index[j] == idx)
return;
tmp = av_realloc_array(program->stream_index, program->nb_stream_indexes+1, sizeof(unsigned int));
if (!tmp)
return;
program->stream_index = tmp;
program->stream_index[program->nb_stream_indexes++] = idx;
return;
}
}
uint64_t ff_ntp_time(void)
{
return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
}
uint64_t ff_get_formatted_ntp_time(uint64_t ntp_time_us)
{
uint64_t ntp_ts, frac_part, sec;
uint32_t usec;
sec = ntp_time_us / 1000000;
usec = ntp_time_us % 1000000;
frac_part = usec * 0xFFFFFFFFULL;
frac_part /= 1000000;
if (sec > 0xFFFFFFFFULL)
av_log(NULL, AV_LOG_WARNING, "NTP time format roll over detected\n");
ntp_ts = sec << 32;
ntp_ts |= frac_part;
return ntp_ts;
}
int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags)
{
const char *p;
char *q, buf1[20], c;
int nd, len, percentd_found;
q = buf;
p = path;
percentd_found = 0;
for (;;) {
c = *p++;
if (c == '\0')
break;
if (c == '%') {
do {
nd = 0;
while (av_isdigit(*p))
nd = nd * 10 + *p++ - '0';
c = *p++;
} while (av_isdigit(c));
switch (c) {
case '%':
goto addchar;
case 'd':
if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentd_found)
goto fail;
percentd_found = 1;
if (number < 0)
nd += 1;
snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
len = strlen(buf1);
if ((q - buf + len) > buf_size - 1)
goto fail;
memcpy(q, buf1, len);
q += len;
break;
default:
goto fail;
}
} else {
addchar:
if ((q - buf) < buf_size - 1)
*q++ = c;
}
}
if (!percentd_found)
goto fail;
*q = '\0';
return 0;
fail:
*q = '\0';
return -1;
}
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
{
return av_get_frame_filename2(buf, buf_size, path, number, 0);
}
void av_url_split(char *proto, int proto_size,
char *authorization, int authorization_size,
char *hostname, int hostname_size,
int *port_ptr, char *path, int path_size, const char *url)
{
const char *p, *ls, *at, *at2, *col, *brk;
if (port_ptr)
*port_ptr = -1;
if (proto_size > 0)
proto[0] = 0;
if (authorization_size > 0)
authorization[0] = 0;
if (hostname_size > 0)
hostname[0] = 0;
if (path_size > 0)
path[0] = 0;
if ((p = strchr(url, ':'))) {
av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url));
p++;
if (*p == '/')
p++;
if (*p == '/')
p++;
} else {
av_strlcpy(path, url, path_size);
return;
}
ls = p + strcspn(p, "/?#");
av_strlcpy(path, ls, path_size);
if (ls != p) {
at2 = p;
while ((at = strchr(p, '@')) && at < ls) {
av_strlcpy(authorization, at2,
FFMIN(authorization_size, at + 1 - at2));
p = at + 1;
}
if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) {
av_strlcpy(hostname, p + 1,
FFMIN(hostname_size, brk - p));
if (brk[1] == ':' && port_ptr)
*port_ptr = atoi(brk + 2);
} else if ((col = strchr(p, ':')) && col < ls) {
av_strlcpy(hostname, p,
FFMIN(col + 1 - p, hostname_size));
if (port_ptr)
*port_ptr = atoi(col + 1);
} else
av_strlcpy(hostname, p,
FFMIN(ls + 1 - p, hostname_size));
}
}
int ff_mkdir_p(const char *path)
{
int ret = 0;
char *temp = av_strdup(path);
char *pos = temp;
char tmp_ch = '\0';
if (!path || !temp) {
return -1;
}
if (!av_strncasecmp(temp, "/", 1) || !av_strncasecmp(temp, "\\", 1)) {
pos++;
} else if (!av_strncasecmp(temp, "./", 2) || !av_strncasecmp(temp, ".\\", 2)) {
pos += 2;
}
for ( ; *pos != '\0'; ++pos) {
if (*pos == '/' || *pos == '\\') {
tmp_ch = *pos;
*pos = '\0';
ret = mkdir(temp, 0755);
*pos = tmp_ch;
}
}
if ((*(pos - 1) != '/') || (*(pos - 1) != '\\')) {
ret = mkdir(temp, 0755);
}
av_free(temp);
return ret;
}
char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase)
{
int i;
static const char hex_table_uc[16] = { '0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'A', 'B',
'C', 'D', 'E', 'F' };
static const char hex_table_lc[16] = { '0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f' };
const char *hex_table = lowercase ? hex_table_lc : hex_table_uc;
for (i = 0; i < s; i++) {
buff[i * 2] = hex_table[src[i] >> 4];
buff[i * 2 + 1] = hex_table[src[i] & 0xF];
}
return buff;
}
int ff_hex_to_data(uint8_t *data, const char *p)
{
int c, len, v;
len = 0;
v = 1;
for (;;) {
p += strspn(p, SPACE_CHARS);
if (*p == '\0')
break;
c = av_toupper((unsigned char) *p++);
if (c >= '0' && c <= '9')
c = c - '0';
else if (c >= 'A' && c <= 'F')
c = c - 'A' + 10;
else
break;
v = (v << 4) | c;
if (v & 0x100) {
if (data)
data[len] = v;
len++;
v = 1;
}
}
return len;
}
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits,
unsigned int pts_num, unsigned int pts_den)
{
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",
s->index, pts_num / new_tb.num);
} else
av_log(NULL, AV_LOG_WARNING,
"st:%d has too large timebase, reducing\n", s->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,
s->index);
return;
}
s->time_base = new_tb;
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
s->codec->pkt_timebase = new_tb;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
s->internal->avctx->pkt_timebase = new_tb;
s->pts_wrap_bits = pts_wrap_bits;
}
void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf,
void *context)
{
const char *ptr = str;
for (;;) {
const char *key;
char *dest = NULL, *dest_end;
int key_len, dest_len = 0;
while (*ptr && (av_isspace(*ptr) || *ptr == ','))
ptr++;
if (!*ptr)
break;
key = ptr;
if (!(ptr = strchr(key, '=')))
break;
ptr++;
key_len = ptr - key;
callback_get_buf(context, key, key_len, &dest, &dest_len);
dest_end = dest + dest_len - 1;
if (*ptr == '\"') {
ptr++;
while (*ptr && *ptr != '\"') {
if (*ptr == '\\') {
if (!ptr[1])
break;
if (dest && dest < dest_end)
*dest++ = ptr[1];
ptr += 2;
} else {
if (dest && dest < dest_end)
*dest++ = *ptr;
ptr++;
}
}
if (*ptr == '\"')
ptr++;
} else {
for (; *ptr && !(av_isspace(*ptr) || *ptr == ','); ptr++)
if (dest && dest < dest_end)
*dest++ = *ptr;
}
if (dest)
*dest = 0;
}
}
int ff_find_stream_index(AVFormatContext *s, int id)
{
int i;
for (i = 0; i < s->nb_streams; i++)
if (s->streams[i]->id == id)
return i;
return -1;
}
int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
int std_compliance)
{
if (ofmt) {
unsigned int codec_tag;
if (ofmt->query_codec)
return ofmt->query_codec(codec_id, std_compliance);
else if (ofmt->codec_tag)
return !!av_codec_get_tag2(ofmt->codec_tag, codec_id, &codec_tag);
else if (codec_id == ofmt->video_codec ||
codec_id == ofmt->audio_codec ||
codec_id == ofmt->subtitle_codec ||
codec_id == ofmt->data_codec)
return 1;
}
return AVERROR_PATCHWELCOME;
}
int avformat_network_init(void)
{
#if CONFIG_NETWORK
int ret;
if ((ret = ff_network_init()) < 0)
return ret;
if ((ret = ff_tls_init()) < 0)
return ret;
#endif
return 0;
}
int avformat_network_deinit(void)
{
#if CONFIG_NETWORK
ff_network_close();
ff_tls_deinit();
#endif
return 0;
}
int ff_add_param_change(AVPacket *pkt, int32_t channels,
uint64_t channel_layout, int32_t sample_rate,
int32_t width, int32_t height)
{
uint32_t flags = 0;
int size = 4;
uint8_t *data;
if (!pkt)
return AVERROR(EINVAL);
if (channels) {
size += 4;
flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT;
}
if (channel_layout) {
size += 8;
flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT;
}
if (sample_rate) {
size += 4;
flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE;
}
if (width || height) {
size += 8;
flags |= AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS;
}
data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size);
if (!data)
return AVERROR(ENOMEM);
bytestream_put_le32(&data, flags);
if (channels)
bytestream_put_le32(&data, channels);
if (channel_layout)
bytestream_put_le64(&data, channel_layout);
if (sample_rate)
bytestream_put_le32(&data, sample_rate);
if (width || height) {
bytestream_put_le32(&data, width);
bytestream_put_le32(&data, height);
}
return 0;
}
AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame)
{
AVRational undef = {0, 1};
AVRational stream_sample_aspect_ratio = stream ? stream->sample_aspect_ratio : undef;
AVRational codec_sample_aspect_ratio = stream && stream->codecpar ? stream->codecpar->sample_aspect_ratio : undef;
AVRational frame_sample_aspect_ratio = frame ? frame->sample_aspect_ratio : codec_sample_aspect_ratio;
av_reduce(&stream_sample_aspect_ratio.num, &stream_sample_aspect_ratio.den,
stream_sample_aspect_ratio.num, stream_sample_aspect_ratio.den, INT_MAX);
if (stream_sample_aspect_ratio.num <= 0 || stream_sample_aspect_ratio.den <= 0)
stream_sample_aspect_ratio = undef;
av_reduce(&frame_sample_aspect_ratio.num, &frame_sample_aspect_ratio.den,
frame_sample_aspect_ratio.num, frame_sample_aspect_ratio.den, INT_MAX);
if (frame_sample_aspect_ratio.num <= 0 || frame_sample_aspect_ratio.den <= 0)
frame_sample_aspect_ratio = undef;
if (stream_sample_aspect_ratio.num)
return stream_sample_aspect_ratio;
else
return frame_sample_aspect_ratio;
}
AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame)
{
AVRational fr = st->r_frame_rate;
AVRational codec_fr = st->internal->avctx->framerate;
AVRational avg_fr = st->avg_frame_rate;
if (avg_fr.num > 0 && avg_fr.den > 0 && fr.num > 0 && fr.den > 0 &&
av_q2d(avg_fr) < 70 && av_q2d(fr) > 210) {
fr = avg_fr;
}
if (st->internal->avctx->ticks_per_frame > 1) {
if ( codec_fr.num > 0 && codec_fr.den > 0 &&
(fr.num == 0 || av_q2d(codec_fr) < av_q2d(fr)*0.7 && fabs(1.0 - av_q2d(av_div_q(avg_fr, fr))) > 0.1))
fr = codec_fr;
}
return fr;
}
static int match_stream_specifier(AVFormatContext *s, AVStream *st,
const char *spec, const char **indexptr, AVProgram **p)
{
int match = 1;
while (*spec) {
if (*spec <= '9' && *spec >= '0') {
if (indexptr)
*indexptr = spec;
return match;
} else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' ||
*spec == 't' || *spec == 'V') {
enum AVMediaType type;
int nopic = 0;
switch (*spec++) {
case 'v': type = AVMEDIA_TYPE_VIDEO; break;
case 'a': type = AVMEDIA_TYPE_AUDIO; break;
case 's': type = AVMEDIA_TYPE_SUBTITLE; break;
case 'd': type = AVMEDIA_TYPE_DATA; break;
case 't': type = AVMEDIA_TYPE_ATTACHMENT; break;
case 'V': type = AVMEDIA_TYPE_VIDEO; nopic = 1; break;
default: av_assert0(0);
}
if (*spec && *spec++ != ':')
return AVERROR(EINVAL);
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
if (type != st->codecpar->codec_type
&& (st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN || st->codec->codec_type != type))
match = 0;
FF_ENABLE_DEPRECATION_WARNINGS
#else
if (type != st->codecpar->codec_type)
match = 0;
#endif
if (nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC))
match = 0;
} else if (*spec == 'p' && *(spec + 1) == ':') {
int prog_id, i, j;
int found = 0;
char *endptr;
spec += 2;
prog_id = strtol(spec, &endptr, 0);
if (spec == endptr || (*endptr && *endptr++ != ':'))
return AVERROR(EINVAL);
spec = endptr;
if (match) {
for (i = 0; i < s->nb_programs; i++) {
if (s->programs[i]->id != prog_id)
continue;
for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) {
if (st->index == s->programs[i]->stream_index[j]) {
found = 1;
if (p)
*p = s->programs[i];
i = s->nb_programs;
break;
}
}
}
}
if (!found)
match = 0;
} else if (*spec == '#' ||
(*spec == 'i' && *(spec + 1) == ':')) {
int stream_id;
char *endptr;
spec += 1 + (*spec == 'i');
stream_id = strtol(spec, &endptr, 0);
if (spec == endptr || *endptr)
return AVERROR(EINVAL);
return match && (stream_id == st->id);
} else if (*spec == 'm' && *(spec + 1) == ':') {
AVDictionaryEntry *tag;
char *key, *val;
int ret;
if (match) {
spec += 2;
val = strchr(spec, ':');
key = val ? av_strndup(spec, val - spec) : av_strdup(spec);
if (!key)
return AVERROR(ENOMEM);
tag = av_dict_get(st->metadata, key, NULL, 0);
if (tag) {
if (!val || !strcmp(tag->value, val + 1))
ret = 1;
else
ret = 0;
} else
ret = 0;
av_freep(&key);
}
return match && ret;
} else if (*spec == 'u' && *(spec + 1) == '\0') {
AVCodecParameters *par = st->codecpar;
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
AVCodecContext *codec = st->codec;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
int val;
switch (par->codec_type) {
case AVMEDIA_TYPE_AUDIO:
val = par->sample_rate && par->channels;
#if FF_API_LAVF_AVCTX
val = val || (codec->sample_rate && codec->channels);
#endif
if (par->format == AV_SAMPLE_FMT_NONE
#if FF_API_LAVF_AVCTX
&& codec->sample_fmt == AV_SAMPLE_FMT_NONE
#endif
)
return 0;
break;
case AVMEDIA_TYPE_VIDEO:
val = par->width && par->height;
#if FF_API_LAVF_AVCTX
val = val || (codec->width && codec->height);
#endif
if (par->format == AV_PIX_FMT_NONE
#if FF_API_LAVF_AVCTX
&& codec->pix_fmt == AV_PIX_FMT_NONE
#endif
)
return 0;
break;
case AVMEDIA_TYPE_UNKNOWN:
val = 0;
break;
default:
val = 1;
break;
}
#if FF_API_LAVF_AVCTX
return match && ((par->codec_id != AV_CODEC_ID_NONE || codec->codec_id != AV_CODEC_ID_NONE) && val != 0);
#else
return match && (par->codec_id != AV_CODEC_ID_NONE && val != 0);
#endif
} else {
return AVERROR(EINVAL);
}
}
return match;
}
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
const char *spec)
{
int ret, index;
char *endptr;
const char *indexptr = NULL;
AVProgram *p = NULL;
int nb_streams;
ret = match_stream_specifier(s, st, spec, &indexptr, &p);
if (ret < 0)
goto error;
if (!indexptr)
return ret;
index = strtol(indexptr, &endptr, 0);
if (*endptr) {
ret = AVERROR(EINVAL);
goto error;
}
if (spec == indexptr)
return (index == st->index);
nb_streams = p ? p->nb_stream_indexes : s->nb_streams;
for (int i = 0; i < nb_streams && index >= 0; i++) {
AVStream *candidate = p ? s->streams[p->stream_index[i]] : s->streams[i];
ret = match_stream_specifier(s, candidate, spec, NULL, NULL);
if (ret < 0)
goto error;
if (ret > 0 && index-- == 0 && st == candidate)
return 1;
}
return 0;
error:
if (ret == AVERROR(EINVAL))
av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec);
return ret;
}
int ff_generate_avci_extradata(AVStream *st)
{
static const uint8_t avci100_1080p_extradata[] = {
0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29,
0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63,
0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19,
0x18, 0x21, 0x02, 0x56, 0xb9, 0x3d, 0x7d, 0x7e,
0x4f, 0xe3, 0x3f, 0x11, 0xf1, 0x9e, 0x08, 0xb8,
0x8c, 0x54, 0x43, 0xc0, 0x78, 0x02, 0x27, 0xe2,
0x70, 0x1e, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00,
0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xca,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48,
0xd0
};
static const uint8_t avci100_1080i_extradata[] = {
0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29,
0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63,
0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19,
0x18, 0x21, 0x03, 0x3a, 0x46, 0x65, 0x6a, 0x65,
0x24, 0xad, 0xe9, 0x12, 0x32, 0x14, 0x1a, 0x26,
0x34, 0xad, 0xa4, 0x41, 0x82, 0x23, 0x01, 0x50,
0x2b, 0x1a, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2e,
0x11, 0x12, 0x08, 0xc6, 0x8c, 0x04, 0x41, 0x28,
0x4c, 0x34, 0xf0, 0x1e, 0x01, 0x13, 0xf2, 0xe0,
0x3c, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x03,
0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x94, 0x20,
0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48,
0xd0
};
static const uint8_t avci50_1080p_extradata[] = {
0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28,
0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18,
0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c,
0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6f, 0x37,
0xcd, 0xf9, 0xbf, 0x81, 0x6b, 0xf3, 0x7c, 0xde,
0x6e, 0x6c, 0xd3, 0x3c, 0x05, 0xa0, 0x22, 0x7e,
0x5f, 0xfc, 0x00, 0x0c, 0x00, 0x13, 0x8c, 0x04,
0x04, 0x05, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00,
0x00, 0x03, 0x00, 0x32, 0x84, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12,
0x11
};
static const uint8_t avci50_1080i_extradata[] = {
0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28,
0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18,
0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c,
0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6e, 0x61,
0x87, 0x3e, 0x73, 0x4d, 0x98, 0x0c, 0x03, 0x06,
0x9c, 0x0b, 0x73, 0xe6, 0xc0, 0xb5, 0x18, 0x63,
0x0d, 0x39, 0xe0, 0x5b, 0x02, 0xd4, 0xc6, 0x19,
0x1a, 0x79, 0x8c, 0x32, 0x34, 0x24, 0xf0, 0x16,
0x81, 0x13, 0xf7, 0xff, 0x80, 0x02, 0x00, 0x01,
0xf1, 0x80, 0x80, 0x80, 0xa0, 0x00, 0x00, 0x03,
0x00, 0x20, 0x00, 0x00, 0x06, 0x50, 0x80, 0x00,
0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12,
0x11
};
static const uint8_t avci100_720p_extradata[] = {
0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29,
0xb6, 0xd4, 0x20, 0x2a, 0x33, 0x1d, 0xc7, 0x62,
0xa1, 0x08, 0x40, 0x54, 0x66, 0x3b, 0x8e, 0xc5,
0x42, 0x02, 0x10, 0x25, 0x64, 0x2c, 0x89, 0xe8,
0x85, 0xe4, 0x21, 0x4b, 0x90, 0x83, 0x06, 0x95,
0xd1, 0x06, 0x46, 0x97, 0x20, 0xc8, 0xd7, 0x43,
0x08, 0x11, 0xc2, 0x1e, 0x4c, 0x91, 0x0f, 0x01,
0x40, 0x16, 0xec, 0x07, 0x8c, 0x04, 0x04, 0x05,
0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03,
0x00, 0x64, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x31, 0x12,
0x11
};
static const uint8_t avci50_720p_extradata[] = {
0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x20,
0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18,
0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c,
0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6f, 0x37,
0xcd, 0xf9, 0xbf, 0x81, 0x6b, 0xf3, 0x7c, 0xde,
0x6e, 0x6c, 0xd3, 0x3c, 0x0f, 0x01, 0x6e, 0xff,
0xc0, 0x00, 0xc0, 0x01, 0x38, 0xc0, 0x40, 0x40,
0x50, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00,
0x06, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12,
0x11
};
const uint8_t *data = NULL;
int ret, size = 0;
if (st->codecpar->width == 1920) {
if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) {
data = avci100_1080p_extradata;
size = sizeof(avci100_1080p_extradata);
} else {
data = avci100_1080i_extradata;
size = sizeof(avci100_1080i_extradata);
}
} else if (st->codecpar->width == 1440) {
if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) {
data = avci50_1080p_extradata;
size = sizeof(avci50_1080p_extradata);
} else {
data = avci50_1080i_extradata;
size = sizeof(avci50_1080i_extradata);
}
} else if (st->codecpar->width == 1280) {
data = avci100_720p_extradata;
size = sizeof(avci100_720p_extradata);
} else if (st->codecpar->width == 960) {
data = avci50_720p_extradata;
size = sizeof(avci50_720p_extradata);
}
if (!size)
return 0;
if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
return ret;
memcpy(st->codecpar->extradata, data, size);
return 0;
}
uint8_t *av_stream_get_side_data(const AVStream *st,
enum AVPacketSideDataType type, int *size)
{
int i;
for (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;
int i;
for (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 ((unsigned)st->nb_side_data + 1 >= INT_MAX / sizeof(*st->side_data))
return AVERROR(ERANGE);
tmp = av_realloc(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,
int 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;
}
int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args)
{
int ret;
const AVBitStreamFilter *bsf;
AVBSFContext *bsfc;
av_assert0(!st->internal->bsfc);
if (!(bsf = av_bsf_get_by_name(name))) {
av_log(NULL, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n", name);
return AVERROR_BSF_NOT_FOUND;
}
if ((ret = av_bsf_alloc(bsf, &bsfc)) < 0)
return ret;
bsfc->time_base_in = st->time_base;
if ((ret = avcodec_parameters_copy(bsfc->par_in, st->codecpar)) < 0) {
av_bsf_free(&bsfc);
return ret;
}
if (args && bsfc->filter->priv_class) {
const AVOption *opt = av_opt_next(bsfc->priv_data, NULL);
const char * shorthand[2] = {NULL};
if (opt)
shorthand[0] = opt->name;
if ((ret = av_opt_set_from_string(bsfc->priv_data, args, shorthand, "=", ":")) < 0) {
av_bsf_free(&bsfc);
return ret;
}
}
if ((ret = av_bsf_init(bsfc)) < 0) {
av_bsf_free(&bsfc);
return ret;
}
st->internal->bsfc = bsfc;
av_log(NULL, AV_LOG_VERBOSE,
"Automatically inserted bitstream filter '%s'; args='%s'\n",
name, args ? args : "");
return 1;
}
#if FF_API_OLD_BSF
FF_DISABLE_DEPRECATION_WARNINGS
int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
AVBitStreamFilterContext *bsfc)
{
int ret = 0;
while (bsfc) {
AVPacket new_pkt = *pkt;
int a = av_bitstream_filter_filter(bsfc, codec, NULL,
&new_pkt.data, &new_pkt.size,
pkt->data, pkt->size,
pkt->flags & AV_PKT_FLAG_KEY);
if (a == 0 && new_pkt.size == 0 && new_pkt.side_data_elems == 0) {
av_packet_unref(pkt);
memset(pkt, 0, sizeof(*pkt));
return 0;
}
if(a == 0 && new_pkt.data != pkt->data) {
uint8_t *t = av_malloc(new_pkt.size + AV_INPUT_BUFFER_PADDING_SIZE);
if (t) {
memcpy(t, new_pkt.data, new_pkt.size);
memset(t + new_pkt.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
new_pkt.data = t;
new_pkt.buf = NULL;
a = 1;
} else {
a = AVERROR(ENOMEM);
}
}
if (a > 0) {
new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size,
av_buffer_default_free, NULL, 0);
if (new_pkt.buf) {
pkt->side_data = NULL;
pkt->side_data_elems = 0;
av_packet_unref(pkt);
} else {
av_freep(&new_pkt.data);
a = AVERROR(ENOMEM);
}
}
if (a < 0) {
av_log(codec, AV_LOG_ERROR,
"Failed to open bitstream filter %s for stream %d with codec %s",
bsfc->filter->name, pkt->stream_index,
codec->codec ? codec->codec->name : "copy");
ret = a;
break;
}
*pkt = new_pkt;
bsfc = bsfc->next;
}
return ret;
}
FF_ENABLE_DEPRECATION_WARNINGS
#endif
int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options)
{
if (!s->oformat)
return AVERROR(EINVAL);
if (!(s->oformat->flags & AVFMT_NOFILE))
return s->io_open(s, &s->pb, url, AVIO_FLAG_WRITE, options);
return 0;
}
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
{
if (*pb)
s->io_close(s, *pb);
*pb = NULL;
}
int ff_is_http_proto(char *filename) {
const char *proto = avio_find_protocol_name(filename);
return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0;
}
int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds)
{
AVDictionaryEntry *entry;
int64_t parsed_timestamp;
int ret;
if ((entry = av_dict_get(s->metadata, "creation_time", NULL, 0))) {
if ((ret = av_parse_time(&parsed_timestamp, entry->value, 0)) >= 0) {
*timestamp = return_seconds ? parsed_timestamp / 1000000 : parsed_timestamp;
return 1;
} else {
av_log(s, AV_LOG_WARNING, "Failed to parse creation_time %s\n", entry->value);
return ret;
}
}
return 0;
}
int ff_standardize_creation_time(AVFormatContext *s)
{
int64_t timestamp;
int ret = ff_parse_creation_time_metadata(s, ×tamp, 0);
if (ret == 1)
return avpriv_dict_set_timestamp(&s->metadata, "creation_time", timestamp);
return ret;
}
int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette)
{
uint8_t *side_data;
int size;
side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size);
if (side_data) {
if (size != AVPALETTE_SIZE) {
av_log(s, AV_LOG_ERROR, "Invalid palette side data\n");
return AVERROR_INVALIDDATA;
}
memcpy(palette, side_data, AVPALETTE_SIZE);
return 1;
}
if (ret == CONTAINS_PAL) {
int i;
for (i = 0; i < AVPALETTE_COUNT; i++)
palette[i] = AV_RL32(pkt->data + pkt->size - AVPALETTE_SIZE + i*4);
return 1;
}
return 0;
}
int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf)
{
int ret;
char *str;
ret = av_bprint_finalize(buf, &str);
if (ret < 0)
return ret;
if (!av_bprint_is_complete(buf)) {
av_free(str);
return AVERROR(ENOMEM);
}
par->extradata = str;
par->extradata_size = buf->len;
return 0;
}
int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,
AVStream *ost, const AVStream *ist,
enum AVTimebaseSource copy_tb)
{
const AVCodecContext *dec_ctx = ist->codec;
AVCodecContext *enc_ctx = ost->codec;
enc_ctx->time_base = ist->time_base;
if (!strcmp(ofmt->name, "avi")) {
#if FF_API_R_FRAME_RATE
if (copy_tb == AVFMT_TBCF_AUTO && ist->r_frame_rate.num
&& av_q2d(ist->r_frame_rate) >= av_q2d(ist->avg_frame_rate)
&& 0.5/av_q2d(ist->r_frame_rate) > av_q2d(ist->time_base)
&& 0.5/av_q2d(ist->r_frame_rate) > av_q2d(dec_ctx->time_base)
&& av_q2d(ist->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500
|| copy_tb == AVFMT_TBCF_R_FRAMERATE) {
enc_ctx->time_base.num = ist->r_frame_rate.den;
enc_ctx->time_base.den = 2*ist->r_frame_rate.num;
enc_ctx->ticks_per_frame = 2;
} else
#endif
if (copy_tb == AVFMT_TBCF_AUTO && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->time_base)
&& av_q2d(ist->time_base) < 1.0/500
|| copy_tb == AVFMT_TBCF_DECODER) {
enc_ctx->time_base = dec_ctx->time_base;
enc_ctx->time_base.num *= dec_ctx->ticks_per_frame;
enc_ctx->time_base.den *= 2;
enc_ctx->ticks_per_frame = 2;
}
} else if (!(ofmt->flags & AVFMT_VARIABLE_FPS)
&& !av_match_name(ofmt->name, "mov,mp4,3gp,3g2,psp,ipod,ismv,f4v")) {
if (copy_tb == AVFMT_TBCF_AUTO && dec_ctx->time_base.den
&& av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->time_base)
&& av_q2d(ist->time_base) < 1.0/500
|| copy_tb == AVFMT_TBCF_DECODER) {
enc_ctx->time_base = dec_ctx->time_base;
enc_ctx->time_base.num *= dec_ctx->ticks_per_frame;
}
}
if ((enc_ctx->codec_tag == AV_RL32("tmcd") || ost->codecpar->codec_tag == AV_RL32("tmcd"))
&& dec_ctx->time_base.num < dec_ctx->time_base.den
&& dec_ctx->time_base.num > 0
&& 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) {
enc_ctx->time_base = dec_ctx->time_base;
}
if (ost->avg_frame_rate.num)
enc_ctx->time_base = av_inv_q(ost->avg_frame_rate);
av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den,
enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX);
return 0;
}
AVRational av_stream_get_codec_timebase(const AVStream *st)
{
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
return st->codec->time_base;
FF_ENABLE_DEPRECATION_WARNINGS
#else
return st->internal->avctx->time_base;
#endif
}
void ff_format_set_url(AVFormatContext *s, char *url)
{
av_assert0(url);
av_freep(&s->url);
s->url = url;
#if FF_API_FORMAT_FILENAME
FF_DISABLE_DEPRECATION_WARNINGS
av_strlcpy(s->filename, url, sizeof(s->filename));
FF_ENABLE_DEPRECATION_WARNINGS
#endif
}