]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/utils.c
Remove redundant fastmemcpy.h #include, it is indirectly #included by avutil.h.
[ffmpeg] / libavformat / utils.c
index 417e81c5d760ea21b841b0518a37657f2e420807..ab7345ede2022cd5795e5ceb111b381049a3ae6a 100644 (file)
@@ -237,13 +237,12 @@ int av_filename_number_test(const char *filename)
     return filename && (av_get_frame_filename(buf, sizeof(buf), filename, 1)>=0);
 }
 
-AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)
+static AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)
 {
     AVInputFormat *fmt1, *fmt;
-    int score, score_max;
+    int score;
 
     fmt = NULL;
-    score_max = 0;
     for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) {
         if (!is_opened == !(fmt1->flags & AVFMT_NOFILE))
             continue;
@@ -255,14 +254,19 @@ AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)
                 score = 50;
             }
         }
-        if (score > score_max) {
-            score_max = score;
+        if (score > *score_max) {
+            *score_max = score;
             fmt = fmt1;
         }
     }
     return fmt;
 }
 
+AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened){
+    int score=0;
+    return av_probe_input_format2(pd, is_opened, &score);
+}
+
 /************************************************************/
 /* input media file */
 
@@ -292,7 +296,7 @@ static const AVOption options[]={
 {"genpts", "generate pts", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_GENPTS, INT_MIN, INT_MAX, D, "fflags"},
 {"track", " set the track number", OFFSET(track), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E},
 {"year", "set the year", OFFSET(year), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, E},
-{"analyzeduration", NULL, OFFSET(max_analyze_duration), FF_OPT_TYPE_INT, 3*AV_TIME_BASE, 0, INT_MAX, D},
+{"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), FF_OPT_TYPE_INT, 3*AV_TIME_BASE, 0, INT_MAX, D},
 {NULL},
 };
 
@@ -413,8 +417,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
 
     if (!fmt || must_open_file) {
         /* if no file needed do not try to open one */
-        if (url_fopen(pb, filename, URL_RDONLY) < 0) {
-            err = AVERROR_IO;
+        if ((err=url_fopen(pb, filename, URL_RDONLY)) < 0) {
             goto fail;
         }
         file_opened = 1;
@@ -423,8 +426,9 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
         }
 
         for(probe_size= PROBE_BUF_MIN; probe_size<=PROBE_BUF_MAX && !fmt; probe_size<<=1){
+            int score= probe_size < PROBE_BUF_MAX ? AVPROBE_SCORE_MAX/4 : 0;
             /* read probe data */
-            pd->buf= av_realloc(pd->buf, probe_size);
+            pd->buf= av_realloc(pd->buf, probe_size + AVPROBE_PADDING_SIZE);
             pd->buf_size = get_buffer(pb, pd->buf, probe_size);
             if (url_fseek(pb, 0, SEEK_SET) < 0) {
                 url_fclose(pb);
@@ -435,7 +439,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
                 }
             }
             /* guess file format */
-            fmt = av_probe_input_format(pd, 1);
+            fmt = av_probe_input_format2(pd, 1, &score);
         }
         av_freep(&pd->buf);
     }
@@ -447,7 +451,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
     }
 
     /* XXX: suppress this hack for redirectors */
-#ifdef CONFIG_NETWORK
+#ifdef CONFIG_REDIR_DEMUXER
     if (fmt == &redir_demuxer) {
         err = redir_open(ic_ptr, pb);
         url_fclose(pb);
@@ -479,6 +483,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
 
 int av_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
+    av_init_packet(pkt);
     return s->iformat->read_packet(s, pkt);
 }
 
@@ -579,6 +584,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
                                AVCodecParserContext *pc, AVPacket *pkt)
 {
     int num, den, presentation_delayed, delay, i;
+    int64_t offset;
     /* handle wrapping */
     if(st->cur_dts != AV_NOPTS_VALUE){
         if(pkt->pts != AV_NOPTS_VALUE)
@@ -594,6 +600,16 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
         }
     }
 
