FFT: factor a shuffle out of the inner loop and merge it into fft_permute.
[ffmpeg.git] / ffplay.c
index 38a2fe1..170acfd 100644 (file)
--- a/ffplay.c
+++ b/ffplay.c
@@ -58,6 +58,7 @@
 const char program_name[] = "FFplay";
 const int program_birth_year = 2003;
 
+//#define DEBUG
 //#define DEBUG_SYNC
 
 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
@@ -1016,12 +1017,12 @@ static int refresh_thread(void *opaque)
 {
     VideoState *is= opaque;
     while(!is->abort_request){
-    SDL_Event event;
-    event.type = FF_REFRESH_EVENT;
-    event.user.data1 = opaque;
+        SDL_Event event;
+        event.type = FF_REFRESH_EVENT;
+        event.user.data1 = opaque;
         if(!is->refresh){
             is->refresh=1;
-    SDL_PushEvent(&event);
+            SDL_PushEvent(&event);
         }
         usleep(is->audio_st && is->show_audio ? rdftspeed*1000 : 5000); //FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly
     }
@@ -1242,7 +1243,8 @@ retry:
             }
 
             /* display picture */
-            video_display(is);
+            if (!display_disable)
+                video_display(is);
 
             /* update queue size and signal for next picture */
             if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
@@ -1260,7 +1262,8 @@ retry:
            than nothing, just to test the implementation */
 
         /* display picture */
-        video_display(is);
+        if (!display_disable)
+            video_display(is);
     }
     if (show_status) {
         static int64_t last_time;
@@ -1541,56 +1544,49 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke
 {
     int len1, got_picture, i;
 
-        if (packet_queue_get(&is->videoq, pkt, 1) < 0)
-            return -1;
+    if (packet_queue_get(&is->videoq, pkt, 1) < 0)
+        return -1;
 
-        if(pkt->data == flush_pkt.data){
-            avcodec_flush_buffers(is->video_st->codec);
+    if (pkt->data == flush_pkt.data) {
+        avcodec_flush_buffers(is->video_st->codec);
 
-            SDL_LockMutex(is->pictq_mutex);
-            //Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
-            for(i=0; i<VIDEO_PICTURE_QUEUE_SIZE; i++){
-                is->pictq[i].target_clock= 0;
-            }
-            while (is->pictq_size && !is->videoq.abort_request) {
-                SDL_CondWait(is->pictq_cond, is->pictq_mutex);
-            }
-            is->video_current_pos= -1;
-            SDL_UnlockMutex(is->pictq_mutex);
-
-            init_pts_correction(&is->pts_ctx);
-            is->frame_last_pts= AV_NOPTS_VALUE;
-            is->frame_last_delay = 0;
-            is->frame_timer = (double)av_gettime() / 1000000.0;
-            is->skip_frames= 1;
-            is->skip_frames_index= 0;
-            return 0;
+        SDL_LockMutex(is->pictq_mutex);
+        //Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
+        for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
+            is->pictq[i].target_clock= 0;
         }
+        while (is->pictq_size && !is->videoq.abort_request) {
+            SDL_CondWait(is->pictq_cond, is->pictq_mutex);
+        }
+        is->video_current_pos = -1;
+        SDL_UnlockMutex(is->pictq_mutex);
 
-        /* NOTE: ipts is the PTS of the _first_ picture beginning in
-           this packet, if any */
-        is->video_st->codec->reordered_opaque= pkt->pts;
-        len1 = avcodec_decode_video2(is->video_st->codec,
-                                    frame, &got_picture,
-                                    pkt);
+        init_pts_correction(&is->pts_ctx);
+        is->frame_last_pts = AV_NOPTS_VALUE;
+        is->frame_last_delay = 0;
+        is->frame_timer = (double)av_gettime() / 1000000.0;
+        is->skip_frames = 1;
+        is->skip_frames_index = 0;
+        return 0;
+    }
 
-        if (got_picture) {
-            if (decoder_reorder_pts == -1) {
-                *pts = guess_correct_pts(&is->pts_ctx, frame->reordered_opaque, pkt->dts);
-            } else if (decoder_reorder_pts) {
-                *pts = frame->reordered_opaque;
-            } else {
-                *pts = pkt->dts;
-            }
+    len1 = avcodec_decode_video2(is->video_st->codec,
+                                 frame, &got_picture,
+                                 pkt);
 
-            if (*pts == AV_NOPTS_VALUE) {
-                *pts = 0;
-            }
+    if (got_picture) {
+        if (decoder_reorder_pts == -1) {
+            *pts = guess_correct_pts(&is->pts_ctx, frame->pkt_pts, frame->pkt_dts);
+        } else if (decoder_reorder_pts) {
+            *pts = frame->pkt_pts;
+        } else {
+            *pts = frame->pkt_dts;
+        }
+
+        if (*pts == AV_NOPTS_VALUE) {
+            *pts = 0;
         }
 
-//            if (len1 < 0)
-//                break;
-    if (got_picture){
         is->skip_frames_index += 1;
         if(is->skip_frames_index >= is->skip_frames){
             is->skip_frames_index -= FFMAX(is->skip_frames, 1.0);
@@ -1616,6 +1612,9 @@ static int input_get_buffer(AVCodecContext *codec, AVFrame *pic)
     int i, w, h, stride[4];
     unsigned edge;
 
+    if (codec->codec->capabilities & CODEC_CAP_NEG_LINESIZES)
+        perms |= AV_PERM_NEG_LINESIZES;
+
     if(pic->buffer_hints & FF_BUFFER_HINTS_VALID) {
         if(pic->buffer_hints & FF_BUFFER_HINTS_READABLE) perms |= AV_PERM_READ;
         if(pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE) perms |= AV_PERM_PRESERVE;
@@ -1649,6 +1648,8 @@ static int input_get_buffer(AVCodecContext *codec, AVFrame *pic)
     pic->age    = INT_MAX;
     pic->type   = FF_BUFFER_TYPE_USER;
     pic->reordered_opaque = codec->reordered_opaque;
+    if(codec->pkt) pic->pkt_pts = codec->pkt->pts;
+    else           pic->pkt_pts = AV_NOPTS_VALUE;
     return 0;
 }
 
@@ -1674,6 +1675,8 @@ static int input_reget_buffer(AVCodecContext *codec, AVFrame *pic)
     }
 
     pic->reordered_opaque = codec->reordered_opaque;
+    if(codec->pkt) pic->pkt_pts = codec->pkt->pts;
+    else           pic->pkt_pts = AV_NOPTS_VALUE;
     return 0;
 }
 
@@ -1691,6 +1694,7 @@ static int input_init(AVFilterContext *ctx, const char *args, void *opaque)
         codec->get_buffer     = input_get_buffer;
         codec->release_buffer = input_release_buffer;
         codec->reget_buffer   = input_reget_buffer;
+        codec->thread_safe_callbacks = 1;
     }
 
     priv->frame = avcodec_alloc_frame();
@@ -1779,30 +1783,20 @@ static AVFilter input_filter =
                                   { .name = NULL }},
 };
 
-#endif  /* CONFIG_AVFILTER */
-
-static int video_thread(void *arg)
+static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters)
 {
-    VideoState *is = arg;
-    AVFrame *frame= avcodec_alloc_frame();
-    int64_t pts_int;
-    double pts;
-    int ret;
-
-#if CONFIG_AVFILTER
-    int64_t pos;
     char sws_flags_str[128];
+    int ret;
     FFSinkContext ffsink_ctx = { .pix_fmt = PIX_FMT_YUV420P };
     AVFilterContext *filt_src = NULL, *filt_out = NULL;
-    AVFilterGraph *graph = avfilter_graph_alloc();
     snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags);
     graph->scale_sws_opts = av_strdup(sws_flags_str);
 
