summaryrefslogtreecommitdiff
path: root/ffmpeg/libavformat/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffmpeg/libavformat/utils.c')
-rw-r--r--ffmpeg/libavformat/utils.c1163
1 files changed, 514 insertions, 649 deletions
diff --git a/ffmpeg/libavformat/utils.c b/ffmpeg/libavformat/utils.c
index f9acc0e..40d886f 100644
--- a/ffmpeg/libavformat/utils.c
+++ b/ffmpeg/libavformat/utils.c
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/* #define DEBUG */
+#include <stdint.h>
#include "avformat.h"
#include "avio_internal.h"
@@ -27,9 +27,9 @@
#include "libavcodec/internal.h"
#include "libavcodec/raw.h"
#include "libavcodec/bytestream.h"
-#include "libavutil/avassert.h"
#include "libavutil/opt.h"
#include "libavutil/dict.h"
+#include "libavutil/internal.h"
#include "libavutil/pixdesc.h"
#include "metadata.h"
#include "id3v2.h"
@@ -99,156 +99,34 @@ static int64_t wrap_timestamp(AVStream *st, int64_t timestamp)
return timestamp;
}
-#define MAKE_ACCESSORS(str, name, type, field) \
- type av_##name##_get_##field(const str *s) { return s->field; } \
- void av_##name##_set_##field(str *s, type v) { s->field = v; }
-
MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate)
+MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec)
+MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, audio_codec)
+MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, subtitle_codec)
-/** head of registered input format linked list */
-static AVInputFormat *first_iformat = NULL;
-/** head of registered output format linked list */
-static AVOutputFormat *first_oformat = NULL;
-
-AVInputFormat *av_iformat_next(AVInputFormat *f)
-{
- if(f) return f->next;
- else return first_iformat;
-}
-
-AVOutputFormat *av_oformat_next(AVOutputFormat *f)
-{
- if(f) return f->next;
- else return first_oformat;
-}
-
-void av_register_input_format(AVInputFormat *format)
-{
- AVInputFormat **p;
- p = &first_iformat;
- while (*p != NULL) p = &(*p)->next;
- *p = format;
- format->next = NULL;
-}
-
-void av_register_output_format(AVOutputFormat *format)
-{
- AVOutputFormat **p;
- p = &first_oformat;
- while (*p != NULL) p = &(*p)->next;
- *p = format;
- format->next = NULL;
-}
-
-int av_match_ext(const char *filename, const char *extensions)
+static AVCodec *find_decoder(AVFormatContext *s, AVStream *st, enum AVCodecID codec_id)
{
- const char *ext, *p;
- char ext1[32], *q;
-
- if(!filename)
- return 0;
+ if (st->codec->codec)
+ return st->codec->codec;
- ext = strrchr(filename, '.');
- if (ext) {
- ext++;
- p = extensions;
- for(;;) {
- q = ext1;
- while (*p != '\0' && *p != ',' && q-ext1<sizeof(ext1)-1)
- *q++ = *p++;
- *q = '\0';
- if (!av_strcasecmp(ext1, ext))
- return 1;
- if (*p == '\0')
- break;
- p++;
- }
- }
- return 0;
-}
-
-static int match_format(const char *name, const char *names)
-{
- const char *p;
- int len, namelen;
-
- if (!name || !names)
- return 0;
-
- namelen = strlen(name);
- while ((p = strchr(names, ','))) {
- len = FFMAX(p - names, namelen);
- if (!av_strncasecmp(name, names, len))
- return 1;
- names = p+1;
- }
- return !av_strcasecmp(name, names);
-}
-
-AVOutputFormat *av_guess_format(const char *short_name, const char *filename,
- const char *mime_type)
-{
- AVOutputFormat *fmt = NULL, *fmt_found;
- int score_max, score;
-
- /* specific test for image sequences */
-#if CONFIG_IMAGE2_MUXER
- if (!short_name && filename &&
- av_filename_number_test(filename) &&
- ff_guess_image2_codec(filename) != AV_CODEC_ID_NONE) {
- return av_guess_format("image2", NULL, NULL);
- }
-#endif
- /* Find the proper file type. */
- fmt_found = NULL;
- score_max = 0;
- while ((fmt = av_oformat_next(fmt))) {
- score = 0;
- if (fmt->name && short_name && match_format(short_name, fmt->name))
- score += 100;
- if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
- score += 10;
- if (filename && fmt->extensions &&
- av_match_ext(filename, fmt->extensions)) {
- score += 5;
- }
- if (score > score_max) {
- score_max = score;
- fmt_found = fmt;
- }
+ switch(st->codec->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 fmt_found;
-}
-
-enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name,
- const char *filename, const char *mime_type, enum AVMediaType type){
- if(type == AVMEDIA_TYPE_VIDEO){
- enum AVCodecID codec_id= AV_CODEC_ID_NONE;
-#if CONFIG_IMAGE2_MUXER
- if(!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")){
- codec_id= ff_guess_image2_codec(filename);
- }
-#endif
- if(codec_id == AV_CODEC_ID_NONE)
- codec_id= fmt->video_codec;
- return codec_id;
- }else if(type == AVMEDIA_TYPE_AUDIO)
- return fmt->audio_codec;
- else if (type == AVMEDIA_TYPE_SUBTITLE)
- return fmt->subtitle_codec;
- else
- return AV_CODEC_ID_NONE;
+ return avcodec_find_decoder(codec_id);
}
-AVInputFormat *av_find_input_format(const char *short_name)
+int av_format_get_probe_score(const AVFormatContext *s)
{
- AVInputFormat *fmt = NULL;
- while ((fmt = av_iformat_next(fmt))) {
- if (match_format(short_name, fmt->name))
- return fmt;
- }
- return NULL;
+ return s->probe_score;
}
/* an arbitrarily chosen "sane" max packet size -- 50M */
@@ -280,7 +158,7 @@ int ffio_limit(AVIOContext *s, int size)
*/
static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
{
- int orig_pos = pkt->pos; // av_grow_packet might reset pos
+ int64_t orig_pos = pkt->pos; // av_grow_packet might reset pos
int orig_size = pkt->size;
int ret;
@@ -372,10 +250,10 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score
if (fmt1->read_probe) {
score = fmt1->read_probe(&lpd);
if(fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions))
- score = FFMAX(score, nodat ? AVPROBE_SCORE_MAX/4-1 : 1);
+ score = FFMAX(score, nodat ? AVPROBE_SCORE_EXTENSION / 2 - 1 : 1);
} else if (fmt1->extensions) {
if (av_match_ext(lpd.filename, fmt1->extensions)) {
- score = 50;
+ score = AVPROBE_SCORE_EXTENSION;
}
}
if (score > score_max) {
@@ -384,6 +262,8 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score
}else if (score == score_max)
fmt = NULL;
}
+ if(nodat)
+ score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max);
*score_ret= score_max;
return fmt;
@@ -458,11 +338,7 @@ int av_demuxer_open(AVFormatContext *ic){
}
-/** size of probe buffer, for guessing file type from file contents */
-#define PROBE_BUF_MIN 2048
-#define PROBE_BUF_MAX (1<<20)
-
-int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
+int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt,
const char *filename, void *logctx,
unsigned int offset, unsigned int max_probe_size)
{
@@ -470,6 +346,7 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
unsigned char *buf = NULL;
uint8_t *mime_type;
int ret = 0, probe_size, buf_offset = 0;
+ int score = 0;
if (!max_probe_size) {
max_probe_size = PROBE_BUF_MAX;
@@ -494,20 +371,15 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
for(probe_size= PROBE_BUF_MIN; probe_size<=max_probe_size && !*fmt;
probe_size = FFMIN(probe_size<<1, FFMAX(max_probe_size, probe_size+1))) {
- int score = probe_size < max_probe_size ? AVPROBE_SCORE_RETRY : 0;
- void *buftmp;
if (probe_size < offset) {
continue;
}
+ score = probe_size < max_probe_size ? AVPROBE_SCORE_RETRY : 0;
/* read probe data */
- buftmp = av_realloc(buf, probe_size + AVPROBE_PADDING_SIZE);
- if(!buftmp){
- av_free(buf);
- return AVERROR(ENOMEM);
- }
- buf=buftmp;
+ if ((ret = av_reallocp(&buf, probe_size + AVPROBE_PADDING_SIZE)) < 0)
+ return ret;
if ((ret = avio_read(pb, buf + buf_offset, probe_size - buf_offset)) < 0) {
/* fail if error was not end of file, otherwise, lower score */
if (ret != AVERROR_EOF) {
@@ -529,6 +401,11 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
av_log(logctx, AV_LOG_WARNING, "Format %s detected only with low score of %d, misdetection possible!\n", (*fmt)->name, score);
}else
av_log(logctx, AV_LOG_DEBUG, "Format %s probed with size=%d and score=%d\n", (*fmt)->name, probe_size, score);
+#if 0
+ FILE *f = fopen("probestat.tmp", "ab");
+ fprintf(f, "probe_size:%d format:%s score:%d filename:%s\n", probe_size, (*fmt)->name, score, filename);
+ fclose(f);
+#endif
}
}
@@ -540,9 +417,18 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
/* rewind. reuse probe buffer to avoid seeking */
ret = ffio_rewind_with_probe_data(pb, &buf, pd.buf_size);
- return ret;
+ return ret < 0 ? ret : score;
}
+int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
+ const char *filename, void *logctx,
+ unsigned int offset, unsigned int max_probe_size)
+{
+ int ret = av_probe_input_buffer2(pb, fmt, filename, logctx, offset, max_probe_size);
+ return ret < 0 ? ret : 0;
+}
+
+
/* open input file and probe the format if necessary */
static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options)
{
@@ -553,7 +439,7 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o
if (s->pb) {
s->flags |= AVFMT_FLAG_CUSTOM_IO;
if (!s->iformat)
- return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize);
+ return av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->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");
@@ -562,14 +448,14 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o
if ( (s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
(!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
- return 0;
+ return score;
if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ | s->avio_flags,
&s->interrupt_callback, options)) < 0)
return ret;
if (s->iformat)
return 0;
- return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize);
+ return av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->probesize);
}
static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
@@ -629,6 +515,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
if ((ret = init_input(s, filename, &tmp)) < 0)
goto fail;
+ s->probe_score = ret;
avio_skip(s->pb, s->skip_initial_bytes);
/* check filename in case an image number is expected */
@@ -665,7 +552,8 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
goto fail;
if (id3v2_extra_meta) {
- if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac")) {
+ if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") ||
+ !strcmp(s->iformat->name, "tta")) {
if((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0)
goto fail;
} else
@@ -715,7 +603,7 @@ static void force_codec_ids(AVFormatContext *s, AVStream *st)
}
}
-static void probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
+static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
{
if(st->request_probe>0){
AVProbeData *pd = &st->probe_data;
@@ -725,8 +613,12 @@ static void probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
if (pkt) {
uint8_t *new_buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
- if(!new_buf)
+ 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;
@@ -758,11 +650,76 @@ no_packet:
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;
+
+ // reference time stamp should be 60 s before first time stamp
+ pts_wrap_reference = ref - av_rescale(60, st->time_base.den, st->time_base.num);
+ // if first time stamp is not more than 1/8 and 60s before the wrap point, subtract rather than add wrap offset
+ 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++) {
+ 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);
+ }
+
+ // update every program with differing pts_wrap_reference
+ 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;
+ int ret, i, err;
AVStream *st;
for(;;){
@@ -771,8 +728,10 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
if (pktl) {
*pkt = pktl->pkt;
st = s->streams[pkt->stream_index];
- if (s->raw_packet_buffer_remaining_size <= 0)
- probe_codec(s, st, NULL);
+ if (s->raw_packet_buffer_remaining_size <= 0) {
+ if ((err = probe_codec(s, st, NULL)) < 0)
+ return err;
+ }
if(st->request_probe <= 0){
s->raw_packet_buffer = pktl->next;
s->raw_packet_buffer_remaining_size += pkt->size;
@@ -791,7 +750,8 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->probe_packets) {
- probe_codec(s, st, NULL);
+ if ((err = probe_codec(s, st, NULL)) < 0)
+ return err;
}
av_assert0(st->request_probe <= 0);
}
@@ -807,15 +767,23 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
continue;
}
- if(!(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA))
- av_packet_merge_side_data(pkt);
-
if(pkt->stream_index >= (unsigned)s->nb_streams){
av_log(s, AV_LOG_ERROR, "Invalid stream index %d\n", pkt->stream_index);
continue;
}
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) {
+ // correct first time stamps to negative values
+ 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);
@@ -831,7 +799,8 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
add_to_pktbuf(&s->raw_packet_buffer, pkt, &s->raw_packet_buffer_end);
s->raw_packet_buffer_remaining_size -= pkt->size;
- probe_codec(s, st, pkt);
+ if ((err = probe_codec(s, st, pkt)) < 0)
+ return err;
}
}
@@ -870,7 +839,7 @@ int ff_get_audio_frame_size(AVCodecContext *enc, int size, int mux)
if ((frame_size = av_get_audio_frame_duration(enc, size)) > 0)
return frame_size;
- /* fallback to using frame_size if muxing */
+ /* Fall back on using frame_size if muxing. */
if (enc->frame_size > 1)
return enc->frame_size;
@@ -950,7 +919,7 @@ static int is_intra_only(AVCodecContext *enc){
static int has_decode_delay_been_guessed(AVStream *st)
{
if(st->codec->codec_id != AV_CODEC_ID_H264) return 1;
- if(!st->info) // if we have left find_stream_info then nb_decoded_frames wont increase anymore for stream copy
+ if(!st->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy
return 1;
#if CONFIG_H264_DECODER
if(st->codec->has_b_frames &&
@@ -974,65 +943,6 @@ static AVPacketList *get_next_pkt(AVFormatContext *s, AVStream *st, AVPacketList
return NULL;
}
-static int update_wrap_reference(AVFormatContext *s, AVStream *st, int stream_index)
-{
- if (s->correct_ts_overflow && st->pts_wrap_bits < 63 &&
- st->pts_wrap_reference == AV_NOPTS_VALUE && st->first_dts != AV_NOPTS_VALUE) {
- int i;
-
- // reference time stamp should be 60 s before first time stamp
- int64_t pts_wrap_reference = st->first_dts - av_rescale(60, st->time_base.den, st->time_base.num);
- // if first time stamp is not more than 1/8 and 60s before the wrap point, subtract rather than add wrap offset
- int pts_wrap_behavior = (st->first_dts < (1LL<<st->pts_wrap_bits) - (1LL<<st->pts_wrap_bits-3)) ||
- (st->first_dts < (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;
-
- AVProgram *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++) {
- 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);
- }
-
- // update every program with differing pts_wrap_reference
- 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;
- }
- return 0;
-}
-
static void update_initial_timestamps(AVFormatContext *s, int stream_index,
int64_t dts, int64_t pts, AVPacket *pkt)
{
@@ -1077,15 +987,6 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
}
}
- if (update_wrap_reference(s, st, stream_index) && st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) {
- // correct first time stamps to negative values
- st->first_dts = wrap_timestamp(st, st->first_dts);
- st->cur_dts = wrap_timestamp(st, st->cur_dts);
- pkt->dts = wrap_timestamp(st, pkt->dts);
- pkt->pts = wrap_timestamp(st, pkt->pts);
- pts = wrap_timestamp(st, pts);
- }
-
if (st->start_time == AV_NOPTS_VALUE)
st->start_time = pts;
}
@@ -1106,7 +1007,8 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st,
}
}
if(pktl && pktl->pkt.dts != st->first_dts) {
- av_log(s, AV_LOG_DEBUG, "first_dts %s not matching first dts %s in the queue\n", av_ts2str(st->first_dts), av_ts2str(pktl->pkt.dts));
+ av_log(s, AV_LOG_DEBUG, "first_dts %s not matching first dts %s (pts %s, duration %d) 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) {
@@ -1148,7 +1050,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
if((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE)
pkt->dts= AV_NOPTS_VALUE;
- if (st->codec->codec_id != AV_CODEC_ID_H264 && pc && pc->pict_type == AV_PICTURE_TYPE_B)
+ if (pc && pc->pict_type == AV_PICTURE_TYPE_B
+ && !st->codec->has_b_frames)
//FIXME Set low_delay = 0 when has_b_frames = 1
st->codec->has_b_frames = 1;
@@ -1162,7 +1065,9 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
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 (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
@@ -1174,7 +1079,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
// Note, if this is misbehaving for a H.264 file then possibly presentation_delayed is not set correctly.
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")) // otherwise we discard correct timestamps for vc1-wmapro.ism
+ if ( strcmp(s->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2")
+ && strcmp(s->iformat->name, "flv")) // otherwise we discard correct timestamps for vc1-wmapro.ism
pkt->dts= AV_NOPTS_VALUE;
}
@@ -1198,25 +1104,6 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
pkt->dts += offset;
}
- if (pc && pc->dts_sync_point >= 0) {
- // we have synchronization info from the parser
- int64_t den = st->codec->time_base.den * (int64_t) st->time_base.num;
- if (den > 0) {
- int64_t num = st->codec->time_base.num * (int64_t) st->time_base.den;
- if (pkt->dts != AV_NOPTS_VALUE) {
- // got DTS from the stream, update reference timestamp
- st->reference_dts = pkt->dts - pc->dts_ref_dts_delta * num / den;
- pkt->pts = pkt->dts + pc->pts_dts_delta * num / den;
- } else if (st->reference_dts != AV_NOPTS_VALUE) {
- // compute DTS based on reference timestamp
- pkt->dts = st->reference_dts + pc->dts_ref_dts_delta * num / den;
- pkt->pts = pkt->dts + pc->pts_dts_delta * num / den;
- }
- if (pc->dts_sync_point > 0)
- st->reference_dts = pkt->dts; // new reference
- }
- }
-
/* This may be redundant, but it should not hurt. */
if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts > pkt->dts)
presentation_delayed = 1;
@@ -1338,6 +1225,13 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
if (!out_pkt.size)
continue;
+ 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;
+ }
+
/* set the duration */
out_pkt.duration = 0;
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -1377,8 +1271,10 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
out_pkt.buf = pkt->buf;
pkt->buf = NULL;
#if FF_API_DESTRUCT_PACKET
+FF_DISABLE_DEPRECATION_WARNINGS
out_pkt.destruct = pkt->destruct;
pkt->destruct = NULL;
+FF_ENABLE_DEPRECATION_WARNINGS
#endif
}
if ((ret = av_dup_packet(&out_pkt)) < 0)
@@ -1502,6 +1398,9 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
st->skip_to_keyframe = 0;
if (st->skip_to_keyframe) {
av_free_packet(&cur_pkt);
+ if (got_packet) {
+ *pkt = cur_pkt;
+ }
got_packet = 0;
}
}
@@ -1509,6 +1408,21 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
if (!got_packet && s->parse_queue)
ret = read_from_packet_buffer(&s->parse_queue, &s->parse_queue_end, pkt);
+ if (ret >= 0) {
+ AVStream *st = s->streams[pkt->stream_index];
+ if (st->skip_samples) {
+ uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
+ if (p) {
+ AV_WL32(p, st->skip_samples);
+ av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d\n", st->skip_samples);
+ }
+ st->skip_samples = 0;
+ }
+ }
+
+ if(ret >= 0 && !(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA))
+ av_packet_merge_side_data(pkt);
+
if(s->debug & FF_FDEBUG_TS)
av_log(s, AV_LOG_DEBUG, "read_frame_internal stream=%d, pts=%s, dts=%s, size=%d, duration=%d, flags=%d\n",
pkt->stream_index,
@@ -1598,13 +1512,6 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
return_packet:
st = s->streams[pkt->stream_index];
- if (st->skip_samples) {
- uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
- AV_WL32(p, st->skip_samples);
- av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d\n", st->skip_samples);
- st->skip_samples = 0;
- }
-
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);
@@ -1672,7 +1579,6 @@ void ff_read_frame_flush(AVFormatContext *s)
st->last_IP_pts = AV_NOPTS_VALUE;
if(st->first_dts == AV_NOPTS_VALUE) st->cur_dts = RELATIVE_TS_BASE;
else st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */
- st->reference_dts = AV_NOPTS_VALUE;
st->probe_packets = MAX_PROBE_PACKETS;
@@ -1721,6 +1627,9 @@ int ff_add_index_entry(AVIndexEntry **index_entries,
if(timestamp == AV_NOPTS_VALUE)
return AVERROR(EINVAL);
+ if (size < 0 || size > 0x3FFFFFFF)
+ return AVERROR(EINVAL);
+
if (is_relative(timestamp)) //FIXME this maintains previous behavior but we should shift by the correct offset once known
timestamp -= RELATIVE_TS_BASE;
@@ -1738,7 +1647,7 @@ int ff_add_index_entry(AVIndexEntry **index_entries,
if(index<0){
index= (*nb_index_entries)++;
ie= &entries[index];
- assert(index==0 || ie[-1].timestamp < timestamp);
+ av_assert0(index==0 || ie[-1].timestamp < timestamp);
}else{
ie= &entries[index];
if(ie->timestamp != timestamp){
@@ -1850,14 +1759,14 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
av_dlog(s, "using cached pos_min=0x%"PRIx64" dts_min=%s\n",
pos_min, av_ts2str(ts_min));
}else{
- assert(index==0);
+ av_assert1(index==0);
}
index= av_index_search_timestamp(st, target_ts, flags & ~AVSEEK_FLAG_BACKWARD);
- assert(index < st->nb_index_entries);
+ av_assert0(index < st->nb_index_entries);
if(index >= 0){
e= &st->index_entries[index];
- assert(e->timestamp >= target_ts);
+ av_assert1(e->timestamp >= target_ts);
pos_max= e->pos;
ts_max= e->timestamp;
pos_limit= pos_max - e->min_distance;
@@ -1880,14 +1789,51 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_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, filesize;
+ int64_t start_pos;
int no_change;
+ int ret;
av_dlog(s, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts));
@@ -1904,27 +1850,8 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
}
if(ts_max == AV_NOPTS_VALUE){
- int step= 1024;
- filesize = avio_size(s->pb);
- pos_max = filesize - 1;
- do{
- pos_max = FFMAX(0, pos_max - step);
- ts_max = ff_read_timestamp(s, stream_index, &pos_max, pos_max + step, read_timestamp);
- step += step;
- }while(ts_max == AV_NOPTS_VALUE && pos_max > 0);
- 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;
- ts_max= tmp_ts;
- pos_max= tmp_pos;
- if(tmp_pos >= filesize)
- break;
- }
+ if ((ret = ff_find_last_ts(s, stream_index, &ts_max, &pos_max, read_timestamp)) < 0)
+ return ret;
pos_limit= pos_max;
}
@@ -2014,6 +1941,8 @@ static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, in
avio_seek(s->pb, pos, SEEK_SET);
+ s->io_repositioned = 1;
+
return 0;
}
@@ -2037,7 +1966,7 @@ static int seek_frame_generic(AVFormatContext *s,
int nonkey=0;
if(st->nb_index_entries){
- assert(st->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;
@@ -2127,7 +2056,19 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index,
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
{
- int ret = seek_frame_internal(s, stream_index, timestamp, 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);
@@ -2144,6 +2085,7 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int
if(s->seek2any>0)
flags |= AVSEEK_FLAG_ANY;
+ flags &= ~AVSEEK_FLAG_BACKWARD;
if (s->iformat->read_seek2) {
int ret;
@@ -2171,8 +2113,8 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int
//try to seek via read_timestamp()
}
- //Fallback to old API if new is not implemented but old is
- //Note the old has somewhat different semantics
+ // Fall back on old API if new is not implemented but old is.
+ // Note the old API has somewhat different semantics.
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);
@@ -2304,16 +2246,21 @@ static void fill_all_stream_timings(AVFormatContext *ic)
static void estimate_timings_from_bit_rate(AVFormatContext *ic)
{
int64_t filesize, duration;
- int bit_rate, i;
+ int i, show_warning = 0;
AVStream *st;
/* if bit_rate is already set, we believe it */
if (ic->bit_rate <= 0) {
- bit_rate = 0;
+ int bit_rate = 0;
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
- if (st->codec->bit_rate > 0)
- bit_rate += st->codec->bit_rate;
+ if (st->codec->bit_rate > 0) {
+ if (INT_MAX - st->codec->bit_rate < bit_rate) {
+ bit_rate = 0;
+ break;
+ }
+ bit_rate += st->codec->bit_rate;
+ }
}
ic->bit_rate = bit_rate;
}
@@ -2325,12 +2272,17 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
if (filesize > 0) {
for(i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
- duration= av_rescale(8*filesize, st->time_base.den, ic->bit_rate*(int64_t)st->time_base.num);
- if (st->duration == AV_NOPTS_VALUE)
+ if ( st->time_base.num <= INT64_MAX / ic->bit_rate
+ && st->duration == AV_NOPTS_VALUE) {
+ duration= av_rescale(8*filesize, 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
@@ -2410,7 +2362,6 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
st= ic->streams[i];
st->cur_dts= st->first_dts;
st->last_IP_pts = AV_NOPTS_VALUE;
- st->reference_dts = AV_NOPTS_VALUE;
}
}
@@ -2438,7 +2389,6 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
fill_all_stream_timings(ic);
ic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM;
} else {
- av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this may be inaccurate\n");
/* less precise: use bitrate info */
estimate_timings_from_bit_rate(ic);
ic->duration_estimation_method = AVFMT_DURATION_FROM_BITRATE;
@@ -2507,11 +2457,11 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
}
/* returns 1 or 0 if or if not decoded data was returned, or a negative error */
-static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **options)
+static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, AVDictionary **options)
{
const AVCodec *codec;
int got_picture = 1, ret = 0;
- AVFrame *frame = avcodec_alloc_frame();
+ AVFrame *frame = av_frame_alloc();
AVSubtitle subtitle;
AVPacket pkt = *avpkt;
@@ -2521,8 +2471,7 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
if (!avcodec_is_open(st->codec) && !st->info->found_decoder) {
AVDictionary *thread_opt = NULL;
- codec = st->codec->codec ? st->codec->codec :
- avcodec_find_decoder(st->codec->codec_id);
+ codec = find_decoder(s, st, st->codec->codec_id);
if (!codec) {
st->info->found_decoder = -1;
@@ -2555,7 +2504,6 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
!has_decode_delay_been_guessed(st) ||
(!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) {
got_picture = 0;
- avcodec_get_frame_defaults(frame);
switch(st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
ret = avcodec_decode_video2(st->codec, frame,
@@ -2585,7 +2533,7 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
ret = -1;
fail:
- avcodec_free_frame(&frame);
+ av_frame_free(&frame);
return ret;
}
@@ -2733,9 +2681,158 @@ int av_find_stream_info(AVFormatContext *ic)
}
#endif
+int ff_alloc_extradata(AVCodecContext *avctx, int size)
+{
+ int ret;
+
+ if (size < 0 || size >= INT32_MAX - FF_INPUT_BUFFER_PADDING_SIZE) {
+ avctx->extradata_size = 0;
+ return AVERROR(EINVAL);
+ }
+ avctx->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (avctx->extradata) {
+ memset(avctx->extradata + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ avctx->extradata_size = size;
+ ret = 0;
+ } else {
+ avctx->extradata_size = 0;
+ ret = AVERROR(ENOMEM);
+ }
+ return ret;
+}
+
+int ff_get_extradata(AVCodecContext *avctx, AVIOContext *pb, int size)
+{
+ int ret = ff_alloc_extradata(avctx, size);
+ if (ret < 0)
+ return ret;
+ ret = avio_read(pb, avctx->extradata, size);
+ if (ret != size) {
+ av_freep(&avctx->extradata);
+ avctx->extradata_size = 0;
+ av_log(avctx, 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);
+
+// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
+ 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;
+ }
+ }
+ }
+ 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;
+ }
+ }
+ }
+ }
+
+ // ignore the first 4 values, they might have some random jitter
+ 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->codec->codec_type != AVMEDIA_TYPE_VIDEO)
+ continue;
+ // the check for tb_unreliable() is not completely correct, since this is not about handling
+ // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
+ // ipmovie.c produces.
+ if (tb_unreliable(st->codec) && 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->codec)) {
+ int num = 0;
+ double best_error= 0.01;
+
+ 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*12.0)/get_std_framerate(j))
+ continue;
+ if(!st->info->codec_info_duration && 1.0 < (1001*12.0)/get_std_framerate(j))
+ 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(NULL, AV_LOG_DEBUG, "rfps: %f %f\n", get_std_framerate(j) / 12.0/1001, error);
+ }
+ }
+ // do not increase frame rate by more than 1 % in order to match a standard rate.
+ if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate)))
+ av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
+ }
+
+ av_freep(&st->info->duration_error);
+ st->info->last_dts = AV_NOPTS_VALUE;
+ st->info->duration_count = 0;
+ st->info->rfps_duration_sum = 0;
+ }
+}
+
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
{
- int i, count, ret, j;
+ int i, count, ret = 0, j;
int64_t read_size;
AVStream *st;
AVPacket pkt1, *pkt;
@@ -2744,7 +2841,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
int flush_codecs = ic->probesize > 0;
if(ic->pb)
- av_log(ic, AV_LOG_DEBUG, "File position before avformat_find_stream_info() is %"PRId64"\n", avio_tell(ic->pb));
+ av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d\n",
+ avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count);
for(i=0;i<ic->nb_streams;i++) {
const AVCodec *codec;
@@ -2773,8 +2871,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
avcodec_get_name(st->codec->codec_id));
}
}
- codec = st->codec->codec ? st->codec->codec :
- avcodec_find_decoder(st->codec->codec_id);
+ codec = find_decoder(ic, st, st->codec->codec_id);
/* force thread count to 1 since the h264 decoder will not extract SPS
* and PPS to extradata during multi-threaded decoding */
@@ -2782,15 +2879,16 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
/* Ensure that subtitle_header is properly set. */
if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
- && codec && !st->codec->codec)
- avcodec_open2(st->codec, codec, options ? &options[i]
- : &thread_opt);
+ && codec && !st->codec->codec) {
+ if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)
+ av_log(ic, AV_LOG_WARNING, "Failed to open codec in av_find_stream_info\n");
+ }
//try to just open decoders, in case this is enough to get parameters
if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) {
if (codec && !st->codec->codec)
- avcodec_open2(st->codec, codec, options ? &options[i]
- : &thread_opt);
+ if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)
+ av_log(ic, AV_LOG_WARNING, "Failed to open codec in av_find_stream_info\n");
}
if (!options)
av_dict_free(&thread_opt);
@@ -2859,7 +2957,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
av_log(ic, AV_LOG_DEBUG, "Probe buffer size limit of %d bytes reached\n", ic->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]->info->duration_count <= 1 &&
+ strcmp(ic->iformat->name, "image2"))
av_log(ic, AV_LOG_WARNING,
"Stream #%d: not enough frames to estimate rate; "
"consider increasing probesize\n", i);
@@ -2877,18 +2976,23 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
break;
}
- if (ic->flags & AVFMT_FLAG_NOBUFFER) {
- pkt = &pkt1;
- } else {
+ if (ic->flags & AVFMT_FLAG_NOBUFFER)
+ free_packet_buffer(&ic->packet_buffer, &ic->packet_buffer_end);
+ {
pkt = add_to_pktbuf(&ic->packet_buffer, &pkt1,
&ic->packet_buffer_end);
+ if (!pkt) {
+ ret = AVERROR(ENOMEM);
+ goto find_stream_info_err;
+ }
if ((ret = av_dup_packet(pkt)) < 0)
goto find_stream_info_err;
}
- read_size += pkt->size;
-
st = ic->streams[pkt->stream_index];
+ if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC))
+ read_size += pkt->size;
+
if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {
/* check for non-increasing dts */
if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
@@ -2928,57 +3032,30 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
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 (t >= ic->max_analyze_duration) {
- av_log(ic, AV_LOG_WARNING, "max_analyze_duration %d reached at %"PRId64" microseconds\n", ic->max_analyze_duration, t);
+ av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %d reached at %"PRId64" microseconds\n", ic->max_analyze_duration, t);
break;
}
if (pkt->duration) {
st->info->codec_info_duration += pkt->duration;
- st->info->codec_info_duration_fields += st->parser && st->codec->ticks_per_frame==2 ? st->parser->repeat_pict + 1 : 2;
+ st->info->codec_info_duration_fields += st->parser && st->need_parsing && st->codec->ticks_per_frame==2 ? st->parser->repeat_pict + 1 : 2;
}
}
#if FF_API_R_FRAME_RATE
- {
- int64_t last = st->info->last_dts;
-
- if( pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last
- && pkt->dts - (uint64_t)last < INT64_MAX){
- double dts= (is_relative(pkt->dts) ? pkt->dts - RELATIVE_TS_BASE : pkt->dts) * av_q2d(st->time_base);
- int64_t duration= pkt->dts - last;
-
- if (!st->info->duration_error)
- st->info->duration_error = av_mallocz(sizeof(st->info->duration_error[0])*2);
-
-// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
-// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
- for (i=0; i<MAX_STD_TIMEBASES; i++) {
- 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;
- }
- }
- st->info->duration_count++;
- // ignore the first 4 values, they might have some random jitter
- if (st->info->duration_count > 3 && is_relative(pkt->dts) == is_relative(last))
- st->info->duration_gcd = av_gcd(st->info->duration_gcd, duration);
- }
- if (pkt->dts != AV_NOPTS_VALUE)
- st->info->last_dts = pkt->dts;
- }
+ ff_rfps_add_frame(ic, st, pkt->dts);
#endif
if(st->parser && st->parser->parser->split && !st->codec->extradata){
int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) {
- st->codec->extradata_size= i;
- st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- if (!st->codec->extradata)
+ if (ff_alloc_extradata(st->codec, i))
return AVERROR(ENOMEM);
memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
- memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
}
}
@@ -2991,7 +3068,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
least one frame of codec data, this makes sure the codec initializes
the channel configuration and does not only trust the values from the container.
*/
- try_decode_frame(st, pkt, (options && i < orig_nb_streams ) ? &options[i] : NULL);
+ try_decode_frame(ic, st, pkt, (options && i < orig_nb_streams ) ? &options[i] : NULL);
st->codec_info_nb_frames++;
count++;
@@ -3002,16 +3079,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
int err = 0;
av_init_packet(&empty_pkt);
- ret = -1; /* we could not have all the codec parameters before EOF */
for(i=0;i<ic->nb_streams;i++) {
- const char *errmsg;
st = ic->streams[i];
/* flush the decoders */
if (st->info->found_decoder == 1) {
do {
- err = try_decode_frame(st, &empty_pkt,
+ err = try_decode_frame(ic, st, &empty_pkt,
(options && i < orig_nb_streams) ?
&options[i] : NULL);
} while (err > 0 && !has_codec_parameters(st, NULL));
@@ -3021,17 +3096,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
"decoding for stream %d failed\n", st->index);
}
}
-
- if (!has_codec_parameters(st, &errmsg)) {
- char buf[256];
- avcodec_string(buf, sizeof(buf), st->codec, 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;
- }
}
}
@@ -3040,6 +3104,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
st = ic->streams[i];
avcodec_close(st->codec);
}
+
+ ff_rfps_calculate(ic);
+
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
@@ -3054,6 +3121,10 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
int best_fps = 0;
double best_error = 0.01;
+ 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);
@@ -3074,40 +3145,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
best_fps, 12*1001, INT_MAX);
}
}
- // the check for tb_unreliable() is not completely correct, since this is not about handling
- // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
- // ipmovie.c produces.
- if (tb_unreliable(st->codec) && 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->codec)) {
- int num = 0;
- double best_error= 0.01;
-
- 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*12.0)/get_std_framerate(j))
- continue;
- if(!st->info->codec_info_duration && 1.0 < (1001*12.0)/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(NULL, AV_LOG_DEBUG, "rfps: %f %f\n", get_std_framerate(j) / 12.0/1001, error);
- }
- }
- // do not increase frame rate by more than 1 % in order to match a standard rate.
- if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate)))
- av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
- }
if (!st->r_frame_rate.num){
if( st->codec->time_base.den * (int64_t)st->time_base.num
@@ -3141,19 +3178,37 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
if(ic->probesize)
estimate_timings(ic, old_offset);
+ if (ret >= 0 && ic->nb_streams)
+ ret = -1; /* we could not have all the codec parameters before EOF */
+ for(i=0;i<ic->nb_streams;i++) {
+ const char *errmsg;
+ st = ic->streams[i];
+ if (!has_codec_parameters(st, &errmsg)) {
+ char buf[256];
+ avcodec_string(buf, sizeof(buf), st->codec, 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);
find_stream_info_err:
for (i=0; i < ic->nb_streams; i++) {
st = ic->streams[i];
- if (ic->streams[i]->codec)
+ if (ic->streams[i]->codec && ic->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
ic->streams[i]->codec->thread_count = 0;
if (st->info)
av_freep(&st->info->duration_error);
av_freep(&ic->streams[i]->info);
}
if(ic->pb)
- av_log(ic, AV_LOG_DEBUG, "File position after avformat_find_stream_info() is %"PRId64"\n", avio_tell(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;
}
@@ -3204,7 +3259,7 @@ int av_find_best_stream(AVFormatContext *ic,
if (st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED|AV_DISPOSITION_VISUAL_IMPAIRED))
continue;
if (decoder_ret) {
- decoder = avcodec_find_decoder(st->codec->codec_id);
+ decoder = find_decoder(ic, st, st->codec->codec_id);
if (!decoder) {
if (ret < 0)
ret = AVERROR_DECODER_NOT_FOUND;
@@ -3264,6 +3319,7 @@ void ff_free_stream(AVFormatContext *s, AVStream *st){
if (st->attached_pic.data)
av_free_packet(&st->attached_pic);
av_dict_free(&st->metadata);
+ av_freep(&st->probe_data.buf);
av_freep(&st->index_entries);
av_freep(&st->codec->extradata);
av_freep(&st->codec->subtitle_header);
@@ -3272,7 +3328,6 @@ void ff_free_stream(AVFormatContext *s, AVStream *st){
if (st->info)
av_freep(&st->info->duration_error);
av_freep(&st->info);
- av_freep(&st->probe_data.buf);
av_freep(&s->streams[ --s->nb_streams ]);
}
@@ -3316,8 +3371,14 @@ void av_close_input_file(AVFormatContext *s)
void avformat_close_input(AVFormatContext **ps)
{
- AVFormatContext *s = *ps;
- AVIOContext *pb = s->pb;
+ AVFormatContext *s;
+ AVIOContext *pb;
+
+ if (!ps || !*ps)
+ return;
+
+ s = *ps;
+ pb = s->pb;
if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
(s->flags & AVFMT_FLAG_CUSTOM_IO))
@@ -3355,7 +3416,7 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
if (s->nb_streams >= INT_MAX/sizeof(*streams))
return NULL;
- streams = av_realloc(s->streams, (s->nb_streams + 1) * sizeof(*streams));
+ streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));
if (!streams)
return NULL;
s->streams = streams;
@@ -3392,7 +3453,6 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
st->last_IP_pts = AV_NOPTS_VALUE;
for(i=0; i<MAX_REORDER_DELAY+1; i++)
st->pts_buffer[i]= AV_NOPTS_VALUE;
- st->reference_dts = AV_NOPTS_VALUE;
st->sample_aspect_ratio = (AVRational){0,1};
@@ -3477,7 +3537,7 @@ void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int i
if(program->stream_index[j] == idx)
return;
- tmp = av_realloc(program->stream_index, sizeof(unsigned int)*(program->nb_stream_indexes+1));
+ tmp = av_realloc_array(program->stream_index, program->nb_stream_indexes+1, sizeof(unsigned int));
if(!tmp)
return;
program->stream_index = tmp;
@@ -3788,27 +3848,11 @@ static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int
av_hex_dump(f, pkt->data, pkt->size);
}
-#if FF_API_PKT_DUMP
-void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload)
-{
- AVRational tb = { 1, AV_TIME_BASE };
- pkt_dump_internal(NULL, f, 0, pkt, dump_payload, tb);
-}
-#endif
-
void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st)
{
pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base);
}
-#if FF_API_PKT_DUMP
-void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload)
-{
- AVRational tb = { 1, AV_TIME_BASE };
- pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, tb);
-}
-#endif
-
void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload,
AVStream *st)
{
@@ -3956,72 +4000,6 @@ void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits,
s->pts_wrap_bits = pts_wrap_bits;
}
-int ff_url_join(char *str, int size, const char *proto,
- const char *authorization, const char *hostname,
- int port, const char *fmt, ...)
-{
-#if CONFIG_NETWORK
- struct addrinfo hints = { 0 }, *ai;
-#endif
-
- str[0] = '\0';
- if (proto)
- av_strlcatf(str, size, "%s://", proto);
- if (authorization && authorization[0])
- av_strlcatf(str, size, "%s@", authorization);
-#if CONFIG_NETWORK && defined(AF_INET6)
- /* Determine if hostname is a numerical IPv6 address,
- * properly escape it within [] in that case. */
- hints.ai_flags = AI_NUMERICHOST;
- if (!getaddrinfo(hostname, NULL, &hints, &ai)) {
- if (ai->ai_family == AF_INET6) {
- av_strlcat(str, "[", size);
- av_strlcat(str, hostname, size);
- av_strlcat(str, "]", size);
- } else {
- av_strlcat(str, hostname, size);
- }
- freeaddrinfo(ai);
- } else
-#endif
- /* Not an IPv6 address, just output the plain string. */
- av_strlcat(str, hostname, size);
-
- if (port >= 0)
- av_strlcatf(str, size, ":%d", port);
- if (fmt) {
- va_list vl;
- int len = strlen(str);
-
- va_start(vl, fmt);
- vsnprintf(str + len, size > len ? size - len : 0, fmt, vl);
- va_end(vl);
- }
- return strlen(str);
-}
-
-int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt,
- AVFormatContext *src)
-{
- AVPacket local_pkt;
-
- local_pkt = *pkt;
- local_pkt.stream_index = dst_stream;
- if (pkt->pts != AV_NOPTS_VALUE)
- local_pkt.pts = av_rescale_q(pkt->pts,
- src->streams[pkt->stream_index]->time_base,
- dst->streams[dst_stream]->time_base);
- if (pkt->dts != AV_NOPTS_VALUE)
- local_pkt.dts = av_rescale_q(pkt->dts,
- src->streams[pkt->stream_index]->time_base,
- dst->streams[dst_stream]->time_base);
- if (pkt->duration)
- local_pkt.duration = av_rescale_q(pkt->duration,
- src->streams[pkt->stream_index]->time_base,
- dst->streams[dst_stream]->time_base);
- return av_write_frame(dst, &local_pkt);
-}
-
void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf,
void *context)
{
@@ -4086,75 +4064,6 @@ int ff_find_stream_index(AVFormatContext *s, int id)
return -1;
}
-void ff_make_absolute_url(char *buf, int size, const char *base,
- const char *rel)
-{
- char *sep, *path_query;
- /* Absolute path, relative to the current server */
- if (base && strstr(base, "://") && rel[0] == '/') {
- if (base != buf)
- av_strlcpy(buf, base, size);
- sep = strstr(buf, "://");
- if (sep) {
- /* Take scheme from base url */
- if (rel[1] == '/') {
- sep[1] = '\0';
- } else {
- /* Take scheme and host from base url */
- sep += 3;
- sep = strchr(sep, '/');
- if (sep)
- *sep = '\0';
- }
- }
- av_strlcat(buf, rel, size);
- return;
- }
- /* If rel actually is an absolute url, just copy it */
- if (!base || strstr(rel, "://") || rel[0] == '/') {
- av_strlcpy(buf, rel, size);
- return;
- }
- if (base != buf)
- av_strlcpy(buf, base, size);
-
- /* Strip off any query string from base */
- path_query = strchr(buf, '?');
- if (path_query != NULL)
- *path_query = '\0';
-
- /* Is relative path just a new query part? */
- if (rel[0] == '?') {
- av_strlcat(buf, rel, size);
- return;
- }
-
- /* Remove the file name from the base url */
- sep = strrchr(buf, '/');
- if (sep)
- sep[1] = '\0';
- else
- buf[0] = '\0';
- while (av_strstart(rel, "../", NULL) && sep) {
- /* Remove the path delimiter at the end */
- sep[0] = '\0';
- sep = strrchr(buf, '/');
- /* If the next directory name to pop off is "..", break here */
- if (!strcmp(sep ? &sep[1] : buf, "..")) {
- /* Readd the slash we just removed */
- av_strlcat(buf, "/", size);
- break;
- }
- /* Cut off the directory name */
- if (sep)
- sep[1] = '\0';
- else
- buf[0] = '\0';
- rel += 3;
- }
- av_strlcat(buf, rel, size);
-}
-
int64_t ff_iso8601_to_unix_time(const char *datestr)
{
struct tm time1 = {0}, time2 = {0};
@@ -4244,15 +4153,6 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels,
return 0;
}
-const struct AVCodecTag *avformat_get_riff_video_tags(void)
-{
- return ff_codec_bmp_tags;
-}
-const struct AVCodecTag *avformat_get_riff_audio_tags(void)
-{
- return ff_codec_wav_tags;
-}
-
AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame)
{
AVRational undef = {0, 1};
@@ -4276,6 +4176,22 @@ AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *strea
return frame_sample_aspect_ratio;
}
+AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame)
+{
+ AVRational fr = st->r_frame_rate;
+
+ if (st->codec->ticks_per_frame > 1) {
+ AVRational codec_fr = av_inv_q(st->codec->time_base);
+ AVRational avg_fr = st->avg_frame_rate;
+ codec_fr.den *= st->codec->ticks_per_frame;
+ if ( codec_fr.num > 0 && codec_fr.den > 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;
+}
+
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
const char *spec)
{
@@ -4337,7 +4253,7 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
return AVERROR(EINVAL);
}
-void ff_generate_avci_extradata(AVStream *st)
+int ff_generate_avci_extradata(AVStream *st)
{
static const uint8_t avci100_1080p_extradata[] = {
// SPS
@@ -4404,8 +4320,10 @@ void ff_generate_avci_extradata(AVStream *st)
0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x31, 0x12,
0x11
};
+
+ const uint8_t *data = NULL;
int size = 0;
- const uint8_t *data = 0;
+
if (st->codec->width == 1920) {
if (st->codec->field_order == AV_FIELD_PROGRESSIVE) {
data = avci100_1080p_extradata;
@@ -4421,67 +4339,14 @@ void ff_generate_avci_extradata(AVStream *st)
data = avci100_720p_extradata;
size = sizeof(avci100_720p_extradata);
}
+
if (!size)
- return;
+ return 0;
+
av_freep(&st->codec->extradata);
- st->codec->extradata_size = 0;
- st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
- if (!st->codec->extradata)
- return;
+ if (ff_alloc_extradata(st->codec, size))
+ return AVERROR(ENOMEM);
memcpy(st->codec->extradata, data, size);
- st->codec->extradata_size = size;
-}
-static int match_host_pattern(const char *pattern, const char *hostname)
-{
- int len_p, len_h;
- if (!strcmp(pattern, "*"))
- return 1;
- // Skip a possible *. at the start of the pattern
- if (pattern[0] == '*')
- pattern++;
- if (pattern[0] == '.')
- pattern++;
- len_p = strlen(pattern);
- len_h = strlen(hostname);
- if (len_p > len_h)
- return 0;
- // Simply check if the end of hostname is equal to 'pattern'
- if (!strcmp(pattern, &hostname[len_h - len_p])) {
- if (len_h == len_p)
- return 1; // Exact match
- if (hostname[len_h - len_p - 1] == '.')
- return 1; // The matched substring is a domain and not just a substring of a domain
- }
return 0;
}
-
-int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
-{
- char *buf, *start;
- int ret = 0;
- if (!no_proxy)
- return 0;
- if (!hostname)
- return 0;
- buf = av_strdup(no_proxy);
- if (!buf)
- return 0;
- start = buf;
- while (start) {
- char *sep, *next = NULL;
- start += strspn(start, " ,");
- sep = start + strcspn(start, " ,");
- if (*sep) {
- next = sep + 1;
- *sep = '\0';
- }
- if (match_host_pattern(start, hostname)) {
- ret = 1;
- break;
- }
- start = next;
- }
- av_free(buf);
- return ret;
-}