X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=4a69baae2170db22af95bdfb90ce2c3b816abb7f;hb=14120c95f02a677cb2e4008c2856d5cc715b2ccd;hp=d6bee908b5e8846d0f4cc340409e2e6fc2deb907;hpb=dd57251cb0945c1eaf7eebbf23cdab77278ce05f;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index d6bee908b5e..4a69baae217 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -19,11 +19,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" +#include "internal.h" #include "libavcodec/opt.h" +#include "metadata.h" #include "libavutil/avstring.h" #include "riff.h" #include #include +#include #undef NDEBUG #include @@ -33,8 +36,60 @@ * various utility functions for use within FFmpeg */ -static void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den); -static void av_frac_add(AVFrac *f, int64_t incr); +unsigned avformat_version(void) +{ + return LIBAVFORMAT_VERSION_INT; +} + +/* fraction handling */ + +/** + * f = val + (num / den) + 0.5. + * + * 'num' is normalized so that it is such as 0 <= num < den. + * + * @param f fractional number + * @param val integer value + * @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) +{ + num += (den >> 1); + if (num >= den) { + val += num / den; + num = num % den; + } + f->val = val; + f->num = num; + f->den = den; +} + +/** + * Fractional addition to f: f = f + (incr / f->den). + * + * @param f fractional number + * @param incr increment, can be positive or negative + */ +static void av_frac_add(AVFrac *f, int64_t incr) +{ + int64_t num, den; + + num = f->num + incr; + den = f->den; + if (num < 0) { + f->val += num / den; + num = num % den; + if (num < 0) { + num += den; + f->val--; + } + } else if (num >= den) { + f->val += num / den; + num = num % den; + } + f->num = num; +} /** head of registered input format linked list */ AVInputFormat *first_iformat = NULL; @@ -98,6 +153,24 @@ int match_ext(const char *filename, const char *extensions) 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 (!strncasecmp(name, names, len)) + return 1; + names = p+1; + } + return !strcasecmp(name, names); +} + AVOutputFormat *guess_format(const char *short_name, const char *filename, const char *mime_type) { @@ -105,7 +178,7 @@ AVOutputFormat *guess_format(const char *short_name, const char *filename, int score_max, score; /* specific test for image sequences */ -#ifdef CONFIG_IMAGE2_MUXER +#if CONFIG_IMAGE2_MUXER if (!short_name && filename && av_filename_number_test(filename) && av_guess_image2_codec(filename) != CODEC_ID_NONE) { @@ -159,7 +232,7 @@ enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, if(type == CODEC_TYPE_VIDEO){ enum CodecID codec_id= CODEC_ID_NONE; -#ifdef CONFIG_IMAGE2_MUXER +#if CONFIG_IMAGE2_MUXER if(!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")){ codec_id= av_guess_image2_codec(filename); } @@ -177,7 +250,7 @@ AVInputFormat *av_find_input_format(const char *short_name) { AVInputFormat *fmt; for(fmt = first_iformat; fmt != NULL; fmt = fmt->next) { - if (!strcmp(fmt->name, short_name)) + if (match_format(short_name, fmt->name)) return fmt; } return NULL; @@ -197,6 +270,7 @@ void av_init_packet(AVPacket *pkt) pkt->dts = AV_NOPTS_VALUE; pkt->pos = -1; pkt->duration = 0; + pkt->convergence_duration = 0; pkt->flags = 0; pkt->stream_index = 0; pkt->destruct= av_destruct_packet_nofree; @@ -239,7 +313,7 @@ int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size) int av_dup_packet(AVPacket *pkt) { - if (pkt->destruct != av_destruct_packet) { + if (((pkt->destruct == av_destruct_packet_nofree) || (pkt->destruct == NULL)) && pkt->data) { uint8_t *data; /* We duplicate the packet and don't forget to add the padding again. */ if((unsigned)pkt->size > (unsigned)pkt->size + FF_INPUT_BUFFER_PADDING_SIZE) @@ -299,14 +373,22 @@ static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score) fmt = av_probe_input_format2(pd, 1, &score); if (fmt) { - if (!strcmp(fmt->name, "mp3")) + if (!strcmp(fmt->name, "mp3")) { st->codec->codec_id = CODEC_ID_MP3; - else if (!strcmp(fmt->name, "ac3")) + st->codec->codec_type = CODEC_TYPE_AUDIO; + } else if (!strcmp(fmt->name, "ac3")) { st->codec->codec_id = CODEC_ID_AC3; - else if (!strcmp(fmt->name, "mpegvideo")) + st->codec->codec_type = CODEC_TYPE_AUDIO; + } else if (!strcmp(fmt->name, "mpegvideo")) { st->codec->codec_id = CODEC_ID_MPEG2VIDEO; - else if (!strcmp(fmt->name, "h264")) + st->codec->codec_type = CODEC_TYPE_VIDEO; + } else if (!strcmp(fmt->name, "m4v")) { + st->codec->codec_id = CODEC_ID_MPEG4; + st->codec->codec_type = CODEC_TYPE_VIDEO; + } else if (!strcmp(fmt->name, "h264")) { st->codec->codec_id = CODEC_ID_H264; + st->codec->codec_type = CODEC_TYPE_VIDEO; + } } return !!fmt; } @@ -317,63 +399,6 @@ static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score) /** * Open a media file from an IO stream. 'fmt' must be specified. */ -static const char* format_to_name(void* ptr) -{ - AVFormatContext* fc = (AVFormatContext*) ptr; - if(fc->iformat) return fc->iformat->name; - else if(fc->oformat) return fc->oformat->name; - else return "NULL"; -} - -#define OFFSET(x) offsetof(AVFormatContext,x) -#define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C -//these names are too long to be readable -#define E AV_OPT_FLAG_ENCODING_PARAM -#define D AV_OPT_FLAG_DECODING_PARAM - -static const AVOption options[]={ -{"probesize", NULL, OFFSET(probesize), FF_OPT_TYPE_INT, 32000, 32, INT_MAX, D}, /* 32000 from mpegts.c: 1.0 second at 24Mbit/s */ -{"muxrate", "set mux rate", OFFSET(mux_rate), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E}, -{"packetsize", "set packet size", OFFSET(packet_size), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E}, -{"fflags", NULL, OFFSET(flags), FF_OPT_TYPE_FLAGS, DEFAULT, INT_MIN, INT_MAX, D|E, "fflags"}, -{"ignidx", "ignore index", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_IGNIDX, INT_MIN, INT_MAX, D, "fflags"}, -{"genpts", "generate pts", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_GENPTS, INT_MIN, INT_MAX, D, "fflags"}, -{"track", " set the track number", OFFSET(track), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E}, -{"year", "set the year", OFFSET(year), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, E}, -{"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), FF_OPT_TYPE_INT, 3*AV_TIME_BASE, 0, INT_MAX, D}, -{"cryptokey", "decryption key", OFFSET(key), FF_OPT_TYPE_BINARY, 0, 0, 0, D}, -{"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), FF_OPT_TYPE_INT, 1<<20, 0, INT_MAX, D}, -{"rtbufsize", "max memory used for buffering real-time frames", OFFSET(max_picture_buffer), FF_OPT_TYPE_INT, 3041280, 0, INT_MAX, D}, /* defaults to 1s of 15fps 352x288 YUYV422 video */ -{"fdebug", "print specific debug info", OFFSET(debug), FF_OPT_TYPE_FLAGS, DEFAULT, 0, INT_MAX, E|D, "fdebug"}, -{"ts", NULL, 0, FF_OPT_TYPE_CONST, FF_FDEBUG_TS, INT_MIN, INT_MAX, E|D, "fdebug"}, -{NULL}, -}; - -#undef E -#undef D -#undef DEFAULT - -static const AVClass av_format_context_class = { "AVFormatContext", format_to_name, options }; - -static void avformat_get_context_defaults(AVFormatContext *s) -{ - memset(s, 0, sizeof(AVFormatContext)); - - s->av_class = &av_format_context_class; - - av_opt_set_defaults(s); -} - -AVFormatContext *av_alloc_format_context(void) -{ - AVFormatContext *ic; - ic = av_malloc(sizeof(AVFormatContext)); - if (!ic) return ic; - avformat_get_context_defaults(ic); - ic->av_class = &av_format_context_class; - return ic; -} - int av_open_input_stream(AVFormatContext **ic_ptr, ByteIOContext *pb, const char *filename, AVInputFormat *fmt, AVFormatParameters *ap) @@ -421,6 +446,10 @@ int av_open_input_stream(AVFormatContext **ic_ptr, if (pb && !ic->data_offset) ic->data_offset = url_ftell(ic->pb); +#if LIBAVFORMAT_VERSION_MAJOR < 53 + ff_metadata_demux_compat(ic); +#endif + *ic_ptr = ic; return 0; fail: @@ -524,16 +553,17 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, /*******************************************************/ -static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt){ - AVPacketList *pktl; - AVPacketList **plast_pktl= packet_buffer; - - while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last? - - pktl = av_mallocz(sizeof(AVPacketList)); +static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, + AVPacketList **plast_pktl){ + AVPacketList *pktl = av_mallocz(sizeof(AVPacketList)); if (!pktl) return NULL; + if (*packet_buffer) + (*plast_pktl)->next = pktl; + else + *packet_buffer = pktl; + /* add the packet in the buffered packet list */ *plast_pktl = pktl; pktl->pkt= *pkt; @@ -563,11 +593,6 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; st= s->streams[pkt->stream_index]; - if(!pktl && st->codec->codec_id!=CODEC_ID_PROBE) - return ret; - - add_to_pktbuf(&s->raw_packet_buffer, pkt); - switch(st->codec->codec_type){ case CODEC_TYPE_VIDEO: if(s->video_codec_id) st->codec->codec_id= s->video_codec_id; @@ -580,6 +605,11 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) break; } + if(!pktl && st->codec->codec_id!=CODEC_ID_PROBE) + return ret; + + add_to_pktbuf(&s->raw_packet_buffer, pkt, &s->raw_packet_buffer_end); + if(st->codec->codec_id == CODEC_ID_PROBE){ AVProbeData *pd = &st->probe_data; @@ -682,6 +712,8 @@ static int is_intra_only(AVCodecContext *enc){ case CODEC_ID_ASV1: case CODEC_ID_ASV2: case CODEC_ID_VCR1: + case CODEC_ID_DNXHD: + case CODEC_ID_JPEG2000: return 1; default: break; } @@ -760,11 +792,28 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, int num, den, presentation_delayed, delay, i; int64_t offset; + /* do we have a video B-frame ? */ + delay= st->codec->has_b_frames; + presentation_delayed = 0; + /* XXX: need has_b_frame, but cannot get it if the codec is + not initialized */ + if (delay && + pc && pc->pict_type != FF_B_TYPE) + presentation_delayed = 1; + if(pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && pkt->dts > pkt->pts && st->pts_wrap_bits<63 /*&& pkt->dts-(1LL<pts_wrap_bits) < pkt->pts*/){ pkt->dts -= 1LL<pts_wrap_bits; } + // some mpeg2 in mpeg-ps lack dts (issue171 / input_file.mpg) + // we take the conservative approach and discard both + // 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_ERROR, "invalid dts/pts combination\n"); + pkt->dts= pkt->pts= AV_NOPTS_VALUE; + } + if (pkt->duration == 0) { compute_frame_duration(&num, &den, st, pc, pkt); if (den && num) { @@ -786,14 +835,6 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->dts += offset; } - /* do we have a video B-frame ? */ - delay= st->codec->has_b_frames; - presentation_delayed = 0; - /* XXX: need has_b_frame, but cannot get it if the codec is - not initialized */ - if (delay && - pc && pc->pict_type != FF_B_TYPE) - presentation_delayed = 1; /* 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; @@ -842,10 +883,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } } - if(pkt->pts != AV_NOPTS_VALUE){ + if(pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY){ st->pts_buffer[0]= pkt->pts; - for(i=1; ipts_buffer[i] == AV_NOPTS_VALUE; i++) - st->pts_buffer[i]= (i-delay-1) * pkt->duration; for(i=0; ipts_buffer[i] > st->pts_buffer[i+1]; i++) FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]); if(pkt->dts == AV_NOPTS_VALUE) @@ -889,24 +928,24 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (!st->need_parsing || !st->parser) { /* no parsing needed: we just output the packet as is */ /* raw data support */ - *pkt = s->cur_pkt; + *pkt = st->cur_pkt; st->cur_pkt.data= NULL; compute_pkt_fields(s, st, NULL, pkt); s->cur_st = NULL; break; - } else if (s->cur_len > 0 && st->discard < AVDISCARD_ALL) { + } else if (st->cur_len > 0 && st->discard < AVDISCARD_ALL) { len = av_parser_parse(st->parser, st->codec, &pkt->data, &pkt->size, - s->cur_ptr, s->cur_len, - s->cur_pkt.pts, s->cur_pkt.dts); - s->cur_pkt.pts = AV_NOPTS_VALUE; - s->cur_pkt.dts = AV_NOPTS_VALUE; + st->cur_ptr, st->cur_len, + st->cur_pkt.pts, st->cur_pkt.dts); + st->cur_pkt.pts = AV_NOPTS_VALUE; + st->cur_pkt.dts = AV_NOPTS_VALUE; /* increment read pointer */ - s->cur_ptr += len; - s->cur_len -= len; + st->cur_ptr += len; + st->cur_len -= len; /* return packet if any */ if (pkt->size) { + pkt->pos = st->cur_pkt.pos; // Isn't quite accurate but close. got_packet: - pkt->pos = s->cur_pkt.pos; // Isn't quite accurate but close. pkt->duration = 0; pkt->stream_index = st->index; pkt->pts = st->parser->pts; @@ -924,12 +963,13 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) } } else { /* free packet */ - av_free_packet(&s->cur_pkt); + av_free_packet(&st->cur_pkt); s->cur_st = NULL; } } else { + AVPacket cur_pkt; /* read next packet */ - ret = av_read_packet(s, &s->cur_pkt); + ret = av_read_packet(s, &cur_pkt); if (ret < 0) { if (ret == AVERROR(EAGAIN)) return ret; @@ -948,31 +988,32 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) /* no more packets: really terminate parsing */ return ret; } + st = s->streams[cur_pkt.stream_index]; + st->cur_pkt= cur_pkt; - if(s->cur_pkt.pts != AV_NOPTS_VALUE && - s->cur_pkt.dts != AV_NOPTS_VALUE && - s->cur_pkt.pts < s->cur_pkt.dts){ + if(st->cur_pkt.pts != AV_NOPTS_VALUE && + st->cur_pkt.dts != AV_NOPTS_VALUE && + st->cur_pkt.pts < st->cur_pkt.dts){ av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n", - s->cur_pkt.stream_index, - s->cur_pkt.pts, - s->cur_pkt.dts, - s->cur_pkt.size); -// av_free_packet(&s->cur_pkt); + st->cur_pkt.stream_index, + st->cur_pkt.pts, + st->cur_pkt.dts, + st->cur_pkt.size); +// av_free_packet(&st->cur_pkt); // return -1; } - st = s->streams[s->cur_pkt.stream_index]; if(s->debug & FF_FDEBUG_TS) av_log(s, AV_LOG_DEBUG, "av_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, flags=%d\n", - s->cur_pkt.stream_index, - s->cur_pkt.pts, - s->cur_pkt.dts, - s->cur_pkt.size, - s->cur_pkt.flags); + st->cur_pkt.stream_index, + st->cur_pkt.pts, + st->cur_pkt.dts, + st->cur_pkt.size, + st->cur_pkt.flags); s->cur_st = st; - s->cur_ptr = s->cur_pkt.data; - s->cur_len = s->cur_pkt.size; + st->cur_ptr = st->cur_pkt.data; + st->cur_len = st->cur_pkt.size; if (st->need_parsing && !st->parser) { st->parser = av_parser_init(st->codec->codec_id); if (!st->parser) { @@ -983,7 +1024,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) } if(st->parser && (s->iformat->flags & AVFMT_GENERIC_INDEX)){ st->parser->next_frame_offset= - st->parser->cur_offset= s->cur_pkt.pos; + st->parser->cur_offset= st->cur_pkt.pos; } } } @@ -1043,7 +1084,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) return ret; } - if(av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt)) < 0) + if(av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt, + &s->packet_buffer_end)) < 0) return AVERROR(ENOMEM); }else{ assert(!s->packet_buffer); @@ -1099,15 +1141,7 @@ static void av_read_frame_flush(AVFormatContext *s) flush_packet_queue(s); - /* free previous packet */ - if (s->cur_st) { - if (s->cur_st->parser) - av_free_packet(&s->cur_pkt); - s->cur_st = NULL; - } - /* fail safe */ - s->cur_ptr = NULL; - s->cur_len = 0; + s->cur_st = NULL; /* for each stream, reset read state */ for(i = 0; i < s->nb_streams; i++) { @@ -1116,9 +1150,13 @@ static void av_read_frame_flush(AVFormatContext *s) if (st->parser) { av_parser_close(st->parser); st->parser = NULL; + av_free_packet(&st->cur_pkt); } st->last_IP_pts = AV_NOPTS_VALUE; st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */ + /* fail safe */ + st->cur_ptr = NULL; + st->cur_len = 0; } } @@ -1430,7 +1468,7 @@ static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, static int av_seek_frame_generic(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { - int index; + int index, ret; AVStream *st; AVIndexEntry *ie; @@ -1445,13 +1483,18 @@ static int av_seek_frame_generic(AVFormatContext *s, if(st->nb_index_entries){ assert(st->index_entries); ie= &st->index_entries[st->nb_index_entries-1]; - url_fseek(s->pb, ie->pos, SEEK_SET); + if ((ret = url_fseek(s->pb, ie->pos, SEEK_SET)) < 0) + return ret; av_update_cur_dts(s, st, ie->timestamp); - }else - url_fseek(s->pb, 0, SEEK_SET); - + }else{ + if ((ret = url_fseek(s->pb, 0, SEEK_SET)) < 0) + return ret; + } for(i=0;; i++) { - int ret = av_read_frame(s, &pkt); + int ret; + do{ + ret = av_read_frame(s, &pkt); + }while(ret == AVERROR(EAGAIN)); if(ret<0) break; av_free_packet(&pkt); @@ -1471,8 +1514,8 @@ static int av_seek_frame_generic(AVFormatContext *s, return 0; } ie = &st->index_entries[index]; - url_fseek(s->pb, ie->pos, SEEK_SET); - + if ((ret = url_fseek(s->pb, ie->pos, SEEK_SET)) < 0) + return ret; av_update_cur_dts(s, st, ie->timestamp); return 0; @@ -1497,7 +1540,6 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f /* 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); } - st= s->streams[stream_index]; /* first, we try the format specific seek */ if (s->iformat->read_seek) @@ -1637,7 +1679,7 @@ static void av_estimate_timings_from_bit_rate(AVFormatContext *ic) #define DURATION_MAX_READ_SIZE 250000 /* only usable for MPEG-PS streams */ -static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offset) +static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) { AVPacket pkt1, *pkt = &pkt1; AVStream *st; @@ -1645,9 +1687,6 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse int64_t end_time; int64_t filesize, offset, duration; - /* free previous packet */ - if (ic->cur_st && ic->cur_st->parser) - av_free_packet(&ic->cur_pkt); ic->cur_st = NULL; /* flush packet queue */ @@ -1658,6 +1697,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse if (st->parser) { av_parser_close(st->parser); st->parser= NULL; + av_free_packet(&st->cur_pkt); } } @@ -1677,7 +1717,9 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse if (i == ic->nb_streams) break; - ret = av_read_packet(ic, pkt); + do{ + ret = av_read_packet(ic, pkt); + }while(ret == AVERROR(EAGAIN)); if (ret != 0) break; read_size += pkt->size; @@ -1702,7 +1744,9 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse if (read_size >= DURATION_MAX_READ_SIZE) break; - ret = av_read_packet(ic, pkt); + do{ + ret = av_read_packet(ic, pkt); + }while(ret == AVERROR(EAGAIN)); if (ret != 0) break; read_size += pkt->size; @@ -1730,7 +1774,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse } } -static void av_estimate_timings(AVFormatContext *ic, offset_t old_offset) +static void av_estimate_timings(AVFormatContext *ic, int64_t old_offset) { int64_t file_size; @@ -1782,7 +1826,7 @@ static int has_codec_parameters(AVCodecContext *enc) int val; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: - val = enc->sample_rate && enc->channels; + val = enc->sample_rate && enc->channels && enc->sample_fmt != SAMPLE_FMT_NONE; if(!enc->frame_size && (enc->codec_id == CODEC_ID_VORBIS || enc->codec_id == CODEC_ID_AAC)) @@ -1864,7 +1908,7 @@ enum CodecID codec_get_id(const AVCodecTag *tags, unsigned int tag) return CODEC_ID_NONE; } -unsigned int av_codec_get_tag(const AVCodecTag *tags[4], enum CodecID id) +unsigned int av_codec_get_tag(const AVCodecTag * const *tags, enum CodecID id) { int i; for(i=0; tags && tags[i]; i++){ @@ -1874,7 +1918,7 @@ unsigned int av_codec_get_tag(const AVCodecTag *tags[4], enum CodecID id) return 0; } -enum CodecID av_codec_get_id(const AVCodecTag *tags[4], unsigned int tag) +enum CodecID av_codec_get_id(const AVCodecTag * const *tags, unsigned int tag) { int i; for(i=0; tags && tags[i]; i++){ @@ -1910,7 +1954,7 @@ static void compute_chapters_end(AVFormatContext *s) #define MAX_STD_TIMEBASES (60*12+5) static int get_std_framerate(int i){ if(i<60*12) return i*1001; - else return ((int[]){24,30,60,12,15})[i-60*12]*1000*12; + else return ((const int[]){24,30,60,12,15})[i-60*12]*1000*12; } /* @@ -1924,8 +1968,8 @@ static int get_std_framerate(int i){ static int tb_unreliable(AVCodecContext *c){ if( c->time_base.den >= 101L*c->time_base.num || c->time_base.den < 5L*c->time_base.num -/* || c->codec_tag == ff_get_fourcc("DIVX") - || c->codec_tag == ff_get_fourcc("XVID")*/ +/* || c->codec_tag == AV_RL32("DIVX") + || c->codec_tag == AV_RL32("XVID")*/ || c->codec_id == CODEC_ID_MPEG2VIDEO) return 1; return 0; @@ -1939,7 +1983,7 @@ int av_find_stream_info(AVFormatContext *ic) int64_t last_dts[MAX_STREAMS]; int duration_count[MAX_STREAMS]={0}; double (*duration_error)[MAX_STD_TIMEBASES]; - offset_t old_offset = url_ftell(ic->pb); + int64_t old_offset = url_ftell(ic->pb); int64_t codec_info_duration[MAX_STREAMS]={0}; int codec_info_nb_frames[MAX_STREAMS]={0}; @@ -2003,6 +2047,8 @@ int av_find_stream_info(AVFormatContext *ic) /* NOTE: a new stream can be added there if no header in file (AVFMTCTX_NOHEADER) */ ret = av_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 */ @@ -2019,9 +2065,11 @@ int av_find_stream_info(AVFormatContext *ic) break; } - pkt= add_to_pktbuf(&ic->packet_buffer, &pkt1); - if(av_dup_packet(pkt) < 0) + pkt= add_to_pktbuf(&ic->packet_buffer, &pkt1, &ic->packet_buffer_end); + if(av_dup_packet(pkt) < 0) { + av_free(duration_error); return AVERROR(ENOMEM); + } read_size += pkt->size; @@ -2100,7 +2148,7 @@ int av_find_stream_info(AVFormatContext *ic) for(i=0;inb_streams;i++) { st = ic->streams[i]; if (st->codec->codec_type == CODEC_TYPE_VIDEO) { - if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_sample) + 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); if(duration_count[i] @@ -2132,8 +2180,8 @@ int av_find_stream_info(AVFormatContext *ic) } } }else if(st->codec->codec_type == CODEC_TYPE_AUDIO) { - if(!st->codec->bits_per_sample) - st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id); + if(!st->codec->bits_per_coded_sample) + st->codec->bits_per_coded_sample= av_get_bits_per_sample(st->codec->codec_id); } } @@ -2196,10 +2244,6 @@ void av_close_input_stream(AVFormatContext *s) int i; AVStream *st; - /* free previous packet */ - if (s->cur_st && s->cur_st->parser) - av_free_packet(&s->cur_pkt); - if (s->iformat->read_close) s->iformat->read_close(s); for(i=0;inb_streams;i++) { @@ -2207,7 +2251,9 @@ void av_close_input_stream(AVFormatContext *s) st = s->streams[i]; if (st->parser) { av_parser_close(st->parser); + av_free_packet(&st->cur_pkt); } + av_metadata_free(&st->metadata); av_free(st->index_entries); av_free(st->codec->extradata); av_free(st->codec); @@ -2218,6 +2264,7 @@ void av_close_input_stream(AVFormatContext *s) for(i=s->nb_programs-1; i>=0; i--) { av_freep(&s->programs[i]->provider_name); av_freep(&s->programs[i]->name); + av_metadata_free(&s->programs[i]->metadata); av_freep(&s->programs[i]->stream_index); av_freep(&s->programs[i]); } @@ -2226,9 +2273,11 @@ void av_close_input_stream(AVFormatContext *s) av_freep(&s->priv_data); while(s->nb_chapters--) { av_free(s->chapters[s->nb_chapters]->title); + av_metadata_free(&s->chapters[s->nb_chapters]->metadata); av_free(s->chapters[s->nb_chapters]); } av_freep(&s->chapters); + av_metadata_free(&s->metadata); av_free(s); } @@ -2274,6 +2323,8 @@ AVStream *av_new_stream(AVFormatContext *s, int id) for(i=0; ipts_buffer[i]= AV_NOPTS_VALUE; + st->sample_aspect_ratio = (AVRational){0,1}; + s->streams[s->nb_streams++] = st; return st; } @@ -2376,6 +2427,9 @@ int av_write_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "sample rate not set\n"); return -1; } + if(!st->codec->block_align) + st->codec->block_align = st->codec->channels * + av_get_bits_per_sample(st->codec->codec_id) >> 3; break; case CODEC_TYPE_VIDEO: if(st->codec->time_base.num<=0 || st->codec->time_base.den<=0){ //FIXME audio too? @@ -2386,6 +2440,10 @@ int av_write_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "dimensions not set\n"); return -1; } + 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"); + return -1; + } break; } @@ -2407,6 +2465,10 @@ int av_write_header(AVFormatContext *s) return AVERROR(ENOMEM); } +#if LIBAVFORMAT_VERSION_MAJOR < 53 + ff_metadata_mux_compat(s); +#endif + if(s->oformat->write_header){ ret = s->oformat->write_header(s); if (ret < 0) @@ -2466,7 +2528,7 @@ static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){ } //calculate dts from pts - if(pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE){ + if(pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY){ st->pts_buffer[0]= pkt->pts; for(i=1; ipts_buffer[i] == AV_NOPTS_VALUE; i++) st->pts_buffer[i]= (i-delay-1) * pkt->duration; @@ -2510,18 +2572,6 @@ static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){ return 0; } -static void truncate_ts(AVStream *st, AVPacket *pkt){ - int64_t pts_mask = (2LL << (st->pts_wrap_bits-1)) - 1; - -// if(pkt->dts < 0) -// pkt->dts= 0; //this happens for low_delay=0 and B-frames, FIXME, needs further investigation about what we should do here - - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts &= pts_mask; - if (pkt->dts != AV_NOPTS_VALUE) - pkt->dts &= pts_mask; -} - int av_write_frame(AVFormatContext *s, AVPacket *pkt) { int ret = compute_pkt_fields2(s->streams[pkt->stream_index], pkt); @@ -2529,8 +2579,6 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) if(ret<0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) return ret; - truncate_ts(s->streams[pkt->stream_index], pkt); - ret= s->oformat->write_packet(s, pkt); if(!ret) ret= url_ferror(s->pb); @@ -2626,7 +2674,6 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ if(ret<=0) //FIXME cleanup needed for ret<0 ? return ret; - truncate_ts(s->streams[opkt.stream_index], &opkt); ret= s->oformat->write_packet(s, &opkt); av_free_packet(&opkt); @@ -2651,7 +2698,6 @@ int av_write_trailer(AVFormatContext *s) if(!ret) break; - truncate_ts(s->streams[pkt.stream_index], &pkt); ret= s->oformat->write_packet(s, &pkt); av_free_packet(&pkt); @@ -2702,7 +2748,7 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out char buf[256]; int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); AVStream *st = ic->streams[i]; - int g = ff_gcd(st->time_base.num, st->time_base.den); + int g = av_gcd(st->time_base.num, st->time_base.den); avcodec_string(buf, sizeof(buf), st->codec, is_output); av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i); /* the pid is an important information, so we display it */ @@ -2713,6 +2759,17 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out av_log(NULL, AV_LOG_INFO, "(%s)", st->language); av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g); av_log(NULL, AV_LOG_INFO, ": %s", buf); + if (st->sample_aspect_ratio.num && // default + av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) { + AVRational display_aspect_ratio; + av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, + st->codec->width*st->sample_aspect_ratio.num, + st->codec->height*st->sample_aspect_ratio.den, + 1024*1024); + av_log(NULL, AV_LOG_INFO, ", PAR %d:%d DAR %d:%d", + st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, + display_aspect_ratio.num, display_aspect_ratio.den); + } if(st->codec->codec_type == CODEC_TYPE_VIDEO){ if(st->r_frame_rate.den && st->r_frame_rate.num) av_log(NULL, AV_LOG_INFO, ", %5.2f tb(r)", av_q2d(st->r_frame_rate)); @@ -2780,6 +2837,7 @@ void dump_format(AVFormatContext *ic, dump_stream_format(ic, i, index, is_output); } +#if LIBAVFORMAT_VERSION_MAJOR < 53 int parse_image_size(int *width_ptr, int *height_ptr, const char *str) { return av_parse_video_frame_size(width_ptr, height_ptr, str); @@ -2793,10 +2851,8 @@ int parse_frame_rate(int *frame_rate_num, int *frame_rate_den, const char *arg) *frame_rate_den= frame_rate.den; return ret; } +#endif -/** - * Gets the current time in microseconds. - */ int64_t av_gettime(void) { struct timeval tv; @@ -2810,11 +2866,11 @@ int64_t parse_date(const char *datestr, int duration) int64_t t; struct tm dt; int i; - static const char *date_fmt[] = { + static const char * const date_fmt[] = { "%Y-%m-%d", "%Y%m%d", }; - static const char *time_fmt[] = { + static const char * const time_fmt[] = { "%H:%M:%S", "%H%M%S", }; @@ -2839,7 +2895,7 @@ int64_t parse_date(const char *datestr, int duration) q = NULL; if (!duration) { /* parse the year-month-day part */ - for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) { + for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) { q = small_strptime(p, date_fmt[i], &dt); if (q) { break; @@ -2863,7 +2919,7 @@ int64_t parse_date(const char *datestr, int duration) p++; /* parse the hour-minute-second part */ - for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) { + for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) { q = small_strptime(p, time_fmt[i], &dt); if (q) { break; @@ -3149,60 +3205,30 @@ void url_split(char *proto, int proto_size, } } -void av_set_pts_info(AVStream *s, int pts_wrap_bits, - int pts_num, int pts_den) +char *ff_data_to_hex(char *buff, const uint8_t *src, int s) { - s->pts_wrap_bits = pts_wrap_bits; - s->time_base.num = pts_num; - s->time_base.den = pts_den; -} - -/* fraction handling */ + int i; + static const char hex_table[16] = { '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F' }; -/** - * f = val + (num / den) + 0.5. - * - * 'num' is normalized so that it is such as 0 <= num < den. - * - * @param f fractional number - * @param val integer value - * @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) -{ - num += (den >> 1); - if (num >= den) { - val += num / den; - num = num % den; + for(i = 0; i < s; i++) { + buff[i * 2] = hex_table[src[i] >> 4]; + buff[i * 2 + 1] = hex_table[src[i] & 0xF]; } - f->val = val; - f->num = num; - f->den = den; + + return buff; } -/** - * Fractional addition to f: f = f + (incr / f->den). - * - * @param f fractional number - * @param incr increment, can be positive or negative - */ -static void av_frac_add(AVFrac *f, int64_t incr) +void av_set_pts_info(AVStream *s, int pts_wrap_bits, + int pts_num, int pts_den) { - int64_t num, den; + unsigned int gcd= av_gcd(pts_num, pts_den); + s->pts_wrap_bits = pts_wrap_bits; + s->time_base.num = pts_num/gcd; + s->time_base.den = pts_den/gcd; - num = f->num + incr; - den = f->den; - if (num < 0) { - f->val += num / den; - num = num % den; - if (num < 0) { - num += den; - f->val--; - } - } else if (num >= den) { - f->val += num / den; - num = num % den; - } - f->num = num; + if(gcd>1) + av_log(NULL, AV_LOG_DEBUG, "st:%d removing common factor %d from timebase\n", s->index, gcd); }