]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/utils.c
ensure that the codec_id detection in av_find_stream_info() does not
[ffmpeg] / libavformat / utils.c
index 87025c13eb958b71c82d66705f5c3815d6a65ebb..dd2d6823a296dcd5a33bd4581d17ba0bc40ef778 100644 (file)
@@ -589,12 +589,42 @@ static int is_intra_only(AVCodecContext *enc){
     return 0;
 }
 
+static void update_initial_timestamps(AVFormatContext *s, int stream_index, int64_t dts){
+    AVStream *st= s->streams[stream_index];
+    AVPacketList *pktl= s->packet_buffer;
+
+    if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE)
+        return;
+
+    st->first_dts= dts - st->cur_dts;
+    st->cur_dts= dts;
+
+    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)
+            pktl->pkt.pts += st->first_dts;
+
+        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;
+    }
+}
+
 static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
                                AVCodecParserContext *pc, AVPacket *pkt)
 {
     int num, den, presentation_delayed, delay, i;
     int64_t offset;
 
+    if(pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && pkt->dts > pkt->pts && st->pts_wrap_bits<63
+       /*&& pkt->dts-(1LL<<st->pts_wrap_bits) < pkt->pts*/){
+        pkt->dts -= 1LL<<st->pts_wrap_bits;
+    }
+
     if (pkt->duration == 0) {
         compute_frame_duration(&num, &den, st, pc, pkt);
         if (den && num) {
@@ -628,7 +658,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
         presentation_delayed = 1;
 
     if(st->cur_dts == AV_NOPTS_VALUE){
-        st->cur_dts = -delay * pkt->duration;
+        st->cur_dts = 0; //FIXME maybe set it to 0 during init
     }
 
 //    av_log(NULL, AV_LOG_DEBUG, "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);
@@ -639,6 +669,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             /* PTS = presentation time stamp */
             if (pkt->dts == AV_NOPTS_VALUE)
                 pkt->dts = st->last_IP_pts;
+            update_initial_timestamps(s, pkt->stream_index, pkt->dts);
             if (pkt->dts == AV_NOPTS_VALUE)
                 pkt->dts = st->cur_dts;
 
@@ -664,6 +695,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             /* presentation is not delayed : PTS and DTS are the same */
             if(pkt->pts == AV_NOPTS_VALUE)
                 pkt->pts = pkt->dts;
+            update_initial_timestamps(s, pkt->stream_index, pkt->pts);
             if(pkt->pts == AV_NOPTS_VALUE)
                 pkt->pts = st->cur_dts;
             pkt->dts = pkt->pts;
@@ -679,6 +711,9 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             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(delay>1){
+            update_initial_timestamps(s, pkt->stream_index, pkt->dts); // this should happen on the first packet
+        }
         if(pkt->dts > st->cur_dts)
             st->cur_dts = pkt->dts;
     }
@@ -808,6 +843,22 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
     return 0;
 }
 
+static AVPacket *add_to_pktbuf(AVFormatContext *s, AVPacket *pkt){
+    AVPacketList *pktl= s->packet_buffer;
+    AVPacketList **plast_pktl= &s->packet_buffer;
+
+    while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last?
+
+    pktl = av_mallocz(sizeof(AVPacketList));
+    if (!pktl)
+        return NULL;
+
+    /* add the packet in the buffered packet list */
+    *plast_pktl = pktl;
+    pktl->pkt= *pkt;
+    return &pktl->pkt;
+}
+
 int av_read_frame(AVFormatContext *s, AVPacket *pkt)
 {
     AVPacketList *pktl;
@@ -843,7 +894,6 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
             }
         }
         if(genpts){
-            AVPacketList **plast_pktl= &s->packet_buffer;
             int ret= av_read_frame_internal(s, pkt);
             if(ret<0){
                 if(pktl && ret != AVERROR(EAGAIN)){
@@ -853,19 +903,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
                     return ret;
             }
 
-            /* duplicate the packet */
-            if (av_dup_packet(pkt) < 0)
+            if(av_dup_packet(add_to_pktbuf(s, pkt)) < 0)
                 return AVERROR(ENOMEM);
-
-            while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last?
-
-            pktl = av_mallocz(sizeof(AVPacketList));
-            if (!pktl)
-                return AVERROR(ENOMEM);
-
-            /* add the packet in the buffered packet list */
-            *plast_pktl = pktl;
-            pktl->pkt= *pkt;
         }else{
             assert(!s->packet_buffer);
             return av_read_frame_internal(s, pkt);
@@ -1707,7 +1746,6 @@ int av_find_stream_info(AVFormatContext *ic)
     int i, count, ret, read_size, j;
     AVStream *st;
     AVPacket pkt1, *pkt;
-    AVPacketList *pktl=NULL, **ppktl;
     int64_t last_dts[MAX_STREAMS];
     int duration_count[MAX_STREAMS]={0};
     double (*duration_error)[MAX_STD_TIMEBASES];
@@ -1744,7 +1782,6 @@ int av_find_stream_info(AVFormatContext *ic)
     memset(probe_data, 0, sizeof(probe_data));
     count = 0;
     read_size = 0;
-    ppktl = &ic->packet_buffer;
     for(;;) {
         /* check if one codec still needs to be handled */
         for(i=0;i<ic->nb_streams;i++) {
@@ -1760,6 +1797,8 @@ int av_find_stream_info(AVFormatContext *ic)
             if (st->codec->codec_type == CODEC_TYPE_AUDIO &&
                 st->codec->codec_id == CODEC_ID_NONE)
                 break;
+            if(st->first_dts == AV_NOPTS_VALUE)
+                break;
         }
         if (i == ic->nb_streams) {
             /* NOTE: if the format has no header, then we need to read
@@ -1796,24 +1835,9 @@ int av_find_stream_info(AVFormatContext *ic)
             break;
         }
 
-        pktl = av_mallocz(sizeof(AVPacketList));
-        if (!pktl) {
-            ret = AVERROR(ENOMEM);
-            break;
-        }
-
-        /* add the packet in the buffered packet list */
-        *ppktl = pktl;
-        ppktl = &pktl->next;
-
-        pkt = &pktl->pkt;
-        *pkt = pkt1;
-
-        /* duplicate the packet */
-        if (av_dup_packet(pkt) < 0) {
-            ret = AVERROR(ENOMEM);
-            break;
-        }
+        pkt= add_to_pktbuf(ic, &pkt1);
+        if(av_dup_packet(pkt) < 0)
+            return AVERROR(ENOMEM);
 
         read_size += pkt->size;
 
@@ -1946,11 +1970,20 @@ int av_find_stream_info(AVFormatContext *ic)
 
     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 (codec_identified[st->index])
+            break;
+    }
+    //FIXME this is a mess
+    if(i!=ic->nb_streams){
+        av_read_frame_flush(ic);
+        for(i=0;i<ic->nb_streams;i++) {
+            st = ic->streams[i];
+            if (codec_identified[st->index]) {
+                av_seek_frame(ic, st->index, 0.0, 0);
+            }
+            st->cur_dts= st->first_dts;
         }
+        url_fseek(&ic->pb, ic->data_offset, SEEK_SET);
     }
 
 #if 0
@@ -2058,6 +2091,7 @@ AVStream *av_new_stream(AVFormatContext *s, int id)
     st->start_time = AV_NOPTS_VALUE;
     st->duration = AV_NOPTS_VALUE;
     st->cur_dts = AV_NOPTS_VALUE;
+    st->first_dts = AV_NOPTS_VALUE;
 
     /* default pts settings is MPEG like */
     av_set_pts_info(st, 33, 1, 90000);