#include "avio_internal.h"
#include "internal.h"
#include "libavcodec/internal.h"
+#include "libavcodec/bytestream.h"
#include "libavutil/opt.h"
#include "libavutil/dict.h"
#include "libavutil/pixdesc.h"
#include "metadata.h"
#include "id3v2.h"
+#include "libavutil/avassert.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;
}
/************************************************************/
/* input media file */
-#if FF_API_FORMAT_PARAMETERS
-static AVDictionary *convert_format_parameters(AVFormatParameters *ap)
-{
- char buf[1024];
- AVDictionary *opts = NULL;
-
- if (ap->time_base.num) {
- snprintf(buf, sizeof(buf), "%d/%d", ap->time_base.den, ap->time_base.num);
- av_dict_set(&opts, "framerate", buf, 0);
- }
- if (ap->sample_rate) {
- snprintf(buf, sizeof(buf), "%d", ap->sample_rate);
- av_dict_set(&opts, "sample_rate", buf, 0);
- }
- if (ap->channels) {
- snprintf(buf, sizeof(buf), "%d", ap->channels);
- av_dict_set(&opts, "channels", buf, 0);
- }
- if (ap->width || ap->height) {
- snprintf(buf, sizeof(buf), "%dx%d", ap->width, ap->height);
- av_dict_set(&opts, "video_size", buf, 0);
- }
- if (ap->pix_fmt != PIX_FMT_NONE) {
- av_dict_set(&opts, "pixel_format", av_get_pix_fmt_name(ap->pix_fmt), 0);
- }
- if (ap->channel) {
- snprintf(buf, sizeof(buf), "%d", ap->channel);
- av_dict_set(&opts, "channel", buf, 0);
- }
- if (ap->standard) {
- av_dict_set(&opts, "standard", ap->standard, 0);
- }
- if (ap->mpeg2ts_compute_pcr) {
- av_dict_set(&opts, "mpeg2ts_compute_pcr", "1", 0);
- }
- if (ap->initial_pause) {
- av_dict_set(&opts, "initial_pause", "1", 0);
- }
- return opts;
-}
-
-/**
- * Open a media file from an IO stream. 'fmt' must be specified.
- */
-int av_open_input_stream(AVFormatContext **ic_ptr,
- AVIOContext *pb, const char *filename,
- AVInputFormat *fmt, AVFormatParameters *ap)
-{
- int err;
- AVDictionary *opts;
- AVFormatContext *ic;
- AVFormatParameters default_ap;
-
- if(!ap){
- ap=&default_ap;
- memset(ap, 0, sizeof(default_ap));
- }
- opts = convert_format_parameters(ap);
-
- if(!ap->prealloced_context)
- ic = avformat_alloc_context();
- else
- ic = *ic_ptr;
- if (!ic) {
- err = AVERROR(ENOMEM);
- goto fail;
- }
- ic->pb = pb;
-
- err = avformat_open_input(ic_ptr, filename, fmt, &opts);
-
-fail:
- av_dict_free(&opts);
- return err;
-}
-#endif
-
/** size of probe buffer, for guessing file type from file contents */
#define PROBE_BUF_MIN 2048
#define PROBE_BUF_MAX (1<<20)
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) {
return ret;
}
-#if FF_API_FORMAT_PARAMETERS
-int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
- AVInputFormat *fmt,
- int buf_size,
- AVFormatParameters *ap)
-{
- int err;
- AVDictionary *opts = convert_format_parameters(ap);
-
- if (!ap->prealloced_context)
- *ic_ptr = NULL;
-
- err = avformat_open_input(ic_ptr, filename, fmt, &opts);
-
- av_dict_free(&opts);
- return err;
-}
-#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 };
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 */
ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC);
if (s->iformat->read_header)
- if ((ret = s->iformat->read_header(s, &ap)) < 0)
+ if ((ret = s->iformat->read_header(s)) < 0)
goto fail;
if (s->pb && !s->data_offset)
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:
if((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE)
pkt->dts= AV_NOPTS_VALUE;
- if (st->codec->codec_id != CODEC_ID_H264 && pc && pc->pict_type == AV_PICTURE_TYPE_B)
- //FIXME Set low_delay = 0 when has_b_frames = 1
- st->codec->has_b_frames = 1;
-
/* do we have a video B-frame ? */
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)
/* update flags */
if(is_intra_only(st->codec))
pkt->flags |= AV_PKT_FLAG_KEY;
- else if (pc) {
- pkt->flags = 0;
- /* keyframe computation */
- if (pc->key_frame == 1)
- pkt->flags |= AV_PKT_FLAG_KEY;
- else if (pc->key_frame == -1 && pc->pict_type == AV_PICTURE_TYPE_I)
- pkt->flags |= AV_PKT_FLAG_KEY;
- }
if (pc)
pkt->convergence_duration = pc->convergence_duration;
}
-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;
if (pkt->size) {
got_packet:
pkt->duration = 0;
+ if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ if (st->codec->sample_rate > 0) {
+ pkt->duration = av_rescale_q_rnd(st->parser->duration,
+ (AVRational){ 1, st->codec->sample_rate },
+ st->time_base,
+ AV_ROUND_DOWN);
+ }
+ } else if (st->codec->time_base.num != 0 &&
+ st->codec->time_base.den != 0) {
+ pkt->duration = av_rescale_q_rnd(st->parser->duration,
+ st->codec->time_base,
+ st->time_base,
+ AV_ROUND_DOWN);
+ }
pkt->stream_index = st->index;
pkt->pts = st->parser->pts;
pkt->dts = st->parser->dts;
pkt->pos = st->parser->pos;
+ if (st->parser->key_frame == 1 ||
+ (st->parser->key_frame == -1 &&
+ st->parser->pict_type == AV_PICTURE_TYPE_I))
+ pkt->flags |= AV_PKT_FLAG_KEY;
if(pkt->data == st->cur_pkt.data && pkt->size == st->cur_pkt.size){
s->cur_st = NULL;
pkt->destruct= st->cur_pkt.destruct;
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,
return 0;
}
+static int read_from_packet_buffer(AVFormatContext *s, AVPacket *pkt)
+{
+ AVPacketList *pktl = s->packet_buffer;
+ av_assert0(pktl);
+ *pkt = pktl->pkt;
+ s->packet_buffer = pktl->next;
+ av_freep(&pktl);
+ return 0;
+}
+
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{
- AVPacketList *pktl;
- int eof=0;
- const int genpts= s->flags & AVFMT_FLAG_GENPTS;
+ const int genpts = s->flags & AVFMT_FLAG_GENPTS;
+ int eof = 0;
+
+ if (!genpts)
+ return s->packet_buffer ? read_from_packet_buffer(s, pkt) :
+ read_frame_internal(s, pkt);
+
+ for (;;) {
+ int ret;
+ AVPacketList *pktl = s->packet_buffer;
- for(;;){
- pktl = s->packet_buffer;
if (pktl) {
- AVPacket *next_pkt= &pktl->pkt;
+ AVPacket *next_pkt = &pktl->pkt;
- if(genpts && next_pkt->dts != AV_NOPTS_VALUE){
+ if (next_pkt->dts != AV_NOPTS_VALUE) {
int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits;
- while(pktl && next_pkt->pts == AV_NOPTS_VALUE){
- if( pktl->pkt.stream_index == next_pkt->stream_index
- && (0 > av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2LL << (wrap_bits - 1)))
- && av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) { //not b frame
- next_pkt->pts= pktl->pkt.dts;
+ while (pktl && next_pkt->pts == AV_NOPTS_VALUE) {
+ if (pktl->pkt.stream_index == next_pkt->stream_index &&
+ (av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2LL << (wrap_bits - 1)) < 0) &&
+ av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) { //not b frame
+ next_pkt->pts = pktl->pkt.dts;
}
- pktl= pktl->next;
+ pktl = pktl->next;
}
pktl = s->packet_buffer;
}
- if( next_pkt->pts != AV_NOPTS_VALUE
- || next_pkt->dts == AV_NOPTS_VALUE
- || !genpts || eof){
- /* read packet from packet buffer, if there is data */
- *pkt = *next_pkt;
- s->packet_buffer = pktl->next;
- av_free(pktl);
- return 0;
- }
+ /* read packet from packet buffer, if there is data */
+ if (!(next_pkt->pts == AV_NOPTS_VALUE &&
+ next_pkt->dts != AV_NOPTS_VALUE && !eof))
+ return read_from_packet_buffer(s, pkt);
}
- if(genpts){
- int ret= av_read_frame_internal(s, pkt);
- if(ret<0){
- if(pktl && ret != AVERROR(EAGAIN)){
- eof=1;
- continue;
- }else
- return ret;
- }
- if(av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt,
- &s->packet_buffer_end)) < 0)
- return AVERROR(ENOMEM);
- }else{
- assert(!s->packet_buffer);
- return av_read_frame_internal(s, pkt);
+ ret = read_frame_internal(s, pkt);
+ if (ret < 0) {
+ if (pktl && ret != AVERROR(EAGAIN)) {
+ eof = 1;
+ continue;
+ } else
+ return ret;
}
+
+ if (av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt,
+ &s->packet_buffer_end)) < 0)
+ return AVERROR(ENOMEM);
}
}
}
}
-void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){
+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);
}
-int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
+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 )){
+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)
+/* 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)
{
- int16_t *samples;
AVCodec *codec;
- int got_picture, data_size, ret=0;
+ int got_picture = 1, ret = 0;
AVFrame picture;
+ AVPacket pkt = *avpkt;
+
+ if (!avcodec_is_open(st->codec)) {
+ AVDictionary *thread_opt = NULL;
+
+ codec = st->codec->codec ? st->codec->codec :
+ avcodec_find_decoder(st->codec->codec_id);
- if(!st->codec->codec){
- codec = avcodec_find_decoder(st->codec->codec_id);
if (!codec)
return -1;
- ret = avcodec_open(st->codec, codec);
+
+ /* force thread count to 1 since the h264 decoder will not extract SPS
+ * and PPS to extradata during multi-threaded decoding */
+ av_dict_set(options ? options : &thread_opt, "threads", "1", 0);
+ ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt);
+ if (!options)
+ av_dict_free(&thread_opt);
if (ret < 0)
return ret;
}
- if(!has_codec_parameters(st->codec) || !has_decode_delay_been_guessed(st)){
+ while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
+ 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;
+ ret = got_picture;
+ }
}
- 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;
}
-int av_find_stream_info(AVFormatContext *ic)
+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;
+ AVDictionary *thread_opt = NULL;
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)
- st->time_base= */
- if(!st->codec->time_base.num)
- st->codec->time_base= st->time_base;
- }
+
//only for the split stuff
if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE)) {
st->parser = av_parser_init(st->codec->codec_id);
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
}
}
- assert(!st->codec->codec);
- codec = avcodec_find_decoder(st->codec->codec_id);
+ codec = st->codec->codec ? st->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;
+ /* force thread count to 1 since the h264 decoder will not extract SPS
+ * and PPS to extradata during multi-threaded decoding */
+ av_dict_set(options ? &options[i] : &thread_opt, "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]
+ : &thread_opt);
//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]
+ : &thread_opt);
}
+ if (!options)
+ av_dict_free(&thread_opt);
}
for (i=0; i<ic->nb_streams; i++) {
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)) {
- /* EOF or error */
+ ret = read_frame_internal(ic, &pkt1);
+ if (ret == AVERROR(EAGAIN))
+ continue;
+
+ if (ret < 0) {
+ /* EOF or error*/
+ AVPacket empty_pkt = { 0 };
+ int err;
+ 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++) {
st = ic->streams[i];
- if (!has_codec_parameters(st->codec)){
+
+ /* flush the decoders */
+ do {
+ err = try_decode_frame(st, &empty_pkt,
+ (options && i < orig_nb_streams) ?
+ &options[i] : NULL);
+ } while (err > 0 && !has_codec_parameters(st->codec));
+
+ if (err < 0) {
+ av_log(ic, AV_LOG_WARNING,
+ "decoding for stream %d failed\n", st->index);
+ } else if (!has_codec_parameters(st->codec)){
char buf[256];
avcodec_string(buf, sizeof(buf), st->codec, 0);
- av_log(ic, AV_LOG_WARNING, "Could not find codec parameters (%s)\n", buf);
+ av_log(ic, AV_LOG_WARNING,
+ "Could not find codec parameters (%s)\n", buf);
} else {
ret = 0;
}
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(st->parser && st->parser->parser->split && !st->codec->extradata){
int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
- if(i){
+ 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)
+ return AVERROR(ENOMEM);
memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
}
/* 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++;
// close codecs which were opened in try_decode_frame()
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
- if(st->codec->codec)
- avcodec_close(st->codec);
+ avcodec_close(st->codec);
}
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
(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.
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
- <= st->codec->time_base.num * st->codec->ticks_per_frame * (int64_t)st->time_base.den){
- st->r_frame_rate.num = st->codec->time_base.den;
- st->r_frame_rate.den = st->codec->time_base.num * st->codec->ticks_per_frame;
- }else{
- st->r_frame_rate.num = st->time_base.den;
- st->r_frame_rate.den = st->time_base.num;
- }
- }
}else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
if(!st->codec->bits_per_coded_sample)
st->codec->bits_per_coded_sample= av_get_bits_per_sample(st->codec->codec_id);
}
}
- av_estimate_timings(ic, old_offset);
+ estimate_timings(ic, old_offset);
compute_chapters_end(ic);
#endif
find_stream_info_err:
- for (i=0; i < ic->nb_streams; i++)
+ for (i=0; i < ic->nb_streams; i++) {
+ if (ic->streams[i]->codec)
+ ic->streams[i]->codec->thread_count = 0;
av_freep(&ic->streams[i]->info);
+ }
return ret;
}
return AVERROR(ENOSYS);
}
-void av_close_input_stream(AVFormatContext *s)
-{
- flush_packet_queue(s);
- if (s->iformat->read_close)
- s->iformat->read_close(s);
- avformat_free_context(s);
-}
-
void avformat_free_context(AVFormatContext *s)
{
int i;
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);
}
-AVStream *av_new_stream(AVFormatContext *s, int id)
+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;
/************************************************************/
/* output media file */
-#if FF_API_FORMAT_PARAMETERS
-int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap)
-{
- int ret;
-
- if (s->oformat->priv_data_size > 0) {
- s->priv_data = av_mallocz(s->oformat->priv_data_size);
- if (!s->priv_data)
- return AVERROR(ENOMEM);
- if (s->oformat->priv_class) {
- *(const AVClass**)s->priv_data= s->oformat->priv_class;
- av_opt_set_defaults(s->priv_data);
- }
- } else
- s->priv_data = NULL;
-
- if (s->oformat->set_parameters) {
- ret = s->oformat->set_parameters(s, ap);
- if (ret < 0)
- return ret;
- }
- return 0;
-}
-#endif
-
static int validate_codec_tag(AVFormatContext *s, AVStream *st)
{
const AVCodecTag *avctag;
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;
return 1;
}
-#if FF_API_FORMAT_PARAMETERS
-int av_write_header(AVFormatContext *s)
-{
- return avformat_write_header(s, NULL);
-}
-#endif
-
int avformat_write_header(AVFormatContext *s, AVDictionary **options)
{
int ret = 0, i;
goto fail;
}
if(av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)){
- av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between encoder and muxer layer\n");
+ av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between muxer "
+ "(%d/%d) and encoder layer (%d/%d)\n",
+ st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
+ st->codec->sample_aspect_ratio.num,
+ st->codec->sample_aspect_ratio.den);
ret = AVERROR(EINVAL);
goto fail;
}
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;
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
{
- int ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt);
+ int ret;
+
+ if (!pkt) {
+ if (s->oformat->flags & AVFMT_ALLOW_FLUSH)
+ return s->oformat->write_packet(s, pkt);
+ return 1;
+ }
+
+ ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt);
if(ret<0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
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){
- if(s->oformat->interleave_packet)
- return s->oformat->interleave_packet(s, out, in, flush);
- else
+static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){
+ if (s->oformat->interleave_packet) {
+ int ret = s->oformat->interleave_packet(s, out, in, flush);
+ if (in)
+ av_free_packet(in);
+ return ret;
+ } else
return av_interleave_packet_per_dts(s, out, in, flush);
}
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;
dump_metadata(NULL, st->metadata, " ");
}
-#if FF_API_DUMP_FORMAT
-void dump_format(AVFormatContext *ic,
- int index,
- const char *url,
- int is_output)
-{
- av_dump_format(ic, index, url, is_output);
-}
-#endif
-
void av_dump_format(AVFormatContext *ic,
int index,
const char *url,
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 (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
}
-#if FF_API_PARSE_DATE
-#include "libavutil/parseutils.h"
-
-int64_t parse_date(const char *timestr, int duration)
-{
- int64_t timeval;
- av_parse_time(&timeval, timestr, duration);
- return timeval;
-}
-#endif
-
-#if FF_API_FIND_INFO_TAG
-#include "libavutil/parseutils.h"
-
-int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
-{
- return av_find_info_tag(arg, arg_size, tag1, info);
-}
-#endif
-
int av_get_frame_filename(char *buf, int buf_size,
const char *path, int number)
{
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)
{
return len;
}
-void av_set_pts_info(AVStream *s, int pts_wrap_bits,
- unsigned int pts_num, unsigned int pts_den)
+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;
+}
+
+int ff_add_param_change(AVPacket *pkt, int32_t channels,
+ uint64_t channel_layout, int32_t sample_rate,
+ int32_t width, int32_t height)
+{
+ uint32_t flags = 0;
+ int size = 4;
+ uint8_t *data;
+ if (!pkt)
+ return AVERROR(EINVAL);
+ if (channels) {
+ size += 4;
+ flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT;
+ }
+ if (channel_layout) {
+ size += 8;
+ flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT;
+ }
+ if (sample_rate) {
+ size += 4;
+ flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE;
+ }
+ if (width || height) {
+ size += 8;
+ flags |= AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS;
+ }
+ data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size);
+ if (!data)
+ return AVERROR(ENOMEM);
+ bytestream_put_le32(&data, flags);
+ if (channels)
+ bytestream_put_le32(&data, channels);
+ if (channel_layout)
+ bytestream_put_le64(&data, channel_layout);
+ if (sample_rate)
+ bytestream_put_le32(&data, sample_rate);
+ if (width || height) {
+ bytestream_put_le32(&data, width);
+ bytestream_put_le32(&data, height);
+ }
+ return 0;
+}
+
+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;
+}