diff options
Diffstat (limited to 'lib/ffmpeg/libavformat/utils.c')
-rw-r--r-- | lib/ffmpeg/libavformat/utils.c | 424 |
1 files changed, 314 insertions, 110 deletions
diff --git a/lib/ffmpeg/libavformat/utils.c b/lib/ffmpeg/libavformat/utils.c index 7bc89f816f..e2881bad04 100644 --- a/lib/ffmpeg/libavformat/utils.c +++ b/lib/ffmpeg/libavformat/utils.c @@ -21,8 +21,9 @@ #include "avformat.h" #include "internal.h" #include "libavcodec/internal.h" -#include "libavcodec/opt.h" +#include "libavutil/opt.h" #include "metadata.h" +#include "id3v2.h" #include "libavutil/avstring.h" #include "riff.h" #include "audiointerleave.h" @@ -109,8 +110,14 @@ static void av_frac_add(AVFrac *f, int64_t incr) } /** head of registered input format linked list */ +#if !FF_API_FIRST_FORMAT +static +#endif AVInputFormat *first_iformat = NULL; /** head of registered output format linked list */ +#if !FF_API_FIRST_FORMAT +static +#endif AVOutputFormat *first_oformat = NULL; AVInputFormat *av_iformat_next(AVInputFormat *f) @@ -188,7 +195,7 @@ static int match_format(const char *name, const char *names) return !strcasecmp(name, names); } -#if LIBAVFORMAT_VERSION_MAJOR < 53 +#if FF_API_GUESS_FORMAT AVOutputFormat *guess_format(const char *short_name, const char *filename, const char *mime_type) { @@ -199,7 +206,7 @@ AVOutputFormat *guess_format(const char *short_name, const char *filename, AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type) { - AVOutputFormat *fmt, *fmt_found; + AVOutputFormat *fmt = NULL, *fmt_found; int score_max, score; /* specific test for image sequences */ @@ -213,8 +220,7 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename, /* Find the proper file type. */ fmt_found = NULL; score_max = 0; - fmt = first_oformat; - while (fmt != NULL) { + while ((fmt = av_oformat_next(fmt))) { score = 0; if (fmt->name && short_name && !strcmp(fmt->name, short_name)) score += 100; @@ -228,12 +234,11 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename, score_max = score; fmt_found = fmt; } - fmt = fmt->next; } return fmt_found; } -#if LIBAVFORMAT_VERSION_MAJOR < 53 +#if FF_API_GUESS_FORMAT AVOutputFormat *guess_stream_format(const char *short_name, const char *filename, const char *mime_type) { @@ -269,21 +274,23 @@ enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, 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 CODEC_ID_NONE; } AVInputFormat *av_find_input_format(const char *short_name) { - AVInputFormat *fmt; - for(fmt = first_iformat; fmt != NULL; fmt = fmt->next) { + AVInputFormat *fmt = NULL; + while ((fmt = av_iformat_next(fmt))) { if (match_format(short_name, fmt->name)) return fmt; } return NULL; } -#if LIBAVFORMAT_VERSION_MAJOR < 53 && CONFIG_SHARED && HAVE_SYMVER +#if FF_API_SYMVER && CONFIG_SHARED && HAVE_SYMVER FF_SYMVER(void, av_destruct_packet_nofree, (AVPacket *pkt), "LIBAVFORMAT_52") { av_destruct_packet_nofree(pkt); @@ -334,6 +341,21 @@ int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size) return ret; } +int av_append_packet(ByteIOContext *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 = get_buffer(s, pkt->data + old_size, size); + av_shrink_packet(pkt, old_size + FFMAX(ret, 0)); + return ret; +} + int av_filename_number_test(const char *filename) { @@ -343,18 +365,27 @@ int av_filename_number_test(const char *filename) AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max) { - AVInputFormat *fmt1, *fmt; + AVProbeData lpd = *pd; + AVInputFormat *fmt1 = NULL, *fmt; int score; + 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; + } + } + fmt = NULL; - for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) { + while ((fmt1 = av_iformat_next(fmt1))) { if (!is_opened == !(fmt1->flags & AVFMT_NOFILE)) continue; score = 0; if (fmt1->read_probe) { - score = fmt1->read_probe(pd); + score = fmt1->read_probe(&lpd); } else if (fmt1->extensions) { - if (av_match_ext(pd->filename, fmt1->extensions)) { + if (av_match_ext(lpd.filename, fmt1->extensions)) { score = 50; } } @@ -448,6 +479,10 @@ int av_open_input_stream(AVFormatContext **ic_ptr, ic->priv_data = NULL; } + // e.g. AVFMT_NOFILE formats will not have a ByteIOContext + if (ic->pb) + ff_id3v2_read(ic, ID3v2_DEFAULT_MAGIC); + if (ic->iformat->read_header) { err = ic->iformat->read_header(ic, ap); if (err < 0) @@ -457,7 +492,7 @@ int av_open_input_stream(AVFormatContext **ic_ptr, if (pb && !ic->data_offset) ic->data_offset = url_ftell(ic->pb); -#if LIBAVFORMAT_VERSION_MAJOR < 53 +#if FF_API_OLD_METADATA ff_metadata_demux_compat(ic); #endif @@ -474,6 +509,8 @@ int av_open_input_stream(AVFormatContext **ic_ptr, if (st) { av_free(st->priv_data); av_free(st->codec->extradata); + av_free(st->codec); + av_free(st->info); } av_free(st); } @@ -775,7 +812,7 @@ static void compute_frame_duration(int *pnum, int *pden, AVStream *st, break; case AVMEDIA_TYPE_AUDIO: frame_size = get_audio_frame_size(st->codec, pkt->size); - if (frame_size < 0) + if (frame_size <= 0 || st->codec->sample_rate <= 0) break; *pnum = frame_size; *pden = st->codec->sample_rate; @@ -1160,10 +1197,6 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) }else if(st->need_parsing == AVSTREAM_PARSE_FULL_ONCE){ st->parser->flags |= PARSER_FLAG_ONCE; } - if(st->parser && (s->iformat->flags & AVFMT_GENERIC_INDEX)){ - st->parser->next_frame_offset= - st->parser->cur_offset= st->cur_pkt.pos; - } } } } @@ -1841,10 +1874,11 @@ static void av_estimate_timings_from_bit_rate(AVFormatContext *ic) AVStream *st; /* if bit_rate is already set, we believe it */ - if (ic->bit_rate == 0) { + if (ic->bit_rate <= 0) { 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; } ic->bit_rate = bit_rate; @@ -1875,7 +1909,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset AVPacket pkt1, *pkt = &pkt1; AVStream *st; int read_size, i, ret; - int64_t end_time, start_time[MAX_STREAMS]; + int64_t end_time; int64_t filesize, offset, duration; int retry=0; @@ -1884,13 +1918,9 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset /* flush packet queue */ flush_packet_queue(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){ - start_time[i]= st->start_time; - }else if(st->first_dts != AV_NOPTS_VALUE){ - start_time[i]= st->first_dts; - }else + if (st->start_time == AV_NOPTS_VALUE && st->first_dts == AV_NOPTS_VALUE) av_log(st->codec, AV_LOG_WARNING, "start time is not set in av_estimate_timings_from_pts\n"); if (st->parser) { @@ -1923,9 +1953,11 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset read_size += pkt->size; st = ic->streams[pkt->stream_index]; if (pkt->pts != AV_NOPTS_VALUE && - start_time[pkt->stream_index] != AV_NOPTS_VALUE) { - end_time = pkt->pts; - duration = end_time - start_time[pkt->stream_index]; + (st->start_time != AV_NOPTS_VALUE || + st->first_dts != AV_NOPTS_VALUE)) { + duration = end_time = pkt->pts; + if (st->start_time != AV_NOPTS_VALUE) duration -= st->start_time; + else duration -= st->first_dts; if (duration < 0) duration += 1LL<<st->pts_wrap_bits; if (duration > 0) { @@ -1943,7 +1975,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset fill_all_stream_timings(ic); url_fseek(ic->pb, old_offset, SEEK_SET); - for(i=0; i<ic->nb_streams; i++){ + 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; @@ -2044,7 +2076,7 @@ static int has_codec_parameters(AVCodecContext *enc) int val; switch(enc->codec_type) { case AVMEDIA_TYPE_AUDIO: - val = enc->sample_rate && enc->channels && enc->sample_fmt != SAMPLE_FMT_NONE; + val = enc->sample_rate && enc->channels && enc->sample_fmt != AV_SAMPLE_FMT_NONE; if(!enc->frame_size && (enc->codec_id == CODEC_ID_VORBIS || enc->codec_id == CODEC_ID_AAC || @@ -2067,7 +2099,7 @@ static int has_codec_parameters(AVCodecContext *enc) static int has_decode_delay_been_guessed(AVStream *st) { return st->codec->codec_id != CODEC_ID_H264 || - st->codec_info_nb_frames >= 4 + st->codec->has_b_frames; + st->codec_info_nb_frames >= 6 + st->codec->has_b_frames; } static int try_decode_frame(AVStream *st, AVPacket *avpkt) @@ -2174,7 +2206,6 @@ static void compute_chapters_end(AVFormatContext *s) } } -#define MAX_STD_TIMEBASES (60*12+5) static int get_std_framerate(int i){ if(i<60*12) return i*1001; else return ((const int[]){24,30,60,12,15})[i-60*12]*1000*12; @@ -2205,24 +2236,18 @@ int av_find_stream_info(AVFormatContext *ic) int i, count, ret, read_size, j; AVStream *st; AVPacket pkt1, *pkt; - int64_t last_dts[MAX_STREAMS]; - int64_t duration_gcd[MAX_STREAMS]={0}; - int duration_count[MAX_STREAMS]={0}; - double (*duration_error)[MAX_STD_TIMEBASES]; int64_t old_offset = url_ftell(ic->pb); - int64_t codec_info_duration[MAX_STREAMS]={0}; - - duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error)); - if (!duration_error) return AVERROR(ENOMEM); for(i=0;i<ic->nb_streams;i++) { + AVCodec *codec; st = ic->streams[i]; if (st->codec->codec_id == CODEC_ID_AAC) { st->codec->sample_rate = 0; st->codec->frame_size = 0; st->codec->channels = 0; } - if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){ + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || + st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { /* if(!st->time_base.num) st->time_base= */ if(!st->codec->time_base.num) @@ -2236,16 +2261,29 @@ int av_find_stream_info(AVFormatContext *ic) } } assert(!st->codec->codec); + codec = avcodec_find_decoder(st->codec->codec_id); + + /* Force decoding of at least one frame of codec data + * this makes sure the codec initializes the channel configuration + * and does not trust the values from the container. + */ + if (codec && codec->capabilities & CODEC_CAP_CHANNEL_CONF) + st->codec->channels = 0; + + /* Ensure that subtitle_header is properly set. */ + if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE + && codec && !st->codec->codec) + avcodec_open(st->codec, codec); + //try to just open decoders, in case this is enough to get parameters if(!has_codec_parameters(st->codec)){ - AVCodec *codec = avcodec_find_decoder(st->codec->codec_id); - if (codec) + if (codec && !st->codec->codec) avcodec_open(st->codec, codec); } } - for(i=0;i<MAX_STREAMS;i++){ - last_dts[i]= AV_NOPTS_VALUE; + for (i=0; i<ic->nb_streams; i++) { + ic->streams[i]->info->last_dts = AV_NOPTS_VALUE; } count = 0; @@ -2264,11 +2302,11 @@ int av_find_stream_info(AVFormatContext *ic) break; /* variable fps and no guess at the real fps */ if( tb_unreliable(st->codec) && !(st->r_frame_rate.num && st->avg_frame_rate.num) - && duration_count[i]<20 && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + && st->info->duration_count<20 && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) break; if(st->parser && st->parser->parser->split && !st->codec->extradata) break; - if(st->first_dts == AV_NOPTS_VALUE && (st->codec->codec_type == CODEC_TYPE_VIDEO || st->codec->codec_type == CODEC_TYPE_AUDIO)) + if(st->first_dts == AV_NOPTS_VALUE && (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || st->codec->codec_type == AVMEDIA_TYPE_AUDIO)) break; } if (i == ic->nb_streams) { @@ -2292,9 +2330,7 @@ int av_find_stream_info(AVFormatContext *ic) /* NOTE: a new stream can be added there if no header in file (AVFMTCTX_NOHEADER) */ ret = av_read_frame_internal(ic, &pkt1); - if(ret == AVERROR(EAGAIN)) - continue; - if (ret < 0) { + if (ret < 0 && ret != AVERROR(EAGAIN)) { /* EOF or error */ ret = -1; /* we could not have all the codec parameters before EOF */ for(i=0;i<ic->nb_streams;i++) { @@ -2310,25 +2346,25 @@ int av_find_stream_info(AVFormatContext *ic) break; } + if (ret == AVERROR(EAGAIN)) + continue; + pkt= add_to_pktbuf(&ic->packet_buffer, &pkt1, &ic->packet_buffer_end); - if(av_dup_packet(pkt) < 0) { - av_free(duration_error); - return AVERROR(ENOMEM); - } + if ((ret = av_dup_packet(pkt)) < 0) + goto find_stream_info_err; read_size += pkt->size; st = ic->streams[pkt->stream_index]; - if(st->codec_info_nb_frames>1) { - if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration){ + if (st->codec_info_nb_frames>1) { + if (st->time_base.den > 0 && av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) { av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n"); break; } - codec_info_duration[st->index] += pkt->duration; + st->info->codec_info_duration += pkt->duration; } { - int index= pkt->stream_index; - int64_t last= last_dts[index]; + int64_t last = st->info->last_dts; int64_t duration= pkt->dts - last; if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){ @@ -2336,21 +2372,21 @@ int av_find_stream_info(AVFormatContext *ic) // if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) // av_log(NULL, AV_LOG_ERROR, "%f\n", dur); - if(duration_count[index] < 2) - memset(duration_error[index], 0, sizeof(*duration_error)); - for(i=1; i<MAX_STD_TIMEBASES; i++){ + if (st->info->duration_count < 2) + memset(st->info->duration_error, 0, sizeof(st->info->duration_error)); + for (i=1; i<FF_ARRAY_ELEMS(st->info->duration_error); i++) { int framerate= get_std_framerate(i); int ticks= lrintf(dur*framerate/(1001*12)); double error= dur - ticks*1001*12/(double)framerate; - duration_error[index][i] += error*error; + st->info->duration_error[i] += error*error; } - duration_count[index]++; + st->info->duration_count++; // ignore the first 4 values, they might have some random jitter - if (duration_count[index] > 3) - duration_gcd[index] = av_gcd(duration_gcd[index], duration); + if (st->info->duration_count > 3) + st->info->duration_gcd = av_gcd(st->info->duration_gcd, duration); } - if(last == AV_NOPTS_VALUE || duration_count[index]<=1) - last_dts[pkt->stream_index]= pkt->dts; + if (last == AV_NOPTS_VALUE || st->info->duration_count <= 1) + st->info->last_dts = pkt->dts; } if(st->parser && st->parser->parser->split && !st->codec->extradata){ int i= st->parser->parser->split(st->codec, pkt->data, pkt->size); @@ -2381,10 +2417,10 @@ int av_find_stream_info(AVFormatContext *ic) } for(i=0;i<ic->nb_streams;i++) { st = ic->streams[i]; - if(st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && codec_info_duration[i]) + if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && st->info->codec_info_duration) av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den, - codec_info_duration[i] *(int64_t)st->time_base.num, 60000); + st->info->codec_info_duration*(int64_t)st->time_base.num, 60000); if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample) st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt); @@ -2392,18 +2428,18 @@ int av_find_stream_info(AVFormatContext *ic) // 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) && duration_count[i] > 15 && duration_gcd[i] > 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 * duration_gcd[i], INT_MAX); - if(duration_count[i] && !st->r_frame_rate.num + 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) /*&& //FIXME we should not special-case MPEG-2, but this needs testing with non-MPEG-2 ... - st->time_base.num*duration_sum[i]/duration_count[i]*101LL > st->time_base.den*/){ + st->time_base.num*duration_sum[i]/st->info->duration_count*101LL > st->time_base.den*/){ int num = 0; double best_error= 2*av_q2d(st->time_base); - best_error= best_error*best_error*duration_count[i]*1000*12*30; + best_error = best_error*best_error*st->info->duration_count*1000*12*30; - for(j=1; j<MAX_STD_TIMEBASES; j++){ - double error= duration_error[i][j] * get_std_framerate(j); + for (j=1; j<FF_ARRAY_ELEMS(st->info->duration_error); j++) { + double error = st->info->duration_error[j] * get_std_framerate(j); // if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) // av_log(NULL, AV_LOG_ERROR, "%f %f\n", get_std_framerate(j) / 12.0/1001, error); if(error < best_error){ @@ -2461,8 +2497,70 @@ int av_find_stream_info(AVFormatContext *ic) } #endif - av_free(duration_error); + find_stream_info_err: + for (i=0; i < ic->nb_streams; i++) + av_freep(&ic->streams[i]->info); + return ret; +} + +static AVProgram *find_program_from_stream(AVFormatContext *ic, int s) +{ + int i, j; + + for (i = 0; i < ic->nb_programs; i++) + for (j = 0; j < ic->programs[i]->nb_stream_indexes; j++) + if (ic->programs[i]->stream_index[j] == s) + return ic->programs[i]; + 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 i, nb_streams = ic->nb_streams, stream_number = 0; + int ret = AVERROR_STREAM_NOT_FOUND, best_count = -1; + unsigned *program = NULL; + AVCodec *decoder = NULL, *best_decoder = NULL; + + if (related_stream >= 0 && wanted_stream_nb < 0) { + AVProgram *p = find_program_from_stream(ic, related_stream); + if (p) { + program = p->stream_index; + nb_streams = p->nb_stream_indexes; + } + } + for (i = 0; i < nb_streams; i++) { + AVStream *st = ic->streams[program ? program[i] : i]; + AVCodecContext *avctx = st->codec; + if (avctx->codec_type != type) + continue; + if (wanted_stream_nb >= 0 && stream_number++ != wanted_stream_nb) + continue; + if (decoder_ret) { + decoder = avcodec_find_decoder(ic->streams[i]->codec->codec_id); + if (!decoder) { + if (ret < 0) + ret = AVERROR_DECODER_NOT_FOUND; + continue; + } + } + if (best_count >= st->codec_info_nb_frames) + continue; + best_count = st->codec_info_nb_frames; + ret = i; + best_decoder = decoder; + if (program && i == nb_streams - 1 && ret < 0) { + program = NULL; + nb_streams = ic->nb_streams; + i = 0; /* no related stream found, try again with everything */ + } + } + if (decoder_ret) + *decoder_ret = best_decoder; return ret; } @@ -2491,6 +2589,7 @@ void av_close_input_stream(AVFormatContext *s) int i; AVStream *st; + flush_packet_queue(s); if (s->iformat->read_close) s->iformat->read_close(s); for(i=0;i<s->nb_streams;i++) { @@ -2503,15 +2602,17 @@ void av_close_input_stream(AVFormatContext *s) av_metadata_free(&st->metadata); av_free(st->index_entries); av_free(st->codec->extradata); + av_free(st->codec->subtitle_header); av_free(st->codec); -#if LIBAVFORMAT_VERSION_INT < (53<<16) +#if FF_API_OLD_METADATA av_free(st->filename); #endif av_free(st->priv_data); + av_free(st->info); av_free(st); } for(i=s->nb_programs-1; i>=0; i--) { -#if LIBAVFORMAT_VERSION_INT < (53<<16) +#if FF_API_OLD_METADATA av_freep(&s->programs[i]->provider_name); av_freep(&s->programs[i]->name); #endif @@ -2520,10 +2621,9 @@ void av_close_input_stream(AVFormatContext *s) av_freep(&s->programs[i]); } av_freep(&s->programs); - flush_packet_queue(s); av_freep(&s->priv_data); while(s->nb_chapters--) { -#if LIBAVFORMAT_VERSION_INT < (53<<16) +#if FF_API_OLD_METADATA av_free(s->chapters[s->nb_chapters]->title); #endif av_metadata_free(&s->chapters[s->nb_chapters]->metadata); @@ -2531,6 +2631,7 @@ void av_close_input_stream(AVFormatContext *s) } av_freep(&s->chapters); av_metadata_free(&s->metadata); + av_freep(&s->key); av_free(s); } @@ -2547,14 +2648,29 @@ AVStream *av_new_stream(AVFormatContext *s, int id) AVStream *st; int i; +#if FF_API_MAX_STREAMS if (s->nb_streams >= MAX_STREAMS){ av_log(s, AV_LOG_ERROR, "Too many streams\n"); return NULL; } +#else + AVStream **streams; + + if (s->nb_streams >= INT_MAX/sizeof(*streams)) + return NULL; + streams = av_realloc(s->streams, (s->nb_streams + 1) * sizeof(*streams)); + if (!streams) + return NULL; + s->streams = streams; +#endif st = av_mallocz(sizeof(AVStream)); if (!st) return NULL; + if (!(st->info = av_mallocz(sizeof(*st->info)))) { + av_free(st); + return NULL; + } st->codec= avcodec_alloc_context(); if (s->iformat) { @@ -2626,7 +2742,7 @@ AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int6 return NULL; dynarray_add(&s->chapters, &s->nb_chapters, chapter); } -#if LIBAVFORMAT_VERSION_INT < (53<<16) +#if FF_API_OLD_METADATA av_free(chapter->title); #endif av_metadata_set2(&chapter->metadata, "title", title, 0); @@ -2649,6 +2765,10 @@ int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap) s->priv_data = av_mallocz(s->oformat->priv_data_size); if (!s->priv_data) return AVERROR(ENOMEM); + if (s->oformat->priv_class) { + *(const AVClass**)s->priv_data= s->oformat->priv_class; + av_opt_set_defaults(s->priv_data); + } } else s->priv_data = NULL; @@ -2699,7 +2819,7 @@ int av_write_header(AVFormatContext *s) AVStream *st; // some sanity checks - if (s->nb_streams == 0) { + if (s->nb_streams == 0 && !(s->oformat->flags & AVFMT_NOSTREAMS)) { av_log(s, AV_LOG_ERROR, "no streams\n"); return AVERROR(EINVAL); } @@ -2743,8 +2863,8 @@ int av_write_header(AVFormatContext *s) char tagbuf[32]; av_get_codec_tag_string(tagbuf, sizeof(tagbuf), st->codec->codec_tag); av_log(s, AV_LOG_ERROR, - "Tag %s/0x%08x incompatible with output codec '%s'\n", - tagbuf, st->codec->codec_tag, st->codec->codec->name); + "Tag %s/0x%08x incompatible with output codec id '%d'\n", + tagbuf, st->codec->codec_tag, st->codec->codec_id); return AVERROR_INVALIDDATA; } }else @@ -2762,22 +2882,13 @@ int av_write_header(AVFormatContext *s) return AVERROR(ENOMEM); } -#if LIBAVFORMAT_VERSION_MAJOR < 53 +#if FF_API_OLD_METADATA ff_metadata_mux_compat(s); #endif /* set muxer identification string */ - if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { - AVMetadata *m; - AVMetadataTag *t; - - if (!(m = av_mallocz(sizeof(AVMetadata)))) - return AVERROR(ENOMEM); - av_metadata_set2(&m, "encoder", LIBAVFORMAT_IDENT, 0); - metadata_conv(&m, s->oformat->metadata_conv, NULL); - if ((t = av_metadata_get(m, "", NULL, AV_METADATA_IGNORE_SUFFIX))) - av_metadata_set2(&s->metadata, t->key, t->value, 0); - av_metadata_free(&m); + if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { + av_metadata_set2(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0); } if(s->oformat->write_header){ @@ -2851,12 +2962,12 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){ if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){ av_log(s, AV_LOG_ERROR, - "st:%d error, non monotone timestamps %"PRId64" >= %"PRId64"\n", + "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %"PRId64" >= %"PRId64"\n", st->index, st->cur_dts, pkt->dts); return -1; } if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){ - av_log(s, AV_LOG_ERROR, "st:%d error, pts < dts\n", st->index); + av_log(s, AV_LOG_ERROR, "pts < dts in stream %d\n", st->index); return -1; } @@ -2934,7 +3045,7 @@ next_non_null: *next_point= this_pktl; } -int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt) +static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt) { AVStream *st = s->streams[ pkt ->stream_index]; AVStream *st2= s->streams[ next->stream_index]; @@ -3182,7 +3293,7 @@ void dump_format(AVFormatContext *ic, int secs, us; av_log(NULL, AV_LOG_INFO, ", start: "); secs = ic->start_time / AV_TIME_BASE; - us = 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)); } @@ -3226,16 +3337,18 @@ void dump_format(AVFormatContext *ic, av_free(printed); } -#if LIBAVFORMAT_VERSION_MAJOR < 53 +#if FF_API_PARSE_FRAME_PARAM +#include "libavcore/parseutils.h" + int parse_image_size(int *width_ptr, int *height_ptr, const char *str) { - return av_parse_video_frame_size(width_ptr, height_ptr, str); + return av_parse_video_size(width_ptr, height_ptr, str); } int parse_frame_rate(int *frame_rate_num, int *frame_rate_den, const char *arg) { AVRational frame_rate; - int ret = av_parse_video_frame_rate(&frame_rate, arg); + int ret = av_parse_video_rate(&frame_rate, arg); *frame_rate_num= frame_rate.num; *frame_rate_den= frame_rate.den; return ret; @@ -3401,8 +3514,8 @@ int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info) } p++; } - *q = '\0'; } + *q = '\0'; if (!strcmp(tag, tag1)) return 1; if (*p != '&') @@ -3543,7 +3656,7 @@ void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload) pkt_dump_internal(avcl, NULL, level, pkt, dump_payload); } -#if LIBAVFORMAT_VERSION_MAJOR < 53 +#if FF_API_URL_SPLIT attribute_deprecated void ff_url_split(char *proto, int proto_size, char *authorization, int authorization_size, @@ -3643,6 +3756,34 @@ char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase) return buff; } +int ff_hex_to_data(uint8_t *data, const char *p) +{ + int c, len, v; + + len = 0; + v = 1; + for (;;) { + p += strspn(p, SPACE_CHARS); + if (*p == '\0') + break; + c = toupper((unsigned char) *p++); + if (c >= '0' && c <= '9') + c = c - '0'; + else if (c >= 'A' && c <= 'F') + c = c - 'A' + 10; + else + break; + v = (v << 4) | c; + if (v & 0x100) { + if (data) + data[len] = v; + len++; + v = 1; + } + } + return len; +} + void av_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den) { @@ -3721,3 +3862,66 @@ int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, return av_write_frame(dst, &local_pkt); } +void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, + void *context) +{ + const char *ptr = str; + + /* Parse key=value pairs. */ + for (;;) { + const char *key; + char *dest = NULL, *dest_end; + int key_len, dest_len = 0; + + /* Skip whitespace and potential commas. */ + while (*ptr && (isspace(*ptr) || *ptr == ',')) + ptr++; + if (!*ptr) + break; + + key = ptr; + + if (!(ptr = strchr(key, '='))) + break; + ptr++; + key_len = ptr - key; + + callback_get_buf(context, key, key_len, &dest, &dest_len); + dest_end = dest + dest_len - 1; + + if (*ptr == '\"') { + ptr++; + while (*ptr && *ptr != '\"') { + if (*ptr == '\\') { + if (!ptr[1]) + break; + if (dest && dest < dest_end) + *dest++ = ptr[1]; + ptr += 2; + } else { + if (dest && dest < dest_end) + *dest++ = *ptr; + ptr++; + } + } + if (*ptr == '\"') + ptr++; + } else { + for (; *ptr && !(isspace(*ptr) || *ptr == ','); ptr++) + if (dest && dest < dest_end) + *dest++ = *ptr; + } + if (dest) + *dest = 0; + } +} + +int ff_find_stream_index(AVFormatContext *s, int id) +{ + int i; + for (i = 0; i < s->nb_streams; i++) { + if (s->streams[i]->id == id) + return i; + } + return -1; +} |