X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=bbdc2cdb8aba592c1d3864e3b15b2bdb5498545c;hb=80e919b17435da18c0f2be6403a0315cf4b40a1a;hp=b932322ed776c62345384ca86e7501f1734932fb;hpb=55f9037f38bc3beacb2f5a17408c1d24c077d7fd;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index b932322ed77..bbdc2cdb8ab 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -19,33 +19,36 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* #define DEBUG */ +#undef NDEBUG +#include +#include +#include + +#include "config.h" -#include "avformat.h" -#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/dict.h" +#include "libavutil/internal.h" #include "libavutil/mathematics.h" +#include "libavutil/opt.h" #include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" #include "libavutil/time.h" -#include "riff.h" + +#include "libavcodec/bytestream.h" +#include "libavcodec/internal.h" + #include "audiointerleave.h" -#include "url.h" -#include +#include "avformat.h" +#include "id3v2.h" +#include "internal.h" +#include "metadata.h" #if CONFIG_NETWORK #include "network.h" #endif - -#undef NDEBUG -#include +#include "riff.h" +#include "url.h" /** * @file @@ -68,264 +71,89 @@ const char *avformat_license(void) return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; } -/** head of registered input format linked list */ -static AVInputFormat *first_iformat = NULL; -/** head of registered output format linked list */ -static AVOutputFormat *first_oformat = NULL; +/* an arbitrarily chosen "sane" max packet size -- 50M */ +#define SANE_CHUNK_SIZE (50000000) -AVInputFormat *av_iformat_next(AVInputFormat *f) +/* Read the data in sane-sized chunks and append to pkt. + * Return the number of bytes read or an error. */ +static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size) { - if(f) return f->next; - else return first_iformat; -} - -AVOutputFormat *av_oformat_next(AVOutputFormat *f) -{ - if(f) return f->next; - else return first_oformat; -} - -void av_register_input_format(AVInputFormat *format) -{ - AVInputFormat **p; - p = &first_iformat; - while (*p != NULL) p = &(*p)->next; - *p = format; - format->next = NULL; -} - -void av_register_output_format(AVOutputFormat *format) -{ - AVOutputFormat **p; - p = &first_oformat; - while (*p != NULL) p = &(*p)->next; - *p = format; - format->next = NULL; -} - -int av_match_ext(const char *filename, const char *extensions) -{ - const char *ext, *p; - char ext1[32], *q; + int64_t chunk_size = size; + int64_t orig_pos = pkt->pos; // av_grow_packet might reset pos + int orig_size = pkt->size; + int ret = 0; - if(!filename) - return 0; + do { + int prev_size = pkt->size; + int read_size; - ext = strrchr(filename, '.'); - if (ext) { - ext++; - p = extensions; - for(;;) { - q = ext1; - while (*p != '\0' && *p != ',' && q-ext1 SANE_CHUNK_SIZE) { + int64_t filesize = avio_size(s) - avio_tell(s); + chunk_size = FFMAX(filesize, SANE_CHUNK_SIZE); } - } - return 0; -} - -static int match_format(const char *name, const char *names) -{ - const char *p; - int len, namelen; - - if (!name || !names) - return 0; + read_size = FFMIN(size, chunk_size); - namelen = strlen(name); - while ((p = strchr(names, ','))) { - len = FFMAX(p - names, namelen); - if (!av_strncasecmp(name, names, len)) - return 1; - names = p+1; - } - return !av_strcasecmp(name, names); -} - -AVOutputFormat *av_guess_format(const char *short_name, const char *filename, - const char *mime_type) -{ - AVOutputFormat *fmt = NULL, *fmt_found; - int score_max, score; + ret = av_grow_packet(pkt, read_size); + if (ret < 0) + break; - /* specific test for image sequences */ -#if CONFIG_IMAGE2_MUXER - if (!short_name && filename && - av_filename_number_test(filename) && - ff_guess_image2_codec(filename) != AV_CODEC_ID_NONE) { - return av_guess_format("image2", NULL, NULL); - } -#endif - /* Find the proper file type. */ - fmt_found = NULL; - score_max = 0; - while ((fmt = av_oformat_next(fmt))) { - score = 0; - if (fmt->name && short_name && !av_strcasecmp(fmt->name, short_name)) - score += 100; - if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type)) - score += 10; - if (filename && fmt->extensions && - av_match_ext(filename, fmt->extensions)) { - score += 5; - } - if (score > score_max) { - score_max = score; - fmt_found = fmt; + ret = avio_read(s, pkt->data + prev_size, read_size); + if (ret != read_size) { + av_shrink_packet(pkt, prev_size + FFMAX(ret, 0)); + break; } - } - return fmt_found; -} -enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, - const char *filename, const char *mime_type, enum AVMediaType type){ - if(type == AVMEDIA_TYPE_VIDEO){ - enum AVCodecID codec_id= AV_CODEC_ID_NONE; - -#if CONFIG_IMAGE2_MUXER - if(!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")){ - codec_id= ff_guess_image2_codec(filename); - } -#endif - if(codec_id == AV_CODEC_ID_NONE) - codec_id= fmt->video_codec; - return codec_id; - }else if(type == AVMEDIA_TYPE_AUDIO) - return fmt->audio_codec; - else if (type == AVMEDIA_TYPE_SUBTITLE) - return fmt->subtitle_codec; - else - return AV_CODEC_ID_NONE; -} + size -= read_size; + } while (size > 0); -AVInputFormat *av_find_input_format(const char *short_name) -{ - AVInputFormat *fmt = NULL; - while ((fmt = av_iformat_next(fmt))) { - if (match_format(short_name, fmt->name)) - return fmt; - } - return NULL; + pkt->pos = orig_pos; + if (!pkt->size) + av_packet_unref(pkt); + return pkt->size > orig_size ? pkt->size - orig_size : ret; } - int av_get_packet(AVIOContext *s, AVPacket *pkt, int size) { - int ret= av_new_packet(pkt, size); - - if(ret<0) - return ret; - - pkt->pos= avio_tell(s); - - ret= avio_read(s, pkt->data, size); - if(ret<=0) - av_free_packet(pkt); - else - av_shrink_packet(pkt, ret); + av_init_packet(pkt); + pkt->data = NULL; + pkt->size = 0; + pkt->pos = avio_tell(s); - return ret; + return append_packet_chunked(s, pkt, size); } int av_append_packet(AVIOContext *s, AVPacket *pkt, int size) { - int ret; - int old_size; if (!pkt->size) return av_get_packet(s, pkt, size); - old_size = pkt->size; - ret = av_grow_packet(pkt, size); - if (ret < 0) - return ret; - ret = avio_read(s, pkt->data + old_size, size); - av_shrink_packet(pkt, old_size + FFMAX(ret, 0)); - return ret; + return append_packet_chunked(s, pkt, size); } - int av_filename_number_test(const char *filename) { char buf[1024]; - return filename && (av_get_frame_filename(buf, sizeof(buf), filename, 1)>=0); -} - -AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max) -{ - AVProbeData lpd = *pd; - AVInputFormat *fmt1 = NULL, *fmt; - int score, id3 = 0; - - if (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) { - int id3len = ff_id3v2_tag_len(lpd.buf); - if (lpd.buf_size > id3len + 16) { - lpd.buf += id3len; - lpd.buf_size -= id3len; - } - id3 = 1; - } - - fmt = NULL; - while ((fmt1 = av_iformat_next(fmt1))) { - if (!is_opened == !(fmt1->flags & AVFMT_NOFILE)) - continue; - score = 0; - if (fmt1->read_probe) { - score = fmt1->read_probe(&lpd); - } else if (fmt1->extensions) { - if (av_match_ext(lpd.filename, fmt1->extensions)) { - score = 50; - } - } - if (score > *score_max) { - *score_max = score; - fmt = fmt1; - }else if (score == *score_max) - fmt = NULL; - } - - /* a hack for files with huge id3v2 tags -- try to guess by file extension. */ - 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; - break; - } - } - - 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; -} - -AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened){ - int score=0; - return av_probe_input_format2(pd, is_opened, &score); + return filename && + (av_get_frame_filename(buf, sizeof(buf), filename, 1) >= 0); } -static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeData *pd, int score) +static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, + AVProbeData *pd, int score) { static const struct { - const char *name; enum AVCodecID id; enum AVMediaType type; + const char *name; + enum AVCodecID id; + enum AVMediaType type; } fmt_id_type[] = { - { "aac" , AV_CODEC_ID_AAC , AVMEDIA_TYPE_AUDIO }, - { "ac3" , AV_CODEC_ID_AC3 , AVMEDIA_TYPE_AUDIO }, - { "dts" , AV_CODEC_ID_DTS , AVMEDIA_TYPE_AUDIO }, - { "eac3" , AV_CODEC_ID_EAC3 , AVMEDIA_TYPE_AUDIO }, - { "h264" , AV_CODEC_ID_H264 , AVMEDIA_TYPE_VIDEO }, - { "m4v" , AV_CODEC_ID_MPEG4 , AVMEDIA_TYPE_VIDEO }, - { "mp3" , AV_CODEC_ID_MP3 , AVMEDIA_TYPE_AUDIO }, + { "aac", AV_CODEC_ID_AAC, AVMEDIA_TYPE_AUDIO }, + { "ac3", AV_CODEC_ID_AC3, AVMEDIA_TYPE_AUDIO }, + { "dts", AV_CODEC_ID_DTS, AVMEDIA_TYPE_AUDIO }, + { "eac3", AV_CODEC_ID_EAC3, AVMEDIA_TYPE_AUDIO }, + { "h264", AV_CODEC_ID_H264, AVMEDIA_TYPE_VIDEO }, + { "latm", AV_CODEC_ID_AAC_LATM, AVMEDIA_TYPE_AUDIO }, + { "m4v", AV_CODEC_ID_MPEG4, AVMEDIA_TYPE_VIDEO }, + { "mp3", AV_CODEC_ID_MP3, AVMEDIA_TYPE_AUDIO }, { "mpegvideo", AV_CODEC_ID_MPEG2VIDEO, AVMEDIA_TYPE_VIDEO }, { 0 } }; @@ -333,12 +161,20 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeDa if (fmt) { int i; - av_log(s, AV_LOG_DEBUG, "Probe with size=%d, packets=%d detected %s with score=%d\n", - pd->buf_size, MAX_PROBE_PACKETS - st->probe_packets, fmt->name, score); + av_log(s, AV_LOG_DEBUG, + "Probe with size=%d, packets=%d detected %s with score=%d\n", + pd->buf_size, MAX_PROBE_PACKETS - st->probe_packets, + fmt->name, score); for (i = 0; fmt_id_type[i].name; i++) { if (!strcmp(fmt->name, fmt_id_type[i].name)) { - st->codec->codec_id = fmt_id_type[i].id; - st->codec->codec_type = fmt_id_type[i].type; + st->codecpar->codec_id = fmt_id_type[i].id; + st->codecpar->codec_type = fmt_id_type[i].type; +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + st->codec->codec_type = st->codecpar->codec_type; + st->codec->codec_id = st->codecpar->codec_id; +FF_ENABLE_DEPRECATION_WARNINGS +#endif break; } } @@ -349,137 +185,107 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeDa /************************************************************/ /* input media file */ -/** size of probe buffer, for guessing file type from file contents */ -#define PROBE_BUF_MIN 2048 -#define PROBE_BUF_MAX (1<<20) - -int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, - const char *filename, void *logctx, - unsigned int offset, unsigned int max_probe_size) -{ - AVProbeData pd = { filename ? filename : "", NULL, -offset }; - unsigned char *buf = NULL; - int ret = 0, probe_size; - - if (!max_probe_size) { - max_probe_size = PROBE_BUF_MAX; - } else if (max_probe_size > PROBE_BUF_MAX) { - max_probe_size = PROBE_BUF_MAX; - } else if (max_probe_size < PROBE_BUF_MIN) { - return AVERROR(EINVAL); - } - - if (offset >= max_probe_size) { - return AVERROR(EINVAL); - } - - for(probe_size= PROBE_BUF_MIN; probe_size<=max_probe_size && !*fmt; - probe_size = FFMIN(probe_size<<1, FFMAX(max_probe_size, probe_size+1))) { - int score = probe_size < max_probe_size ? AVPROBE_SCORE_MAX/4 : 0; - int buf_offset = (probe_size == PROBE_BUF_MIN) ? 0 : probe_size>>1; - - if (probe_size < offset) { - continue; - } - - /* read probe data */ - buf = av_realloc(buf, probe_size + AVPROBE_PADDING_SIZE); - if ((ret = avio_read(pb, buf + buf_offset, probe_size - buf_offset)) < 0) { - /* fail if error was not end of file, otherwise, lower score */ - if (ret != AVERROR_EOF) { - av_free(buf); - return ret; - } - score = 0; - ret = 0; /* error was end of file, nothing read */ - } - pd.buf_size += ret; - pd.buf = &buf[offset]; - - memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE); - - /* guess file format */ - *fmt = av_probe_input_format2(&pd, 1, &score); - if(*fmt){ - if(score <= AVPROBE_SCORE_MAX/4){ //this can only be true in the last iteration - av_log(logctx, AV_LOG_WARNING, "Format detected only with low score of %d, misdetection possible!\n", score); - }else - av_log(logctx, AV_LOG_DEBUG, "Probed with size=%d and score=%d\n", probe_size, score); - } - } - - if (!*fmt) { - av_free(buf); - return AVERROR_INVALIDDATA; - } - - /* rewind. reuse probe buffer to avoid seeking */ - if ((ret = ffio_rewind_with_probe_data(pb, buf, pd.buf_size)) < 0) - av_free(buf); - - return ret; -} - -/* open input file and probe the format if necessary */ -static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options) +/* Open input file and probe the format if necessary. */ +static int init_input(AVFormatContext *s, const char *filename, + AVDictionary **options) { int ret; - AVProbeData pd = {filename, NULL, 0}; + AVProbeData pd = { filename, NULL, 0 }; if (s->pb) { s->flags |= AVFMT_FLAG_CUSTOM_IO; if (!s->iformat) - return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize); + return av_probe_input_buffer(s->pb, &s->iformat, filename, + s, 0, s->probesize); else if (s->iformat->flags & AVFMT_NOFILE) return AVERROR(EINVAL); return 0; } - if ( (s->iformat && s->iformat->flags & AVFMT_NOFILE) || + if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) || (!s->iformat && (s->iformat = av_probe_input_format(&pd, 0)))) return 0; - if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ, - &s->interrupt_callback, options)) < 0) + ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ, options); + if (ret < 0) return ret; if (s->iformat) return 0; - return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize); + return av_probe_input_buffer(s->pb, &s->iformat, filename, + s, 0, s->probesize); } -static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, - AVPacketList **plast_pktl){ +static int add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, + AVPacketList **plast_pktl, int ref) +{ AVPacketList *pktl = av_mallocz(sizeof(AVPacketList)); + int ret; + if (!pktl) - return NULL; + return AVERROR(ENOMEM); + + if (ref) { + if ((ret = av_packet_ref(&pktl->pkt, pkt)) < 0) { + av_free(pktl); + return ret; + } + } else { + pktl->pkt = *pkt; + } if (*packet_buffer) (*plast_pktl)->next = pktl; else *packet_buffer = pktl; - /* add the packet in the buffered packet list */ + /* Add the packet in the buffered packet list. */ *plast_pktl = pktl; - pktl->pkt= *pkt; - return &pktl->pkt; + return 0; } -static void queue_attached_pictures(AVFormatContext *s) +static int queue_attached_pictures(AVFormatContext *s) { - int i; + int i, ret; for (i = 0; i < s->nb_streams; i++) if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC && s->streams[i]->discard < AVDISCARD_ALL) { - AVPacket copy = s->streams[i]->attached_pic; - copy.destruct = NULL; - add_to_pktbuf(&s->raw_packet_buffer, ©, &s->raw_packet_buffer_end); + + ret = add_to_pktbuf(&s->internal->raw_packet_buffer, + &s->streams[i]->attached_pic, + &s->internal->raw_packet_buffer_end, 1); + if (ret < 0) + return ret; } + return 0; +} + +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS +static int update_stream_avctx(AVFormatContext *s) +{ + int i, ret; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + + if (!st->internal->need_codec_update) + continue; + + ret = avcodec_parameters_to_context(st->codec, st->codecpar); + if (ret < 0) + return ret; + + st->internal->need_codec_update = 0; + } + return 0; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif -int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options) +int avformat_open_input(AVFormatContext **ps, const char *filename, + AVInputFormat *fmt, AVDictionary **options) { AVFormatContext *s = *ps; - int ret = 0; + int i, ret = 0; AVDictionary *tmp = NULL; ID3v2ExtraMeta *id3v2_extra_meta = NULL; @@ -497,7 +303,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma if ((ret = init_input(s, filename, &tmp)) < 0) goto fail; - /* check filename in case an image number is expected */ + /* Check filename in case an image number is expected. */ if (s->iformat->flags & AVFMT_NEEDNUMBER) { if (!av_filename_number_test(filename)) { ret = AVERROR(EINVAL); @@ -508,14 +314,14 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma s->duration = s->start_time = AV_NOPTS_VALUE; av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename)); - /* allocate private data */ + /* Allocate private data. */ if (s->iformat->priv_data_size > 0) { if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) { ret = AVERROR(ENOMEM); goto fail; } if (s->iformat->priv_class) { - *(const AVClass**)s->priv_data = s->iformat->priv_class; + *(const AVClass **) s->priv_data = s->iformat->priv_class; av_opt_set_defaults(s->priv_data); if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0) goto fail; @@ -535,12 +341,20 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma goto fail; ff_id3v2_free_extra_meta(&id3v2_extra_meta); - queue_attached_pictures(s); + if ((ret = queue_attached_pictures(s)) < 0) + goto fail; + + if (s->pb && !s->internal->data_offset) + s->internal->data_offset = avio_tell(s->pb); + + s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; - if (s->pb && !s->data_offset) - s->data_offset = avio_tell(s->pb); +#if FF_API_LAVF_AVCTX + update_stream_avctx(s); +#endif - s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; + for (i = 0; i < s->nb_streams; i++) + s->streams[i]->internal->orig_codec_id = s->streams[i]->codecpar->codec_id; if (options) { av_dict_free(options); @@ -561,61 +375,67 @@ fail: /*******************************************************/ -static void probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt) +static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt) { - if(st->codec->codec_id == AV_CODEC_ID_PROBE){ + if (st->codecpar->codec_id == AV_CODEC_ID_PROBE) { AVProbeData *pd = &st->probe_data; av_log(s, AV_LOG_DEBUG, "probing stream %d\n", st->index); --st->probe_packets; if (pkt) { - pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE); - memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size); + int err; + if ((err = av_reallocp(&pd->buf, pd->buf_size + pkt->size + + AVPROBE_PADDING_SIZE)) < 0) + return err; + memcpy(pd->buf + pd->buf_size, pkt->data, pkt->size); pd->buf_size += pkt->size; - memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); + memset(pd->buf + pd->buf_size, 0, AVPROBE_PADDING_SIZE); } else { st->probe_packets = 0; if (!pd->buf_size) { - av_log(s, AV_LOG_ERROR, "nothing to probe for stream %d\n", - st->index); - return; + av_log(s, AV_LOG_ERROR, + "nothing to probe for stream %d\n", st->index); + return 0; } } if (!st->probe_packets || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) { - set_codec_from_probe_data(s, st, pd, st->probe_packets > 0 ? AVPROBE_SCORE_MAX/4 : 0); - if(st->codec->codec_id != AV_CODEC_ID_PROBE){ - pd->buf_size=0; + set_codec_from_probe_data(s, st, pd, st->probe_packets > 0 + ? AVPROBE_SCORE_MAX / 4 : 0); + if (st->codecpar->codec_id != AV_CODEC_ID_PROBE) { + pd->buf_size = 0; av_freep(&pd->buf); av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index); } } } + return 0; } int ff_read_packet(AVFormatContext *s, AVPacket *pkt) { - int ret, i; + int ret, i, err; AVStream *st; - for(;;){ - AVPacketList *pktl = s->raw_packet_buffer; + for (;;) { + AVPacketList *pktl = s->internal->raw_packet_buffer; if (pktl) { *pkt = pktl->pkt; - st = s->streams[pkt->stream_index]; - if (st->codec->codec_id != AV_CODEC_ID_PROBE || !st->probe_packets || - s->raw_packet_buffer_remaining_size < pkt->size) { + st = s->streams[pkt->stream_index]; + if (st->codecpar->codec_id != AV_CODEC_ID_PROBE || + !st->probe_packets || + s->internal->raw_packet_buffer_remaining_size < pkt->size) { AVProbeData *pd; - if (st->probe_packets) { - probe_codec(s, st, NULL); - } + if (st->probe_packets) + if ((err = probe_codec(s, st, NULL)) < 0) + return err; pd = &st->probe_data; av_freep(&pd->buf); pd->buf_size = 0; - s->raw_packet_buffer = pktl->next; - s->raw_packet_buffer_remaining_size += pkt->size; + s->internal->raw_packet_buffer = pktl->next; + s->internal->raw_packet_buffer_remaining_size += pkt->size; av_free(pktl); return 0; } @@ -624,122 +444,112 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->data = NULL; pkt->size = 0; av_init_packet(pkt); - ret= s->iformat->read_packet(s, pkt); + ret = s->iformat->read_packet(s, pkt); if (ret < 0) { if (!pktl || ret == AVERROR(EAGAIN)) return ret; for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (st->probe_packets) { - probe_codec(s, st, NULL); - } + if (st->probe_packets) + if ((err = probe_codec(s, st, NULL)) < 0) + return err; } continue; } + if (!pkt->buf) { + AVPacket tmp = { 0 }; + ret = av_packet_ref(&tmp, pkt); + if (ret < 0) + return ret; + *pkt = tmp; + } + 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); + av_packet_unref(pkt); continue; } - st= s->streams[pkt->stream_index]; + st = s->streams[pkt->stream_index]; - switch(st->codec->codec_type){ + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: - if(s->video_codec_id) st->codec->codec_id= s->video_codec_id; + if (s->video_codec_id) + st->codecpar->codec_id = s->video_codec_id; break; case AVMEDIA_TYPE_AUDIO: - if(s->audio_codec_id) st->codec->codec_id= s->audio_codec_id; + if (s->audio_codec_id) + st->codecpar->codec_id = s->audio_codec_id; break; case AVMEDIA_TYPE_SUBTITLE: - if(s->subtitle_codec_id)st->codec->codec_id= s->subtitle_codec_id; + if (s->subtitle_codec_id) + st->codecpar->codec_id = s->subtitle_codec_id; break; } - if(!pktl && (st->codec->codec_id != AV_CODEC_ID_PROBE || - !st->probe_packets)) + if (!pktl && (st->codecpar->codec_id != AV_CODEC_ID_PROBE || + !st->probe_packets)) return ret; - add_to_pktbuf(&s->raw_packet_buffer, pkt, &s->raw_packet_buffer_end); - s->raw_packet_buffer_remaining_size -= pkt->size; + err = add_to_pktbuf(&s->internal->raw_packet_buffer, pkt, + &s->internal->raw_packet_buffer_end, 0); + if (err) + return err; + s->internal->raw_packet_buffer_remaining_size -= pkt->size; - probe_codec(s, st, pkt); + if ((err = probe_codec(s, st, pkt)) < 0) + return err; } } -#if FF_API_READ_PACKET -int av_read_packet(AVFormatContext *s, AVPacket *pkt) -{ - return ff_read_packet(s, pkt); -} -#endif - - /**********************************************************/ -/** - * Get the number of samples of an audio frame. Return -1 on error. - */ -int ff_get_audio_frame_size(AVCodecContext *enc, int size, int mux) -{ - int frame_size; - - /* give frame_size priority if demuxing */ - if (!mux && enc->frame_size > 1) - return enc->frame_size; - - if ((frame_size = av_get_audio_frame_duration(enc, size)) > 0) - return frame_size; - - /* fallback to using frame_size if muxing */ - if (enc->frame_size > 1) - return enc->frame_size; - - return -1; -} - - /** * Return the frame duration in seconds. Return 0 if not available. */ -void ff_compute_frame_duration(int *pnum, int *pden, AVStream *st, +void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStream *st, AVCodecParserContext *pc, AVPacket *pkt) { + AVRational codec_framerate = s->iformat ? st->internal->avctx->framerate : + (AVRational){ 0, 1 }; int frame_size; *pnum = 0; *pden = 0; - switch(st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: if (st->avg_frame_rate.num) { *pnum = st->avg_frame_rate.den; *pden = st->avg_frame_rate.num; - } else if(st->time_base.num*1000LL > st->time_base.den) { + } 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){ - *pnum = st->codec->time_base.num; - *pden = st->codec->time_base.den; + } else if (codec_framerate.den * 1000LL > codec_framerate.num) { + *pnum = codec_framerate.den; + *pden = codec_framerate.num; if (pc && pc->repeat_pict) { - *pnum = (*pnum) * (1 + pc->repeat_pict); + if (*pnum > INT_MAX / (1 + pc->repeat_pict)) + *pden /= 1 + pc->repeat_pict; + else + *pnum *= 1 + pc->repeat_pict; } - //If this codec can be interlaced or progressive then we need a parser to compute duration of a packet - //Thus if we have no parser in such case leave duration undefined. - if(st->codec->ticks_per_frame>1 && !pc){ + /* If this codec can be interlaced or progressive then we need + * a parser to compute duration of a packet. Thus if we have + * no parser in such case leave duration undefined. */ + if (st->internal->avctx->ticks_per_frame > 1 && !pc) *pnum = *pden = 0; - } } break; case AVMEDIA_TYPE_AUDIO: - frame_size = ff_get_audio_frame_size(st->codec, pkt->size, 0); - if (frame_size <= 0 || st->codec->sample_rate <= 0) + frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size); + if (frame_size <= 0 || st->codecpar->sample_rate <= 0) break; *pnum = frame_size; - *pden = st->codec->sample_rate; + *pden = st->codecpar->sample_rate; break; default: break; @@ -759,27 +569,29 @@ static int is_intra_only(enum AVCodecID id) static void update_initial_timestamps(AVFormatContext *s, int stream_index, int64_t dts, int64_t pts) { - AVStream *st= s->streams[stream_index]; - AVPacketList *pktl= s->packet_buffer; + AVStream *st = s->streams[stream_index]; + AVPacketList *pktl = s->internal->packet_buffer; - if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE) + if (st->first_dts != AV_NOPTS_VALUE || + dts == AV_NOPTS_VALUE || + st->cur_dts == AV_NOPTS_VALUE) return; - st->first_dts= dts - st->cur_dts; - st->cur_dts= dts; + st->first_dts = dts - st->cur_dts; + st->cur_dts = dts; - for(; pktl; pktl= pktl->next){ - if(pktl->pkt.stream_index != stream_index) + for (; pktl; pktl = pktl->next) { + if (pktl->pkt.stream_index != stream_index) continue; - //FIXME think more about this check - if(pktl->pkt.pts != AV_NOPTS_VALUE && pktl->pkt.pts == pktl->pkt.dts) + // FIXME: think more about this check + if (pktl->pkt.pts != AV_NOPTS_VALUE && pktl->pkt.pts == pktl->pkt.dts) pktl->pkt.pts += st->first_dts; - if(pktl->pkt.dts != AV_NOPTS_VALUE) + if (pktl->pkt.dts != AV_NOPTS_VALUE) pktl->pkt.dts += st->first_dts; - if(st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE) - st->start_time= pktl->pkt.pts; + if (st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE) + st->start_time = pktl->pkt.pts; } if (st->start_time == AV_NOPTS_VALUE) st->start_time = pts; @@ -788,39 +600,42 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, static void update_initial_durations(AVFormatContext *s, AVStream *st, int stream_index, int duration) { - AVPacketList *pktl= s->packet_buffer; - int64_t cur_dts= 0; + AVPacketList *pktl = s->internal->packet_buffer; + int64_t cur_dts = 0; - if(st->first_dts != AV_NOPTS_VALUE){ - cur_dts= st->first_dts; - for(; pktl; pktl= pktl->next){ - if(pktl->pkt.stream_index == stream_index){ - if(pktl->pkt.pts != pktl->pkt.dts || pktl->pkt.dts != AV_NOPTS_VALUE || pktl->pkt.duration) + if (st->first_dts != AV_NOPTS_VALUE) { + cur_dts = st->first_dts; + for (; pktl; pktl = pktl->next) { + if (pktl->pkt.stream_index == stream_index) { + if (pktl->pkt.pts != pktl->pkt.dts || + pktl->pkt.dts != AV_NOPTS_VALUE || + pktl->pkt.duration) break; cur_dts -= duration; } } - pktl= s->packet_buffer; + pktl = s->internal->packet_buffer; st->first_dts = cur_dts; - }else if(st->cur_dts) + } else if (st->cur_dts) return; - for(; pktl; pktl= pktl->next){ - if(pktl->pkt.stream_index != stream_index) + for (; pktl; pktl = pktl->next) { + if (pktl->pkt.stream_index != stream_index) continue; - if(pktl->pkt.pts == pktl->pkt.dts && pktl->pkt.dts == AV_NOPTS_VALUE - && !pktl->pkt.duration){ - pktl->pkt.dts= cur_dts; - if(!st->codec->has_b_frames) - pktl->pkt.pts= cur_dts; + if (pktl->pkt.pts == pktl->pkt.dts && + pktl->pkt.dts == AV_NOPTS_VALUE && + !pktl->pkt.duration) { + pktl->pkt.dts = cur_dts; + if (!st->internal->avctx->has_b_frames) + pktl->pkt.pts = cur_dts; cur_dts += duration; - if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) + if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) pktl->pkt.duration = duration; - }else + } else break; } - if(st->first_dts == AV_NOPTS_VALUE) - st->cur_dts= cur_dts; + if (st->first_dts == AV_NOPTS_VALUE) + st->cur_dts = cur_dts; } static void compute_pkt_fields(AVFormatContext *s, AVStream *st, @@ -832,83 +647,74 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, if (s->flags & AVFMT_FLAG_NOFILLIN) return; - if((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE) - pkt->dts= AV_NOPTS_VALUE; + if ((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE) + pkt->dts = AV_NOPTS_VALUE; /* do we have a video B-frame ? */ - delay= st->codec->has_b_frames; + delay = st->internal->avctx->has_b_frames; presentation_delayed = 0; /* XXX: need has_b_frame, but cannot get it if the codec is - not initialized */ + * not initialized */ if (delay && pc && pc->pict_type != AV_PICTURE_TYPE_B) 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; + if (pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && + st->pts_wrap_bits < 63 && + pkt->dts - (1LL << (st->pts_wrap_bits - 1)) > pkt->pts) { + pkt->dts -= 1LL << st->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){ + /* Some MPEG-2 in MPEG-PS lack dts (issue #171 / input_file.mpg). + * We take the conservative approach and discard both. + * Note: If this is misbehaving for an H.264 file, then possibly + * presentation_delayed is not set correctly. */ + if (delay == 1 && pkt->dts == pkt->pts && + pkt->dts != AV_NOPTS_VALUE && presentation_delayed) { av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination\n"); - pkt->dts= pkt->pts= AV_NOPTS_VALUE; + pkt->dts = AV_NOPTS_VALUE; } - if (pkt->duration == 0 && st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { - ff_compute_frame_duration(&num, &den, st, pc, pkt); + if (pkt->duration == 0 && st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { + ff_compute_frame_duration(s, &num, &den, st, pc, pkt); if (den && num) { - pkt->duration = av_rescale_rnd(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num, AV_ROUND_DOWN); + pkt->duration = av_rescale_rnd(1, num * (int64_t) st->time_base.den, + den * (int64_t) st->time_base.num, + AV_ROUND_DOWN); - if(pkt->duration != 0 && s->packet_buffer) - update_initial_durations(s, st, pkt->stream_index, pkt->duration); + if (pkt->duration != 0 && s->internal->packet_buffer) + update_initial_durations(s, st, pkt->stream_index, + pkt->duration); } } - /* correct timestamps with byte offset if demuxers only have timestamps - on packet boundaries */ - if(pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size){ + /* Correct timestamps with byte offset if demuxers only have timestamps + * on packet boundaries */ + if (pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size) { /* this will estimate bitrate based on this frame's duration and size */ offset = av_rescale(pc->offset, pkt->duration, pkt->size); - if(pkt->pts != AV_NOPTS_VALUE) + if (pkt->pts != AV_NOPTS_VALUE) pkt->pts += offset; - if(pkt->dts != AV_NOPTS_VALUE) + if (pkt->dts != AV_NOPTS_VALUE) pkt->dts += offset; } - if (pc && pc->dts_sync_point >= 0) { - // we have synchronization info from the parser - int64_t den = st->codec->time_base.den * (int64_t) st->time_base.num; - if (den > 0) { - int64_t num = st->codec->time_base.num * (int64_t) st->time_base.den; - if (pkt->dts != AV_NOPTS_VALUE) { - // got DTS from the stream, update reference timestamp - st->reference_dts = pkt->dts - pc->dts_ref_dts_delta * num / den; - pkt->pts = pkt->dts + pc->pts_dts_delta * num / den; - } else if (st->reference_dts != AV_NOPTS_VALUE) { - // compute DTS based on reference timestamp - pkt->dts = st->reference_dts + pc->dts_ref_dts_delta * num / den; - pkt->pts = pkt->dts + pc->pts_dts_delta * num / den; - } - if (pc->dts_sync_point > 0) - st->reference_dts = pkt->dts; // new reference - } - } - /* This may be redundant, but it should not hurt. */ - if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts > pkt->dts) + if (pkt->dts != AV_NOPTS_VALUE && + pkt->pts != AV_NOPTS_VALUE && + pkt->pts > pkt->dts) presentation_delayed = 1; - av_dlog(NULL, - "IN delayed:%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64" st:%d pc:%p\n", + av_log(NULL, AV_LOG_TRACE, + "IN delayed:%d pts:%"PRId64", dts:%"PRId64" " + "cur_dts:%"PRId64" st:%d pc:%p\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, pkt->stream_index, pc); - /* interpolate PTS and DTS if they are not present */ - //We skip H264 currently because delay and has_b_frames are not reliably set - if((delay==0 || (delay==1 && pc)) && st->codec->codec_id != AV_CODEC_ID_H264){ + /* Interpolate PTS and DTS if they are not present. We skip H.264 + * currently because delay and has_b_frames are not reliably set. */ + if ((delay == 0 || (delay == 1 && pc)) && + st->codecpar->codec_id != AV_CODEC_ID_H264) { if (presentation_delayed) { /* DTS = decompression timestamp */ /* PTS = presentation timestamp */ @@ -918,31 +724,31 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, if (pkt->dts == AV_NOPTS_VALUE) pkt->dts = st->cur_dts; - /* this is tricky: the dts must be incremented by the duration - of the frame we are displaying, i.e. the last I- or P-frame */ + /* This is tricky: the dts must be incremented by the duration + * of the frame we are displaying, i.e. the last I- or P-frame. */ if (st->last_IP_duration == 0) st->last_IP_duration = pkt->duration; - if(pkt->dts != AV_NOPTS_VALUE) + if (pkt->dts != AV_NOPTS_VALUE) st->cur_dts = pkt->dts + st->last_IP_duration; - st->last_IP_duration = pkt->duration; - st->last_IP_pts= pkt->pts; - /* cannot compute PTS if not present (we can compute it only - by knowing the future */ + st->last_IP_duration = pkt->duration; + st->last_IP_pts = pkt->pts; + /* Cannot compute PTS if not present (we can compute it only + * by knowing the future. */ } else if (pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration || - st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { int duration = pkt->duration; - if (!duration && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - ff_compute_frame_duration(&num, &den, st, pc, pkt); + if (!duration && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + ff_compute_frame_duration(s, &num, &den, st, pc, pkt); if (den && num) { - duration = av_rescale_rnd(1, num * (int64_t)st->time_base.den, - den * (int64_t)st->time_base.num, - AV_ROUND_DOWN); - if (duration != 0 && s->packet_buffer) { + duration = av_rescale_rnd(1, + num * (int64_t) st->time_base.den, + den * (int64_t) st->time_base.num, + AV_ROUND_DOWN); + if (duration != 0 && s->internal->packet_buffer) update_initial_durations(s, st, pkt->stream_index, duration); - } } } @@ -962,28 +768,33 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } } - if(pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY){ - st->pts_buffer[0]= pkt->pts; - 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) - pkt->dts= st->pts_buffer[0]; - if(st->codec->codec_id == AV_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) + if (pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY) { + st->pts_buffer[0] = pkt->pts; + 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) + pkt->dts = st->pts_buffer[0]; + // We skipped it above so we try here. + if (st->codecpar->codec_id == AV_CODEC_ID_H264) + // This should happen on the first packet + update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts); + if (pkt->dts > st->cur_dts) st->cur_dts = pkt->dts; } - av_dlog(NULL, + av_log(NULL, AV_LOG_TRACE, "OUTdelayed:%d/%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64"\n", presentation_delayed, delay, pkt->pts, pkt->dts, st->cur_dts); /* update flags */ - if (is_intra_only(st->codec->codec_id)) + if (is_intra_only(st->codecpar->codec_id)) pkt->flags |= AV_PKT_FLAG_KEY; +#if FF_API_CONVERGENCE_DURATION +FF_DISABLE_DEPRECATION_WARNINGS if (pc) pkt->convergence_duration = pc->convergence_duration; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } static void free_packet_buffer(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) @@ -991,28 +802,28 @@ static void free_packet_buffer(AVPacketList **pkt_buf, AVPacketList **pkt_buf_en while (*pkt_buf) { AVPacketList *pktl = *pkt_buf; *pkt_buf = pktl->next; - av_free_packet(&pktl->pkt); + av_packet_unref(&pktl->pkt); av_freep(&pktl); } *pkt_buf_end = NULL; } /** - * Parse a packet, add all split parts to parse_queue + * Parse a packet, add all split parts to parse_queue. * - * @param pkt packet to parse, NULL when flushing the parser at end of stream + * @param pkt Packet to parse, NULL when flushing the parser at end of stream. */ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) { AVPacket out_pkt = { 0 }, flush_pkt = { 0 }; - AVStream *st = s->streams[stream_index]; - uint8_t *data = pkt ? pkt->data : NULL; - int size = pkt ? pkt->size : 0; + AVStream *st = s->streams[stream_index]; + uint8_t *data = pkt ? pkt->data : NULL; + int size = pkt ? pkt->size : 0; int ret = 0, got_output = 0; if (!pkt) { av_init_packet(&flush_pkt); - pkt = &flush_pkt; + pkt = &flush_pkt; got_output = 1; } @@ -1020,7 +831,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) int len; av_init_packet(&out_pkt); - len = av_parser_parse2(st->parser, st->codec, + len = av_parser_parse2(st->parser, st->internal->avctx, &out_pkt.data, &out_pkt.size, data, size, pkt->pts, pkt->dts, pkt->pos); @@ -1034,27 +845,29 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) if (!out_pkt.size) continue; + if (pkt->side_data) { + out_pkt.side_data = pkt->side_data; + out_pkt.side_data_elems = pkt->side_data_elems; + pkt->side_data = NULL; + pkt->side_data_elems = 0; + } + /* set the duration */ out_pkt.duration = 0; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->codec->sample_rate > 0) { - out_pkt.duration = av_rescale_q_rnd(st->parser->duration, - (AVRational){ 1, st->codec->sample_rate }, - st->time_base, - AV_ROUND_DOWN); + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->internal->avctx->sample_rate > 0) { + out_pkt.duration = + av_rescale_q_rnd(st->parser->duration, + (AVRational) { 1, st->internal->avctx->sample_rate }, + st->time_base, + AV_ROUND_DOWN); } - } else if (st->codec->time_base.num != 0 && - st->codec->time_base.den != 0) { - out_pkt.duration = av_rescale_q_rnd(st->parser->duration, - st->codec->time_base, - st->time_base, - AV_ROUND_DOWN); } out_pkt.stream_index = st->index; - out_pkt.pts = st->parser->pts; - out_pkt.dts = st->parser->dts; - out_pkt.pos = st->parser->pos; + out_pkt.pts = st->parser->pts; + out_pkt.dts = st->parser->dts; + out_pkt.pos = st->parser->pos; if (st->parser->key_frame == 1 || (st->parser->key_frame == -1 && @@ -1070,21 +883,14 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) 0, 0, AVINDEX_KEYFRAME); } - if (out_pkt.data == pkt->data && out_pkt.size == pkt->size) { - out_pkt.destruct = pkt->destruct; - pkt->destruct = NULL; - } - if ((ret = av_dup_packet(&out_pkt)) < 0) - goto fail; - - if (!add_to_pktbuf(&s->parse_queue, &out_pkt, &s->parse_queue_end)) { - av_free_packet(&out_pkt); - ret = AVERROR(ENOMEM); + if ((ret = add_to_pktbuf(&s->internal->parse_queue, &out_pkt, + &s->internal->parse_queue_end, + 1))) { + av_packet_unref(&out_pkt); goto fail; } } - /* end of the stream => close and free the parser */ if (pkt == &flush_pkt) { av_parser_close(st->parser); @@ -1092,7 +898,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) } fail: - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } @@ -1102,8 +908,8 @@ static int read_from_packet_buffer(AVPacketList **pkt_buffer, { AVPacketList *pktl; av_assert0(*pkt_buffer); - pktl = *pkt_buffer; - *pkt = pktl->pkt; + pktl = *pkt_buffer; + *pkt = pktl->pkt; *pkt_buffer = pktl->next; if (!pktl->next) *pkt_buffer_end = NULL; @@ -1114,10 +920,11 @@ static int read_from_packet_buffer(AVPacketList **pkt_buffer, static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) { int ret = 0, i, got_packet = 0; + AVDictionary *metadata = NULL; av_init_packet(pkt); - while (!got_packet && !s->parse_queue) { + while (!got_packet && !s->internal->parse_queue) { AVStream *st; AVPacket cur_pkt; @@ -1127,7 +934,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (ret == AVERROR(EAGAIN)) return ret; /* flush the parsers */ - for(i = 0; i < s->nb_streams; i++) { + for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; if (st->parser && st->need_parsing) parse_packet(s, NULL, st->index); @@ -1142,31 +949,28 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (cur_pkt.pts != AV_NOPTS_VALUE && cur_pkt.dts != AV_NOPTS_VALUE && cur_pkt.pts < cur_pkt.dts) { - av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n", - cur_pkt.stream_index, - cur_pkt.pts, - cur_pkt.dts, - cur_pkt.size); + av_log(s, AV_LOG_WARNING, + "Invalid timestamps stream=%d, pts=%"PRId64", " + "dts=%"PRId64", size=%d\n", + cur_pkt.stream_index, cur_pkt.pts, + cur_pkt.dts, cur_pkt.size); } if (s->debug & FF_FDEBUG_TS) - av_log(s, AV_LOG_DEBUG, "ff_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n", - cur_pkt.stream_index, - cur_pkt.pts, - cur_pkt.dts, - cur_pkt.size, - cur_pkt.duration, - cur_pkt.flags); + av_log(s, AV_LOG_DEBUG, + "ff_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", " + "size=%d, duration=%"PRId64", flags=%d\n", + cur_pkt.stream_index, cur_pkt.pts, cur_pkt.dts, + cur_pkt.size, cur_pkt.duration, cur_pkt.flags); if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) { - st->parser = av_parser_init(st->codec->codec_id); - if (!st->parser) { + st->parser = av_parser_init(st->codecpar->codec_id); + if (!st->parser) /* no parser available: just output the raw packets */ st->need_parsing = AVSTREAM_PARSE_NONE; - } else if(st->need_parsing == AVSTREAM_PARSE_HEADERS) { + else if (st->need_parsing == AVSTREAM_PARSE_HEADERS) st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - } else if(st->need_parsing == AVSTREAM_PARSE_FULL_ONCE) { + else if (st->need_parsing == AVSTREAM_PARSE_FULL_ONCE) st->parser->flags |= PARSER_FLAG_ONCE; - } } if (!st->need_parsing || !st->parser) { @@ -1176,7 +980,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && (pkt->flags & AV_PKT_FLAG_KEY) && pkt->dts != AV_NOPTS_VALUE) { ff_reduce_index(s, st->index); - av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME); + av_add_index_entry(st, pkt->pos, pkt->dts, + 0, 0, AVINDEX_KEYFRAME); } got_packet = 1; } else if (st->discard < AVDISCARD_ALL) { @@ -1184,21 +989,31 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) return ret; } else { /* free packet */ - av_free_packet(&cur_pkt); + av_packet_unref(&cur_pkt); } } - if (!got_packet && s->parse_queue) - ret = read_from_packet_buffer(&s->parse_queue, &s->parse_queue_end, pkt); + if (!got_packet && s->internal->parse_queue) + ret = read_from_packet_buffer(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt); - if(s->debug & FF_FDEBUG_TS) - 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, - pkt->size, - pkt->duration, - pkt->flags); + av_opt_get_dict_val(s, "metadata", AV_OPT_SEARCH_CHILDREN, &metadata); + if (metadata) { + s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED; + av_dict_copy(&s->metadata, metadata, 0); + av_dict_free(&metadata); + av_opt_set_dict_val(s, "metadata", NULL, AV_OPT_SEARCH_CHILDREN); + } + +#if FF_API_LAVF_AVCTX + update_stream_avctx(s); +#endif + + if (s->debug & FF_FDEBUG_TS) + av_log(s, AV_LOG_DEBUG, + "read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", " + "size=%d, duration=%"PRId64", flags=%d\n", + pkt->stream_index, pkt->pts, pkt->dts, + pkt->size, pkt->duration, pkt->flags); return ret; } @@ -1206,17 +1021,17 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) int av_read_frame(AVFormatContext *s, AVPacket *pkt) { const int genpts = s->flags & AVFMT_FLAG_GENPTS; - int eof = 0; + int eof = 0; if (!genpts) - return s->packet_buffer ? read_from_packet_buffer(&s->packet_buffer, - &s->packet_buffer_end, - pkt) : - read_frame_internal(s, pkt); + return s->internal->packet_buffer + ? read_from_packet_buffer(&s->internal->packet_buffer, + &s->internal->packet_buffer_end, pkt) + : read_frame_internal(s, pkt); for (;;) { int ret; - AVPacketList *pktl = s->packet_buffer; + AVPacketList *pktl = s->internal->packet_buffer; if (pktl) { AVPacket *next_pkt = &pktl->pkt; @@ -1226,19 +1041,20 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) 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 + 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 = s->packet_buffer; + pktl = s->internal->packet_buffer; } /* 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->packet_buffer, - &s->packet_buffer_end, pkt); + return read_from_packet_buffer(&s->internal->packet_buffer, + &s->internal->packet_buffer_end, pkt); } ret = read_frame_internal(s, pkt); @@ -1250,20 +1066,21 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) return ret; } - if (av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt, - &s->packet_buffer_end)) < 0) - return AVERROR(ENOMEM); + ret = add_to_pktbuf(&s->internal->packet_buffer, pkt, + &s->internal->packet_buffer_end, 1); + if (ret < 0) + return ret; } } /* XXX: suppress the packet queue */ static void flush_packet_queue(AVFormatContext *s) { - free_packet_buffer(&s->parse_queue, &s->parse_queue_end); - free_packet_buffer(&s->packet_buffer, &s->packet_buffer_end); - free_packet_buffer(&s->raw_packet_buffer, &s->raw_packet_buffer_end); + free_packet_buffer(&s->internal->parse_queue, &s->internal->parse_queue_end); + free_packet_buffer(&s->internal->packet_buffer, &s->internal->packet_buffer_end); + free_packet_buffer(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end); - s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; + s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; } /*******************************************************/ @@ -1277,21 +1094,20 @@ int av_find_default_stream_index(AVFormatContext *s) if (s->nb_streams <= 0) return -1; - for(i = 0; i < s->nb_streams; i++) { + for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) { return i; } - if (first_audio_index < 0 && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + if (first_audio_index < 0 && + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) first_audio_index = i; } return first_audio_index >= 0 ? first_audio_index : 0; } -/** - * Flush the frame reader. - */ +/** Flush the frame reader. */ void ff_read_frame_flush(AVFormatContext *s) { AVStream *st; @@ -1299,8 +1115,8 @@ void ff_read_frame_flush(AVFormatContext *s) flush_packet_queue(s); - /* for each stream, reset read state */ - for(i = 0; i < s->nb_streams; i++) { + /* Reset read state for each stream. */ + for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; if (st->parser) { @@ -1308,13 +1124,13 @@ void ff_read_frame_flush(AVFormatContext *s) st->parser = NULL; } st->last_IP_pts = AV_NOPTS_VALUE; - st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */ - st->reference_dts = AV_NOPTS_VALUE; + /* We set the current DTS to an unspecified origin. */ + st->cur_dts = AV_NOPTS_VALUE; st->probe_packets = MAX_PROBE_PACKETS; - for(j=0; jpts_buffer[j]= AV_NOPTS_VALUE; + for (j = 0; j < MAX_REORDER_DELAY + 1; j++) + st->pts_buffer[j] = AV_NOPTS_VALUE; } } @@ -1322,76 +1138,81 @@ void ff_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) { int i; - for(i = 0; i < s->nb_streams; i++) { + for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - st->cur_dts = av_rescale(timestamp, - st->time_base.den * (int64_t)ref_st->time_base.num, - st->time_base.num * (int64_t)ref_st->time_base.den); + st->cur_dts = + av_rescale(timestamp, + st->time_base.den * (int64_t) ref_st->time_base.num, + st->time_base.num * (int64_t) ref_st->time_base.den); } } void ff_reduce_index(AVFormatContext *s, int stream_index) { - AVStream *st= s->streams[stream_index]; - unsigned int max_entries= s->max_index_size / sizeof(AVIndexEntry); + AVStream *st = s->streams[stream_index]; + unsigned int max_entries = s->max_index_size / sizeof(AVIndexEntry); - if((unsigned)st->nb_index_entries >= max_entries){ + if ((unsigned) st->nb_index_entries >= max_entries) { int i; - for(i=0; 2*inb_index_entries; i++) - st->index_entries[i]= st->index_entries[2*i]; - st->nb_index_entries= i; + for (i = 0; 2 * i < st->nb_index_entries; i++) + st->index_entries[i] = st->index_entries[2 * i]; + st->nb_index_entries = i; } } int ff_add_index_entry(AVIndexEntry **index_entries, int *nb_index_entries, unsigned int *index_entries_allocated_size, - int64_t pos, int64_t timestamp, int size, int distance, int flags) + int64_t pos, int64_t timestamp, + int size, int distance, int flags) { AVIndexEntry *entries, *ie; int index; - if((unsigned)*nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry)) + if ((unsigned) *nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry)) return -1; entries = av_fast_realloc(*index_entries, index_entries_allocated_size, (*nb_index_entries + 1) * sizeof(AVIndexEntry)); - if(!entries) + if (!entries) return -1; - *index_entries= entries; + *index_entries = entries; - index= ff_index_search_timestamp(*index_entries, *nb_index_entries, timestamp, AVSEEK_FLAG_ANY); + index = ff_index_search_timestamp(*index_entries, *nb_index_entries, + timestamp, AVSEEK_FLAG_ANY); - if(index<0){ - index= (*nb_index_entries)++; - ie= &entries[index]; - assert(index==0 || ie[-1].timestamp < timestamp); - }else{ - ie= &entries[index]; - if(ie->timestamp != timestamp){ - if(ie->timestamp <= timestamp) + if (index < 0) { + index = (*nb_index_entries)++; + ie = &entries[index]; + assert(index == 0 || ie[-1].timestamp < timestamp); + } else { + ie = &entries[index]; + if (ie->timestamp != timestamp) { + if (ie->timestamp <= timestamp) return -1; - memmove(entries + index + 1, entries + index, sizeof(AVIndexEntry)*(*nb_index_entries - index)); + memmove(entries + index + 1, entries + index, + sizeof(AVIndexEntry) * (*nb_index_entries - index)); (*nb_index_entries)++; - }else if(ie->pos == pos && distance < ie->min_distance) //do not reduce the distance - distance= ie->min_distance; + } else if (ie->pos == pos && distance < ie->min_distance) + // do not reduce the distance + distance = ie->min_distance; } - ie->pos = pos; - ie->timestamp = timestamp; - ie->min_distance= distance; - ie->size= size; - ie->flags = flags; + ie->pos = pos; + ie->timestamp = timestamp; + ie->min_distance = distance; + ie->size = size; + ie->flags = flags; return index; } -int av_add_index_entry(AVStream *st, - int64_t pos, int64_t timestamp, int size, int distance, int flags) +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, + int size, int distance, int flags) { return ff_add_index_entry(&st->index_entries, &st->nb_index_entries, &st->index_entries_allocated_size, pos, @@ -1404,44 +1225,43 @@ int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries, int a, b, m; int64_t timestamp; - a = - 1; + a = -1; b = nb_entries; - //optimize appending index entries at the end - if(b && entries[b-1].timestamp < wanted_timestamp) - a= b-1; + // Optimize appending index entries at the end. + if (b && entries[b - 1].timestamp < wanted_timestamp) + a = b - 1; while (b - a > 1) { - m = (a + b) >> 1; + m = (a + b) >> 1; timestamp = entries[m].timestamp; - if(timestamp >= wanted_timestamp) + if (timestamp >= wanted_timestamp) b = m; - if(timestamp <= wanted_timestamp) + if (timestamp <= wanted_timestamp) a = m; } - m= (flags & AVSEEK_FLAG_BACKWARD) ? a : b; + m = (flags & AVSEEK_FLAG_BACKWARD) ? a : b; - if(!(flags & AVSEEK_FLAG_ANY)){ - while(m>=0 && m= 0 && m < nb_entries && + !(entries[m].flags & AVINDEX_KEYFRAME)) m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1; - } - } - if(m == nb_entries) + if (m == nb_entries) return -1; - return m; + return m; } -int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, - int flags) +int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags) { return ff_index_search_timestamp(st->index_entries, st->nb_index_entries, wanted_timestamp, flags); } -int ff_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; + AVInputFormat *avif = s->iformat; int64_t av_uninit(pos_min), av_uninit(pos_max), pos, pos_limit; int64_t ts_min, ts_max, ts; int index; @@ -1451,44 +1271,49 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts if (stream_index < 0) return -1; - av_dlog(s, "read_seek: %d %"PRId64"\n", stream_index, target_ts); + av_log(s, AV_LOG_TRACE, "read_seek: %d %"PRId64"\n", stream_index, target_ts); - ts_max= - ts_min= AV_NOPTS_VALUE; - pos_limit= -1; //gcc falsely says it may be uninitialized + ts_max = + ts_min = AV_NOPTS_VALUE; + pos_limit = -1; // GCC falsely says it may be uninitialized. - st= s->streams[stream_index]; - if(st->index_entries){ + st = s->streams[stream_index]; + if (st->index_entries) { AVIndexEntry *e; - index= av_index_search_timestamp(st, target_ts, flags | AVSEEK_FLAG_BACKWARD); //FIXME whole func must be checked for non-keyframe entries in index case, especially read_timestamp() - index= FFMAX(index, 0); - e= &st->index_entries[index]; - - if(e->timestamp <= target_ts || e->pos == e->min_distance){ - pos_min= e->pos; - ts_min= e->timestamp; - av_dlog(s, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n", - pos_min,ts_min); - }else{ - assert(index==0); + /* FIXME: Whole function must be checked for non-keyframe entries in + * index case, especially read_timestamp(). */ + index = av_index_search_timestamp(st, target_ts, + flags | AVSEEK_FLAG_BACKWARD); + index = FFMAX(index, 0); + e = &st->index_entries[index]; + + if (e->timestamp <= target_ts || e->pos == e->min_distance) { + pos_min = e->pos; + ts_min = e->timestamp; + av_log(s, AV_LOG_TRACE, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n", + pos_min, ts_min); + } else { + assert(index == 0); } - index= av_index_search_timestamp(st, target_ts, flags & ~AVSEEK_FLAG_BACKWARD); + index = av_index_search_timestamp(st, target_ts, + flags & ~AVSEEK_FLAG_BACKWARD); assert(index < st->nb_index_entries); - if(index >= 0){ - e= &st->index_entries[index]; + if (index >= 0) { + e = &st->index_entries[index]; assert(e->timestamp >= target_ts); - pos_max= e->pos; - ts_max= e->timestamp; - pos_limit= pos_max - e->min_distance; - av_dlog(s, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%"PRId64"\n", - pos_max,pos_limit, ts_max); + pos_max = e->pos; + ts_max = e->timestamp; + pos_limit = pos_max - e->min_distance; + av_log(s, AV_LOG_TRACE, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64 + " dts_max=%"PRId64"\n", pos_max, pos_limit, ts_max); } } - pos= ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ts, avif->read_timestamp); - if(pos<0) + 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; /* do the seek */ @@ -1502,130 +1327,140 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts 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 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; - av_dlog(s, "gen_seek: %d %"PRId64"\n", stream_index, target_ts); + av_log(s, AV_LOG_TRACE, "gen_seek: %d %"PRId64"\n", stream_index, target_ts); - if(ts_min == AV_NOPTS_VALUE){ - pos_min = s->data_offset; - ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); + if (ts_min == AV_NOPTS_VALUE) { + pos_min = s->internal->data_offset; + ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); if (ts_min == AV_NOPTS_VALUE) return -1; } - if(ts_max == AV_NOPTS_VALUE){ - int step= 1024; + if (ts_max == AV_NOPTS_VALUE) { + int step = 1024; filesize = avio_size(s->pb); - pos_max = filesize - 1; - do{ + pos_max = filesize - 1; + do { pos_max -= step; - ts_max = read_timestamp(s, stream_index, &pos_max, pos_max + step); - step += step; - }while(ts_max == AV_NOPTS_VALUE && pos_max >= step); + ts_max = read_timestamp(s, stream_index, &pos_max, + pos_max + step); + step += step; + } while (ts_max == AV_NOPTS_VALUE && pos_max >= step); if (ts_max == AV_NOPTS_VALUE) return -1; - for(;;){ - int64_t tmp_pos= pos_max + 1; - int64_t tmp_ts= read_timestamp(s, stream_index, &tmp_pos, INT64_MAX); - if(tmp_ts == AV_NOPTS_VALUE) + for (;;) { + int64_t tmp_pos = pos_max + 1; + int64_t tmp_ts = read_timestamp(s, stream_index, + &tmp_pos, INT64_MAX); + if (tmp_ts == AV_NOPTS_VALUE) break; - ts_max= tmp_ts; - pos_max= tmp_pos; - if(tmp_pos >= filesize) + ts_max = tmp_ts; + pos_max = tmp_pos; + if (tmp_pos >= filesize) break; } - pos_limit= pos_max; + pos_limit = pos_max; } - if(ts_min > ts_max){ + if (ts_min > ts_max) return -1; - }else if(ts_min == ts_max){ - pos_limit= pos_min; - } + else if (ts_min == ts_max) + pos_limit = pos_min; - no_change=0; + no_change = 0; while (pos_min < pos_limit) { - av_dlog(s, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64" dts_max=%"PRId64"\n", - pos_min, pos_max, ts_min, ts_max); + av_log(s, AV_LOG_TRACE, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64 + " dts_max=%"PRId64"\n", pos_min, pos_max, ts_min, ts_max); assert(pos_limit <= pos_max); - if(no_change==0){ - int64_t approximate_keyframe_distance= pos_max - pos_limit; + if (no_change == 0) { + int64_t approximate_keyframe_distance = pos_max - pos_limit; // interpolate position (better than dichotomy) - pos = av_rescale(target_ts - ts_min, pos_max - pos_min, ts_max - ts_min) - + pos_min - approximate_keyframe_distance; - }else if(no_change==1){ - // bisection, if interpolation failed to change min or max pos last time - pos = (pos_min + pos_limit)>>1; - }else{ + pos = av_rescale(target_ts - ts_min, pos_max - pos_min, + ts_max - ts_min) + + pos_min - approximate_keyframe_distance; + } else if (no_change == 1) { + // bisection if interpolation did not change min / max pos last time + pos = (pos_min + pos_limit) >> 1; + } else { /* linear search if bisection failed, can only happen if there - are very few or no keyframes between min/max */ - pos=pos_min; - } - if(pos <= pos_min) - pos= pos_min + 1; - else if(pos > pos_limit) - pos= pos_limit; - start_pos= pos; - - ts = read_timestamp(s, stream_index, &pos, INT64_MAX); //may pass pos_limit instead of -1 - if(pos == pos_max) + * are very few or no keyframes between min/max */ + pos = pos_min; + } + if (pos <= pos_min) + pos = pos_min + 1; + else if (pos > pos_limit) + pos = pos_limit; + start_pos = pos; + + // May pass pos_limit instead of -1. + ts = read_timestamp(s, stream_index, &pos, INT64_MAX); + if (pos == pos_max) no_change++; else - no_change=0; - av_dlog(s, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64" target:%"PRId64" limit:%"PRId64" start:%"PRId64" noc:%d\n", + no_change = 0; + av_log(s, AV_LOG_TRACE, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64 + " target:%"PRId64" limit:%"PRId64" start:%"PRId64" noc:%d\n", pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, start_pos, no_change); - if(ts == AV_NOPTS_VALUE){ + if (ts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n"); return -1; } assert(ts != AV_NOPTS_VALUE); if (target_ts <= ts) { pos_limit = start_pos - 1; - pos_max = pos; - ts_max = ts; + pos_max = pos; + ts_max = ts; } if (target_ts >= ts) { pos_min = pos; - ts_min = ts; + ts_min = ts; } } - pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; - ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max; + pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; + ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max; pos_min = pos; - ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); + ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); pos_min++; ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX); - av_dlog(s, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n", + av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n", pos, ts_min, target_ts, ts_max); - *ts_ret= ts; + *ts_ret = ts; return pos; } -static int 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; - pos_min = s->data_offset; + pos_min = s->internal->data_offset; pos_max = avio_size(s->pb) - 1; - if (pos < pos_min) pos= pos_min; - else if(pos > pos_max) pos= pos_max; + if (pos < pos_min) + pos = pos_min; + else if (pos > pos_max) + pos = pos_max; avio_seek(s->pb, pos, SEEK_SET); return 0; } -static int seek_frame_generic(AVFormatContext *s, - int stream_index, int64_t timestamp, int flags) +static int seek_frame_generic(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) { int index; int64_t ret; @@ -1636,34 +1471,34 @@ static int seek_frame_generic(AVFormatContext *s, index = av_index_search_timestamp(st, timestamp, flags); - if(index < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp) + if (index < 0 && st->nb_index_entries && + timestamp < st->index_entries[0].timestamp) return -1; - if(index < 0 || index==st->nb_index_entries-1){ + if (index < 0 || index == st->nb_index_entries - 1) { AVPacket pkt; - if(st->nb_index_entries){ + if (st->nb_index_entries) { assert(st->index_entries); - ie= &st->index_entries[st->nb_index_entries-1]; + ie = &st->index_entries[st->nb_index_entries - 1]; if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0) return ret; ff_update_cur_dts(s, st, ie->timestamp); - }else{ - if ((ret = avio_seek(s->pb, s->data_offset, SEEK_SET)) < 0) + } else { + if ((ret = avio_seek(s->pb, s->internal->data_offset, SEEK_SET)) < 0) return ret; } for (;;) { int read_status; - do{ + do { 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){ - if((pkt.flags & AV_PKT_FLAG_KEY) && pkt.dts > timestamp) + av_packet_unref(&pkt); + if (stream_index == pkt.stream_index) + if ((pkt.flags & AV_PKT_FLAG_KEY) && pkt.dts > timestamp) break; - } } index = av_index_search_timestamp(st, timestamp, flags); } @@ -1671,10 +1506,9 @@ static int seek_frame_generic(AVFormatContext *s, return -1; ff_read_frame_flush(s); - if (s->iformat->read_seek){ - if(s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0) + if (s->iformat->read_seek) + if (s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0) return 0; - } ie = &st->index_entries[index]; if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0) return ret; @@ -1696,14 +1530,15 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index, return seek_frame_byte(s, stream_index, timestamp, flags); } - if(stream_index < 0){ - stream_index= av_find_default_stream_index(s); - if(stream_index < 0) + if (stream_index < 0) { + stream_index = av_find_default_stream_index(s); + if (stream_index < 0) return -1; - st= s->streams[stream_index]; + st = s->streams[stream_index]; /* 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); + timestamp = av_rescale(timestamp, st->time_base.den, + AV_TIME_BASE * (int64_t) st->time_base.num); } /* first, we try the format specific seek */ @@ -1712,54 +1547,59 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index, ret = s->iformat->read_seek(s, stream_index, timestamp, flags); } else ret = -1; - if (ret >= 0) { + if (ret >= 0) return 0; - } - if (s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) { + 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 + } else return -1; } -int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +int av_seek_frame(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) { int ret = seek_frame_internal(s, stream_index, timestamp, flags); if (ret >= 0) - queue_attached_pictures(s); + ret = queue_attached_pictures(s); return ret; } -int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) +int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, + int64_t ts, int64_t max_ts, int flags) { - if(min_ts > ts || max_ts < ts) + if (min_ts > ts || max_ts < ts) return -1; if (s->iformat->read_seek2) { int ret; ff_read_frame_flush(s); - ret = s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags); + ret = s->iformat->read_seek2(s, stream_index, min_ts, + ts, max_ts, flags); if (ret >= 0) - queue_attached_pictures(s); + ret = queue_attached_pictures(s); return ret; } - if(s->iformat->read_timestamp){ - //try to seek via read_timestamp() + if (s->iformat->read_timestamp) { + // try to seek via read_timestamp() } - //Fallback to old API if new is not implemented but old is - //Note the old has somewat different sematics - 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)); + // Fall back on old API if new is not implemented but old is. + // Note the old API has somewhat different semantics. + if (s->iformat->read_seek || 1) + return av_seek_frame(s, stream_index, ts, + flags | ((uint64_t) ts - min_ts > + (uint64_t) max_ts - ts + ? AVSEEK_FLAG_BACKWARD : 0)); // try some generic seek like seek_frame_generic() but with new ts semantics } @@ -1776,7 +1616,7 @@ static int has_duration(AVFormatContext *ic) int i; AVStream *st; - for(i = 0;i < ic->nb_streams; i++) { + for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->duration != AV_NOPTS_VALUE) return 1; @@ -1799,22 +1639,25 @@ static void update_stream_timings(AVFormatContext *ic) AVStream *st; start_time = INT64_MAX; - end_time = INT64_MIN; - duration = INT64_MIN; - for(i = 0;i < ic->nb_streams; i++) { + end_time = INT64_MIN; + duration = INT64_MIN; + for (i = 0; i < ic->nb_streams; i++) { 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); - start_time = FFMIN(start_time, start_time1); + start_time1 = av_rescale_q(st->start_time, st->time_base, + AV_TIME_BASE_Q); + 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); + end_time1 = start_time1 + + av_rescale_q(st->duration, st->time_base, + AV_TIME_BASE_Q); 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); - duration = FFMAX(duration, duration1); + duration1 = av_rescale_q(st->duration, st->time_base, + AV_TIME_BASE_Q); + duration = FFMAX(duration, duration1); } } if (start_time != INT64_MAX) { @@ -1824,11 +1667,10 @@ static void update_stream_timings(AVFormatContext *ic) } if (duration != INT64_MIN) { ic->duration = duration; - if (ic->pb && (filesize = avio_size(ic->pb)) > 0) { + if (ic->pb && (filesize = avio_size(ic->pb)) > 0) /* compute the bitrate */ - ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE / - (double)ic->duration; - } + ic->bit_rate = (double) filesize * 8.0 * AV_TIME_BASE / + (double) ic->duration; } } @@ -1838,13 +1680,15 @@ static void fill_all_stream_timings(AVFormatContext *ic) AVStream *st; update_stream_timings(ic); - for(i = 0;i < ic->nb_streams; i++) { + for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->start_time == AV_NOPTS_VALUE) { - if(ic->start_time != AV_NOPTS_VALUE) - st->start_time = av_rescale_q(ic->start_time, AV_TIME_BASE_Q, st->time_base); - if(ic->duration != AV_NOPTS_VALUE) - st->duration = av_rescale_q(ic->duration, AV_TIME_BASE_Q, st->time_base); + if (ic->start_time != AV_NOPTS_VALUE) + st->start_time = av_rescale_q(ic->start_time, AV_TIME_BASE_Q, + st->time_base); + if (ic->duration != AV_NOPTS_VALUE) + st->duration = av_rescale_q(ic->duration, AV_TIME_BASE_Q, + st->time_base); } } } @@ -1852,16 +1696,21 @@ static void fill_all_stream_timings(AVFormatContext *ic) static void estimate_timings_from_bit_rate(AVFormatContext *ic) { int64_t filesize, duration; - int bit_rate, i; + int i; AVStream *st; /* if bit_rate is already set, we believe it */ if (ic->bit_rate <= 0) { - bit_rate = 0; - for(i=0;inb_streams;i++) { + int bit_rate = 0; + for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; - if (st->codec->bit_rate > 0) - bit_rate += st->codec->bit_rate; + if (st->codecpar->bit_rate > 0) { + if (INT_MAX - st->codecpar->bit_rate < bit_rate) { + bit_rate = 0; + break; + } + bit_rate += st->codecpar->bit_rate; + } } ic->bit_rate = bit_rate; } @@ -1871,9 +1720,11 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic) 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]; - duration= av_rescale(8*filesize, st->time_base.den, ic->bit_rate*(int64_t)st->time_base.num); + for (i = 0; i < ic->nb_streams; i++) { + st = ic->streams[i]; + duration = av_rescale(8 * filesize, st->time_base.den, + ic->bit_rate * + (int64_t) st->time_base.num); if (st->duration == AV_NOPTS_VALUE) st->duration = duration; } @@ -1892,19 +1743,20 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) int read_size, i, ret; int64_t end_time; int64_t filesize, offset, duration; - int retry=0; + int retry = 0; /* flush packet queue */ flush_packet_queue(ic); - for (i=0; inb_streams; i++) { + 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 estimate_timings_from_pts\n"); + av_log(ic, AV_LOG_WARNING, + "start time is not set in estimate_timings_from_pts\n"); if (st->parser) { av_parser_close(st->parser); - st->parser= NULL; + st->parser = NULL; } } @@ -1912,24 +1764,24 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) /* XXX: may need to support wrapping */ filesize = ic->pb ? avio_size(ic->pb) : 0; end_time = AV_NOPTS_VALUE; - do{ - offset = filesize - (DURATION_MAX_READ_SIZE<pb, offset, SEEK_SET); read_size = 0; - for(;;) { - if (read_size >= DURATION_MAX_READ_SIZE<<(FFMAX(retry-1,0))) + for (;;) { + if (read_size >= DURATION_MAX_READ_SIZE << (FFMAX(retry - 1, 0))) break; do { ret = ff_read_packet(ic, pkt); - } while(ret == AVERROR(EAGAIN)); + } while (ret == AVERROR(EAGAIN)); if (ret != 0) break; read_size += pkt->size; - st = ic->streams[pkt->stream_index]; + st = ic->streams[pkt->stream_index]; if (pkt->pts != AV_NOPTS_VALUE && (st->start_time != AV_NOPTS_VALUE || st->first_dts != AV_NOPTS_VALUE)) { @@ -1939,26 +1791,25 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) else duration -= st->first_dts; if (duration < 0) - duration += 1LL<pts_wrap_bits; + 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_packet_unref(pkt); } - }while( end_time==AV_NOPTS_VALUE - && filesize > (DURATION_MAX_READ_SIZE< (DURATION_MAX_READ_SIZE << retry) && + ++retry <= DURATION_MAX_RETRY); fill_all_stream_timings(ic); avio_seek(ic->pb, old_offset, SEEK_SET); - for (i=0; inb_streams; i++) { - st= ic->streams[i]; - st->cur_dts= st->first_dts; + for (i = 0; i < ic->nb_streams; i++) { + st = ic->streams[i]; + st->cur_dts = st->first_dts; st->last_IP_pts = AV_NOPTS_VALUE; - st->reference_dts = AV_NOPTS_VALUE; } } @@ -1976,15 +1827,16 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset) if ((!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts")) && - file_size && ic->pb->seekable) { + file_size && (ic->pb->seekable & AVIO_SEEKABLE_NORMAL)) { /* get accurate estimate from the PTSes */ 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 */ + * the components */ fill_all_stream_timings(ic); } else { - av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this may be inaccurate\n"); + av_log(ic, AV_LOG_WARNING, + "Estimating duration from bitrate, this may be inaccurate\n"); /* less precise: use bitrate info */ estimate_timings_from_bit_rate(ic); } @@ -1993,13 +1845,14 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset) { int i; AVStream av_unused *st; - for(i = 0;i < ic->nb_streams; i++) { + for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; - av_dlog(ic, "%d: start_time: %0.3f duration: %0.3f\n", i, + av_log(ic, AV_LOG_TRACE, "%d: start_time: %0.3f duration: %0.3f\n", i, (double) st->start_time / AV_TIME_BASE, (double) st->duration / AV_TIME_BASE); } - av_dlog(ic, "stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n", + av_log(ic, AV_LOG_TRACE, + "stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n", (double) ic->start_time / AV_TIME_BASE, (double) ic->duration / AV_TIME_BASE, ic->bit_rate / 1000); @@ -2008,17 +1861,19 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset) static int has_codec_parameters(AVStream *st) { - AVCodecContext *avctx = st->codec; + AVCodecContext *avctx = st->internal->avctx; int val; + switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: val = avctx->sample_rate && avctx->channels; - if (st->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE) + if (st->info->found_decoder >= 0 && + avctx->sample_fmt == AV_SAMPLE_FMT_NONE) return 0; break; case AVMEDIA_TYPE_VIDEO: val = avctx->width; - if (st->info->found_decoder >= 0 && avctx->pix_fmt == PIX_FMT_NONE) + if (st->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE) return 0; break; default: @@ -2030,37 +1885,45 @@ static int has_codec_parameters(AVStream *st) static int has_decode_delay_been_guessed(AVStream *st) { - return st->codec->codec_id != AV_CODEC_ID_H264 || - st->info->nb_decoded_frames >= 6; + return st->internal->avctx->codec_id != AV_CODEC_ID_H264 || + st->info->nb_decoded_frames >= 6; } /* returns 1 or 0 if or if not decoded data was returned, or a negative error */ -static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **options) +static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, + AVDictionary **options) { + AVCodecContext *avctx = st->internal->avctx; const AVCodec *codec; int got_picture = 1, ret = 0; - AVFrame *frame = avcodec_alloc_frame(); + AVFrame *frame = av_frame_alloc(); AVPacket pkt = *avpkt; if (!frame) return AVERROR(ENOMEM); - if (!avcodec_is_open(st->codec) && !st->info->found_decoder) { + if (!avcodec_is_open(avctx) && !st->info->found_decoder) { AVDictionary *thread_opt = NULL; - codec = st->codec->codec ? st->codec->codec : - avcodec_find_decoder(st->codec->codec_id); +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + codec = st->codec->codec ? st->codec->codec + : avcodec_find_decoder(st->codecpar->codec_id); +FF_ENABLE_DEPRECATION_WARNINGS +#else + codec = avcodec_find_decoder(st->codecpar->codec_id); +#endif if (!codec) { st->info->found_decoder = -1; - ret = -1; + ret = -1; goto fail; } - /* force thread count to 1 since the h264 decoder will not extract SPS - * and PPS to extradata during multi-threaded decoding */ + /* Force thread count to 1 since the H.264 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); + ret = avcodec_open2(avctx, codec, options ? options : &thread_opt); if (!options) av_dict_free(&thread_opt); if (ret < 0) { @@ -2078,33 +1941,32 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option while ((pkt.size > 0 || (!pkt.data && got_picture)) && ret >= 0 && - (!has_codec_parameters(st) || - !has_decode_delay_been_guessed(st) || - (!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) { + (!has_codec_parameters(st) || !has_decode_delay_been_guessed(st) || + (!st->codec_info_nb_frames && + (avctx->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) { got_picture = 0; - avcodec_get_frame_defaults(frame); - switch(st->codec->codec_type) { - case AVMEDIA_TYPE_VIDEO: - ret = avcodec_decode_video2(st->codec, frame, - &got_picture, &pkt); - break; - case AVMEDIA_TYPE_AUDIO: - ret = avcodec_decode_audio4(st->codec, frame, &got_picture, &pkt); - break; - default: - break; + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || + avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + ret = avcodec_send_packet(avctx, &pkt); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + break; + if (ret >= 0) + pkt.size = 0; + ret = avcodec_receive_frame(avctx, frame); + if (ret >= 0) + got_picture = 1; + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + ret = 0; } if (ret >= 0) { if (got_picture) st->info->nb_decoded_frames++; - pkt.data += ret; - pkt.size -= ret; ret = got_picture; } } fail: - avcodec_free_frame(&frame); + av_frame_free(&frame); return ret; } @@ -2121,33 +1983,76 @@ unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id) enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag) { int i; - for(i=0; tags[i].id != AV_CODEC_ID_NONE;i++) { - if(tag == tags[i].tag) + for (i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) + if (tag == tags[i].tag) return tags[i].id; - } - for(i=0; tags[i].id != AV_CODEC_ID_NONE; i++) { + for (i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) if (avpriv_toupper4(tag) == avpriv_toupper4(tags[i].tag)) return tags[i].id; - } return AV_CODEC_ID_NONE; } -unsigned int av_codec_get_tag(const AVCodecTag * const *tags, enum AVCodecID id) +enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags) +{ + if (flt) { + switch (bps) { + case 32: + return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE; + case 64: + return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE; + default: + return AV_CODEC_ID_NONE; + } + } else { + bps >>= 3; + if (sflags & (1 << (bps - 1))) { + switch (bps) { + case 1: + return AV_CODEC_ID_PCM_S8; + case 2: + return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE; + case 3: + return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE; + case 4: + return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE; + default: + return AV_CODEC_ID_NONE; + } + } else { + switch (bps) { + case 1: + return AV_CODEC_ID_PCM_U8; + case 2: + return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE; + case 3: + return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE; + case 4: + return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE; + default: + return AV_CODEC_ID_NONE; + } + } + } +} + +unsigned int av_codec_get_tag(const AVCodecTag *const *tags, enum AVCodecID id) { int i; - for(i=0; tags && tags[i]; i++){ - int tag= ff_codec_get_tag(tags[i], id); - if(tag) return tag; + for (i = 0; tags && tags[i]; i++) { + int tag = ff_codec_get_tag(tags[i], id); + if (tag) + return tag; } return 0; } -enum AVCodecID av_codec_get_id(const AVCodecTag * const *tags, unsigned int tag) +enum AVCodecID av_codec_get_id(const AVCodecTag *const *tags, unsigned int tag) { int i; - for(i=0; tags && tags[i]; i++){ - enum AVCodecID id= ff_codec_get_id(tags[i], tag); - if(id!=AV_CODEC_ID_NONE) return id; + for (i = 0; tags && tags[i]; i++) { + enum AVCodecID id = ff_codec_get_id(tags[i], tag); + if (id != AV_CODEC_ID_NONE) + return id; } return AV_CODEC_ID_NONE; } @@ -2155,17 +2060,20 @@ enum AVCodecID av_codec_get_id(const AVCodecTag * const *tags, unsigned int tag) static void compute_chapters_end(AVFormatContext *s) { unsigned int i, j; - int64_t max_time = s->duration + ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time); + int64_t max_time = s->duration + + ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time); for (i = 0; i < s->nb_chapters; i++) if (s->chapters[i]->end == AV_NOPTS_VALUE) { AVChapter *ch = s->chapters[i]; - int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q, ch->time_base) - : INT64_MAX; + int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q, + ch->time_base) + : INT64_MAX; for (j = 0; j < s->nb_chapters; j++) { - AVChapter *ch1 = s->chapters[j]; - int64_t next_start = av_rescale_q(ch1->start, ch1->time_base, ch->time_base); + AVChapter *ch1 = s->chapters[j]; + int64_t next_start = av_rescale_q(ch1->start, ch1->time_base, + ch->time_base); if (j != i && next_start > ch->start && next_start < end) end = next_start; } @@ -2173,28 +2081,119 @@ static void compute_chapters_end(AVFormatContext *s) } } -static int get_std_framerate(int i){ - if(i<60*12) return i*1001; - else return ((const int[]){24,30,60,12,15})[i-60*12]*1000*12; +static int get_std_framerate(int i) +{ + if (i < 60 * 12) + return (i + 1) * 1001; + else + return ((const int[]) { 24, 30, 60, 12, 15 })[i - 60 * 12] * 1000 * 12; } -/* - * Is the time base unreliable. - * This is a heuristic to balance between quick acceptance of the values in - * the headers vs. some extra checks. - * Old DivX and Xvid often have nonsense timebases like 1fps or 2fps. - * MPEG-2 commonly misuses field repeat flags to store different framerates. - * And there are "variable" fps files this needs to detect as well. - */ -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 == AV_RL32("DIVX") - || c->codec_tag == AV_RL32("XVID")*/ - || c->codec_id == AV_CODEC_ID_MPEG2VIDEO - || c->codec_id == AV_CODEC_ID_H264 - ) - return 1; +static int extract_extradata_init(AVStream *st) +{ + AVStreamInternal *i = st->internal; + const AVBitStreamFilter *f; + int ret; + + f = av_bsf_get_by_name("extract_extradata"); + if (!f) + goto finish; + + /* check that the codec id is supported */ + if (f->codec_ids) { + const enum AVCodecID *ids; + for (ids = f->codec_ids; *ids != AV_CODEC_ID_NONE; ids++) + if (*ids == st->codecpar->codec_id) + break; + if (*ids == AV_CODEC_ID_NONE) + goto finish; + } + + i->extract_extradata.pkt = av_packet_alloc(); + if (!i->extract_extradata.pkt) + return AVERROR(ENOMEM); + + ret = av_bsf_alloc(f, &i->extract_extradata.bsf); + if (ret < 0) + goto fail; + + ret = avcodec_parameters_copy(i->extract_extradata.bsf->par_in, + st->codecpar); + if (ret < 0) + goto fail; + + i->extract_extradata.bsf->time_base_in = st->time_base; + + /* if init fails here, we assume extracting extradata is just not + * supported for this codec, so we return success */ + ret = av_bsf_init(i->extract_extradata.bsf); + if (ret < 0) { + av_bsf_free(&i->extract_extradata.bsf); + ret = 0; + } + +finish: + i->extract_extradata.inited = 1; + + return 0; +fail: + av_bsf_free(&i->extract_extradata.bsf); + av_packet_free(&i->extract_extradata.pkt); + return ret; +} + +static int extract_extradata(AVStream *st, AVPacket *pkt) +{ + AVStreamInternal *i = st->internal; + AVPacket *pkt_ref; + int ret; + + if (!i->extract_extradata.inited) { + ret = extract_extradata_init(st); + if (ret < 0) + return ret; + } + + if (i->extract_extradata.inited && !i->extract_extradata.bsf) + return 0; + + pkt_ref = i->extract_extradata.pkt; + ret = av_packet_ref(pkt_ref, pkt); + if (ret < 0) + return ret; + + ret = av_bsf_send_packet(i->extract_extradata.bsf, pkt_ref); + if (ret < 0) { + av_packet_unref(pkt_ref); + return ret; + } + + while (ret >= 0 && !i->avctx->extradata) { + int extradata_size; + uint8_t *extradata; + + ret = av_bsf_receive_packet(i->extract_extradata.bsf, pkt_ref); + if (ret < 0) { + if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return ret; + continue; + } + + extradata = av_packet_get_side_data(pkt_ref, AV_PKT_DATA_NEW_EXTRADATA, + &extradata_size); + + if (extradata) { + i->avctx->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!i->avctx->extradata) { + av_packet_unref(pkt_ref); + return AVERROR(ENOMEM); + } + memcpy(i->avctx->extradata, extradata, extradata_size); + i->avctx->extradata_size = extradata_size; + } + av_packet_unref(pkt_ref); + } + return 0; } @@ -2202,108 +2201,138 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) { int i, count, ret, read_size, j; AVStream *st; + AVCodecContext *avctx; 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 + int64_t old_offset = avio_tell(ic->pb); + // new streams might appear, no options for those + int orig_nb_streams = ic->nb_streams; - for(i=0;inb_streams;i++) { + for (i = 0; i < ic->nb_streams; i++) { const AVCodec *codec; AVDictionary *thread_opt = NULL; st = ic->streams[i]; + avctx = st->internal->avctx; - //only for the split stuff + // only for the split stuff if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE)) { - st->parser = av_parser_init(st->codec->codec_id); - if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){ + st->parser = av_parser_init(st->codecpar->codec_id); + if (st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser) st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - } } - codec = st->codec->codec ? st->codec->codec : - avcodec_find_decoder(st->codec->codec_id); - /* force thread count to 1 since the h264 decoder will not extract SPS - * and PPS to extradata during multi-threaded decoding */ + /* check if the caller has overridden the codec id */ +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + if (st->codec->codec_id != st->internal->orig_codec_id) { + st->codecpar->codec_id = st->codec->codec_id; + st->codecpar->codec_type = st->codec->codec_type; + st->internal->orig_codec_id = st->codec->codec_id; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (st->codecpar->codec_id != st->internal->orig_codec_id) + st->internal->orig_codec_id = st->codecpar->codec_id; + + ret = avcodec_parameters_to_context(avctx, st->codecpar); + if (ret < 0) + goto find_stream_info_err; + if (st->codecpar->codec_id != AV_CODEC_ID_PROBE && + st->codecpar->codec_id != AV_CODEC_ID_NONE) + st->internal->avctx_inited = 1; + +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + codec = st->codec->codec ? st->codec->codec + : avcodec_find_decoder(st->codecpar->codec_id); +FF_ENABLE_DEPRECATION_WARNINGS +#else + codec = avcodec_find_decoder(st->codecpar->codec_id); +#endif + + /* Force thread count to 1 since the H.264 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_open2(st->codec, codec, options ? &options[i] - : &thread_opt); + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE + && codec && !avctx->codec) + avcodec_open2(avctx, codec, + options ? &options[i] : &thread_opt); - //try to just open decoders, in case this is enough to get parameters + // Try to just open decoders, in case this is enough to get parameters. if (!has_codec_parameters(st)) { - if (codec && !st->codec->codec) - avcodec_open2(st->codec, codec, options ? &options[i] - : &thread_opt); + if (codec && !avctx->codec) + avcodec_open2(avctx, codec, + options ? &options[i] : &thread_opt); } if (!options) av_dict_free(&thread_opt); } - for (i=0; inb_streams; i++) { -#if FF_API_R_FRAME_RATE - ic->streams[i]->info->last_dts = AV_NOPTS_VALUE; -#endif + for (i = 0; i < ic->nb_streams; i++) { ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE; ic->streams[i]->info->fps_last_dts = AV_NOPTS_VALUE; } - count = 0; + count = 0; read_size = 0; - for(;;) { - if (ff_check_interrupt(&ic->interrupt_callback)){ - ret= AVERROR_EXIT; + for (;;) { + if (ff_check_interrupt(&ic->interrupt_callback)) { + ret = AVERROR_EXIT; av_log(ic, AV_LOG_DEBUG, "interrupted\n"); break; } /* check if one codec still needs to be handled */ - for(i=0;inb_streams;i++) { + for (i = 0; i < ic->nb_streams; i++) { int fps_analyze_framecount = 20; st = ic->streams[i]; if (!has_codec_parameters(st)) break; - /* if the timebase is coarse (like the usual millisecond precision - of mkv), we need to analyze more frames to reliably arrive at - the correct fps */ + /* If the timebase is coarse (like the usual millisecond precision + * of mkv), we need to analyze more frames to reliably arrive at + * the correct fps. */ if (av_q2d(st->time_base) > 0.0005) fps_analyze_framecount *= 2; if (ic->fps_probe_size >= 0) fps_analyze_framecount = ic->fps_probe_size; /* variable fps and no guess at the real fps */ - if( tb_unreliable(st->codec) && !st->avg_frame_rate.num - && st->codec_info_nb_frames < fps_analyze_framecount - && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (!st->avg_frame_rate.num && + st->codec_info_nb_frames < fps_analyze_framecount && + st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) break; - if(st->parser && st->parser->parser->split && !st->codec->extradata) + if (!st->codecpar->extradata && + !st->internal->avctx->extradata && + (!st->internal->extract_extradata.inited || + st->internal->extract_extradata.bsf)) break; if (st->first_dts == AV_NOPTS_VALUE && - (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || - st->codec->codec_type == AVMEDIA_TYPE_AUDIO)) + st->codec_info_nb_frames < ic->max_ts_probe && + (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)) break; } if (i == ic->nb_streams) { - /* NOTE: if the format has no header, then we need to read - some packets to get most of the streams, so we cannot - stop here */ + /* NOTE: If the format has no header, then we need to read some + * packets to get most of the streams, so we cannot stop here. */ if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) { - /* if we found the info for all the codecs, we can stop */ + /* If we found the info for all the codecs, we can stop. */ ret = count; av_log(ic, AV_LOG_DEBUG, "All info found\n"); break; } } - /* we did not get all the codec info, but we read too much data */ + /* We did not get all the codec info, but we read too much data. */ if (read_size >= ic->probesize) { ret = count; - av_log(ic, AV_LOG_DEBUG, "Probe buffer size limit %d reached\n", ic->probesize); + av_log(ic, AV_LOG_DEBUG, + "Probe buffer size limit %d reached\n", ic->probesize); break; } - /* NOTE: a new stream can be added there if no header in file - (AVFMTCTX_NOHEADER) */ + /* NOTE: A new stream can be added there if no header in file + * (AVFMTCTX_NOHEADER). */ ret = read_frame_internal(ic, &pkt1); if (ret == AVERROR(EAGAIN)) continue; @@ -2314,16 +2343,17 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int err = 0; av_init_packet(&empty_pkt); - ret = -1; /* we could not have all the codec parameters before EOF */ - for(i=0;inb_streams;i++) { + /* We could not have all the codec parameters before EOF. */ + ret = -1; + for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; /* flush the decoders */ if (st->info->found_decoder == 1) { do { - err = try_decode_frame(st, &empty_pkt, - (options && i < orig_nb_streams) ? - &options[i] : NULL); + err = try_decode_frame(ic, st, &empty_pkt, + (options && i < orig_nb_streams) + ? &options[i] : NULL); } while (err > 0 && !has_codec_parameters(st)); } @@ -2332,7 +2362,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) "decoding for stream %d failed\n", st->index); } else if (!has_codec_parameters(st)) { char buf[256]; - avcodec_string(buf, sizeof(buf), st->codec, 0); + avcodec_string(buf, sizeof(buf), st->internal->avctx, 0); av_log(ic, AV_LOG_WARNING, "Could not find codec parameters (%s)\n", buf); } else { @@ -2342,40 +2372,55 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) break; } - if (ic->flags & AVFMT_FLAG_NOBUFFER) { - pkt = &pkt1; - } else { - pkt = add_to_pktbuf(&ic->packet_buffer, &pkt1, - &ic->packet_buffer_end); - if ((ret = av_dup_packet(pkt)) < 0) + pkt = &pkt1; + + if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { + ret = add_to_pktbuf(&ic->internal->packet_buffer, pkt, + &ic->internal->packet_buffer_end, 0); + if (ret < 0) goto find_stream_info_err; } read_size += pkt->size; st = ic->streams[pkt->stream_index]; + avctx = st->internal->avctx; + if (!st->internal->avctx_inited) { + ret = avcodec_parameters_to_context(avctx, st->codecpar); + if (ret < 0) + goto find_stream_info_err; + st->internal->avctx_inited = 1; + } + if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) { /* check for non-increasing dts */ if (st->info->fps_last_dts != AV_NOPTS_VALUE && st->info->fps_last_dts >= pkt->dts) { - av_log(ic, AV_LOG_WARNING, "Non-increasing DTS in stream %d: " - "packet %d with DTS %"PRId64", packet %d with DTS " - "%"PRId64"\n", st->index, st->info->fps_last_dts_idx, - st->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts); - st->info->fps_first_dts = st->info->fps_last_dts = AV_NOPTS_VALUE; + av_log(ic, AV_LOG_WARNING, + "Non-increasing DTS in stream %d: packet %d with DTS " + "%"PRId64", packet %d with DTS %"PRId64"\n", + st->index, st->info->fps_last_dts_idx, + st->info->fps_last_dts, st->codec_info_nb_frames, + pkt->dts); + st->info->fps_first_dts = + st->info->fps_last_dts = AV_NOPTS_VALUE; } - /* check for a discontinuity in dts - if the difference in dts - * is more than 1000 times the average packet duration in the sequence, - * we treat it as a discontinuity */ + /* Check for a discontinuity in dts. If the difference in dts + * is more than 1000 times the average packet duration in the + * sequence, we treat it as a discontinuity. */ if (st->info->fps_last_dts != AV_NOPTS_VALUE && st->info->fps_last_dts_idx > st->info->fps_first_dts_idx && (pkt->dts - st->info->fps_last_dts) / 1000 > - (st->info->fps_last_dts - st->info->fps_first_dts) / (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) { - av_log(ic, AV_LOG_WARNING, "DTS discontinuity in stream %d: " - "packet %d with DTS %"PRId64", packet %d with DTS " - "%"PRId64"\n", st->index, st->info->fps_last_dts_idx, - st->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts); - st->info->fps_first_dts = st->info->fps_last_dts = AV_NOPTS_VALUE; + (st->info->fps_last_dts - st->info->fps_first_dts) / + (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) { + av_log(ic, AV_LOG_WARNING, + "DTS discontinuity in stream %d: packet %d with DTS " + "%"PRId64", packet %d with DTS %"PRId64"\n", + st->index, st->info->fps_last_dts_idx, + st->info->fps_last_dts, st->codec_info_nb_frames, + pkt->dts); + st->info->fps_first_dts = + st->info->fps_last_dts = AV_NOPTS_VALUE; } /* update stored dts values */ @@ -2383,155 +2428,147 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) st->info->fps_first_dts = pkt->dts; st->info->fps_first_dts_idx = st->codec_info_nb_frames; } - st->info->fps_last_dts = pkt->dts; + st->info->fps_last_dts = pkt->dts; st->info->fps_last_dts_idx = st->codec_info_nb_frames; /* check max_analyze_duration */ if (av_rescale_q(pkt->dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) { - av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n"); + av_log(ic, AV_LOG_WARNING, "max_analyze_duration %d reached\n", + ic->max_analyze_duration); + if (ic->flags & AVFMT_FLAG_NOBUFFER) + av_packet_unref(pkt); break; } } -#if FF_API_R_FRAME_RATE - { - int64_t last = st->info->last_dts; - - if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last){ - int64_t duration= pkt->dts - last; - double dur= duration * av_q2d(st->time_base); - - if (st->info->duration_count < 2) - memset(st->info->duration_error, 0, sizeof(st->info->duration_error)); - for (i=1; iinfo->duration_error); i++) { - int framerate= get_std_framerate(i); - int ticks= lrintf(dur*framerate/(1001*12)); - double error = dur - (double)ticks*1001*12 / framerate; - st->info->duration_error[i] += error*error; - } - st->info->duration_count++; - // ignore the first 4 values, they might have some random jitter - if (st->info->duration_count > 3) - st->info->duration_gcd = av_gcd(st->info->duration_gcd, duration); - } - if (last == AV_NOPTS_VALUE || st->info->duration_count <= 1) - st->info->last_dts = pkt->dts; - } -#endif - if(st->parser && st->parser->parser->split && !st->codec->extradata){ - int i= st->parser->parser->split(st->codec, pkt->data, pkt->size); - if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) { - st->codec->extradata_size= i; - st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) - 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 (!st->internal->avctx->extradata) { + ret = extract_extradata(st, pkt); + if (ret < 0) + goto find_stream_info_err; } - /* 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 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 AV_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(ic, st, pkt, + (options && i < orig_nb_streams) ? &options[i] : NULL); - 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); + if (ic->flags & AVFMT_FLAG_NOBUFFER) + av_packet_unref(pkt); st->codec_info_nb_frames++; count++; } - // close codecs which were opened in try_decode_frame() - for(i=0;inb_streams;i++) { + for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; - avcodec_close(st->codec); - } - for(i=0;inb_streams;i++) { - st = ic->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + avctx = st->internal->avctx; + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { /* estimate average framerate if not set by demuxer */ - if (!st->avg_frame_rate.num && st->info->fps_last_dts != st->info->fps_first_dts) { - int64_t delta_dts = st->info->fps_last_dts - st->info->fps_first_dts; - int delta_packets = st->info->fps_last_dts_idx - st->info->fps_first_dts_idx; - int best_fps = 0; + if (!st->avg_frame_rate.num && + st->info->fps_last_dts != st->info->fps_first_dts) { + int64_t delta_dts = st->info->fps_last_dts - + st->info->fps_first_dts; + int delta_packets = st->info->fps_last_dts_idx - + st->info->fps_first_dts_idx; + int best_fps = 0; double best_error = 0.01; + if (delta_dts >= INT64_MAX / st->time_base.num || + delta_packets >= INT64_MAX / st->time_base.den || + delta_dts < 0) + continue; av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, - delta_packets*(int64_t)st->time_base.den, - delta_dts*(int64_t)st->time_base.num, 60000); + delta_packets * (int64_t) st->time_base.den, + delta_dts * (int64_t) st->time_base.num, 60000); - /* round guessed framerate to a "standard" framerate if it's - * within 1% of the original estimate*/ - for (j = 1; j < MAX_STD_TIMEBASES; j++) { - AVRational std_fps = { get_std_framerate(j), 12*1001 }; - double error = fabs(av_q2d(st->avg_frame_rate) / av_q2d(std_fps) - 1); + /* Round guessed framerate to a "standard" framerate if it's + * within 1% of the original estimate. */ + for (j = 0; j < MAX_STD_TIMEBASES; j++) { + AVRational std_fps = { get_std_framerate(j), 12 * 1001 }; + double error = fabs(av_q2d(st->avg_frame_rate) / + av_q2d(std_fps) - 1); if (error < best_error) { best_error = error; best_fps = std_fps.num; } } - if (best_fps) { + if (best_fps) av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, - best_fps, 12*1001, INT_MAX); - } + best_fps, 12 * 1001, INT_MAX); } -#if FF_API_R_FRAME_RATE - // the check for tb_unreliable() is not completely correct, since this is not about handling - // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g. - // ipmovie.c produces. - if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > 1 && !st->r_frame_rate.num) - av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX); - if (st->info->duration_count && !st->r_frame_rate.num - && tb_unreliable(st->codec)) { - int num = 0; - double best_error= 2*av_q2d(st->time_base); - best_error = best_error*best_error*st->info->duration_count*1000*12*30; - - for (j=1; jinfo->duration_error); j++) { - double error = st->info->duration_error[j] * get_std_framerate(j); - if(error < best_error){ - best_error= error; - num = get_std_framerate(j); - } - } - // do not increase frame rate by more than 1 % in order to match a standard rate. - if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate))) - av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX); - } -#endif - }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); + } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + if (!avctx->bits_per_coded_sample) + avctx->bits_per_coded_sample = + av_get_bits_per_sample(avctx->codec_id); // set stream disposition based on audio service type - switch (st->codec->audio_service_type) { + switch (avctx->audio_service_type) { case AV_AUDIO_SERVICE_TYPE_EFFECTS: - st->disposition = AV_DISPOSITION_CLEAN_EFFECTS; break; + st->disposition = AV_DISPOSITION_CLEAN_EFFECTS; + break; case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED: - st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED; break; + st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED; + break; case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED: - st->disposition = AV_DISPOSITION_HEARING_IMPAIRED; break; + st->disposition = AV_DISPOSITION_HEARING_IMPAIRED; + break; case AV_AUDIO_SERVICE_TYPE_COMMENTARY: - st->disposition = AV_DISPOSITION_COMMENT; break; + st->disposition = AV_DISPOSITION_COMMENT; + break; case AV_AUDIO_SERVICE_TYPE_KARAOKE: - st->disposition = AV_DISPOSITION_KARAOKE; break; + st->disposition = AV_DISPOSITION_KARAOKE; + break; } } } - estimate_timings(ic, old_offset); - compute_chapters_end(ic); - find_stream_info_err: - for (i=0; i < ic->nb_streams; i++) { - if (ic->streams[i]->codec) - ic->streams[i]->codec->thread_count = 0; + /* update the stream parameters from the internal codec contexts */ + for (i = 0; i < ic->nb_streams; i++) { + st = ic->streams[i]; + if (!st->internal->avctx_inited) + continue; + + ret = avcodec_parameters_from_context(st->codecpar, st->internal->avctx); + if (ret < 0) + goto find_stream_info_err; + +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + ret = avcodec_parameters_to_context(st->codec, st->codecpar); + if (ret < 0) + goto find_stream_info_err; + + if (st->internal->avctx->subtitle_header) { + st->codec->subtitle_header = av_malloc(st->internal->avctx->subtitle_header_size); + if (!st->codec->subtitle_header) + goto find_stream_info_err; + st->codec->subtitle_header_size = st->internal->avctx->subtitle_header_size; + memcpy(st->codec->subtitle_header, st->internal->avctx->subtitle_header, + st->codec->subtitle_header_size); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + st->internal->avctx_inited = 0; + } + + estimate_timings(ic, old_offset); + +find_stream_info_err: + for (i = 0; i < ic->nb_streams; i++) { + avcodec_close(ic->streams[i]->internal->avctx); av_freep(&ic->streams[i]->info); + av_bsf_free(&ic->streams[i]->internal->extract_extradata.bsf); + av_packet_free(&ic->streams[i]->internal->extract_extradata.pkt); } return ret; } @@ -2547,12 +2584,9 @@ static AVProgram *find_program_from_stream(AVFormatContext *ic, int s) return NULL; } -int av_find_best_stream(AVFormatContext *ic, - enum AVMediaType type, - int wanted_stream_nb, - int related_stream, - AVCodec **decoder_ret, - int flags) +int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, + int wanted_stream_nb, int related_stream, + AVCodec **decoder_ret, int flags) { int i, nb_streams = ic->nb_streams; int ret = AVERROR_STREAM_NOT_FOUND, best_count = -1; @@ -2562,22 +2596,23 @@ int av_find_best_stream(AVFormatContext *ic, if (related_stream >= 0 && wanted_stream_nb < 0) { AVProgram *p = find_program_from_stream(ic, related_stream); if (p) { - program = p->stream_index; + program = p->stream_index; nb_streams = p->nb_stream_indexes; } } for (i = 0; i < nb_streams; i++) { int real_stream_index = program ? program[i] : i; - AVStream *st = ic->streams[real_stream_index]; - AVCodecContext *avctx = st->codec; - if (avctx->codec_type != type) + AVStream *st = ic->streams[real_stream_index]; + AVCodecParameters *par = st->codecpar; + if (par->codec_type != type) continue; if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb) continue; - if (st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED|AV_DISPOSITION_VISUAL_IMPAIRED)) + if (st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED | + AV_DISPOSITION_VISUAL_IMPAIRED)) continue; if (decoder_ret) { - decoder = avcodec_find_decoder(st->codec->codec_id); + decoder = avcodec_find_decoder(par->codec_id); if (!decoder) { if (ret < 0) ret = AVERROR_DECODER_NOT_FOUND; @@ -2586,13 +2621,14 @@ int av_find_best_stream(AVFormatContext *ic, } if (best_count >= st->codec_info_nb_frames) continue; - best_count = st->codec_info_nb_frames; - ret = real_stream_index; + best_count = st->codec_info_nb_frames; + ret = real_stream_index; best_decoder = decoder; if (program && i == nb_streams - 1 && ret < 0) { - program = NULL; + program = NULL; nb_streams = ic->nb_streams; - i = 0; /* no related stream found, try again with everything */ + /* no related stream found, try again with everything */ + i = 0; } } if (decoder_ret) @@ -2620,60 +2656,89 @@ int av_read_pause(AVFormatContext *s) return AVERROR(ENOSYS); } +static void free_stream(AVStream **pst) +{ + AVStream *st = *pst; + int i; + + if (!st) + return; + + for (i = 0; i < st->nb_side_data; i++) + av_freep(&st->side_data[i].data); + av_freep(&st->side_data); + + if (st->parser) + av_parser_close(st->parser); + + if (st->attached_pic.data) + av_packet_unref(&st->attached_pic); + + if (st->internal) { + avcodec_free_context(&st->internal->avctx); + av_bsf_free(&st->internal->extract_extradata.bsf); + av_packet_free(&st->internal->extract_extradata.pkt); + } + av_freep(&st->internal); + + av_dict_free(&st->metadata); + avcodec_parameters_free(&st->codecpar); + av_freep(&st->probe_data.buf); + av_free(st->index_entries); +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + av_free(st->codec->extradata); + av_free(st->codec->subtitle_header); + av_free(st->codec); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + av_free(st->priv_data); + av_free(st->info); + + av_freep(pst); +} + void avformat_free_context(AVFormatContext *s) { int i; - AVStream *st; + + if (!s) + return; av_opt_free(s); if (s->iformat && s->iformat->priv_class && s->priv_data) av_opt_free(s->priv_data); - for(i=0;inb_streams;i++) { - /* free all data in a stream component */ - st = s->streams[i]; - if (st->parser) { - av_parser_close(st->parser); - } - if (st->attached_pic.data) - av_free_packet(&st->attached_pic); - av_dict_free(&st->metadata); - av_free(st->index_entries); - av_free(st->codec->extradata); - av_free(st->codec->subtitle_header); - av_free(st->codec); - av_free(st->priv_data); - av_free(st->info); - av_free(st); - } - for(i=s->nb_programs-1; i>=0; i--) { + for (i = 0; i < s->nb_streams; i++) + free_stream(&s->streams[i]); + + for (i = s->nb_programs - 1; i >= 0; i--) { av_dict_free(&s->programs[i]->metadata); av_freep(&s->programs[i]->stream_index); av_freep(&s->programs[i]); } av_freep(&s->programs); av_freep(&s->priv_data); - while(s->nb_chapters--) { + while (s->nb_chapters--) { av_dict_free(&s->chapters[s->nb_chapters]->metadata); av_free(s->chapters[s->nb_chapters]); } av_freep(&s->chapters); av_dict_free(&s->metadata); av_freep(&s->streams); + av_freep(&s->internal); 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->pb; + AVIOContext *pb; + + if (!*ps) + return; + + pb = s->pb; if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) || (s->flags & AVFMT_FLAG_CUSTOM_IO)) @@ -2681,10 +2746,9 @@ void avformat_close_input(AVFormatContext **ps) flush_packet_queue(s); - if (s->iformat) { + if (s->iformat) if (s->iformat->read_close) s->iformat->read_close(s); - } avformat_free_context(s); @@ -2693,18 +2757,16 @@ void avformat_close_input(AVFormatContext **ps) avio_close(pb); } -AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) +AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) { AVStream *st; int i; - AVStream **streams; - if (s->nb_streams >= INT_MAX/sizeof(*streams)) + if (av_reallocp_array(&s->streams, s->nb_streams + 1, + sizeof(*s->streams)) < 0) { + s->nb_streams = 0; return NULL; - streams = av_realloc(s->streams, (s->nb_streams + 1) * sizeof(*streams)); - if (!streams) - return NULL; - s->streams = streams; + } st = av_mallocz(sizeof(AVStream)); if (!st) @@ -2714,53 +2776,86 @@ AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) return NULL; } +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS st->codec = avcodec_alloc_context3(c); + if (!st->codec) { + av_free(st->info); + av_free(st); + return NULL; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + st->internal = av_mallocz(sizeof(*st->internal)); + if (!st->internal) + goto fail; + if (s->iformat) { +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS /* no default bitrate if decoding */ st->codec->bit_rate = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + /* default pts setting is MPEG-like */ + avpriv_set_pts_info(st, 33, 1, 90000); + /* we set the current DTS to 0 so that formats without any timestamps + * but durations get some timestamps, formats with some unknown + * timestamps have their first few packets buffered and the + * timestamps corrected before they are returned to the user */ + st->cur_dts = 0; + } else { + st->cur_dts = AV_NOPTS_VALUE; } - st->index = s->nb_streams; + + st->codecpar = avcodec_parameters_alloc(); + if (!st->codecpar) + goto fail; + + st->internal->avctx = avcodec_alloc_context3(NULL); + if (!st->internal->avctx) + goto fail; + + st->index = s->nb_streams; st->start_time = AV_NOPTS_VALUE; - st->duration = AV_NOPTS_VALUE; - /* we set the current DTS to 0 so that formats without any timestamps - but durations get some timestamps, formats with some unknown - timestamps have their first few packets buffered and the - timestamps corrected before they are returned to the user */ - st->cur_dts = 0; - st->first_dts = AV_NOPTS_VALUE; + st->duration = AV_NOPTS_VALUE; + st->first_dts = AV_NOPTS_VALUE; st->probe_packets = MAX_PROBE_PACKETS; - /* default pts setting is MPEG-like */ - avpriv_set_pts_info(st, 33, 1, 90000); st->last_IP_pts = AV_NOPTS_VALUE; - for(i=0; ipts_buffer[i]= AV_NOPTS_VALUE; - st->reference_dts = AV_NOPTS_VALUE; + for (i = 0; i < MAX_REORDER_DELAY + 1; i++) + st->pts_buffer[i] = AV_NOPTS_VALUE; - st->sample_aspect_ratio = (AVRational){0,1}; + st->sample_aspect_ratio = (AVRational) { 0, 1 }; -#if FF_API_R_FRAME_RATE - st->info->last_dts = AV_NOPTS_VALUE; -#endif st->info->fps_first_dts = AV_NOPTS_VALUE; st->info->fps_last_dts = AV_NOPTS_VALUE; +#if FF_API_LAVF_AVCTX + st->internal->need_codec_update = 1; +#endif + s->streams[s->nb_streams++] = st; return st; +fail: + free_stream(&st); + return NULL; } AVProgram *av_new_program(AVFormatContext *ac, int id) { - AVProgram *program=NULL; + AVProgram *program = NULL; int i; - av_dlog(ac, "new_program: id=0x%04x\n", id); + av_log(ac, AV_LOG_TRACE, "new_program: id=0x%04x\n", id); - for(i=0; inb_programs; i++) - if(ac->programs[i]->id == id) + for (i = 0; i < ac->nb_programs; i++) + if (ac->programs[i]->id == id) program = ac->programs[i]; - if(!program){ + if (!program) { program = av_mallocz(sizeof(AVProgram)); if (!program) return NULL; @@ -2772,236 +2867,66 @@ AVProgram *av_new_program(AVFormatContext *ac, int id) return program; } -AVChapter *avpriv_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(i=0; inb_chapters; i++) - if(s->chapters[i]->id == id) + for (i = 0; i < s->nb_chapters; i++) + if (s->chapters[i]->id == id) chapter = s->chapters[i]; - if(!chapter){ - chapter= av_mallocz(sizeof(AVChapter)); - if(!chapter) + if (!chapter) { + chapter = av_mallocz(sizeof(AVChapter)); + if (!chapter) return NULL; dynarray_add(&s->chapters, &s->nb_chapters, chapter); } av_dict_set(&chapter->metadata, "title", title, 0); - chapter->id = id; - chapter->time_base= time_base; - chapter->start = start; - chapter->end = end; + chapter->id = id; + chapter->time_base = time_base; + chapter->start = start; + chapter->end = end; return chapter; } -void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx) +void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned idx) { int i, j; - AVProgram *program=NULL; - void *tmp; + AVProgram *program = NULL; if (idx >= ac->nb_streams) { av_log(ac, AV_LOG_ERROR, "stream index %d is not valid\n", idx); return; } - for(i=0; inb_programs; i++){ - if(ac->programs[i]->id != progid) + for (i = 0; i < ac->nb_programs; i++) { + if (ac->programs[i]->id != progid) continue; program = ac->programs[i]; - for(j=0; jnb_stream_indexes; j++) - if(program->stream_index[j] == idx) + for (j = 0; j < program->nb_stream_indexes; j++) + if (program->stream_index[j] == idx) return; - tmp = av_realloc(program->stream_index, sizeof(unsigned int)*(program->nb_stream_indexes+1)); - if(!tmp) + if (av_reallocp_array(&program->stream_index, + program->nb_stream_indexes + 1, + sizeof(*program->stream_index)) < 0) { + program->nb_stream_indexes = 0; return; - program->stream_index = tmp; + } program->stream_index[program->nb_stream_indexes++] = idx; return; } } -static void print_fps(double d, const char *postfix){ - uint64_t v= lrintf(d*100); - if (v% 100 ) av_log(NULL, AV_LOG_INFO, ", %3.2f %s", d, postfix); - else if(v%(100*1000)) av_log(NULL, AV_LOG_INFO, ", %1.0f %s", d, postfix); - else av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d/1000, postfix); -} - -static void dump_metadata(void *ctx, AVDictionary *m, const char *indent) -{ - if(m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", NULL, 0))){ - AVDictionaryEntry *tag=NULL; - - av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent); - while((tag=av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) { - if(strcmp("language", tag->key)) - av_log(ctx, AV_LOG_INFO, "%s %-16s: %s\n", indent, tag->key, tag->value); - } - } -} - -/* "user interface" functions */ -static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) -{ - char buf[256]; - int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); - AVStream *st = ic->streams[i]; - int g = av_gcd(st->time_base.num, st->time_base.den); - AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); - 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 */ - /* XXX: add a generic system */ - if (flags & AVFMT_SHOW_IDS) - av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id); - if (lang) - av_log(NULL, AV_LOG_INFO, "(%s)", lang->value); - av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames, 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 == AVMEDIA_TYPE_VIDEO){ - if(st->avg_frame_rate.den && st->avg_frame_rate.num) - print_fps(av_q2d(st->avg_frame_rate), "fps"); -#if FF_API_R_FRAME_RATE - if(st->r_frame_rate.den && st->r_frame_rate.num) - print_fps(av_q2d(st->r_frame_rate), "tbr"); -#endif - if(st->time_base.den && st->time_base.num) - print_fps(1/av_q2d(st->time_base), "tbn"); - if(st->codec->time_base.den && st->codec->time_base.num) - print_fps(1/av_q2d(st->codec->time_base), "tbc"); - } - if (st->disposition & AV_DISPOSITION_DEFAULT) - av_log(NULL, AV_LOG_INFO, " (default)"); - if (st->disposition & AV_DISPOSITION_DUB) - av_log(NULL, AV_LOG_INFO, " (dub)"); - if (st->disposition & AV_DISPOSITION_ORIGINAL) - av_log(NULL, AV_LOG_INFO, " (original)"); - if (st->disposition & AV_DISPOSITION_COMMENT) - av_log(NULL, AV_LOG_INFO, " (comment)"); - if (st->disposition & AV_DISPOSITION_LYRICS) - av_log(NULL, AV_LOG_INFO, " (lyrics)"); - if (st->disposition & AV_DISPOSITION_KARAOKE) - av_log(NULL, AV_LOG_INFO, " (karaoke)"); - if (st->disposition & AV_DISPOSITION_FORCED) - av_log(NULL, AV_LOG_INFO, " (forced)"); - if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) - av_log(NULL, AV_LOG_INFO, " (hearing impaired)"); - if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED) - av_log(NULL, AV_LOG_INFO, " (visual impaired)"); - if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS) - av_log(NULL, AV_LOG_INFO, " (clean effects)"); - av_log(NULL, AV_LOG_INFO, "\n"); - dump_metadata(NULL, st->metadata, " "); -} - -void av_dump_format(AVFormatContext *ic, - int index, - const char *url, - int is_output) -{ - int i; - uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL; - if (ic->nb_streams && !printed) - return; - - av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n", - is_output ? "Output" : "Input", - index, - is_output ? ic->oformat->name : ic->iformat->name, - is_output ? "to" : "from", url); - dump_metadata(NULL, ic->metadata, " "); - if (!is_output) { - av_log(NULL, AV_LOG_INFO, " Duration: "); - if (ic->duration != AV_NOPTS_VALUE) { - int hours, mins, secs, us; - secs = ic->duration / AV_TIME_BASE; - us = ic->duration % AV_TIME_BASE; - mins = secs / 60; - secs %= 60; - hours = mins / 60; - mins %= 60; - av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%02d", hours, mins, secs, - (100 * us) / AV_TIME_BASE); - } else { - av_log(NULL, AV_LOG_INFO, "N/A"); - } - if (ic->start_time != AV_NOPTS_VALUE) { - int secs, us; - av_log(NULL, AV_LOG_INFO, ", start: "); - secs = ic->start_time / AV_TIME_BASE; - us = abs(ic->start_time % AV_TIME_BASE); - av_log(NULL, AV_LOG_INFO, "%d.%06d", - secs, (int)av_rescale(us, 1000000, AV_TIME_BASE)); - } - av_log(NULL, AV_LOG_INFO, ", bitrate: "); - if (ic->bit_rate) { - av_log(NULL, AV_LOG_INFO,"%d kb/s", ic->bit_rate / 1000); - } else { - av_log(NULL, AV_LOG_INFO, "N/A"); - } - av_log(NULL, AV_LOG_INFO, "\n"); - } - for (i = 0; i < ic->nb_chapters; i++) { - AVChapter *ch = ic->chapters[i]; - av_log(NULL, AV_LOG_INFO, " Chapter #%d.%d: ", index, i); - av_log(NULL, AV_LOG_INFO, "start %f, ", ch->start * av_q2d(ch->time_base)); - av_log(NULL, AV_LOG_INFO, "end %f\n", ch->end * av_q2d(ch->time_base)); - - dump_metadata(NULL, ch->metadata, " "); - } - if(ic->nb_programs) { - int j, k, total = 0; - for(j=0; jnb_programs; j++) { - AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata, - "name", NULL, 0); - av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id, - name ? name->value : ""); - dump_metadata(NULL, ic->programs[j]->metadata, " "); - for(k=0; kprograms[j]->nb_stream_indexes; k++) { - dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output); - printed[ic->programs[j]->stream_index[k]] = 1; - } - total += ic->programs[j]->nb_stream_indexes; - } - if (total < ic->nb_streams) - av_log(NULL, AV_LOG_INFO, " No Program\n"); - } - for(i=0;inb_streams;i++) - if (!printed[i]) - dump_stream_format(ic, i, index, is_output); - - av_free(printed); -} - -#if FF_API_AV_GETTIME && CONFIG_SHARED && HAVE_SYMVER -FF_SYMVER(int64_t, av_gettime, (void), "LIBAVFORMAT_54") -{ - return av_gettime(); -} -#endif - uint64_t ff_ntp_time(void) { - return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; + return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; } -int av_get_frame_filename(char *buf, int buf_size, - const char *path, int number) +int av_get_frame_filename(char *buf, int buf_size, const char *path, int number) { const char *p; char *q, buf1[20], c; @@ -3010,20 +2935,19 @@ int av_get_frame_filename(char *buf, int buf_size, q = buf; p = path; percentd_found = 0; - for(;;) { + for (;;) { c = *p++; if (c == '\0') break; if (c == '%') { do { nd = 0; - while (isdigit(*p)) { + while (av_isdigit(*p)) nd = nd * 10 + *p++ - '0'; - } c = *p++; - } while (isdigit(c)); + } while (av_isdigit(c)); - switch(c) { + switch (c) { case '%': goto addchar; case 'd': @@ -3041,7 +2965,7 @@ int av_get_frame_filename(char *buf, int buf_size, goto fail; } } else { - addchar: +addchar: if ((q - buf) < buf_size - 1) *q++ = c; } @@ -3050,109 +2974,37 @@ int av_get_frame_filename(char *buf, int buf_size, goto fail; *q = '\0'; return 0; - fail: +fail: *q = '\0'; return -1; } -static void hex_dump_internal(void *avcl, FILE *f, int level, - const uint8_t *buf, int size) -{ - int len, i, j, c; -#undef fprintf -#define PRINT(...) do { if (!f) av_log(avcl, level, __VA_ARGS__); else fprintf(f, __VA_ARGS__); } while(0) - - for(i=0;i 16) - len = 16; - PRINT("%08x ", i); - for(j=0;j<16;j++) { - if (j < len) - PRINT(" %02x", buf[i+j]); - else - PRINT(" "); - } - PRINT(" "); - for(j=0;j '~') - c = '.'; - PRINT("%c", c); - } - PRINT("\n"); - } -#undef PRINT -} - -void av_hex_dump(FILE *f, const uint8_t *buf, int size) -{ - hex_dump_internal(NULL, f, 0, buf, size); -} - -void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size) -{ - hex_dump_internal(avcl, NULL, level, buf, size); -} - -static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int dump_payload, AVRational time_base) -{ -#undef fprintf -#define PRINT(...) do { if (!f) av_log(avcl, level, __VA_ARGS__); else fprintf(f, __VA_ARGS__); } while(0) - PRINT("stream #%d:\n", pkt->stream_index); - PRINT(" keyframe=%d\n", ((pkt->flags & AV_PKT_FLAG_KEY) != 0)); - PRINT(" duration=%0.3f\n", pkt->duration * av_q2d(time_base)); - /* DTS is _always_ valid after av_read_frame() */ - PRINT(" dts="); - if (pkt->dts == AV_NOPTS_VALUE) - PRINT("N/A"); - else - PRINT("%0.3f", pkt->dts * av_q2d(time_base)); - /* PTS may not be known if B-frames are present. */ - PRINT(" pts="); - if (pkt->pts == AV_NOPTS_VALUE) - PRINT("N/A"); - else - PRINT("%0.3f", pkt->pts * av_q2d(time_base)); - PRINT("\n"); - PRINT(" size=%d\n", pkt->size); -#undef PRINT - if (dump_payload) - av_hex_dump(f, pkt->data, pkt->size); -} - -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); -} - -void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload, - AVStream *st) -{ - pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, st->time_base); -} - void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, - int *port_ptr, - char *path, int path_size, - const char *url) + int *port_ptr, char *path, int path_size, const char *url) { const char *p, *ls, *at, *col, *brk; - if (port_ptr) *port_ptr = -1; - if (proto_size > 0) proto[0] = 0; - if (authorization_size > 0) authorization[0] = 0; - if (hostname_size > 0) hostname[0] = 0; - if (path_size > 0) path[0] = 0; + if (port_ptr) + *port_ptr = -1; + if (proto_size > 0) + proto[0] = 0; + if (authorization_size > 0) + authorization[0] = 0; + if (hostname_size > 0) + hostname[0] = 0; + if (path_size > 0) + path[0] = 0; /* parse protocol */ if ((p = strchr(url, ':'))) { av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url)); p++; /* skip ':' */ - if (*p == '/') p++; - if (*p == '/') p++; + if (*p == '/') + p++; + if (*p == '/') + p++; } else { /* no protocol means plain filename */ av_strlcpy(path, url, path_size); @@ -3161,12 +3013,12 @@ void av_url_split(char *proto, int proto_size, /* separate path from hostname */ ls = strchr(p, '/'); - if(!ls) + if (!ls) ls = strchr(p, '?'); - if(ls) + if (ls) av_strlcpy(path, ls, path_size); else - ls = &p[strlen(p)]; // XXX + ls = &p[strlen(p)]; // XXX /* the rest is hostname, use that to parse auth/port */ if (ls != p) { @@ -3186,7 +3038,8 @@ void av_url_split(char *proto, int proto_size, } else if ((col = strchr(p, ':')) && col < ls) { av_strlcpy(hostname, p, FFMIN(col + 1 - p, hostname_size)); - if (port_ptr) *port_ptr = atoi(col + 1); + if (port_ptr) + *port_ptr = atoi(col + 1); } else av_strlcpy(hostname, p, FFMIN(ls + 1 - p, hostname_size)); @@ -3206,7 +3059,7 @@ char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase) 'c', 'd', 'e', 'f' }; const char *hex_table = lowercase ? hex_table_lc : hex_table_uc; - for(i = 0; i < s; i++) { + for (i = 0; i < s; i++) { buff[i * 2] = hex_table[src[i] >> 4]; buff[i * 2 + 1] = hex_table[src[i] & 0xF]; } @@ -3219,12 +3072,12 @@ int ff_hex_to_data(uint8_t *data, const char *p) int c, len, v; len = 0; - v = 1; + v = 1; for (;;) { p += strspn(p, SPACE_CHARS); if (*p == '\0') break; - c = toupper((unsigned char) *p++); + c = av_toupper((unsigned char) *p++); if (c >= '0' && c <= '9') c = c - '0'; else if (c >= 'A' && c <= 'F') @@ -3246,80 +3099,23 @@ void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den) { AVRational new_tb; - if(av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)){ - if(new_tb.num != pts_num) - av_log(NULL, AV_LOG_DEBUG, "st:%d removing common factor %d from timebase\n", s->index, pts_num/new_tb.num); - }else - av_log(NULL, AV_LOG_WARNING, "st:%d has too large timebase, reducing\n", s->index); - - if(new_tb.num <= 0 || new_tb.den <= 0) { - av_log(NULL, AV_LOG_ERROR, "Ignoring attempt to set invalid timebase for st:%d\n", s->index); - return; - } - s->time_base = new_tb; - s->pts_wrap_bits = pts_wrap_bits; -} - -int ff_url_join(char *str, int size, const char *proto, - const char *authorization, const char *hostname, - int port, const char *fmt, ...) -{ -#if CONFIG_NETWORK - struct addrinfo hints = { 0 }, *ai; -#endif - - str[0] = '\0'; - if (proto) - av_strlcatf(str, size, "%s://", proto); - if (authorization && authorization[0]) - av_strlcatf(str, size, "%s@", authorization); -#if CONFIG_NETWORK && defined(AF_INET6) - /* Determine if hostname is a numerical IPv6 address, - * properly escape it within [] in that case. */ - hints.ai_flags = AI_NUMERICHOST; - if (!getaddrinfo(hostname, NULL, &hints, &ai)) { - if (ai->ai_family == AF_INET6) { - av_strlcat(str, "[", size); - av_strlcat(str, hostname, size); - av_strlcat(str, "]", size); - } else { - av_strlcat(str, hostname, size); - } - freeaddrinfo(ai); + if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) { + if (new_tb.num != pts_num) + av_log(NULL, AV_LOG_DEBUG, + "st:%d removing common factor %d from timebase\n", + s->index, pts_num / new_tb.num); } else -#endif - /* Not an IPv6 address, just output the plain string. */ - av_strlcat(str, hostname, size); - - if (port >= 0) - av_strlcatf(str, size, ":%d", port); - if (fmt) { - va_list vl; - int len = strlen(str); + av_log(NULL, AV_LOG_WARNING, + "st:%d has too large timebase, reducing\n", s->index); - va_start(vl, fmt); - vsnprintf(str + len, size > len ? size - len : 0, fmt, vl); - va_end(vl); + if (new_tb.num <= 0 || new_tb.den <= 0) { + av_log(NULL, AV_LOG_ERROR, + "Ignoring attempt to set invalid timebase for st:%d\n", + s->index); + return; } - return strlen(str); -} - -int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, - AVFormatContext *src) -{ - AVPacket local_pkt; - - local_pkt = *pkt; - local_pkt.stream_index = dst_stream; - if (pkt->pts != AV_NOPTS_VALUE) - local_pkt.pts = av_rescale_q(pkt->pts, - src->streams[pkt->stream_index]->time_base, - dst->streams[dst_stream]->time_base); - if (pkt->dts != AV_NOPTS_VALUE) - local_pkt.dts = av_rescale_q(pkt->dts, - src->streams[pkt->stream_index]->time_base, - dst->streams[dst_stream]->time_base); - return av_write_frame(dst, &local_pkt); + s->time_base = new_tb; + s->pts_wrap_bits = pts_wrap_bits; } void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, @@ -3334,7 +3130,7 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, int key_len, dest_len = 0; /* Skip whitespace and potential commas. */ - while (*ptr && (isspace(*ptr) || *ptr == ',')) + while (*ptr && (av_isspace(*ptr) || *ptr == ',')) ptr++; if (!*ptr) break; @@ -3367,7 +3163,7 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, if (*ptr == '\"') ptr++; } else { - for (; *ptr && !(isspace(*ptr) || *ptr == ','); ptr++) + for (; *ptr && !(av_isspace(*ptr) || *ptr == ','); ptr++) if (dest && dest < dest_end) *dest++ = *ptr; } @@ -3379,90 +3175,34 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, int ff_find_stream_index(AVFormatContext *s, int id) { int i; - for (i = 0; i < s->nb_streams; i++) { + for (i = 0; i < s->nb_streams; i++) if (s->streams[i]->id == id) return i; - } return -1; } -void ff_make_absolute_url(char *buf, int size, const char *base, - const char *rel) -{ - char *sep; - /* Absolute path, relative to the current server */ - if (base && strstr(base, "://") && rel[0] == '/') { - if (base != buf) - av_strlcpy(buf, base, size); - sep = strstr(buf, "://"); - if (sep) { - sep += 3; - sep = strchr(sep, '/'); - if (sep) - *sep = '\0'; - } - av_strlcat(buf, rel, size); - return; - } - /* If rel actually is an absolute url, just copy it */ - if (!base || strstr(rel, "://") || rel[0] == '/') { - av_strlcpy(buf, rel, size); - return; - } - if (base != buf) - av_strlcpy(buf, base, size); - /* Remove the file name from the base url */ - sep = strrchr(buf, '/'); - if (sep) - sep[1] = '\0'; - else - buf[0] = '\0'; - while (av_strstart(rel, "../", NULL) && sep) { - /* Remove the path delimiter at the end */ - sep[0] = '\0'; - sep = strrchr(buf, '/'); - /* If the next directory name to pop off is "..", break here */ - if (!strcmp(sep ? &sep[1] : buf, "..")) { - /* Readd the slash we just removed */ - av_strlcat(buf, "/", size); - break; - } - /* Cut off the directory name */ - if (sep) - sep[1] = '\0'; - else - buf[0] = '\0'; - rel += 3; - } - av_strlcat(buf, rel, size); -} - int64_t ff_iso8601_to_unix_time(const char *datestr) { -#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); + struct tm time1 = { 0 }, time2 = { 0 }; + const char *ret1, *ret2; + ret1 = av_small_strptime(datestr, "%Y - %m - %d %T", &time1); + ret2 = av_small_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 AVCodecID codec_id, int std_compliance) +int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID 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 || + else if (codec_id == ofmt->video_codec || + codec_id == ofmt->audio_codec || codec_id == ofmt->subtitle_codec) return 1; } @@ -3500,19 +3240,19 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels, if (!pkt) return AVERROR(EINVAL); if (channels) { - size += 4; + size += 4; flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT; } if (channel_layout) { - size += 8; + size += 8; flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT; } if (sample_rate) { - size += 4; + size += 4; flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE; } if (width || height) { - size += 8; + size += 8; flags |= AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS; } data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size); @@ -3532,11 +3272,180 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels, return 0; } -const struct AVCodecTag *avformat_get_riff_video_tags(void) +int ff_generate_avci_extradata(AVStream *st) +{ + static const uint8_t avci100_1080p_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, + 0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63, + 0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19, + 0x18, 0x21, 0x02, 0x56, 0xb9, 0x3d, 0x7d, 0x7e, + 0x4f, 0xe3, 0x3f, 0x11, 0xf1, 0x9e, 0x08, 0xb8, + 0x8c, 0x54, 0x43, 0xc0, 0x78, 0x02, 0x27, 0xe2, + 0x70, 0x1e, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xca, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48, + 0xd0 + }; + static const uint8_t avci100_1080i_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, + 0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63, + 0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19, + 0x18, 0x21, 0x03, 0x3a, 0x46, 0x65, 0x6a, 0x65, + 0x24, 0xad, 0xe9, 0x12, 0x32, 0x14, 0x1a, 0x26, + 0x34, 0xad, 0xa4, 0x41, 0x82, 0x23, 0x01, 0x50, + 0x2b, 0x1a, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2e, + 0x11, 0x12, 0x08, 0xc6, 0x8c, 0x04, 0x41, 0x28, + 0x4c, 0x34, 0xf0, 0x1e, 0x01, 0x13, 0xf2, 0xe0, + 0x3c, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x03, + 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x94, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48, + 0xd0 + }; + static const uint8_t avci50_1080i_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28, + 0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18, + 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c, + 0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6e, 0x61, + 0x87, 0x3e, 0x73, 0x4d, 0x98, 0x0c, 0x03, 0x06, + 0x9c, 0x0b, 0x73, 0xe6, 0xc0, 0xb5, 0x18, 0x63, + 0x0d, 0x39, 0xe0, 0x5b, 0x02, 0xd4, 0xc6, 0x19, + 0x1a, 0x79, 0x8c, 0x32, 0x34, 0x24, 0xf0, 0x16, + 0x81, 0x13, 0xf7, 0xff, 0x80, 0x01, 0x80, 0x02, + 0x71, 0x80, 0x80, 0x80, 0xa0, 0x00, 0x00, 0x03, + 0x00, 0x20, 0x00, 0x00, 0x06, 0x50, 0x80, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12, + 0x11 + }; + static const uint8_t avci100_720p_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, + 0xb6, 0xd4, 0x20, 0x2a, 0x33, 0x1d, 0xc7, 0x62, + 0xa1, 0x08, 0x40, 0x54, 0x66, 0x3b, 0x8e, 0xc5, + 0x42, 0x02, 0x10, 0x25, 0x64, 0x2c, 0x89, 0xe8, + 0x85, 0xe4, 0x21, 0x4b, 0x90, 0x83, 0x06, 0x95, + 0xd1, 0x06, 0x46, 0x97, 0x20, 0xc8, 0xd7, 0x43, + 0x08, 0x11, 0xc2, 0x1e, 0x4c, 0x91, 0x0f, 0x01, + 0x40, 0x16, 0xec, 0x07, 0x8c, 0x04, 0x04, 0x05, + 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, + 0x00, 0x64, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x31, 0x12, + 0x11 + }; + + const uint8_t *data = NULL; + int size = 0; + + if (st->codecpar->width == 1920) { + if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) { + data = avci100_1080p_extradata; + size = sizeof(avci100_1080p_extradata); + } else { + data = avci100_1080i_extradata; + size = sizeof(avci100_1080i_extradata); + } + } else if (st->codecpar->width == 1440) { + data = avci50_1080i_extradata; + size = sizeof(avci50_1080i_extradata); + } else if (st->codecpar->width == 1280) { + data = avci100_720p_extradata; + size = sizeof(avci100_720p_extradata); + } + + if (!size) + return 0; + + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; + st->codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + return AVERROR(ENOMEM); + + memcpy(st->codecpar->extradata, data, size); + st->codecpar->extradata_size = size; + + return 0; +} + +uint8_t *av_stream_get_side_data(AVStream *st, enum AVPacketSideDataType type, + int *size) { - return ff_codec_bmp_tags; + int i; + + for (i = 0; i < st->nb_side_data; i++) { + if (st->side_data[i].type == type) { + if (size) + *size = st->side_data[i].size; + return st->side_data[i].data; + } + } + return NULL; } -const struct AVCodecTag *avformat_get_riff_audio_tags(void) + +int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, + uint8_t *data, size_t size) +{ + AVPacketSideData *sd, *tmp; + int i; + + for (i = 0; i < st->nb_side_data; i++) { + sd = &st->side_data[i]; + + if (sd->type == type) { + av_freep(&sd->data); + sd->data = data; + sd->size = size; + return 0; + } + } + + if ((unsigned) st->nb_side_data + 1 >= INT_MAX / sizeof(*st->side_data)) + return AVERROR(ERANGE); + + tmp = av_realloc(st->side_data, (st->nb_side_data + 1) * sizeof(*tmp)); + if (!tmp) { + return AVERROR(ENOMEM); + } + + st->side_data = tmp; + st->nb_side_data++; + + sd = &st->side_data[st->nb_side_data - 1]; + sd->type = type; + sd->data = data; + sd->size = size; + + return 0; +} + +uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, + int size) +{ + int ret; + uint8_t *data = av_malloc(size); + + if (!data) + return NULL; + + ret = av_stream_add_side_data(st, type, data, size); + if (ret < 0) { + av_freep(&data); + return NULL; + } + + return data; +} + +void ff_format_io_close(AVFormatContext *s, AVIOContext **pb) { - return ff_codec_wav_tags; + if (*pb) + s->io_close(s, *pb); + *pb = NULL; }