few bistream fixes and verbosity tweaks
[ffmpeg.git] / ffplay.c
index ff655f7..2df39d9 100644 (file)
--- a/ffplay.c
+++ b/ffplay.c
 #undef main /* We don't want SDL to override our main() */
 #endif
 
+#ifdef CONFIG_OS2
+#define INCL_DOS
+ #include <os2.h>
+ #include <stdio.h>
+ void MorphToPM()
+ {
+   PPIB pib;
+   PTIB tib;
+   DosGetInfoBlocks(&tib, &pib);
+   // Change flag from VIO to PM:
+   if (pib->pib_ultype==2) pib->pib_ultype = 3;
+ }
+#endif
+
 #if defined(__linux__)
 #define HAVE_X11
 #endif
@@ -92,6 +109,7 @@ typedef struct VideoState {
     int paused;
     int last_paused;
     int seek_req;
+    int seek_flags;
     int64_t seek_pos;
     AVFormatContext *ic;
     int dtg_active_format;
@@ -113,7 +131,7 @@ typedef struct VideoState {
     /* samples output by the codec. we reserve more space for avsync
        compensation */
     uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]; 
-    int audio_buf_size; /* in bytes */
+    unsigned int audio_buf_size; /* in bytes */
     int audio_buf_index; /* in bytes */
     AVPacket audio_pkt;
     uint8_t *audio_pkt_data;
@@ -143,6 +161,9 @@ typedef struct VideoState {
     SDL_mutex *pictq_mutex;
     SDL_cond *pictq_cond;
     
+    SDL_mutex *video_decoder_mutex;
+    SDL_mutex *audio_decoder_mutex;
+
     //    QETimer *video_timer;
     char filename[1024];
     int width, height, xleft, ytop;
@@ -171,6 +192,8 @@ static int step = 0;
 static int thread_count = 1;
 static int workaround_bugs = 1;
 static int fast = 0;
+static int lowres = 0;
+static int idct = FF_IDCT_AUTO;
 
 /* current context */
 static int is_full_screen;
@@ -587,10 +610,11 @@ static double get_master_clock(VideoState *is)
 }
 
 /* seek in the stream */
-static void stream_seek(VideoState *is, int64_t pos)
+static void stream_seek(VideoState *is, int64_t pos, int rel)
 {
     is->seek_pos = pos;
     is->seek_req = 1;
+    is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
 }
 
 /* pause or resume the video */
@@ -843,16 +867,6 @@ static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
     
     pts = pts1;
 
-    /* if B frames are present, and if the current picture is a I
-       or P frame, we use the last pts */
-    if (is->video_st->codec.has_b_frames && 
-        src_frame->pict_type != FF_B_TYPE) {
-        /* use last pts */
-        pts = is->video_last_P_pts;
-        /* get the pts for the next I or P frame if present */
-        is->video_last_P_pts = pts1;
-    }
-
     if (pts != 0) {
         /* update video clock with pts, if present */
         is->video_clock = pts;
@@ -860,8 +874,7 @@ static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
         pts = is->video_clock;
     }
     /* update video clock for next frame */
-    frame_delay = (double)is->video_st->codec.frame_rate_base / 
-        (double)is->video_st->codec.frame_rate;
+    frame_delay = av_q2d(is->video_st->codec.time_base);
     /* for MPEG2, the frame can be repeated, so we update the
        clock accordingly */
     if (src_frame->repeat_pict) {
@@ -902,28 +915,20 @@ static int video_thread(void *arg)
         /* NOTE: ipts is the PTS of the _first_ picture beginning in
            this packet, if any */
         pts = 0;
-        if (pkt->pts != AV_NOPTS_VALUE)
-            pts = (double)pkt->pts / AV_TIME_BASE;
-
-        if (is->video_st->codec.codec_id == CODEC_ID_RAWVIDEO) {
-            avpicture_fill((AVPicture *)frame, pkt->data, 
-                           is->video_st->codec.pix_fmt,
-                           is->video_st->codec.width,
-                           is->video_st->codec.height);
-            frame->pict_type = FF_I_TYPE;
-            if (output_picture2(is, frame, pts) < 0)
-                goto the_end;
-        } else {
+        if (pkt->dts != AV_NOPTS_VALUE)
+            pts = av_q2d(is->video_st->time_base)*pkt->dts;
+
+            SDL_LockMutex(is->video_decoder_mutex);
             len1 = avcodec_decode_video(&is->video_st->codec, 
                                         frame, &got_picture, 
                                         pkt->data, pkt->size);
+            SDL_UnlockMutex(is->video_decoder_mutex);
 //            if (len1 < 0)
 //                break;
             if (got_picture) {
                 if (output_picture2(is, frame, pts) < 0)
                     goto the_end;
             }
-        }
         av_free_packet(pkt);
         if (step) 
             if (cur_stream)
@@ -1042,9 +1047,11 @@ static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_pt
     for(;;) {
         /* NOTE: the audio packet can contain several frames */
         while (is->audio_pkt_size > 0) {
+            SDL_LockMutex(is->audio_decoder_mutex);
             len1 = avcodec_decode_audio(&is->audio_st->codec, 
                                         (int16_t *)audio_buf, &data_size, 
                                         is->audio_pkt_data, is->audio_pkt_size);
+            SDL_UnlockMutex(is->audio_decoder_mutex);
             if (len1 < 0) {
                 /* if error, we skip the frame */
                 is->audio_pkt_size = 0;
@@ -1089,7 +1096,7 @@ static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_pt
         
         /* if update the audio clock with the pts */
         if (pkt->pts != AV_NOPTS_VALUE) {
-            is->audio_clock = (double)pkt->pts / AV_TIME_BASE;
+            is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
         }
     }
 }
@@ -1173,11 +1180,14 @@ static int stream_component_open(VideoState *is, int stream_index)
     enc->debug_mv = debug_mv;
     enc->debug = debug;
     enc->workaround_bugs = workaround_bugs;
+    enc->lowres = lowres;
+    if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
+    enc->idct_algo= idct;
     if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
     if (!codec ||
         avcodec_open(enc, codec) < 0)
         return -1;
-#if defined(HAVE_PTHREADS) || defined(HAVE_W32THREADS)
+#if defined(HAVE_THREADS)
     if(thread_count>1)
         avcodec_thread_init(enc, thread_count);
 #endif
@@ -1330,6 +1340,7 @@ static int decode_thread(void *arg)
             ret = -1;
             goto fail;
         }
+        ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
     }
 
     /* if seeking requested, we execute it */
@@ -1340,7 +1351,7 @@ static int decode_thread(void *arg)
         /* add the stream start time */
         if (ic->start_time != AV_NOPTS_VALUE)
             timestamp += ic->start_time;
-        ret = av_seek_frame(ic, -1, timestamp);
+        ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
         if (ret < 0) {
             fprintf(stderr, "%s: could not seek to position %0.3f\n", 
                     is->filename, (double)timestamp / AV_TIME_BASE);
@@ -1417,7 +1428,7 @@ static int decode_thread(void *arg)
 #endif
         if (is->seek_req) {
             /* XXX: must lock decoder threads */
-            ret = av_seek_frame(is->ic, -1, is->seek_pos);
+            ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
             if (ret < 0) {
                 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
             }else{
@@ -1426,7 +1437,9 @@ static int decode_thread(void *arg)
                 }
                 if (is->video_stream >= 0) {
                     packet_queue_flush(&is->videoq);
+                    SDL_LockMutex(is->video_decoder_mutex);
                     avcodec_flush_buffers(&ic->streams[video_index]->codec);
+                    SDL_UnlockMutex(is->video_decoder_mutex);
                 }
             }
             is->seek_req = 0;
@@ -1442,7 +1455,11 @@ static int decode_thread(void *arg)
         }
         ret = av_read_frame(ic, pkt);
         if (ret < 0) {
-            break;
+           if (url_feof(&ic->pb) && url_ferror(&ic->pb) == 0) {
+                SDL_Delay(100); /* wait for user event */
+               continue;
+           } else
+               break;
         }
         if (pkt->stream_index == is->audio_stream) {
             packet_queue_put(&is->audioq, pkt);
@@ -1502,6 +1519,9 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
     /* start video display */
     is->pictq_mutex = SDL_CreateMutex();
     is->pictq_cond = SDL_CreateCond();
+    
+    is->audio_decoder_mutex = SDL_CreateMutex();
+    is->video_decoder_mutex = SDL_CreateMutex();
 
     /* add the refresh timer to draw the picture */
     schedule_refresh(is, 40);
@@ -1533,6 +1553,8 @@ static void stream_close(VideoState *is)
     }
     SDL_DestroyMutex(is->pictq_mutex);
     SDL_DestroyCond(is->pictq_cond);
+    SDL_DestroyMutex(is->audio_decoder_mutex);
+    SDL_DestroyMutex(is->video_decoder_mutex);
 }
 
 void stream_cycle_channel(VideoState *is, int codec_type)