-    if (avfilter_graph_create_filter(&filt_src, &input_filter, "src",
-                                     NULL, is, graph) < 0)
+    if ((ret = avfilter_graph_create_filter(&filt_src, &input_filter, "src",
+                                            NULL, is, graph)) < 0)
         goto the_end;
-    if (avfilter_graph_create_filter(&filt_out, &ffsink, "out",
-                                     NULL, &ffsink_ctx, graph) < 0)
+    if ((ret = avfilter_graph_create_filter(&filt_out, &ffsink, "out",
+                                            NULL, &ffsink_ctx, graph)) < 0)
         goto the_end;
 
     if(vfilters) {
@@ -1819,17 +1813,40 @@ static int video_thread(void *arg)
         inputs->pad_idx = 0;
         inputs->next    = NULL;
 
-        if (avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL) < 0)
+        if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
             goto the_end;
         av_freep(&vfilters);
     } else {
-        if(avfilter_link(filt_src, 0, filt_out, 0) < 0)          goto the_end;
+        if ((ret = avfilter_link(filt_src, 0, filt_out, 0)) < 0)
+            goto the_end;
     }
 
-    if (avfilter_graph_config(graph, NULL) < 0)
+    if ((ret = avfilter_graph_config(graph, NULL)) < 0)
         goto the_end;
 
     is->out_video_filter = filt_out;
