Index: patched-ffmpeg-mt/libavformat/utils.c |
=================================================================== |
--- patched-ffmpeg-mt/libavformat/utils.c (revision 41250) |
+++ patched-ffmpeg-mt/libavformat/utils.c (working copy) |
@@ -24,9 +24,14 @@ |
#include "metadata.h" |
#include "libavutil/avstring.h" |
#include "riff.h" |
+#include "audiointerleave.h" |
#include <sys/time.h> |
#include <time.h> |
#include <strings.h> |
+#include <stdarg.h> |
+#if CONFIG_NETWORK |
+#include "network.h" |
+#endif |
#undef NDEBUG |
#include <assert.h> |
@@ -137,13 +142,6 @@ |
format->next = NULL; |
} |
-#if LIBAVFORMAT_VERSION_MAJOR < 53 |
-int match_ext(const char *filename, const char *extensions) |
-{ |
- return av_match_ext(filename, extensions); |
-} |
-#endif |
- |
int av_match_ext(const char *filename, const char *extensions) |
{ |
const char *ext, *p; |
@@ -818,6 +816,11 @@ |
/* do we have a video B-frame ? */ |
delay= st->codec->has_b_frames; |
presentation_delayed = 0; |
+ |
+ // this delay should not count for undecoded frames |
+ if (delay && st->codec->active_thread_type&FF_THREAD_FRAME) |
+ delay -= st->codec->thread_count-1; |
+ |
/* XXX: need has_b_frame, but cannot get it if the codec is |
not initialized */ |
if (delay && |
@@ -1548,6 +1551,9 @@ |
index = av_index_search_timestamp(st, timestamp, flags); |
+ if(index < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp) |
+ return -1; |
+ |
if(index < 0 || index==st->nb_index_entries-1){ |
int i; |
AVPacket pkt; |
@@ -1911,6 +1917,8 @@ |
if(!enc->frame_size && |
(enc->codec_id == CODEC_ID_VORBIS || |
enc->codec_id == CODEC_ID_AAC || |
+ enc->codec_id == CODEC_ID_MP1 || |
+ enc->codec_id == CODEC_ID_MP2 || |
enc->codec_id == CODEC_ID_MP3 || |
enc->codec_id == CODEC_ID_SPEEX)) |
return 0; |
@@ -2069,13 +2077,17 @@ |
double (*duration_error)[MAX_STD_TIMEBASES]; |
int64_t old_offset = url_ftell(ic->pb); |
int64_t codec_info_duration[MAX_STREAMS]={0}; |
- int codec_info_nb_frames[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++) { |
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 == CODEC_TYPE_VIDEO){ |
/* if(!st->time_base.num) |
st->time_base= */ |
@@ -2089,6 +2101,13 @@ |
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; |
} |
} |
+ assert(!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) |
+ avcodec_open(st->codec, codec); |
+ } |
} |
for(i=0;i<MAX_STREAMS;i++){ |
@@ -2110,7 +2129,7 @@ |
if (!has_codec_parameters(st->codec)) |
break; |
/* variable fps and no guess at the real fps */ |
- if( tb_unreliable(st->codec) |
+ if( tb_unreliable(st->codec) && !(st->r_frame_rate.num && st->avg_frame_rate.num) |
&& duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO) |
break; |
if(st->parser && st->parser->parser->split && !st->codec->extradata) |
@@ -2166,15 +2185,14 @@ |
read_size += pkt->size; |
st = ic->streams[pkt->stream_index]; |
- if(codec_info_nb_frames[st->index]>1) { |
+ 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){ |
av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n"); |
break; |
} |
codec_info_duration[st->index] += pkt->duration; |
} |
- if (pkt->duration != 0) |
- codec_info_nb_frames[st->index]++; |
+ st->codec_info_nb_frames++; |
{ |
int index= pkt->stream_index; |
@@ -2230,9 +2248,9 @@ |
} |
for(i=0;i<ic->nb_streams;i++) { |
st = ic->streams[i]; |
- if(codec_info_nb_frames[i]>2 && !st->avg_frame_rate.num) |
+ if(st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && codec_info_duration[i]) |
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, |
- (codec_info_nb_frames[i]-2)*(int64_t)st->time_base.den, |
+ (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den, |
codec_info_duration[i] *(int64_t)st->time_base.num, 60000); |
if (st->codec->codec_type == CODEC_TYPE_VIDEO) { |
if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample) |
@@ -2241,9 +2259,9 @@ |
// 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) |
+ 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] |
+ if(duration_count[i] && !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*/){ |
@@ -2536,7 +2554,7 @@ |
av_log(s, AV_LOG_ERROR, "time base not set\n"); |
return -1; |
} |
- if(st->codec->width<=0 || st->codec->height<=0){ |
+ if((st->codec->width<=0 || st->codec->height<=0) && !(s->oformat->flags & AVFMT_NODIMENSIONS)){ |
av_log(s, AV_LOG_ERROR, "dimensions not set\n"); |
return -1; |
} |
@@ -2573,6 +2591,20 @@ |
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->oformat->write_header){ |
ret = s->oformat->write_header(s); |
if (ret < 0) |
@@ -2635,7 +2667,7 @@ |
if(pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY){ |
st->pts_buffer[0]= pkt->pts; |
for(i=1; i<delay+1 && st->pts_buffer[i] == AV_NOPTS_VALUE; i++) |
- st->pts_buffer[i]= (i-delay-1) * pkt->duration; |
+ st->pts_buffer[i]= pkt->pts + (i-delay-1) * pkt->duration; |
for(i=0; i<delay && st->pts_buffer[i] > st->pts_buffer[i+1]; i++) |
FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]); |
@@ -2731,13 +2763,9 @@ |
{ |
AVStream *st = s->streams[ pkt ->stream_index]; |
AVStream *st2= s->streams[ next->stream_index]; |
- int64_t left = st2->time_base.num * (int64_t)st ->time_base.den; |
- int64_t right= st ->time_base.num * (int64_t)st2->time_base.den; |
- |
- if (pkt->dts == AV_NOPTS_VALUE) |
- return 0; |
- |
- return next->dts * left > pkt->dts * right; //FIXME this can overflow |
+ int64_t a= st2->time_base.num * (int64_t)st ->time_base.den; |
+ int64_t b= st ->time_base.num * (int64_t)st2->time_base.den; |
+ return av_rescale_rnd(pkt->dts, b, a, AV_ROUND_DOWN) < next->dts; |
} |
int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){ |
@@ -2845,8 +2873,10 @@ |
fail: |
if(ret == 0) |
ret=url_ferror(s->pb); |
- for(i=0;i<s->nb_streams;i++) |
+ for(i=0;i<s->nb_streams;i++) { |
av_freep(&s->streams[i]->priv_data); |
+ av_freep(&s->streams[i]->index_entries); |
+ } |
av_freep(&s->priv_data); |
return ret; |
} |
@@ -2915,7 +2945,7 @@ |
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", st->time_base.num/g, st->time_base.den/g); |
+ 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)) { |
@@ -2989,6 +3019,14 @@ |
} |
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; j<ic->nb_programs; j++) { |
@@ -3325,12 +3363,12 @@ |
pkt_dump_internal(avcl, NULL, level, pkt, dump_payload); |
} |
-void 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) |
+void ff_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) |
{ |
const char *p, *ls, *at, *col, *brk; |
@@ -3416,3 +3454,48 @@ |
if(!s->time_base.num || !s->time_base.den) |
s->time_base.num= s->time_base.den= 0; |
} |
+ |
+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, *ai; |
+#endif |
+ |
+ str[0] = '\0'; |
+ if (proto) |
+ av_strlcatf(str, size, "%s://", proto); |
+ if (authorization) |
+ 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. */ |
+ memset(&hints, 0, sizeof(hints)); |
+ 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); |
+ } 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); |
+ |
+ va_start(vl, fmt); |
+ vsnprintf(str + len, size > len ? size - len : 0, fmt, vl); |
+ va_end(vl); |
+ } |
+ return strlen(str); |
+} |