@@ -1687,7 +1709,7 @@ void event_loop(void)
                 if (cur_stream) {
                     pos = get_master_clock(cur_stream);
                     pos += incr;
-                    stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE));
+                    stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
                 }
                 break;
             default:
@@ -1709,7 +1731,7 @@ void event_loop(void)
                ss = (ns%60);
                fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n", frac*100,
                        hh, mm, ss, thh, tmm, tss);
-               stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration));
+               stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
            }
            break;
         case SDL_VIDEORESIZE:
@@ -1808,7 +1830,7 @@ static void opt_vismv(const char *arg)
 static void opt_thread_count(const char *arg)
 {
     thread_count= atoi(arg);
-#if !defined(HAVE_PTHREADS) && !defined(HAVE_W32THREADS)
+#if !defined(HAVE_THREADS)
     fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
 #endif
 }
@@ -1832,6 +1854,8 @@ 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", "" },
+    { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
+    { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo",  "algo" },
 #ifdef CONFIG_NETWORK
     { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
 #endif
@@ -1879,6 +1903,14 @@ int main(int argc, char **argv)
     /* register all codecs, demux and protocols */
     av_register_all();
 
+    #ifdef CONFIG_OS2
+      MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
+      // Make stdout and stderr unbuffered
+      setbuf( stdout, NULL );
+      setbuf( stderr, NULL );
+    #endif
+
     parse_options(argc, argv, options);
 
     if (!input_filename)