+the_end:
+    return ret;
+}
+
+#endif  /* CONFIG_AVFILTER */
+
+static int video_thread(void *arg)
+{
+    VideoState *is = arg;
+    AVFrame *frame= avcodec_alloc_frame();
+    int64_t pts_int;
+    double pts;
+    int ret;
+
+#if CONFIG_AVFILTER
+    AVFilterGraph *graph = avfilter_graph_alloc();
+    AVFilterContext *filt_out = NULL;
+    int64_t pos;
+
+    if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
+        goto the_end;
+    filt_out = is->out_video_filter;
 #endif
 
     for(;;) {
@@ -1850,12 +1867,12 @@ static int video_thread(void *arg)
         }
 
         if (av_cmp_q(tb, is->video_st->time_base)) {
-            int64_t pts1 = pts_int;
+            av_unused int64_t pts1 = pts_int;
             pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base);
-            av_log(NULL, AV_LOG_DEBUG, "video_thread(): "
-                   "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
-                   tb.num, tb.den, pts1,
-                   is->video_st->time_base.num, is->video_st->time_base.den, pts_int);
+            av_dlog(NULL, "video_thread(): "
+                    "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
+                    tb.num, tb.den, pts1,
+                    is->video_st->time_base.num, is->video_st->time_base.den, pts_int);
         }
 #else
         ret = get_video_frame(is, frame, &pts_int, &pkt);
@@ -1883,8 +1900,7 @@ static int video_thread(void *arg)
     }
  the_end:
 #if CONFIG_AVFILTER
-    avfilter_graph_free(graph);
-    av_freep(&graph);
+    avfilter_graph_free(&graph);
 #endif
     av_free(frame);
     return 0;
@@ -2244,7 +2260,7 @@ static int stream_component_open(VideoState *is, int stream_index)
     avctx->skip_loop_filter= skip_loop_filter;
     avctx->error_recognition= error_recognition;
     avctx->error_concealment= error_concealment;
-    avcodec_thread_init(avctx, thread_count);
+    avctx->thread_count= thread_count;
 
     set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0, codec);
 
@@ -2398,8 +2414,6 @@ static int decode_thread(void *arg)
     AVFormatContext *ic;
     int err, i, ret;
     int st_index[AVMEDIA_TYPE_NB];
-    int st_count[AVMEDIA_TYPE_NB]={0};
-    int st_best_packet_count[AVMEDIA_TYPE_NB];
     AVPacket pkt1, *pkt = &pkt1;
     AVFormatParameters params, *ap = &params;
     int eof=0;
@@ -2408,7 +2422,6 @@ static int decode_thread(void *arg)
     ic = avformat_alloc_context();
 
     memset(st_index, -1, sizeof(st_index));
-    memset(st_best_packet_count, -1, sizeof(st_best_packet_count));
     is->video_stream = -1;
     is->audio_stream = -1;
     is->subtitle_stream = -1;
@@ -2464,33 +2477,26 @@ static int decode_thread(void *arg)
         }
     }
 
-    for(i = 0; i < ic->nb_streams; i++) {
-        AVStream *st= ic->streams[i];
-        AVCodecContext *avctx = st->codec;
+    for (i = 0; i < ic->nb_streams; i++)
         ic->streams[i]->discard = AVDISCARD_ALL;
-        if(avctx->codec_type >= (unsigned)AVMEDIA_TYPE_NB)
-            continue;
-        if(st_count[avctx->codec_type]++ != wanted_stream[avctx->codec_type] && wanted_stream[avctx->codec_type] >= 0)
-            continue;
-
-        if(st_best_packet_count[avctx->codec_type] >= st->codec_info_nb_frames)
-            continue;
-        st_best_packet_count[avctx->codec_type]= st->codec_info_nb_frames;
-
-        switch(avctx->codec_type) {
-        case AVMEDIA_TYPE_AUDIO:
-            if (!audio_disable)
-                st_index[AVMEDIA_TYPE_AUDIO] = i;
-            break;
-        case AVMEDIA_TYPE_VIDEO:
-        case AVMEDIA_TYPE_SUBTITLE:
-            if (!video_disable)
-                st_index[avctx->codec_type] = i;
-            break;
-        default:
-            break;
-        }
-    }
+    if (!video_disable)
+        st_index[AVMEDIA_TYPE_VIDEO] =
+            av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
+                                wanted_stream[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
+    if (!audio_disable)
+        st_index[AVMEDIA_TYPE_AUDIO] =
+            av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
+                                wanted_stream[AVMEDIA_TYPE_AUDIO],
+                                st_index[AVMEDIA_TYPE_VIDEO],
+                                NULL, 0);
+    if (!video_disable)
+        st_index[AVMEDIA_TYPE_SUBTITLE] =
+            av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
+                                wanted_stream[AVMEDIA_TYPE_SUBTITLE],
+                                (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
+                                 st_index[AVMEDIA_TYPE_AUDIO] :
+                                 st_index[AVMEDIA_TYPE_VIDEO]),
+                                NULL, 0);
     if (show_status) {
         dump_format(ic, 0, is->filename, 0);
     }