]> git.sesse.net Git - ffmpeg/blobdiff - ffplay.c
avcodec_decode_audio2()
[ffmpeg] / ffplay.c
index e84b95cc22d21a5899744d354f88ef28d20cdd17..3ffc520c5dc29a59a0b14e419dff71d4a0e5d124 100644 (file)
--- a/ffplay.c
+++ b/ffplay.c
@@ -171,10 +171,6 @@ typedef struct VideoState {
     SDL_mutex *pictq_mutex;
     SDL_cond *pictq_cond;
 
-    SDL_mutex *video_decoder_mutex;
-    SDL_mutex *audio_decoder_mutex;
-    SDL_mutex *subtitle_decoder_mutex;
-
     //    QETimer *video_timer;
     char filename[1024];
     int width, height, xleft, ytop;
@@ -188,8 +184,8 @@ static AVInputFormat *file_iformat;
 static const char *input_filename;
 static int fs_screen_width;
 static int fs_screen_height;
-static int screen_width = 640;
-static int screen_height = 480;
+static int screen_width = 0;
+static int screen_height = 0;
 static int audio_disable;
 static int video_disable;
 static int seek_by_bytes;
@@ -217,6 +213,8 @@ static int is_full_screen;
 static VideoState *cur_stream;
 static int64_t audio_callback_time;
 
+AVPacket flush_pkt;
+
 #define FF_ALLOC_EVENT   (SDL_USEREVENT)
 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
 #define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
@@ -260,7 +258,7 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
     AVPacketList *pkt1;
 
     /* duplicate the packet */
-    if (av_dup_packet(pkt) < 0)
+    if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
         return -1;
 
     pkt1 = av_malloc(sizeof(AVPacketList));
@@ -831,9 +829,49 @@ static void video_audio_display(VideoState *s)
     SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
 }
 
+static int video_open(VideoState *is){
+    int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+    int w,h;
+
+    if(is_full_screen) flags |= SDL_FULLSCREEN;
+    else               flags |= SDL_RESIZABLE;
+
+    if (is_full_screen && fs_screen_width) {
+        w = fs_screen_width;
+        h = fs_screen_height;
+    } else if(!is_full_screen && screen_width){
+        w = screen_width;
+        h = screen_height;
+    }else if (is->video_st && is->video_st->codec->width){
+        w = is->video_st->codec->width;
+        h = is->video_st->codec->height;
+    } else {
+        w = 640;
+        h = 480;
+    }
+#ifndef CONFIG_DARWIN
+    screen = SDL_SetVideoMode(w, h, 0, flags);
+#else
+    /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
+    screen = SDL_SetVideoMode(w, h, 24, flags);
+#endif
+    if (!screen) {
+        fprintf(stderr, "SDL: could not set video mode - exiting\n");
+        return -1;
+    }
+    SDL_WM_SetCaption("FFplay", "FFplay");
+
+    is->width = screen->w;
+    is->height = screen->h;
+
+    return 0;
+}
+
 /* display the current picture, if any */
 static void video_display(VideoState *is)
 {
+    if(!screen)
+        video_open(cur_stream);
     if (is->audio_st && is->show_audio)
         video_audio_display(is);
     else if (is->video_st)
@@ -1283,17 +1321,21 @@ static int video_thread(void *arg)
         }
         if (packet_queue_get(&is->videoq, pkt, 1) < 0)
             break;
+
+        if(pkt->data == flush_pkt.data){
+            avcodec_flush_buffers(is->video_st->codec);
+            continue;
+        }
+
         /* NOTE: ipts is the PTS of the _first_ picture beginning in
            this packet, if any */
         pts = 0;
         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) {
@@ -1327,6 +1369,10 @@ static int subtitle_thread(void *arg)
         if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
             break;
 
+        if(pkt->data == flush_pkt.data){
+            avcodec_flush_buffers(is->subtitle_st->codec);
+            continue;
+        }
         SDL_LockMutex(is->subpq_mutex);
         while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
                !is->subtitleq.abort_request) {
@@ -1345,11 +1391,9 @@ static int subtitle_thread(void *arg)
         if (pkt->pts != AV_NOPTS_VALUE)
             pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
 
-        SDL_LockMutex(is->subtitle_decoder_mutex);
         len1 = avcodec_decode_subtitle(is->subtitle_st->codec,
                                     &sp->sub, &got_subtitle,
                                     pkt->data, pkt->size);
-        SDL_UnlockMutex(is->subtitle_decoder_mutex);
 //            if (len1 < 0)
 //                break;
         if (got_subtitle && sp->sub.format == 0) {
@@ -1491,11 +1535,9 @@ 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;
@@ -1535,6 +1577,11 @@ static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_pt
         /* read next packet */
         if (packet_queue_get(&is->audioq, pkt, 1) < 0)
             return -1;
+        if(pkt->data == flush_pkt.data){
+            avcodec_flush_buffers(is->audio_st->codec);
+            continue;
+        }
+
         is->audio_pkt_data = pkt->data;
         is->audio_pkt_size = pkt->size;
 
@@ -1588,7 +1635,6 @@ void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
     }
 }
 