+    /* 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)
+            pkt->pts += offset;
+        if(pkt->dts != AV_NOPTS_VALUE)
+            pkt->dts += offset;
+    }
+
     if(is_intra_only(st->codec))
         pkt->flags |= PKT_FLAG_KEY;
 
@@ -686,6 +702,8 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
     AVStream *st;
     int len, ret, i;
 
+    av_init_packet(pkt);
+
     for(;;) {
         /* select current input stream component */
         st = s->cur_st;
@@ -710,6 +728,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                 /* return packet if any */
                 if (pkt->size) {
                 got_packet:
+                    pkt->pos = s->cur_pkt.pos;              // Isn't quite accurate but close.
                     pkt->duration = 0;
                     pkt->stream_index = st->index;
                     pkt->pts = st->parser->pts;
@@ -766,8 +785,8 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                 st->parser = av_parser_init(st->codec->codec_id);
                 if (!st->parser) {
                     /* no parser available : just output the raw packets */
-                    st->need_parsing = 0;
-                }else if(st->need_parsing == 2){
+                    st->need_parsing = AVSTREAM_PARSE_NONE;
+                }else if(st->need_parsing == AVSTREAM_PARSE_HEADERS){
                     st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
                 }
                 if(st->parser && (s->iformat->flags & AVFMT_GENERIC_INDEX)){
@@ -1198,6 +1217,10 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i
 #ifdef DEBUG_SEEK
 av_log(s, AV_LOG_DEBUG, "%"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);
 #endif
+        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;
@@ -1260,7 +1283,7 @@ static int av_seek_frame_generic(AVFormatContext *s,
 
     index = av_index_search_timestamp(st, timestamp, flags);
 
-    if(index < 0){
+    if(index < 0 || index==st->nb_index_entries-1){
         int i;
         AVPacket pkt;
 
@@ -1650,6 +1673,20 @@ static int try_decode_frame(AVStream *st, const uint8_t *data, int size)
     return ret;
 }
 
+static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score)
+{
+    AVInputFormat *fmt;
+    fmt = av_probe_input_format2(pd, 1, &score);
+
+    if (fmt) {
+        if (strncmp(fmt->name, "mp3", 3) == 0)
+            st->codec->codec_id = CODEC_ID_MP3;
+        else if (strncmp(fmt->name, "ac3", 3) == 0)
+            st->codec->codec_id = CODEC_ID_AC3;
+    }
+    return !!fmt;
+}
+
 /* absolute maximum size we read until we abort */
 #define MAX_READ_SIZE        5000000
 
@@ -1671,6 +1708,8 @@ int av_find_stream_info(AVFormatContext *ic)
     offset_t old_offset = url_ftell(&ic->pb);
     int64_t codec_info_duration[MAX_STREAMS]={0};
     int codec_info_nb_frames[MAX_STREAMS]={0};
+    AVProbeData probe_data[MAX_STREAMS];
+    int codec_identified[MAX_STREAMS]={0};
 
     duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error));
     if (!duration_error) return AVERROR_NOMEM;
@@ -1686,7 +1725,7 @@ int av_find_stream_info(AVFormatContext *ic)
         //only for the split stuff
         if (!st->parser) {
             st->parser = av_parser_init(st->codec->codec_id);
-            if(st->need_parsing == 2 && st->parser){
+            if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){
                 st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
             }
         }
@@ -1696,6 +1735,7 @@ int av_find_stream_info(AVFormatContext *ic)
         last_dts[i]= AV_NOPTS_VALUE;
     }
 
+    memset(probe_data, 0, sizeof(probe_data));
     count = 0;
     read_size = 0;
     ppktl = &ic->packet_buffer;
@@ -1706,11 +1746,14 @@ int av_find_stream_info(AVFormatContext *ic)
             if (!has_codec_parameters(st->codec))
                 break;
             /* variable fps and no guess at the real fps */
