support fixing missing pts by parsing future frames
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 15 Aug 2005 14:22:43 +0000 (14:22 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 15 Aug 2005 14:22:43 +0000 (14:22 +0000)
Originally committed as revision 4526 to svn://svn.ffmpeg.org/ffmpeg/trunk

ffmpeg.c
ffplay.c
libavformat/avformat.h
libavformat/utils.c

index fc3264a..945a81d 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -211,6 +211,7 @@ static int frame_skip_cmp= FF_CMP_DCTMAX;
 extern int loop_input; /* currently a hack */
 static int loop_output = AVFMT_NOOUTPUTLOOP;
 static int gray_only = 0;
+static int genpts = 0;
 
 static int gop_size = 12;
 static int intra_only = 0;
@@ -3031,6 +3032,9 @@ static void opt_input_file(const char *filename)
         print_error(filename, err);
         exit(1);
     }
+
+    if(genpts)
+        ic->flags|= AVFMT_FLAG_GENPTS;
     
     /* If not enough info to get the stream parameters, we decode the
        first frames to get it. (used in mpeg case for example) */
@@ -4340,6 +4344,7 @@ const OptionDef options[] = {
     { "skip_cmp", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&frame_skip_cmp}, "frame skip compare function", "compare function" },
     { "gray", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&gray_only }, "encode/decode grayscale" },
     { "newvideo", OPT_VIDEO, {(void*)opt_new_video_stream}, "add a new video stream to the current output stream" },
+    { "genpts", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&genpts }, "generate pts" },
 
     /* audio options */
     { "ab", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", },
index 60b0b20..967ad1f 100644 (file)
--- a/ffplay.c
+++ b/ffplay.c
@@ -210,6 +210,7 @@ static int step = 0;
 static int thread_count = 1;
 static int workaround_bugs = 1;
 static int fast = 0;
+static int genpts = 0;
 static int lowres = 0;
 static int idct = FF_IDCT_AUTO;
 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
@@ -1802,6 +1803,10 @@ static int decode_thread(void *arg)
 #else
     use_play = 0;
 #endif
+
+    if(genpts)
+        ic->flags |= AVFMT_FLAG_GENPTS;
+
     if (!use_play) {
         err = av_find_stream_info(ic);
         if (err < 0) {
@@ -2356,6 +2361,7 @@ const OptionDef options[] = {
     { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
     { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
     { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
+    { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
     { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
     { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
     { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
index 136f1c0..2b39378 100644 (file)
@@ -5,8 +5,8 @@
 extern "C" {
 #endif
 
-#define LIBAVFORMAT_VERSION_INT ((49<<16)+(0<<8)+0)
-#define LIBAVFORMAT_VERSION     49.0.0
+#define LIBAVFORMAT_VERSION_INT ((49<<16)+(1<<8)+0)
+#define LIBAVFORMAT_VERSION     49.1.0
 #define LIBAVFORMAT_BUILD       LIBAVFORMAT_VERSION_INT
 
 #define LIBAVFORMAT_IDENT       "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
@@ -332,6 +332,8 @@ typedef struct AVFormatContext {
     /* number of times to loop output in formats that support it */
     int loop_output;
     
+    int flags;
+#define AVFMT_FLAG_GENPTS       0x0001 ///< generate pts if missing even if it requires parsing future frames
 } AVFormatContext;
 
 typedef struct AVPacketList {
index 32a4c92..5a81ee0 100644 (file)
@@ -955,16 +955,66 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
 int av_read_frame(AVFormatContext *s, AVPacket *pkt)
 {
     AVPacketList *pktl;
+    int eof=0;
+    const int genpts= s->flags & AVFMT_FLAG_GENPTS;
 
-    pktl = s->packet_buffer;
-    if (pktl) {
-        /* read packet from packet buffer, if there is data */
-        *pkt = pktl->pkt;
-        s->packet_buffer = pktl->next;
-        av_free(pktl);
-        return 0;
-    } else {
-        return av_read_frame_internal(s, pkt);
+    for(;;){
+        pktl = s->packet_buffer;
+        if (pktl) {
+            AVPacket *next_pkt= &pktl->pkt;
+            AVStream *st= s->streams[ next_pkt->stream_index ];
+
+            if(genpts && next_pkt->dts != AV_NOPTS_VALUE){
+                while(pktl && next_pkt->pts == AV_NOPTS_VALUE){
+                    if(   pktl->pkt.stream_index == next_pkt->stream_index 
+                       && next_pkt->dts < pktl->pkt.dts
+                       && pktl->pkt.pts != pktl->pkt.dts //not b frame
+                       /*&& pktl->pkt.dts != AV_NOPTS_VALUE*/){
+                        next_pkt->pts= pktl->pkt.dts;
+                    }
+                    pktl= pktl->next;
+                }
+                pktl = s->packet_buffer;
+            }
+            
+            if(   next_pkt->pts != AV_NOPTS_VALUE 
+               || next_pkt->dts == AV_NOPTS_VALUE 
+               || !genpts || eof){
+                /* read packet from packet buffer, if there is data */
+                *pkt = *next_pkt;
+                s->packet_buffer = pktl->next;
+                av_free(pktl);
+                return 0;
+            }
+        }
+        if(genpts){
+            AVPacketList **plast_pktl= &s->packet_buffer;
+            int ret= av_read_frame_internal(s, pkt);
+            if(ret<0){
+                if(pktl && ret != -EAGAIN){
+                    eof=1;
+                    continue;
+                }else
+                    return ret;
+            }
+            
+            /* duplicate the packet */
+            if (av_dup_packet(pkt) < 0)
+                return AVERROR_NOMEM;
+
+            while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last?
+            
+            pktl = av_mallocz(sizeof(AVPacketList));
+            if (!pktl)
+                return AVERROR_NOMEM;
+    
+            /* 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);
+        }
     }
 }