-
 /* open a given stream. Return 0 if OK */
 static int stream_component_open(VideoState *is, int stream_index)
 {
@@ -1912,29 +1958,23 @@ static int decode_thread(void *arg)
         }
 #endif
         if (is->seek_req) {
-            /* XXX: must lock decoder threads */
-            SDL_LockMutex(is->video_decoder_mutex);
-            SDL_LockMutex(is->audio_decoder_mutex);
-            SDL_LockMutex(is->subtitle_decoder_mutex);
             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{
                 if (is->audio_stream >= 0) {
                     packet_queue_flush(&is->audioq);
-                    avcodec_flush_buffers(ic->streams[audio_index]->codec);
+                    packet_queue_put(&is->audioq, &flush_pkt);
                 }
                 if (is->subtitle_stream >= 0) {
                     packet_queue_flush(&is->subtitleq);
+                    packet_queue_put(&is->subtitleq, &flush_pkt);
                 }
                 if (is->video_stream >= 0) {
                     packet_queue_flush(&is->videoq);
-                    avcodec_flush_buffers(ic->streams[video_index]->codec);
+                    packet_queue_put(&is->videoq, &flush_pkt);
                 }
             }
-            SDL_UnlockMutex(is->subtitle_decoder_mutex);
-            SDL_UnlockMutex(is->audio_decoder_mutex);
-            SDL_UnlockMutex(is->video_decoder_mutex);
             is->seek_req = 0;
         }
 
@@ -2007,10 +2047,6 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
         return NULL;
     pstrcpy(is->filename, sizeof(is->filename), filename);
     is->iformat = iformat;
-    if (screen) {
-        is->width = screen->w;
-        is->height = screen->h;
-    }
     is->ytop = 0;
     is->xleft = 0;
 
@@ -2021,10 +2057,6 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
     is->subpq_mutex = SDL_CreateMutex();
     is->subpq_cond = SDL_CreateCond();
 
-    is->subtitle_decoder_mutex = SDL_CreateMutex();
-    is->audio_decoder_mutex = SDL_CreateMutex();
-    is->video_decoder_mutex = SDL_CreateMutex();
-
     /* add the refresh timer to draw the picture */
     schedule_refresh(is, 40);
 
@@ -2057,9 +2089,6 @@ static void stream_close(VideoState *is)
     SDL_DestroyCond(is->pictq_cond);
     SDL_DestroyMutex(is->subpq_mutex);
     SDL_DestroyCond(is->subpq_cond);
-    SDL_DestroyMutex(is->subtitle_decoder_mutex);
-    SDL_DestroyMutex(is->audio_decoder_mutex);
-    SDL_DestroyMutex(is->video_decoder_mutex);
 }
 
 static void stream_cycle_channel(VideoState *is, int codec_type)
@@ -2114,27 +2143,12 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
 
 static void toggle_full_screen(void)
 {
-    int w, h, flags;
     is_full_screen = !is_full_screen;
     if (!fs_screen_width) {
         /* use default SDL method */
-        SDL_WM_ToggleFullScreen(screen);
-    } else {
-        /* use the recorded resolution */
-        flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
-        if (is_full_screen) {
-            w = fs_screen_width;
-            h = fs_screen_height;
-            flags |= SDL_FULLSCREEN;
-        } else {
-            w = screen_width;
-            h = screen_height;
-            flags |= SDL_RESIZABLE;
-        }
-        screen = SDL_SetVideoMode(w, h, 0, flags);
-        cur_stream->width = w;
-        cur_stream->height = h;
+//        SDL_WM_ToggleFullScreen(screen);
     }
+    video_open(cur_stream);
 }
 
 static void toggle_pause(void)
@@ -2267,8 +2281,8 @@ static void event_loop(void)
             if (cur_stream) {
                 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
                                           SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
-                cur_stream->width = event.resize.w;
-                cur_stream->height = event.resize.h;
+                screen_width = cur_stream->width = event.resize.w;
+                screen_height= cur_stream->height= event.resize.h;
             }
             break;
         case SDL_QUIT:
@@ -2276,6 +2290,7 @@ static void event_loop(void)
             do_exit();
             break;
         case FF_ALLOC_EVENT:
+            video_open(event.user.data1);
             alloc_picture(event.user.data1);
             break;
         case FF_REFRESH_EVENT:
@@ -2290,11 +2305,19 @@ static void event_loop(void)
 void opt_width(const char *arg)
 {
     screen_width = atoi(arg);
+    if(screen_width<=0){
+        fprintf(stderr, "invalid width\n");
+        exit(1);
+    }
 }
 
 void opt_height(const char *arg)
 {
     screen_height = atoi(arg);
+    if(screen_height<=0){
+        fprintf(stderr, "invalid height\n");
+        exit(1);
+    }
 }
 
 static void opt_format(const char *arg)
@@ -2417,7 +2440,7 @@ void parse_arg_file(const char *filename)
 /* Called from the main */
 int main(int argc, char **argv)
 {
-    int flags, w, h;
+    int flags;
 
     /* register all codecs, demux and protocols */
     av_register_all();
@@ -2453,27 +2476,6 @@ int main(int argc, char **argv)
         fs_screen_width = vi->current_w;
         fs_screen_height = vi->current_h;
 #endif
-        flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
-        if (is_full_screen && fs_screen_width) {
-            w = fs_screen_width;
-            h = fs_screen_height;
-            flags |= SDL_FULLSCREEN;
-        } else {
-            w = screen_width;
-            h = screen_height;
-            flags |= SDL_RESIZABLE;
-        }
-#ifndef CONFIG_DARWIN
-        screen = SDL_SetVideoMode(w, h, 0, flags);
-#else
-        /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
-        screen = SDL_SetVideoMode(w, h, 24, flags);
-#endif
-        if (!screen) {
-            fprintf(stderr, "SDL: could not set video mode - exiting\n");
-            exit(1);
-        }
-        SDL_WM_SetCaption("FFplay", "FFplay");
     }
 
     SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
@@ -2481,6 +2483,9 @@ int main(int argc, char **argv)
     SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
     SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
 
+    av_init_packet(&flush_pkt);
+    flush_pkt.data= "FLUSH";
+
     cur_stream = stream_open(input_filename, file_iformat);
 
     event_loop();