#include "metadata.h"
#include "id3v2.h"
#include "libavutil/avstring.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/parseutils.h"
#include "riff.h"
#include "audiointerleave.h"
#include "url.h"
#include <sys/time.h>
#include <time.h>
-#include <strings.h>
#include <stdarg.h>
#if CONFIG_NETWORK
#include "network.h"
* @param num must be >= 0
* @param den must be >= 1
*/
-static void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den)
+static void frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den)
{
num += (den >> 1);
if (num >= den) {
* @param f fractional number
* @param incr increment, can be positive or negative
*/
-static void av_frac_add(AVFrac *f, int64_t incr)
+static void frac_add(AVFrac *f, int64_t incr)
{
int64_t num, den;
while (*p != '\0' && *p != ',' && q-ext1<sizeof(ext1)-1)
*q++ = *p++;
*q = '\0';
- if (!strcasecmp(ext1, ext))
+ if (!av_strcasecmp(ext1, ext))
return 1;
if (*p == '\0')
break;
namelen = strlen(name);
while ((p = strchr(names, ','))) {
len = FFMAX(p - names, namelen);
- if (!strncasecmp(name, names, len))
+ if (!av_strncasecmp(name, names, len))
return 1;
names = p+1;
}
- return !strcasecmp(name, names);
+ return !av_strcasecmp(name, names);
}
AVOutputFormat *av_guess_format(const char *short_name, const char *filename,
}
/* a hack for files with huge id3v2 tags -- try to guess by file extension. */
- if (!fmt && id3 && *score_max < AVPROBE_SCORE_MAX/4) {
+ if (!fmt && is_opened && *score_max < AVPROBE_SCORE_MAX/4) {
while ((fmt = av_iformat_next(fmt)))
if (fmt->extensions && av_match_ext(lpd.filename, fmt->extensions)) {
*score_max = AVPROBE_SCORE_MAX/4;
}
}
+ if (!fmt && id3 && *score_max < AVPROBE_SCORE_MAX/4-1) {
+ while ((fmt = av_iformat_next(fmt)))
+ if (fmt->extensions && av_match_ext("mp3", fmt->extensions)) {
+ *score_max = AVPROBE_SCORE_MAX/4-1;
+ break;
+ }
+ }
+
return fmt;
}
err = AVERROR(ENOMEM);
goto fail;
}
- ic->pb = pb;
+ if (pb && fmt && fmt->flags & AVFMT_NOFILE)
+ av_log(ic, AV_LOG_WARNING, "Custom AVIOContext makes no sense and "
+ "will be ignored with AVFMT_NOFILE format.\n");
+ else
+ ic->pb = pb;
- err = avformat_open_input(ic_ptr, filename, fmt, &opts);
+ if ((err = avformat_open_input(&ic, filename, fmt, &opts)) < 0)
+ goto fail;
+ ic->pb = ic->pb ? ic->pb : pb; // don't leak custom pb if it wasn't set above
fail:
+ *ic_ptr = ic;
av_dict_free(&opts);
return err;
}
return AVERROR(EINVAL);
}
- for(probe_size= PROBE_BUF_MIN; probe_size<=max_probe_size && !*fmt && ret >= 0;
+ 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 ret, score = probe_size < max_probe_size ? AVPROBE_SCORE_MAX/4 : 0;
+ int score = probe_size < max_probe_size ? AVPROBE_SCORE_MAX/4 : 0;
int buf_offset = (probe_size == PROBE_BUF_MIN) ? 0 : probe_size>>1;
if (probe_size < offset) {
#endif
/* open input file and probe the format if necessary */
-static int init_input(AVFormatContext *s, const char *filename)
+static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options)
{
int ret;
AVProbeData pd = {filename, NULL, 0};
(!s->iformat && (s->iformat = av_probe_input_format(&pd, 0))))
return 0;
- if ((ret = avio_open(&s->pb, filename, AVIO_FLAG_READ)) < 0)
- return ret;
+ if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ,
+ &s->interrupt_callback, options)) < 0)
+ return ret;
if (s->iformat)
return 0;
return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0);
{
AVFormatContext *s = *ps;
int ret = 0;
- AVFormatParameters ap = { 0 };
+ AVFormatParameters ap = { { 0 } };
AVDictionary *tmp = NULL;
if (!s && !(s = avformat_alloc_context()))
if ((ret = av_opt_set_dict(s, &tmp)) < 0)
goto fail;
- if ((ret = init_input(s, filename)) < 0)
+ if ((ret = init_input(s, filename, &tmp)) < 0)
goto fail;
/* check filename in case an image number is expected */
s->streams[i]->probe_packets = 0;
continue;
}
+
+ if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) &&
+ (pkt->flags & AV_PKT_FLAG_CORRUPT)) {
+ av_log(s, AV_LOG_WARNING,
+ "Dropped corrupted packet (stream = %d)\n",
+ pkt->stream_index);
+ av_free_packet(pkt);
+ continue;
+ }
+
st= s->streams[pkt->stream_index];
switch(st->codec->codec_type){
memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);
if(av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){
- //FIXME we dont reduce score to 0 for the case of running out of buffer space in bytes
+ //FIXME we do not reduce score to 0 for the case of running out of buffer space in bytes
set_codec_from_probe_data(s, st, pd, st->probe_packets > 0 ? AVPROBE_SCORE_MAX/4 : 0);
if(st->codec->codec_id != CODEC_ID_PROBE){
pd->buf_size=0;
*pden = 0;
switch(st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
- if(st->time_base.num*1000LL > st->time_base.den){
+ if (st->r_frame_rate.num) {
+ *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(st->codec->time_base.num*1000LL > st->codec->time_base.den){
case CODEC_ID_MJPEG:
case CODEC_ID_MJPEGB:
case CODEC_ID_LJPEG:
+ case CODEC_ID_PRORES:
case CODEC_ID_RAWVIDEO:
case CODEC_ID_DVVIDEO:
case CODEC_ID_HUFFYUV:
delay= st->codec->has_b_frames;
presentation_delayed = 0;
- // ignore delay caused by frame threading so that the mpeg2-without-dts
- // warning will not trigger
- if (delay && st->codec->active_thread_type&FF_THREAD_FRAME)
- delay -= st->codec->thread_count-1;
-
/* XXX: need has_b_frame, but cannot get it if the codec is
not initialized */
if (delay &&
FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]);
if(pkt->dts == AV_NOPTS_VALUE)
pkt->dts= st->pts_buffer[0];
- if(st->codec->codec_id == CODEC_ID_H264){ //we skiped it above so we try here
+ if(st->codec->codec_id == CODEC_ID_H264){ // we skipped it above so we try here
update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts); // this should happen on the first packet
}
if(pkt->dts > st->cur_dts)
}
-static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
+static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
{
AVStream *st;
int len, ret, i;
st->cur_pkt.data = NULL;
assert(st->cur_len == 0);
}else{
- pkt->destruct = NULL;
+ pkt->destruct = NULL;
}
compute_pkt_fields(s, st, st->parser, pkt);
}
}
if(s->debug & FF_FDEBUG_TS)
- av_log(s, AV_LOG_DEBUG, "av_read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n",
+ av_log(s, AV_LOG_DEBUG, "read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n",
pkt->stream_index,
pkt->pts,
pkt->dts,
}
}
if(genpts){
- int ret= av_read_frame_internal(s, pkt);
+ int ret= read_frame_internal(s, pkt);
if(ret<0){
if(pktl && ret != AVERROR(EAGAIN)){
eof=1;
return AVERROR(ENOMEM);
}else{
assert(!s->packet_buffer);
- return av_read_frame_internal(s, pkt);
+ return read_frame_internal(s, pkt);
}
}
}
}
}
-void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){
+#if FF_API_SEEK_PUBLIC
+void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
+{
+ ff_update_cur_dts(s, ref_st, timestamp);
+}
+#endif
+
+void ff_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
+{
int i;
for(i = 0; i < s->nb_streams; i++) {
wanted_timestamp, flags);
}
+#if FF_API_SEEK_PUBLIC
int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
+ return ff_seek_frame_binary(s, stream_index, target_ts, flags);
+}
+#endif
+
+int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
+{
AVInputFormat *avif= s->iformat;
int64_t av_uninit(pos_min), av_uninit(pos_max), pos, pos_limit;
int64_t ts_min, ts_max, ts;
}
}
- pos= av_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ts, avif->read_timestamp);
+ 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;
- av_update_cur_dts(s, st, ts);
+ ff_update_cur_dts(s, st, ts);
return 0;
}
-int64_t av_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 )){
+#if FF_API_SEEK_PUBLIC
+int64_t av_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 ))
+{
+ return ff_gen_search(s, stream_index, target_ts, pos_min, pos_max,
+ pos_limit, ts_min, ts_max, flags, ts_ret,
+ read_timestamp);
+}
+#endif
+
+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;
int no_change;
return pos;
}
-static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){
+static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){
int64_t pos_min, pos_max;
#if 0
AVStream *st;
return 0;
}
-static int av_seek_frame_generic(AVFormatContext *s,
+static int seek_frame_generic(AVFormatContext *s,
int stream_index, int64_t timestamp, int flags)
{
int index;
return -1;
if(index < 0 || index==st->nb_index_entries-1){
- int i;
AVPacket pkt;
if(st->nb_index_entries){
ie= &st->index_entries[st->nb_index_entries-1];
if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
return ret;
- av_update_cur_dts(s, st, ie->timestamp);
+ ff_update_cur_dts(s, st, ie->timestamp);
}else{
if ((ret = avio_seek(s->pb, s->data_offset, SEEK_SET)) < 0)
return ret;
}
- for(i=0;; i++) {
- int ret;
+ for (;;) {
+ int read_status;
do{
- ret = av_read_frame(s, &pkt);
- }while(ret == AVERROR(EAGAIN));
- if(ret<0)
+ read_status = av_read_frame(s, &pkt);
+ } while (read_status == AVERROR(EAGAIN));
+ if (read_status < 0)
break;
av_free_packet(&pkt);
if(stream_index == pkt.stream_index){
ie = &st->index_entries[index];
if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
return ret;
- av_update_cur_dts(s, st, ie->timestamp);
+ ff_update_cur_dts(s, st, ie->timestamp);
return 0;
}
int ret;
AVStream *st;
- ff_read_frame_flush(s);
-
- if(flags & AVSEEK_FLAG_BYTE)
- return av_seek_frame_byte(s, stream_index, timestamp, flags);
+ 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);
return -1;
st= s->streams[stream_index];
- /* timestamp for default must be expressed in AV_TIME_BASE units */
+ /* timestamp for default must be expressed in AV_TIME_BASE units */
timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);
}
/* first, we try the format specific seek */
- if (s->iformat->read_seek)
+ if (s->iformat->read_seek) {
+ ff_read_frame_flush(s);
ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
- else
+ } else
ret = -1;
if (ret >= 0) {
return 0;
}
- if(s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH))
- return av_seek_frame_binary(s, stream_index, timestamp, flags);
- else if (!(s->iformat->flags & AVFMT_NOGENSEARCH))
- return av_seek_frame_generic(s, stream_index, timestamp, flags);
+ 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;
}
if(min_ts > ts || max_ts < ts)
return -1;
- ff_read_frame_flush(s);
-
- if (s->iformat->read_seek2)
+ if (s->iformat->read_seek2) {
+ ff_read_frame_flush(s);
return s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags);
+ }
if(s->iformat->read_timestamp){
//try to seek via read_timestamp()
if(s->iformat->read_seek || 1)
return av_seek_frame(s, stream_index, ts, flags | (ts - min_ts > (uint64_t)(max_ts - ts) ? AVSEEK_FLAG_BACKWARD : 0));
- // try some generic seek like av_seek_frame_generic() but with new ts semantics
+ // try some generic seek like seek_frame_generic() but with new ts semantics
}
/*******************************************************/
*
* @return TRUE if the stream has accurate duration for at least one component.
*/
-static int av_has_duration(AVFormatContext *ic)
+static int has_duration(AVFormatContext *ic)
{
int i;
AVStream *st;
*
* Also computes the global bitrate if possible.
*/
-static void av_update_stream_timings(AVFormatContext *ic)
+static void update_stream_timings(AVFormatContext *ic)
{
int64_t start_time, start_time1, end_time, end_time1;
- int64_t duration, duration1;
+ int64_t duration, duration1, filesize;
int i;
AVStream *st;
st = ic->streams[i];
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 (start_time1 < start_time)
- start_time = start_time1;
+ start_time = FFMIN(start_time, start_time1);
if (st->duration != AV_NOPTS_VALUE) {
end_time1 = start_time1
+ av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
- if (end_time1 > end_time)
- end_time = end_time1;
+ end_time = FFMAX(end_time, end_time1);
}
}
if (st->duration != AV_NOPTS_VALUE) {
duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
- if (duration1 > duration)
- duration = duration1;
+ duration = FFMAX(duration, duration1);
}
}
if (start_time != INT64_MAX) {
ic->start_time = start_time;
- if (end_time != INT64_MIN) {
- if (end_time - start_time > duration)
- duration = end_time - start_time;
- }
+ if (end_time != INT64_MIN)
+ duration = FFMAX(duration, end_time - start_time);
}
if (duration != INT64_MIN) {
ic->duration = duration;
- if (ic->file_size > 0) {
+ if (ic->pb && (filesize = avio_size(ic->pb)) > 0) {
/* compute the bitrate */
- ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE /
+ ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE /
(double)ic->duration;
}
}
int i;
AVStream *st;
- av_update_stream_timings(ic);
+ update_stream_timings(ic);
for(i = 0;i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->start_time == AV_NOPTS_VALUE) {
}
}
-static void av_estimate_timings_from_bit_rate(AVFormatContext *ic)
+static void estimate_timings_from_bit_rate(AVFormatContext *ic)
{
int64_t filesize, duration;
int bit_rate, i;
/* if duration is already set, we believe it */
if (ic->duration == AV_NOPTS_VALUE &&
- ic->bit_rate != 0 &&
- ic->file_size != 0) {
- filesize = ic->file_size;
+ ic->bit_rate != 0) {
+ filesize = ic->pb ? avio_size(ic->pb) : 0;
if (filesize > 0) {
for(i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
#define DURATION_MAX_RETRY 3
/* only usable for MPEG-PS streams */
-static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
+static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
{
AVPacket pkt1, *pkt = &pkt1;
AVStream *st;
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)
- av_log(st->codec, AV_LOG_WARNING, "start time is not set in av_estimate_timings_from_pts\n");
+ av_log(st->codec, AV_LOG_WARNING, "start time is not set in estimate_timings_from_pts\n");
if (st->parser) {
av_parser_close(st->parser);
/* estimate the end time (duration) */
/* XXX: may need to support wrapping */
- filesize = ic->file_size;
+ filesize = ic->pb ? avio_size(ic->pb) : 0;
end_time = AV_NOPTS_VALUE;
do{
- offset = filesize - (DURATION_MAX_READ_SIZE<<retry);
- if (offset < 0)
- offset = 0;
+ 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;
+ 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 = av_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)) {
- duration = end_time = pkt->pts;
- if (st->start_time != AV_NOPTS_VALUE) duration -= st->start_time;
- else duration -= st->first_dts;
- if (duration < 0)
- duration += 1LL<<st->pts_wrap_bits;
- if (duration > 0) {
- if (st->duration == AV_NOPTS_VALUE ||
- st->duration < duration)
- st->duration = duration;
+ do {
+ ret = av_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)) {
+ duration = end_time = pkt->pts;
+ if (st->start_time != AV_NOPTS_VALUE)
+ duration -= st->start_time;
+ else
+ duration -= st->first_dts;
+ if (duration < 0)
+ duration += 1LL<<st->pts_wrap_bits;
+ if (duration > 0) {
+ if (st->duration == AV_NOPTS_VALUE || st->duration < duration)
+ st->duration = duration;
+ }
}
+ av_free_packet(pkt);
}
- av_free_packet(pkt);
- }
}while( end_time==AV_NOPTS_VALUE
&& filesize > (DURATION_MAX_READ_SIZE<<retry)
&& ++retry <= DURATION_MAX_RETRY);
}
}
-static void av_estimate_timings(AVFormatContext *ic, int64_t old_offset)
+static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
{
int64_t file_size;
file_size = 0;
} else {
file_size = avio_size(ic->pb);
- if (file_size < 0)
- file_size = 0;
+ file_size = FFMAX(0, file_size);
}
- ic->file_size = file_size;
if ((!strcmp(ic->iformat->name, "mpeg") ||
!strcmp(ic->iformat->name, "mpegts")) &&
file_size && ic->pb->seekable) {
/* get accurate estimate from the PTSes */
- av_estimate_timings_from_pts(ic, old_offset);
- } else if (av_has_duration(ic)) {
+ estimate_timings_from_pts(ic, old_offset);
+ } else if (has_duration(ic)) {
/* at least one component has timings - we use them for all
the components */
fill_all_stream_timings(ic);
} else {
av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this may be inaccurate\n");
/* less precise: use bitrate info */
- av_estimate_timings_from_bit_rate(ic);
+ estimate_timings_from_bit_rate(ic);
}
- av_update_stream_timings(ic);
+ update_stream_timings(ic);
{
int i;
}
}
-static int has_codec_parameters(AVCodecContext *enc)
+static int has_codec_parameters(AVCodecContext *avctx)
{
int val;
- switch(enc->codec_type) {
+ switch (avctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
- val = enc->sample_rate && enc->channels && enc->sample_fmt != AV_SAMPLE_FMT_NONE;
- if(!enc->frame_size &&
- (enc->codec_id == CODEC_ID_VORBIS ||
- enc->codec_id == CODEC_ID_AAC ||
- enc->codec_id == CODEC_ID_MP1 ||
- enc->codec_id == CODEC_ID_MP2 ||
- enc->codec_id == CODEC_ID_MP3 ||
- enc->codec_id == CODEC_ID_SPEEX))
+ val = avctx->sample_rate && avctx->channels && avctx->sample_fmt != AV_SAMPLE_FMT_NONE;
+ if (!avctx->frame_size &&
+ (avctx->codec_id == CODEC_ID_VORBIS ||
+ avctx->codec_id == CODEC_ID_AAC ||
+ avctx->codec_id == CODEC_ID_MP1 ||
+ avctx->codec_id == CODEC_ID_MP2 ||
+ avctx->codec_id == CODEC_ID_MP3 ||
+ avctx->codec_id == CODEC_ID_CELT))
return 0;
break;
case AVMEDIA_TYPE_VIDEO:
- val = enc->width && enc->pix_fmt != PIX_FMT_NONE;
+ val = avctx->width && avctx->pix_fmt != PIX_FMT_NONE;
break;
default:
val = 1;
break;
}
- return enc->codec_id != CODEC_ID_NONE && val != 0;
+ return avctx->codec_id != CODEC_ID_NONE && val != 0;
}
static int has_decode_delay_been_guessed(AVStream *st)
{
return st->codec->codec_id != CODEC_ID_H264 ||
- st->codec_info_nb_frames >= 6 + st->codec->has_b_frames;
+ st->info->nb_decoded_frames >= 6;
}
-static int try_decode_frame(AVStream *st, AVPacket *avpkt)
+static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **options)
{
- int16_t *samples;
AVCodec *codec;
- int got_picture, data_size, ret=0;
+ int got_picture, ret = 0;
AVFrame picture;
+ AVPacket pkt = *avpkt;
if(!st->codec->codec){
codec = avcodec_find_decoder(st->codec->codec_id);
if (!codec)
return -1;
- ret = avcodec_open(st->codec, codec);
+ ret = avcodec_open2(st->codec, codec, options);
if (ret < 0)
return ret;
}
- if(!has_codec_parameters(st->codec) || !has_decode_delay_been_guessed(st)){
+ while (pkt.size > 0 && ret >= 0 &&
+ (!has_codec_parameters(st->codec) ||
+ !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(&picture);
switch(st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
- avcodec_get_frame_defaults(&picture);
ret = avcodec_decode_video2(st->codec, &picture,
- &got_picture, avpkt);
+ &got_picture, &pkt);
break;
case AVMEDIA_TYPE_AUDIO:
- data_size = FFMAX(avpkt->size, AVCODEC_MAX_AUDIO_FRAME_SIZE);
- samples = av_malloc(data_size);
- if (!samples)
- goto fail;
- ret = avcodec_decode_audio3(st->codec, samples,
- &data_size, avpkt);
- av_free(samples);
+ ret = avcodec_decode_audio4(st->codec, &picture, &got_picture, &pkt);
break;
default:
break;
}
+ if (ret >= 0) {
+ if (got_picture)
+ st->info->nb_decoded_frames++;
+ pkt.data += ret;
+ pkt.size -= ret;
+ }
}
- fail:
return ret;
}
return tags[i].id;
}
for(i=0; tags[i].id != CODEC_ID_NONE; i++) {
- if (ff_toupper4(tag) == ff_toupper4(tags[i].tag))
+ if (avpriv_toupper4(tag) == avpriv_toupper4(tags[i].tag))
return tags[i].id;
}
return CODEC_ID_NONE;
return 0;
}
+#if FF_API_FORMAT_PARAMETERS
int av_find_stream_info(AVFormatContext *ic)
+{
+ return avformat_find_stream_info(ic, NULL);
+}
+#endif
+
+int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
{
int i, count, ret, read_size, j;
AVStream *st;
AVPacket pkt1, *pkt;
int64_t old_offset = avio_tell(ic->pb);
+ int orig_nb_streams = ic->nb_streams; // new streams might appear, no options for those
for(i=0;i<ic->nb_streams;i++) {
AVCodec *codec;
st = ic->streams[i];
- if (st->codec->codec_id == CODEC_ID_AAC) {
- st->codec->sample_rate = 0;
- st->codec->frame_size = 0;
- st->codec->channels = 0;
- }
+
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
/* if(!st->time_base.num)
assert(!st->codec->codec);
codec = avcodec_find_decoder(st->codec->codec_id);
- /* Force decoding of at least one frame of codec data
- * this makes sure the codec initializes the channel configuration
- * and does not trust the values from the container.
- */
- if (codec && codec->capabilities & CODEC_CAP_CHANNEL_CONF)
- st->codec->channels = 0;
+ /* this function doesn't flush the decoders, so force thread count
+ * to 1 to fix behavior when thread count > number of frames in the file */
+ if (options)
+ av_dict_set(&options[i], "threads", "1", 0);
/* Ensure that subtitle_header is properly set. */
if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
&& codec && !st->codec->codec)
- avcodec_open(st->codec, codec);
+ avcodec_open2(st->codec, codec, options ? &options[i] : NULL);
//try to just open decoders, in case this is enough to get parameters
if(!has_codec_parameters(st->codec)){
if (codec && !st->codec->codec)
- avcodec_open(st->codec, codec);
+ avcodec_open2(st->codec, codec, options ? &options[i] : NULL);
}
}
count = 0;
read_size = 0;
for(;;) {
- if(url_interrupt_cb()){
+ if (ff_check_interrupt(&ic->interrupt_callback)){
ret= AVERROR_EXIT;
av_log(ic, AV_LOG_DEBUG, "interrupted\n");
break;
/* NOTE: a new stream can be added there if no header in file
(AVFMTCTX_NOHEADER) */
- ret = av_read_frame_internal(ic, &pkt1);
- if (ret < 0 && ret != AVERROR(EAGAIN)) {
+ ret = read_frame_internal(ic, &pkt1);
+ if (ret == AVERROR(EAGAIN))
+ continue;
+
+ if (ret < 0) {
/* EOF or error */
ret = -1; /* we could not have all the codec parameters before EOF */
for(i=0;i<ic->nb_streams;i++) {
break;
}
- if (ret == AVERROR(EAGAIN))
- continue;
-
pkt= add_to_pktbuf(&ic->packet_buffer, &pkt1, &ic->packet_buffer_end);
if ((ret = av_dup_packet(pkt)) < 0)
goto find_stream_info_err;
}
{
int64_t last = st->info->last_dts;
- int64_t duration= pkt->dts - last;
- if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){
+ if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last){
+ int64_t duration= pkt->dts - last;
double dur= duration * av_q2d(st->time_base);
// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
for (i=1; i<FF_ARRAY_ELEMS(st->info->duration_error); i++) {
int framerate= get_std_framerate(i);
int ticks= lrintf(dur*framerate/(1001*12));
- double error= dur - ticks*1001*12/(double)framerate;
+ double error = dur - (double)ticks*1001*12 / framerate;
st->info->duration_error[i] += error*error;
}
st->info->duration_count++;
/* if still no information, we try to open the codec and to
decompress the frame. We try to avoid that in most cases as
it takes longer and uses more memory. For MPEG-4, we need to
- decompress for QuickTime. */
- if (!has_codec_parameters(st->codec) || !has_decode_delay_been_guessed(st))
- try_decode_frame(st, pkt);
+ decompress for QuickTime.
+
+ If CODEC_CAP_CHANNEL_CONF is set this will force decoding of at
+ 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);
st->codec_info_nb_frames++;
count++;
(st->codec_info_nb_frames-2)*(int64_t)st->time_base.den,
st->info->codec_info_duration*(int64_t)st->time_base.num, 60000);
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample)
- st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
-
// 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.
}
}
- av_estimate_timings(ic, old_offset);
+ estimate_timings(ic, old_offset);
compute_chapters_end(ic);
return AVERROR(ENOSYS);
}
+#if FF_API_FORMAT_PARAMETERS
void av_close_input_stream(AVFormatContext *s)
{
flush_packet_queue(s);
s->iformat->read_close(s);
avformat_free_context(s);
}
+#endif
void avformat_free_context(AVFormatContext *s)
{
av_free(s);
}
+#if FF_API_CLOSE_INPUT_FILE
void av_close_input_file(AVFormatContext *s)
{
+ avformat_close_input(&s);
+}
+#endif
+
+void avformat_close_input(AVFormatContext **ps)
+{
+ AVFormatContext *s = *ps;
AVIOContext *pb = (s->iformat->flags & AVFMT_NOFILE) || (s->flags & AVFMT_FLAG_CUSTOM_IO) ?
NULL : s->pb;
- av_close_input_stream(s);
+ flush_packet_queue(s);
+ if (s->iformat->read_close)
+ s->iformat->read_close(s);
+ avformat_free_context(s);
+ *ps = NULL;
if (pb)
avio_close(pb);
}
+#if FF_API_NEW_STREAM
AVStream *av_new_stream(AVFormatContext *s, int id)
+{
+ AVStream *st = avformat_new_stream(s, NULL);
+ if (st)
+ st->id = id;
+ return st;
+}
+#endif
+
+AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c)
{
AVStream *st;
int i;
return NULL;
}
- st->codec= avcodec_alloc_context();
+ st->codec = avcodec_alloc_context3(c);
if (s->iformat) {
/* no default bitrate if decoding */
st->codec->bit_rate = 0;
}
st->index = s->nb_streams;
- st->id = id;
st->start_time = AV_NOPTS_VALUE;
st->duration = AV_NOPTS_VALUE;
/* we set the current DTS to 0 so that formats without any timestamps
st->probe_packets = MAX_PROBE_PACKETS;
/* default pts setting is MPEG-like */
- av_set_pts_info(st, 33, 1, 90000);
+ avpriv_set_pts_info(st, 33, 1, 90000);
st->last_IP_pts = AV_NOPTS_VALUE;
for(i=0; i<MAX_REORDER_DELAY+1; i++)
st->pts_buffer[i]= AV_NOPTS_VALUE;
return program;
}
-AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int64_t start, int64_t end, const char *title)
+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;
for (n = 0; s->oformat->codec_tag[n]; n++) {
avctag = s->oformat->codec_tag[n];
while (avctag->id != CODEC_ID_NONE) {
- if (ff_toupper4(avctag->tag) == ff_toupper4(st->codec->codec_tag)) {
+ if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codec->codec_tag)) {
id = avctag->id;
if (id == st->codec->codec_id)
return 1;
ret = AVERROR_INVALIDDATA;
goto fail;
}
- av_frac_init(&st->pts, 0, 0, den);
+ frac_init(&st->pts, 0, 0, den);
}
}
likely equal to the encoder delay, but it would be better if we
had the real timestamps from the encoder */
if (frame_size >= 0 && (pkt->size || st->pts.num!=st->pts.den>>1 || st->pts.val)) {
- av_frac_add(&st->pts, (int64_t)st->time_base.den * frame_size);
+ frac_add(&st->pts, (int64_t)st->time_base.den * frame_size);
}
break;
case AVMEDIA_TYPE_VIDEO:
- av_frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num);
+ frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num);
break;
default:
break;
return ret;
ret= s->oformat->write_packet(s, pkt);
+
+ if (ret >= 0)
+ s->streams[pkt->stream_index]->nb_frames++;
return ret;
}
* @return 1 if a packet was output, 0 if no packet could be output,
* < 0 if an error occurred
*/
-static int av_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){
+static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){
if(s->oformat->interleave_packet)
return s->oformat->interleave_packet(s, out, in, flush);
else
for(;;){
AVPacket opkt;
- int ret= av_interleave_packet(s, &opkt, pkt, 0);
+ int ret= interleave_packet(s, &opkt, pkt, 0);
if(ret<=0) //FIXME cleanup needed for ret<0 ?
return ret;
ret= s->oformat->write_packet(s, &opkt);
+ if (ret >= 0)
+ s->streams[opkt.stream_index]->nb_frames++;
av_free_packet(&opkt);
pkt= NULL;
for(;;){
AVPacket pkt;
- ret= av_interleave_packet(s, &pkt, NULL, 1);
+ ret= interleave_packet(s, &pkt, NULL, 1);
if(ret<0) //FIXME cleanup needed for ret<0 ?
goto fail;
if(!ret)
break;
ret= s->oformat->write_packet(s, &pkt);
+ if (ret >= 0)
+ s->streams[pkt.stream_index]->nb_frames++;
av_free_packet(&pkt);
av_freep(&s->streams[i]->priv_data);
av_freep(&s->streams[i]->index_entries);
}
- if (s->iformat && s->iformat->priv_class)
+ if (s->oformat->priv_class)
av_opt_free(s->priv_data);
av_freep(&s->priv_data);
return ret;
int is_output)
{
int i;
- uint8_t *printed = av_mallocz(ic->nb_streams);
+ uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL;
if (ic->nb_streams && !printed)
return;
return len;
}
+#if FF_API_SET_PTS_INFO
void av_set_pts_info(AVStream *s, int pts_wrap_bits,
unsigned int pts_num, unsigned int pts_den)
+{
+ avpriv_set_pts_info(s, pts_wrap_bits, pts_num, pts_den);
+}
+#endif
+
+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)){
}
av_strlcat(buf, rel, size);
}
+
+int64_t ff_iso8601_to_unix_time(const char *datestr)
+{
+#if HAVE_STRPTIME
+ struct tm time1 = {0}, time2 = {0};
+ char *ret1, *ret2;
+ ret1 = strptime(datestr, "%Y - %m - %d %T", &time1);
+ ret2 = strptime(datestr, "%Y - %m - %dT%T", &time2);
+ if (ret2 && !ret1)
+ return av_timegm(&time2);
+ else
+ return av_timegm(&time1);
+#else
+ av_log(NULL, AV_LOG_WARNING, "strptime() unavailable on this system, cannot convert "
+ "the date string.\n");
+ return 0;
+#endif
+}
+
+int avformat_query_codec(AVOutputFormat *ofmt, enum CodecID codec_id, int std_compliance)
+{
+ if (ofmt) {
+ if (ofmt->query_codec)
+ return ofmt->query_codec(codec_id, std_compliance);
+ else if (ofmt->codec_tag)
+ return !!av_codec_get_tag(ofmt->codec_tag, codec_id);
+ else if (codec_id == ofmt->video_codec || codec_id == ofmt->audio_codec ||
+ codec_id == ofmt->subtitle_codec)
+ return 1;
+ }
+ return AVERROR_PATCHWELCOME;
+}
+
+int avformat_network_init(void)
+{
+#if CONFIG_NETWORK
+ int ret;
+ ff_network_inited_globally = 1;
+ if ((ret = ff_network_init()) < 0)
+ return ret;
+ ff_tls_init();
+#endif
+ return 0;
+}
+
+int avformat_network_deinit(void)
+{
+#if CONFIG_NETWORK
+ ff_network_close();
+ ff_tls_deinit();
+#endif
+ return 0;
+}