-            if(   st->codec->time_base.den >= 101LL*st->codec->time_base.num
+            if(   (st->codec->time_base.den >= 101LL*st->codec->time_base.num || st->codec->codec_id == CODEC_ID_MPEG2VIDEO)
                && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO)
                 break;
             if(st->parser && st->parser->parser->split && !st->codec->extradata)
                 break;
+            if (st->codec->codec_type == CODEC_TYPE_AUDIO &&
+                st->codec->codec_id == CODEC_ID_NONE)
+                break;
         }
         if (i == ic->nb_streams) {
             /* NOTE: if the format has no header, then we need to read
@@ -1796,6 +1839,13 @@ int av_find_stream_info(AVFormatContext *ic)
             }
             if(last == AV_NOPTS_VALUE || duration_count[index]<=1)
                 last_dts[pkt->stream_index]= pkt->dts;
+
+            if (st->codec->codec_id == CODEC_ID_NONE) {
+                AVProbeData *pd = &(probe_data[st->index]);
+                pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size);
+                memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size);
+                pd->buf_size += pkt->size;
+            }
         }
         if(st->parser && st->parser->parser->split && !st->codec->extradata){
             int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
@@ -1875,12 +1925,28 @@ int av_find_stream_info(AVFormatContext *ic)
                 }
             }
         }else if(st->codec->codec_type == CODEC_TYPE_AUDIO) {
+            if (st->codec->codec_id == CODEC_ID_NONE) {
+                codec_identified[st->index] = set_codec_from_probe_data(st, &(probe_data[st->index]), 0);
+                if (codec_identified[st->index]) {
+                    st->need_parsing = AVSTREAM_PARSE_FULL;
+                }
+            }
             if(!st->codec->bits_per_sample)
                 st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id);
         }
     }
 
     av_estimate_timings(ic, old_offset);
+
+    for(i=0;i<ic->nb_streams;i++) {
+        st = ic->streams[i];
+        if (codec_identified[st->index]) {
+            av_read_frame_flush(ic);
+            av_seek_frame(ic, st->index, 0.0, 0);
+            url_fseek(&ic->pb, ic->data_offset, SEEK_SET);
+        }
+    }
+
 #if 0
     /* correct DTS for b frame streams with no timestamps */
     for(i=0;i<ic->nb_streams;i++) {
@@ -1907,6 +1973,9 @@ int av_find_stream_info(AVFormatContext *ic)
 #endif
 
     av_free(duration_error);
+    for(i=0;i<MAX_STREAMS;i++){
+        av_freep(&(probe_data[i].buf));
+    }
 
     return ret;
 }
@@ -2421,6 +2490,30 @@ static AbvEntry frame_abvs[] = {
     { "qcif",      176, 144,     0,    0 },
     { "cif",       352, 288,     0,    0 },
     { "4cif",      704, 576,     0,    0 },
+    { "qqvga",     160, 120,     0,    0 },
+    { "qvga",      320, 240,     0,    0 },
+    { "vga",       640, 480,     0,    0 },
+    { "svga",      800, 600,     0,    0 },
+    { "xga",      1024, 768,     0,    0 },
+    { "uxga",     1600,1200,     0,    0 },
+    { "qxga",     2048,1536,     0,    0 },
+    { "sxga",     1280,1024,     0,    0 },
+    { "qsxga",    2560,2048,     0,    0 },
+    { "hsxga",    5120,4096,     0,    0 },
+    { "wvga",      852, 480,     0,    0 },
+    { "wxga",     1366, 768,     0,    0 },
+    { "wsxga",    1600,1024,     0,    0 },
+    { "wuxga",    1920,1200,     0,    0 },
+    { "woxga",    2560,1600,     0,    0 },
+    { "wqsxga",   3200,2048,     0,    0 },
+    { "wquxga",   3840,2400,     0,    0 },
+    { "whsxga",   6400,4096,     0,    0 },
+    { "whuxga",   7680,4800,     0,    0 },
+    { "cga",       320, 200,     0,    0 },
+    { "ega",       640, 350,     0,    0 },
+    { "hd480",     852, 480,     0,    0 },
+    { "hd720",    1280, 720,     0,    0 },
+    { "hd1080",   1920,1080,     0,    0 },
 };
 
 int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
@@ -2488,7 +2581,6 @@ int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg)
         return 0;
 }
 
-#ifndef CONFIG_WINCE
 int64_t parse_date(const char *datestr, int duration)
 {
     const char *p;
@@ -2596,7 +2688,6 @@ int64_t parse_date(const char *datestr, int duration)
     }
     return negative ? -t : t;
 }
-#endif /* CONFIG_WINCE */
 
 int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
 {