]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - ffplay.c
subtitles support for ffplay patch by (Ian Caulfield, imc25 : cam ac uk)
[frescor/ffmpeg.git] / ffplay.c
1 /*
2  * FFplay : Simple Media Player based on the ffmpeg libraries
3  * Copyright (c) 2003 Fabrice Bellard
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 #define HAVE_AV_CONFIG_H
20 #include "avformat.h"
21
22 #include "cmdutils.h"
23
24 #include <SDL.h>
25 #include <SDL_thread.h>
26
27 #ifdef CONFIG_WIN32
28 #undef main /* We don't want SDL to override our main() */
29 #endif
30
31 #ifdef CONFIG_OS2
32 #define INCL_DOS
33  #include <os2.h>
34  #include <stdio.h>
35  
36  void MorphToPM()
37  {
38    PPIB pib;
39    PTIB tib;
40  
41    DosGetInfoBlocks(&tib, &pib);
42  
43    // Change flag from VIO to PM:
44    if (pib->pib_ultype==2) pib->pib_ultype = 3;
45  }
46 #endif
47
48 #if defined(__linux__)
49 #define HAVE_X11
50 #endif
51
52 #ifdef HAVE_X11
53 #include <X11/Xlib.h>
54 #endif
55
56 //#define DEBUG_SYNC
57
58 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
59 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
60 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
61
62 /* SDL audio buffer size, in samples. Should be small to have precise
63    A/V sync as SDL does not have hardware buffer fullness info. */
64 #define SDL_AUDIO_BUFFER_SIZE 1024
65
66 /* no AV sync correction is done if below the AV sync threshold */
67 #define AV_SYNC_THRESHOLD 0.01
68 /* no AV correction is done if too big error */
69 #define AV_NOSYNC_THRESHOLD 10.0
70
71 /* maximum audio speed change to get correct sync */
72 #define SAMPLE_CORRECTION_PERCENT_MAX 10
73
74 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
75 #define AUDIO_DIFF_AVG_NB   20
76
77 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
78 #define SAMPLE_ARRAY_SIZE (2*65536)
79
80 typedef struct PacketQueue {
81     AVPacketList *first_pkt, *last_pkt;
82     int nb_packets;
83     int size;
84     int abort_request;
85     SDL_mutex *mutex;
86     SDL_cond *cond;
87 } PacketQueue;
88
89 #define VIDEO_PICTURE_QUEUE_SIZE 1
90 #define SUBPICTURE_QUEUE_SIZE 4
91
92 typedef struct VideoPicture {
93     double pts; /* presentation time stamp for this picture */
94     SDL_Overlay *bmp;
95     int width, height; /* source height & width */
96     int allocated;
97 } VideoPicture;
98
99 typedef struct SubPicture {
100     double pts; /* presentation time stamp for this picture */
101     AVSubtitle sub;
102 } SubPicture;
103
104 enum {
105     AV_SYNC_AUDIO_MASTER, /* default choice */
106     AV_SYNC_VIDEO_MASTER,
107     AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
108 };
109
110 typedef struct VideoState {
111     SDL_Thread *parse_tid;
112     SDL_Thread *video_tid;
113     AVInputFormat *iformat;
114     int no_background;
115     int abort_request;
116     int paused;
117     int last_paused;
118     int seek_req;
119     int seek_flags;
120     int64_t seek_pos;
121     AVFormatContext *ic;
122     int dtg_active_format;
123
124     int audio_stream;
125     
126     int av_sync_type;
127     double external_clock; /* external clock base */
128     int64_t external_clock_time;
129     
130     double audio_clock;
131     double audio_diff_cum; /* used for AV difference average computation */
132     double audio_diff_avg_coef;
133     double audio_diff_threshold;
134     int audio_diff_avg_count;
135     AVStream *audio_st;
136     PacketQueue audioq;
137     int audio_hw_buf_size;
138     /* samples output by the codec. we reserve more space for avsync
139        compensation */
140     uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]; 
141     unsigned int audio_buf_size; /* in bytes */
142     int audio_buf_index; /* in bytes */
143     AVPacket audio_pkt;
144     uint8_t *audio_pkt_data;
145     int audio_pkt_size;
146     
147     int show_audio; /* if true, display audio samples */
148     int16_t sample_array[SAMPLE_ARRAY_SIZE];
149     int sample_array_index;
150     int last_i_start;
151     
152     SDL_Thread *subtitle_tid;
153     int subtitle_stream;
154     int subtitle_stream_changed;
155     AVStream *subtitle_st;
156     PacketQueue subtitleq;
157     SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
158     int subpq_size, subpq_rindex, subpq_windex;
159     SDL_mutex *subpq_mutex;
160     SDL_cond *subpq_cond;
161         
162     double frame_timer;
163     double frame_last_pts;
164     double frame_last_delay;
165     double video_clock;
166     int video_stream;
167     AVStream *video_st;
168     PacketQueue videoq;
169     double video_last_P_pts; /* pts of the last P picture (needed if B
170                                 frames are present) */
171     double video_current_pts; /* current displayed pts (different from
172                                  video_clock if frame fifos are used) */
173     int64_t video_current_pts_time; /* time at which we updated
174                                        video_current_pts - used to
175                                        have running video pts */
176     VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
177     int pictq_size, pictq_rindex, pictq_windex;
178     SDL_mutex *pictq_mutex;
179     SDL_cond *pictq_cond;
180     
181     SDL_mutex *video_decoder_mutex;
182     SDL_mutex *audio_decoder_mutex;
183     SDL_mutex *subtitle_decoder_mutex;
184
185     //    QETimer *video_timer;
186     char filename[1024];
187     int width, height, xleft, ytop;
188 } VideoState;
189
190 void show_help(void);
191 static int audio_write_get_buf_size(VideoState *is);
192
193 /* options specified by the user */
194 static AVInputFormat *file_iformat;
195 static AVImageFormat *image_format;
196 static const char *input_filename;
197 static int fs_screen_width;
198 static int fs_screen_height;
199 static int screen_width = 640;
200 static int screen_height = 480;
201 static int audio_disable;
202 static int video_disable;
203 static int display_disable;
204 static int show_status;
205 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
206 static int64_t start_time = AV_NOPTS_VALUE;
207 static int debug = 0;
208 static int debug_mv = 0;
209 static int step = 0;
210 static int thread_count = 1;
211 static int workaround_bugs = 1;
212 static int fast = 0;
213 static int lowres = 0;
214 static int idct = FF_IDCT_AUTO;
215 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
216 static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
217 static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
218 static int error_resilience = FF_ER_CAREFULL;
219 static int error_concealment = 3;
220
221 /* current context */
222 static int is_full_screen;
223 static VideoState *cur_stream;
224 static int64_t audio_callback_time;
225
226 #define FF_ALLOC_EVENT   (SDL_USEREVENT)
227 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
228 #define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
229
230 SDL_Surface *screen;
231
232 /* packet queue handling */
233 static void packet_queue_init(PacketQueue *q)
234 {
235     memset(q, 0, sizeof(PacketQueue));
236     q->mutex = SDL_CreateMutex();
237     q->cond = SDL_CreateCond();
238 }
239
240 static void packet_queue_flush(PacketQueue *q)
241 {
242     AVPacketList *pkt, *pkt1;
243
244     SDL_LockMutex(q->mutex);
245     for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
246         pkt1 = pkt->next;
247         av_free_packet(&pkt->pkt);
248         av_freep(&pkt);
249     }
250     q->last_pkt = NULL;
251     q->first_pkt = NULL;
252     q->nb_packets = 0;
253     q->size = 0;
254     SDL_UnlockMutex(q->mutex);
255 }
256
257 static void packet_queue_end(PacketQueue *q)
258 {
259     packet_queue_flush(q);
260     SDL_DestroyMutex(q->mutex);
261     SDL_DestroyCond(q->cond);
262 }
263
264 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
265 {
266     AVPacketList *pkt1;
267
268     /* duplicate the packet */
269     if (av_dup_packet(pkt) < 0)
270         return -1;
271     
272     pkt1 = av_malloc(sizeof(AVPacketList));
273     if (!pkt1)
274         return -1;
275     pkt1->pkt = *pkt;
276     pkt1->next = NULL;
277
278
279     SDL_LockMutex(q->mutex);
280
281     if (!q->last_pkt)
282
283         q->first_pkt = pkt1;
284     else
285         q->last_pkt->next = pkt1;
286     q->last_pkt = pkt1;
287     q->nb_packets++;
288     q->size += pkt1->pkt.size;
289     /* XXX: should duplicate packet data in DV case */
290     SDL_CondSignal(q->cond);
291
292     SDL_UnlockMutex(q->mutex);
293     return 0;
294 }
295
296 static void packet_queue_abort(PacketQueue *q)
297 {
298     SDL_LockMutex(q->mutex);
299
300     q->abort_request = 1;
301     
302     SDL_CondSignal(q->cond);
303
304     SDL_UnlockMutex(q->mutex);
305 }
306
307 /* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
308 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
309 {
310     AVPacketList *pkt1;
311     int ret;
312
313     SDL_LockMutex(q->mutex);
314
315     for(;;) {
316         if (q->abort_request) {
317             ret = -1;
318             break;
319         }
320             
321         pkt1 = q->first_pkt;
322         if (pkt1) {
323             q->first_pkt = pkt1->next;
324             if (!q->first_pkt)
325                 q->last_pkt = NULL;
326             q->nb_packets--;
327             q->size -= pkt1->pkt.size;
328             *pkt = pkt1->pkt;
329             av_free(pkt1);
330             ret = 1;
331             break;
332         } else if (!block) {
333             ret = 0;
334             break;
335         } else {
336             SDL_CondWait(q->cond, q->mutex);
337         }
338     }
339     SDL_UnlockMutex(q->mutex);
340     return ret;
341 }
342
343 static inline void fill_rectangle(SDL_Surface *screen, 
344                                   int x, int y, int w, int h, int color)
345 {
346     SDL_Rect rect;
347     rect.x = x;
348     rect.y = y;
349     rect.w = w;
350     rect.h = h;
351     SDL_FillRect(screen, &rect, color);
352 }
353
354 #if 0
355 /* draw only the border of a rectangle */
356 void fill_border(VideoState *s, int x, int y, int w, int h, int color)
357 {
358     int w1, w2, h1, h2;
359
360     /* fill the background */
361     w1 = x;
362     if (w1 < 0)
363         w1 = 0;
364     w2 = s->width - (x + w);
365     if (w2 < 0)
366         w2 = 0;
367     h1 = y;
368     if (h1 < 0)
369         h1 = 0;
370     h2 = s->height - (y + h);
371     if (h2 < 0)
372         h2 = 0;
373     fill_rectangle(screen, 
374                    s->xleft, s->ytop, 
375                    w1, s->height, 
376                    color);
377     fill_rectangle(screen, 
378                    s->xleft + s->width - w2, s->ytop, 
379                    w2, s->height, 
380                    color);
381     fill_rectangle(screen, 
382                    s->xleft + w1, s->ytop, 
383                    s->width - w1 - w2, h1, 
384                    color);
385     fill_rectangle(screen, 
386                    s->xleft + w1, s->ytop + s->height - h2,
387                    s->width - w1 - w2, h2,
388                    color);
389 }
390 #endif
391
392
393
394 #define SCALEBITS 10
395 #define ONE_HALF  (1 << (SCALEBITS - 1))
396 #define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
397
398 #define RGB_TO_Y_CCIR(r, g, b) \
399 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
400   FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
401
402 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
403 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 +         \
404      FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
405
406 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
407 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 -           \
408    FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
409
410 #define ALPHA_BLEND(a, oldp, newp, s)\
411 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
412
413 #define RGBA_IN(r, g, b, a, s)\
414 {\
415     unsigned int v = ((const uint32_t *)(s))[0];\
416     a = (v >> 24) & 0xff;\
417     r = (v >> 16) & 0xff;\
418     g = (v >> 8) & 0xff;\
419     b = v & 0xff;\
420 }
421
422 #define YUVA_IN(y, u, v, a, s, pal)\
423 {\
424     unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)s];\
425     a = (val >> 24) & 0xff;\
426     y = (val >> 16) & 0xff;\
427     u = (val >> 8) & 0xff;\
428     v = val & 0xff;\
429 }
430
431 #define YUVA_OUT(d, y, u, v, a)\
432 {\
433     ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
434 }
435
436
437 #define BPP 1
438
439 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
440 {
441     int wrap, wrap3, width2, skip2;
442     int y, u, v, a, u1, v1, a1, w, h;
443     uint8_t *lum, *cb, *cr;
444     const uint8_t *p;
445     const uint32_t *pal;
446
447     lum = dst->data[0] + rect->y * dst->linesize[0];
448     cb = dst->data[1] + (rect->y >> 1) * dst->linesize[1];
449     cr = dst->data[2] + (rect->y >> 1) * dst->linesize[2];
450
451     width2 = (rect->w + 1) >> 1;
452     skip2 = rect->x >> 1;
453     wrap = dst->linesize[0];
454     wrap3 = rect->linesize;
455     p = rect->bitmap;
456     pal = rect->rgba_palette;  /* Now in YCrCb! */
457     
458     if (rect->y & 1) {
459         lum += rect->x;
460         cb += skip2;
461         cr += skip2;
462     
463         if (rect->x & 1) {
464             YUVA_IN(y, u, v, a, p, pal);
465             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
466             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
467             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
468             cb++;
469             cr++;
470             lum++;
471             p += BPP;
472         }
473         for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
474             YUVA_IN(y, u, v, a, p, pal);
475             u1 = u;
476             v1 = v;
477             a1 = a;
478             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
479
480             YUVA_IN(y, u, v, a, p + BPP, pal);
481             u1 += u;
482             v1 += v;
483             a1 += a;
484             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
485             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
486             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
487             cb++;
488             cr++;
489             p += 2 * BPP;
490             lum += 2;
491         }
492         if (w) {
493             YUVA_IN(y, u, v, a, p, pal);
494             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
495             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
496             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
497         }
498         p += wrap3 + (wrap3 - rect->w * BPP);
499         lum += wrap + (wrap - rect->w - rect->x);
500         cb += dst->linesize[1] - width2 - skip2;
501         cr += dst->linesize[2] - width2 - skip2;
502     }
503     for(h = rect->h - (rect->y & 1); h >= 2; h -= 2) {
504         lum += rect->x;
505         cb += skip2;
506         cr += skip2;
507     
508         if (rect->x & 1) {
509             YUVA_IN(y, u, v, a, p, pal);
510             u1 = u;
511             v1 = v;
512             a1 = a;
513             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
514             p += wrap3;
515             lum += wrap;
516             YUVA_IN(y, u, v, a, p, pal);
517             u1 += u;
518             v1 += v;
519             a1 += a;
520             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
521             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
522             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
523             cb++;
524             cr++;
525             p += -wrap3 + BPP;
526             lum += -wrap + 1;
527         }
528         for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
529             YUVA_IN(y, u, v, a, p, pal);
530             u1 = u;
531             v1 = v;
532             a1 = a;
533             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
534
535             YUVA_IN(y, u, v, a, p, pal);
536             u1 += u;
537             v1 += v;
538             a1 += a;
539             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
540             p += wrap3;
541             lum += wrap;
542
543             YUVA_IN(y, u, v, a, p, pal);
544             u1 += u;
545             v1 += v;
546             a1 += a;
547             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
548
549             YUVA_IN(y, u, v, a, p, pal);
550             u1 += u;
551             v1 += v;
552             a1 += a;
553             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
554
555             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
556             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
557
558             cb++;
559             cr++;
560             p += -wrap3 + 2 * BPP;
561             lum += -wrap + 2;
562         }
563         if (w) {
564             YUVA_IN(y, u, v, a, p, pal);
565             u1 = u;
566             v1 = v;
567             a1 = a;
568             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
569             p += wrap3;
570             lum += wrap;
571             YUVA_IN(y, u, v, a, p, pal);
572             u1 += u;
573             v1 += v;
574             a1 += a;
575             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
576             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
577             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
578             cb++;
579             cr++;
580             p += -wrap3 + BPP;
581             lum += -wrap + 1;
582         }
583         p += wrap3 + (wrap3 - rect->w * BPP);
584         lum += wrap + (wrap - rect->w - rect->x);
585         cb += dst->linesize[1] - width2 - skip2;
586         cr += dst->linesize[2] - width2 - skip2;
587     }
588     /* handle odd height */
589     if (h) {
590         lum += rect->x;
591         cb += skip2;
592         cr += skip2;
593     
594         if (rect->x & 1) {
595             YUVA_IN(y, u, v, a, p, pal);
596             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
597             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
598             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
599             cb++;
600             cr++;
601             lum++;
602             p += BPP;
603         }
604         for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
605             YUVA_IN(y, u, v, a, p, pal);
606             u1 = u;
607             v1 = v;
608             a1 = a;
609             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
610
611             YUVA_IN(y, u, v, a, p + BPP, pal);
612             u1 += u;
613             v1 += v;
614             a1 += a;
615             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
616             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
617             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
618             cb++;
619             cr++;
620             p += 2 * BPP;
621             lum += 2;
622         }
623         if (w) {
624             YUVA_IN(y, u, v, a, p, pal);
625             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
626             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
627             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
628         }
629     }
630 }
631
632 static void free_subpicture(SubPicture *sp)
633 {
634     int i;
635     
636     for (i = 0; i < sp->sub.num_rects; i++)
637     {
638         av_free(sp->sub.rects[i].bitmap);
639         av_free(sp->sub.rects[i].rgba_palette);
640     }
641     
642     av_free(sp->sub.rects);
643     
644     memset(&sp->sub, 0, sizeof(AVSubtitle));
645 }
646
647 static void video_image_display(VideoState *is)
648 {
649     VideoPicture *vp;
650     SubPicture *sp;
651     AVPicture pict;
652     float aspect_ratio;
653     int width, height, x, y;
654     SDL_Rect rect;
655     int i;
656
657     vp = &is->pictq[is->pictq_rindex];
658     if (vp->bmp) {
659         /* XXX: use variable in the frame */
660         if (is->video_st->codec->sample_aspect_ratio.num == 0) 
661             aspect_ratio = 0;
662         else
663             aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio) 
664                 * is->video_st->codec->width / is->video_st->codec->height;;
665         if (aspect_ratio <= 0.0)
666             aspect_ratio = (float)is->video_st->codec->width / 
667                 (float)is->video_st->codec->height;
668         /* if an active format is indicated, then it overrides the
669            mpeg format */
670 #if 0
671         if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
672             is->dtg_active_format = is->video_st->codec->dtg_active_format;
673             printf("dtg_active_format=%d\n", is->dtg_active_format);
674         }
675 #endif
676 #if 0
677         switch(is->video_st->codec->dtg_active_format) {
678         case FF_DTG_AFD_SAME:
679         default:
680             /* nothing to do */
681             break;
682         case FF_DTG_AFD_4_3:
683             aspect_ratio = 4.0 / 3.0;
684             break;
685         case FF_DTG_AFD_16_9:
686             aspect_ratio = 16.0 / 9.0;
687             break;
688         case FF_DTG_AFD_14_9:
689             aspect_ratio = 14.0 / 9.0;
690             break;
691         case FF_DTG_AFD_4_3_SP_14_9:
692             aspect_ratio = 14.0 / 9.0;
693             break;
694         case FF_DTG_AFD_16_9_SP_14_9:
695             aspect_ratio = 14.0 / 9.0;
696             break;
697         case FF_DTG_AFD_SP_4_3:
698             aspect_ratio = 4.0 / 3.0;
699             break;
700         }
701 #endif
702
703         if (is->subtitle_st)
704         {
705             if (is->subpq_size > 0)
706             {
707                 sp = &is->subpq[is->subpq_rindex];
708
709                 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
710                 {
711                     SDL_LockYUVOverlay (vp->bmp);
712
713                     pict.data[0] = vp->bmp->pixels[0];
714                     pict.data[1] = vp->bmp->pixels[2];
715                     pict.data[2] = vp->bmp->pixels[1];
716
717                     pict.linesize[0] = vp->bmp->pitches[0];
718                     pict.linesize[1] = vp->bmp->pitches[2];
719                     pict.linesize[2] = vp->bmp->pitches[1];
720
721                     for (i = 0; i < sp->sub.num_rects; i++)
722                         blend_subrect(&pict, &sp->sub.rects[i]);
723
724                     SDL_UnlockYUVOverlay (vp->bmp);
725                 }
726             }
727         }
728
729
730         /* XXX: we suppose the screen has a 1.0 pixel ratio */
731         height = is->height;
732         width = ((int)rint(height * aspect_ratio)) & -3;
733         if (width > is->width) {
734             width = is->width;
735             height = ((int)rint(width / aspect_ratio)) & -3;
736         }
737         x = (is->width - width) / 2;
738         y = (is->height - height) / 2;
739         if (!is->no_background) {
740             /* fill the background */
741             //            fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
742         } else {
743             is->no_background = 0;
744         }
745         rect.x = is->xleft + x;
746         rect.y = is->xleft + y;
747         rect.w = width;
748         rect.h = height;
749         SDL_DisplayYUVOverlay(vp->bmp, &rect);
750     } else {
751 #if 0
752         fill_rectangle(screen, 
753                        is->xleft, is->ytop, is->width, is->height, 
754                        QERGB(0x00, 0x00, 0x00));
755 #endif
756     }
757 }
758
759 static inline int compute_mod(int a, int b)
760 {
761     a = a % b;
762     if (a >= 0) 
763         return a;
764     else
765         return a + b;
766 }
767
768 static void video_audio_display(VideoState *s)
769 {
770     int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
771     int ch, channels, h, h2, bgcolor, fgcolor;
772     int16_t time_diff;
773     
774     /* compute display index : center on currently output samples */
775     channels = s->audio_st->codec->channels;
776     nb_display_channels = channels;
777     if (!s->paused) {
778         n = 2 * channels;
779         delay = audio_write_get_buf_size(s);
780         delay /= n;
781         
782         /* to be more precise, we take into account the time spent since
783            the last buffer computation */
784         if (audio_callback_time) {
785             time_diff = av_gettime() - audio_callback_time;
786             delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
787         }
788         
789         delay -= s->width / 2;
790         if (delay < s->width)
791             delay = s->width;
792         i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
793         s->last_i_start = i_start;
794     } else {
795         i_start = s->last_i_start;
796     }
797
798     bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
799     fill_rectangle(screen, 
800                    s->xleft, s->ytop, s->width, s->height, 
801                    bgcolor);
802
803     fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
804
805     /* total height for one channel */
806     h = s->height / nb_display_channels;
807     /* graph height / 2 */
808     h2 = (h * 9) / 20;
809     for(ch = 0;ch < nb_display_channels; ch++) {
810         i = i_start + ch;
811         y1 = s->ytop + ch * h + (h / 2); /* position of center line */
812         for(x = 0; x < s->width; x++) {
813             y = (s->sample_array[i] * h2) >> 15;
814             if (y < 0) {
815                 y = -y;
816                 ys = y1 - y;
817             } else {
818                 ys = y1;
819             }
820             fill_rectangle(screen, 
821                            s->xleft + x, ys, 1, y, 
822                            fgcolor);
823             i += channels;
824             if (i >= SAMPLE_ARRAY_SIZE)
825                 i -= SAMPLE_ARRAY_SIZE;
826         }
827     }
828
829     fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
830
831     for(ch = 1;ch < nb_display_channels; ch++) {
832         y = s->ytop + ch * h;
833         fill_rectangle(screen, 
834                        s->xleft, y, s->width, 1, 
835                        fgcolor);
836     }
837     SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
838 }
839
840 /* display the current picture, if any */
841 static void video_display(VideoState *is)
842 {
843     if (is->audio_st && is->show_audio) 
844         video_audio_display(is);
845     else if (is->video_st)
846         video_image_display(is);
847 }
848
849 static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
850 {
851     SDL_Event event;
852     event.type = FF_REFRESH_EVENT;
853     event.user.data1 = opaque;
854     SDL_PushEvent(&event);
855     return 0; /* 0 means stop timer */
856 }
857
858 /* schedule a video refresh in 'delay' ms */
859 static void schedule_refresh(VideoState *is, int delay)
860 {
861     SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
862 }
863
864 /* get the current audio clock value */
865 static double get_audio_clock(VideoState *is)
866 {
867     double pts;
868     int hw_buf_size, bytes_per_sec;
869     pts = is->audio_clock;
870     hw_buf_size = audio_write_get_buf_size(is);
871     bytes_per_sec = 0;
872     if (is->audio_st) {
873         bytes_per_sec = is->audio_st->codec->sample_rate * 
874             2 * is->audio_st->codec->channels;
875     }
876     if (bytes_per_sec)
877         pts -= (double)hw_buf_size / bytes_per_sec;
878     return pts;
879 }
880
881 /* get the current video clock value */
882 static double get_video_clock(VideoState *is)
883 {
884     double delta;
885     if (is->paused) {
886         delta = 0;
887     } else {
888         delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
889     }
890     return is->video_current_pts + delta;
891 }
892
893 /* get the current external clock value */
894 static double get_external_clock(VideoState *is)
895 {
896     int64_t ti;
897     ti = av_gettime();
898     return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
899 }
900
901 /* get the current master clock value */
902 static double get_master_clock(VideoState *is)
903 {
904     double val;
905
906     if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
907         if (is->video_st)
908             val = get_video_clock(is);
909         else
910             val = get_audio_clock(is);
911     } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
912         if (is->audio_st)
913             val = get_audio_clock(is);
914         else
915             val = get_video_clock(is);
916     } else {
917         val = get_external_clock(is);
918     }
919     return val;
920 }
921
922 /* seek in the stream */
923 static void stream_seek(VideoState *is, int64_t pos, int rel)
924 {
925     if (!is->seek_req) {
926         is->seek_pos = pos;
927         is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
928         is->seek_req = 1;
929     }
930 }
931
932 /* pause or resume the video */
933 static void stream_pause(VideoState *is)
934 {
935     is->paused = !is->paused;
936     if (is->paused) {
937         is->video_current_pts = get_video_clock(is);
938     }
939 }
940
941 /* called to display each frame */
942 static void video_refresh_timer(void *opaque)
943 {
944     VideoState *is = opaque;
945     VideoPicture *vp;
946     double actual_delay, delay, sync_threshold, ref_clock, diff;
947
948     SubPicture *sp, *sp2;
949
950     if (is->video_st) {
951         if (is->pictq_size == 0) {
952             /* if no picture, need to wait */
953             schedule_refresh(is, 1);
954         } else {
955             /* dequeue the picture */
956             vp = &is->pictq[is->pictq_rindex];
957
958             /* update current video pts */
959             is->video_current_pts = vp->pts;
960             is->video_current_pts_time = av_gettime();
961
962             /* compute nominal delay */
963             delay = vp->pts - is->frame_last_pts;
964             if (delay <= 0 || delay >= 1.0) {
965                 /* if incorrect delay, use previous one */
966                 delay = is->frame_last_delay;
967             }
968             is->frame_last_delay = delay;
969             is->frame_last_pts = vp->pts;
970
971             /* update delay to follow master synchronisation source */
972             if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
973                  is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
974                 /* if video is slave, we try to correct big delays by
975                    duplicating or deleting a frame */
976                 ref_clock = get_master_clock(is);
977                 diff = vp->pts - ref_clock;
978                 
979                 /* skip or repeat frame. We take into account the
980                    delay to compute the threshold. I still don't know
981                    if it is the best guess */
982                 sync_threshold = AV_SYNC_THRESHOLD;
983                 if (delay > sync_threshold)
984                     sync_threshold = delay;
985                 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
986                     if (diff <= -sync_threshold)
987                         delay = 0;
988                     else if (diff >= sync_threshold)
989                         delay = 2 * delay;
990                 }
991             }
992
993             is->frame_timer += delay;
994             /* compute the REAL delay (we need to do that to avoid
995                long term errors */
996             actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
997             if (actual_delay < 0.010) {
998                 /* XXX: should skip picture */
999                 actual_delay = 0.010;
1000             }
1001             /* launch timer for next picture */
1002             schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
1003
1004 #if defined(DEBUG_SYNC)
1005             printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n", 
1006                    delay, actual_delay, vp->pts, -diff);
1007 #endif
1008
1009             if(is->subtitle_st) {
1010                 if (is->subtitle_stream_changed) {
1011                     SDL_LockMutex(is->subpq_mutex);
1012                     
1013                     while (is->subpq_size) {
1014                         free_subpicture(&is->subpq[is->subpq_rindex]);
1015                     
1016                         /* update queue size and signal for next picture */
1017                         if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1018                             is->subpq_rindex = 0;
1019                                 
1020                         is->subpq_size--;
1021                     }
1022                     is->subtitle_stream_changed = 0;
1023
1024                     SDL_CondSignal(is->subpq_cond);
1025                     SDL_UnlockMutex(is->subpq_mutex);
1026                 } else {
1027                     if (is->subpq_size > 0) {
1028                         sp = &is->subpq[is->subpq_rindex];
1029
1030                         if (is->subpq_size > 1)
1031                             sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1032                         else
1033                             sp2 = NULL;
1034
1035                         if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1036                                 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1037                         {
1038                             free_subpicture(sp);
1039
1040                             /* update queue size and signal for next picture */
1041                             if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1042                                 is->subpq_rindex = 0;
1043
1044                             SDL_LockMutex(is->subpq_mutex);
1045                             is->subpq_size--;
1046                             SDL_CondSignal(is->subpq_cond);
1047                             SDL_UnlockMutex(is->subpq_mutex);
1048                         }
1049                     }
1050                 }
1051             }
1052
1053             /* display picture */
1054             video_display(is);
1055             
1056             /* update queue size and signal for next picture */
1057             if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1058                 is->pictq_rindex = 0;
1059             
1060             SDL_LockMutex(is->pictq_mutex);
1061             is->pictq_size--;
1062             SDL_CondSignal(is->pictq_cond);
1063             SDL_UnlockMutex(is->pictq_mutex);
1064         }
1065     } else if (is->audio_st) {
1066         /* draw the next audio frame */
1067
1068         schedule_refresh(is, 40);
1069
1070         /* if only audio stream, then display the audio bars (better
1071            than nothing, just to test the implementation */
1072         
1073         /* display picture */
1074         video_display(is);
1075     } else {
1076         schedule_refresh(is, 100);
1077     }
1078     if (show_status) {
1079         static int64_t last_time;
1080         int64_t cur_time;
1081         int aqsize, vqsize, sqsize;
1082         double av_diff;
1083         
1084         cur_time = av_gettime();
1085         if (!last_time || (cur_time - last_time) >= 500 * 1000) {
1086             aqsize = 0;
1087             vqsize = 0;
1088             sqsize = 0;
1089             if (is->audio_st)
1090                 aqsize = is->audioq.size;
1091             if (is->video_st)
1092                 vqsize = is->videoq.size;
1093             if (is->subtitle_st)
1094                 sqsize = is->subtitleq.size;
1095             av_diff = 0;
1096             if (is->audio_st && is->video_st)
1097                 av_diff = get_audio_clock(is) - get_video_clock(is);
1098             printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB    \r", 
1099                    get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
1100             fflush(stdout);
1101             last_time = cur_time;
1102         }
1103     }
1104 }
1105
1106 /* allocate a picture (needs to do that in main thread to avoid
1107    potential locking problems */
1108 static void alloc_picture(void *opaque)
1109 {
1110     VideoState *is = opaque;
1111     VideoPicture *vp;
1112
1113     vp = &is->pictq[is->pictq_windex];
1114
1115     if (vp->bmp)
1116         SDL_FreeYUVOverlay(vp->bmp);
1117
1118 #if 0
1119     /* XXX: use generic function */
1120     /* XXX: disable overlay if no hardware acceleration or if RGB format */
1121     switch(is->video_st->codec->pix_fmt) {
1122     case PIX_FMT_YUV420P:
1123     case PIX_FMT_YUV422P:
1124     case PIX_FMT_YUV444P:
1125     case PIX_FMT_YUV422:
1126     case PIX_FMT_YUV410P:
1127     case PIX_FMT_YUV411P:
1128         is_yuv = 1;
1129         break;
1130     default:
1131         is_yuv = 0;
1132         break;
1133     }
1134 #endif
1135     vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1136                                    is->video_st->codec->height,
1137                                    SDL_YV12_OVERLAY, 
1138                                    screen);
1139     vp->width = is->video_st->codec->width;
1140     vp->height = is->video_st->codec->height;
1141
1142     SDL_LockMutex(is->pictq_mutex);
1143     vp->allocated = 1;
1144     SDL_CondSignal(is->pictq_cond);
1145     SDL_UnlockMutex(is->pictq_mutex);
1146 }
1147
1148 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
1149 {
1150     VideoPicture *vp;
1151     int dst_pix_fmt;
1152     AVPicture pict;
1153     
1154     /* wait until we have space to put a new picture */
1155     SDL_LockMutex(is->pictq_mutex);
1156     while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1157            !is->videoq.abort_request) {
1158         SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1159     }
1160     SDL_UnlockMutex(is->pictq_mutex);
1161     
1162     if (is->videoq.abort_request)
1163         return -1;
1164
1165     vp = &is->pictq[is->pictq_windex];
1166
1167     /* alloc or resize hardware picture buffer */
1168     if (!vp->bmp || 
1169         vp->width != is->video_st->codec->width ||
1170         vp->height != is->video_st->codec->height) {
1171         SDL_Event event;
1172
1173         vp->allocated = 0;
1174
1175         /* the allocation must be done in the main thread to avoid
1176            locking problems */
1177         event.type = FF_ALLOC_EVENT;
1178         event.user.data1 = is;
1179         SDL_PushEvent(&event);
1180         
1181         /* wait until the picture is allocated */
1182         SDL_LockMutex(is->pictq_mutex);
1183         while (!vp->allocated && !is->videoq.abort_request) {
1184             SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1185         }
1186         SDL_UnlockMutex(is->pictq_mutex);
1187
1188         if (is->videoq.abort_request)
1189             return -1;
1190     }
1191
1192     /* if the frame is not skipped, then display it */
1193     if (vp->bmp) {
1194         /* get a pointer on the bitmap */
1195         SDL_LockYUVOverlay (vp->bmp);
1196
1197         dst_pix_fmt = PIX_FMT_YUV420P;
1198         pict.data[0] = vp->bmp->pixels[0];
1199         pict.data[1] = vp->bmp->pixels[2];
1200         pict.data[2] = vp->bmp->pixels[1];
1201
1202         pict.linesize[0] = vp->bmp->pitches[0];
1203         pict.linesize[1] = vp->bmp->pitches[2];
1204         pict.linesize[2] = vp->bmp->pitches[1];
1205         img_convert(&pict, dst_pix_fmt, 
1206                     (AVPicture *)src_frame, is->video_st->codec->pix_fmt, 
1207                     is->video_st->codec->width, is->video_st->codec->height);
1208         /* update the bitmap content */
1209         SDL_UnlockYUVOverlay(vp->bmp);
1210
1211         vp->pts = pts;
1212
1213         /* now we can update the picture count */
1214         if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1215             is->pictq_windex = 0;
1216         SDL_LockMutex(is->pictq_mutex);
1217         is->pictq_size++;
1218         SDL_UnlockMutex(is->pictq_mutex);
1219     }
1220     return 0;
1221 }
1222
1223 /* compute the exact PTS for the picture if it is omitted in the stream */
1224 static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
1225 {
1226     double frame_delay, pts;
1227     
1228     pts = pts1;
1229
1230     if (pts != 0) {
1231         /* update video clock with pts, if present */
1232         is->video_clock = pts;
1233     } else {
1234         pts = is->video_clock;
1235     }
1236     /* update video clock for next frame */
1237     frame_delay = av_q2d(is->video_st->codec->time_base);
1238     /* for MPEG2, the frame can be repeated, so we update the
1239        clock accordingly */
1240     if (src_frame->repeat_pict) {
1241         frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
1242     }
1243     is->video_clock += frame_delay;
1244
1245 #if defined(DEBUG_SYNC) && 0
1246     {
1247         int ftype;
1248         if (src_frame->pict_type == FF_B_TYPE)
1249             ftype = 'B';
1250         else if (src_frame->pict_type == FF_I_TYPE)
1251             ftype = 'I';
1252         else
1253             ftype = 'P';
1254         printf("frame_type=%c clock=%0.3f pts=%0.3f\n", 
1255                ftype, pts, pts1);
1256     }
1257 #endif
1258     return queue_picture(is, src_frame, pts);
1259 }
1260
1261 static int video_thread(void *arg)
1262 {
1263     VideoState *is = arg;
1264     AVPacket pkt1, *pkt = &pkt1;
1265     int len1, got_picture;
1266     AVFrame *frame= avcodec_alloc_frame();
1267     double pts;
1268
1269     for(;;) {
1270         while (is->paused && !is->videoq.abort_request) {
1271             SDL_Delay(10);
1272         }
1273         if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1274             break;
1275         /* NOTE: ipts is the PTS of the _first_ picture beginning in
1276            this packet, if any */
1277         pts = 0;
1278         if (pkt->dts != AV_NOPTS_VALUE)
1279             pts = av_q2d(is->video_st->time_base)*pkt->dts;
1280
1281             SDL_LockMutex(is->video_decoder_mutex);
1282             len1 = avcodec_decode_video(is->video_st->codec, 
1283                                         frame, &got_picture, 
1284                                         pkt->data, pkt->size);
1285             SDL_UnlockMutex(is->video_decoder_mutex);
1286 //            if (len1 < 0)
1287 //                break;
1288             if (got_picture) {
1289                 if (output_picture2(is, frame, pts) < 0)
1290                     goto the_end;
1291             }
1292         av_free_packet(pkt);
1293         if (step) 
1294             if (cur_stream)
1295                 stream_pause(cur_stream);
1296     }
1297  the_end:
1298     av_free(frame);
1299     return 0;
1300 }
1301
1302 static int subtitle_thread(void *arg)
1303 {
1304     VideoState *is = arg;
1305     SubPicture *sp;
1306     AVPacket pkt1, *pkt = &pkt1;
1307     int len1, got_subtitle;
1308     double pts;
1309     int i, j;
1310     int r, g, b, y, u, v, a;
1311
1312     for(;;) {
1313         while (is->paused && !is->subtitleq.abort_request) {
1314             SDL_Delay(10);
1315         }
1316         if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1317             break;
1318             
1319         SDL_LockMutex(is->subpq_mutex);
1320         while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1321                !is->subtitleq.abort_request) {
1322             SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1323         }
1324         SDL_UnlockMutex(is->subpq_mutex);
1325         
1326         if (is->subtitleq.abort_request)
1327             goto the_end;
1328             
1329         sp = &is->subpq[is->subpq_windex];
1330
1331        /* NOTE: ipts is the PTS of the _first_ picture beginning in
1332            this packet, if any */
1333         pts = 0;
1334         if (pkt->pts != AV_NOPTS_VALUE)
1335             pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1336
1337         SDL_LockMutex(is->subtitle_decoder_mutex);
1338         len1 = avcodec_decode_subtitle(is->subtitle_st->codec, 
1339                                     &sp->sub, &got_subtitle, 
1340                                     pkt->data, pkt->size);
1341         SDL_UnlockMutex(is->subtitle_decoder_mutex);
1342 //            if (len1 < 0)
1343 //                break;
1344         if (got_subtitle && sp->sub.format == 0) {
1345             sp->pts = pts;
1346             
1347             for (i = 0; i < sp->sub.num_rects; i++)
1348             {
1349                 for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
1350                 {
1351                     RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
1352                     y = RGB_TO_Y_CCIR(r, g, b);
1353                     u = RGB_TO_U_CCIR(r, g, b, 0);
1354                     v = RGB_TO_V_CCIR(r, g, b, 0);
1355                     YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
1356                 }
1357             }
1358
1359             /* now we can update the picture count */
1360             if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1361                 is->subpq_windex = 0;
1362             SDL_LockMutex(is->subpq_mutex);
1363             is->subpq_size++;
1364             SDL_UnlockMutex(is->subpq_mutex);
1365         }
1366         av_free_packet(pkt);
1367 //        if (step) 
1368 //            if (cur_stream)
1369 //                stream_pause(cur_stream);
1370     }
1371  the_end:
1372     return 0;
1373 }
1374
1375 /* copy samples for viewing in editor window */
1376 static void update_sample_display(VideoState *is, short *samples, int samples_size)
1377 {
1378     int size, len, channels;
1379
1380     channels = is->audio_st->codec->channels;
1381
1382     size = samples_size / sizeof(short);
1383     while (size > 0) {
1384         len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1385         if (len > size)
1386             len = size;
1387         memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1388         samples += len;
1389         is->sample_array_index += len;
1390         if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1391             is->sample_array_index = 0;
1392         size -= len;
1393     }
1394 }
1395
1396 /* return the new audio buffer size (samples can be added or deleted
1397    to get better sync if video or external master clock) */
1398 static int synchronize_audio(VideoState *is, short *samples, 
1399                              int samples_size1, double pts)
1400 {
1401     int n, samples_size;
1402     double ref_clock;
1403     
1404     n = 2 * is->audio_st->codec->channels;
1405     samples_size = samples_size1;
1406
1407     /* if not master, then we try to remove or add samples to correct the clock */
1408     if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
1409          is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1410         double diff, avg_diff;
1411         int wanted_size, min_size, max_size, nb_samples;
1412             
1413         ref_clock = get_master_clock(is);
1414         diff = get_audio_clock(is) - ref_clock;
1415         
1416         if (diff < AV_NOSYNC_THRESHOLD) {
1417             is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1418             if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1419                 /* not enough measures to have a correct estimate */
1420                 is->audio_diff_avg_count++;
1421             } else {
1422                 /* estimate the A-V difference */
1423                 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1424
1425                 if (fabs(avg_diff) >= is->audio_diff_threshold) {
1426                     wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
1427                     nb_samples = samples_size / n;
1428                 
1429                     min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1430                     max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1431                     if (wanted_size < min_size)
1432                         wanted_size = min_size;
1433                     else if (wanted_size > max_size)
1434                         wanted_size = max_size;
1435                     
1436                     /* add or remove samples to correction the synchro */
1437                     if (wanted_size < samples_size) {
1438                         /* remove samples */
1439                         samples_size = wanted_size;
1440                     } else if (wanted_size > samples_size) {
1441                         uint8_t *samples_end, *q;
1442                         int nb;
1443                         
1444                         /* add samples */
1445                         nb = (samples_size - wanted_size);
1446                         samples_end = (uint8_t *)samples + samples_size - n;
1447                         q = samples_end + n;
1448                         while (nb > 0) {
1449                             memcpy(q, samples_end, n);
1450                             q += n;
1451                             nb -= n;
1452                         }
1453                         samples_size = wanted_size;
1454                     }
1455                 }
1456 #if 0
1457                 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n", 
1458                        diff, avg_diff, samples_size - samples_size1, 
1459                        is->audio_clock, is->video_clock, is->audio_diff_threshold);
1460 #endif
1461             }
1462         } else {
1463             /* too big difference : may be initial PTS errors, so
1464                reset A-V filter */
1465             is->audio_diff_avg_count = 0;
1466             is->audio_diff_cum = 0;
1467         }
1468     }
1469
1470     return samples_size;
1471 }
1472
1473 /* decode one audio frame and returns its uncompressed size */
1474 static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
1475 {
1476     AVPacket *pkt = &is->audio_pkt;
1477     int n, len1, data_size;
1478     double pts;
1479
1480     for(;;) {
1481         /* NOTE: the audio packet can contain several frames */
1482         while (is->audio_pkt_size > 0) {
1483             SDL_LockMutex(is->audio_decoder_mutex);
1484             len1 = avcodec_decode_audio(is->audio_st->codec, 
1485                                         (int16_t *)audio_buf, &data_size, 
1486                                         is->audio_pkt_data, is->audio_pkt_size);
1487             SDL_UnlockMutex(is->audio_decoder_mutex);
1488             if (len1 < 0) {
1489                 /* if error, we skip the frame */
1490                 is->audio_pkt_size = 0;
1491                 break;
1492             }
1493             
1494             is->audio_pkt_data += len1;
1495             is->audio_pkt_size -= len1;
1496             if (data_size <= 0)
1497                 continue;
1498             /* if no pts, then compute it */
1499             pts = is->audio_clock;
1500             *pts_ptr = pts;
1501             n = 2 * is->audio_st->codec->channels;
1502             is->audio_clock += (double)data_size / 
1503                 (double)(n * is->audio_st->codec->sample_rate);
1504 #if defined(DEBUG_SYNC)
1505             {
1506                 static double last_clock;
1507                 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1508                        is->audio_clock - last_clock,
1509                        is->audio_clock, pts);
1510                 last_clock = is->audio_clock;
1511             }
1512 #endif
1513             return data_size;
1514         }
1515
1516         /* free the current packet */
1517         if (pkt->data)
1518             av_free_packet(pkt);
1519         
1520         if (is->paused || is->audioq.abort_request) {
1521             return -1;
1522         }
1523         
1524         /* read next packet */
1525         if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1526             return -1;
1527         is->audio_pkt_data = pkt->data;
1528         is->audio_pkt_size = pkt->size;
1529         
1530         /* if update the audio clock with the pts */
1531         if (pkt->pts != AV_NOPTS_VALUE) {
1532             is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
1533         }
1534     }
1535 }
1536
1537 /* get the current audio output buffer size, in samples. With SDL, we
1538    cannot have a precise information */
1539 static int audio_write_get_buf_size(VideoState *is)
1540 {
1541     return is->audio_hw_buf_size - is->audio_buf_index;
1542 }
1543
1544
1545 /* prepare a new audio buffer */
1546 void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1547 {
1548     VideoState *is = opaque;
1549     int audio_size, len1;
1550     double pts;
1551
1552     audio_callback_time = av_gettime();
1553     
1554     while (len > 0) {
1555         if (is->audio_buf_index >= is->audio_buf_size) {
1556            audio_size = audio_decode_frame(is, is->audio_buf, &pts);
1557            if (audio_size < 0) {
1558                 /* if error, just output silence */
1559                is->audio_buf_size = 1024;
1560                memset(is->audio_buf, 0, is->audio_buf_size);
1561            } else {
1562                if (is->show_audio)
1563                    update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1564                audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size, 
1565                                               pts);
1566                is->audio_buf_size = audio_size;
1567            }
1568            is->audio_buf_index = 0;
1569         }
1570         len1 = is->audio_buf_size - is->audio_buf_index;
1571         if (len1 > len)
1572             len1 = len;
1573         memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1574         len -= len1;
1575         stream += len1;
1576         is->audio_buf_index += len1;
1577     }
1578 }
1579
1580
1581 /* open a given stream. Return 0 if OK */
1582 static int stream_component_open(VideoState *is, int stream_index)
1583 {
1584     AVFormatContext *ic = is->ic;
1585     AVCodecContext *enc;
1586     AVCodec *codec;
1587     SDL_AudioSpec wanted_spec, spec;
1588
1589     if (stream_index < 0 || stream_index >= ic->nb_streams)
1590         return -1;
1591     enc = ic->streams[stream_index]->codec;
1592     
1593     /* prepare audio output */
1594     if (enc->codec_type == CODEC_TYPE_AUDIO) {
1595         wanted_spec.freq = enc->sample_rate;
1596         wanted_spec.format = AUDIO_S16SYS;
1597         /* hack for AC3. XXX: suppress that */
1598         if (enc->channels > 2)
1599             enc->channels = 2;
1600         wanted_spec.channels = enc->channels;
1601         wanted_spec.silence = 0;
1602         wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1603         wanted_spec.callback = sdl_audio_callback;
1604         wanted_spec.userdata = is;
1605         if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1606             fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1607             return -1;
1608         }
1609         is->audio_hw_buf_size = spec.size;
1610     }
1611
1612     codec = avcodec_find_decoder(enc->codec_id);
1613     enc->debug_mv = debug_mv;
1614     enc->debug = debug;
1615     if(debug)
1616         av_log_set_level(AV_LOG_DEBUG);
1617     enc->workaround_bugs = workaround_bugs;
1618     enc->lowres = lowres;
1619     if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
1620     enc->idct_algo= idct;
1621     if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
1622     enc->skip_frame= skip_frame;
1623     enc->skip_idct= skip_idct;
1624     enc->skip_loop_filter= skip_loop_filter;
1625     enc->error_resilience= error_resilience;
1626     enc->error_concealment= error_concealment;
1627     if (!codec ||
1628         avcodec_open(enc, codec) < 0)
1629         return -1;
1630 #if defined(HAVE_THREADS)
1631     if(thread_count>1)
1632         avcodec_thread_init(enc, thread_count);
1633 #endif
1634     enc->thread_count= thread_count;
1635     switch(enc->codec_type) {
1636     case CODEC_TYPE_AUDIO:
1637         is->audio_stream = stream_index;
1638         is->audio_st = ic->streams[stream_index];
1639         is->audio_buf_size = 0;
1640         is->audio_buf_index = 0;
1641
1642         /* init averaging filter */
1643         is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1644         is->audio_diff_avg_count = 0;
1645         /* since we do not have a precise anough audio fifo fullness,
1646            we correct audio sync only if larger than this threshold */
1647         is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1648
1649         memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1650         packet_queue_init(&is->audioq);
1651         SDL_PauseAudio(0);
1652         break;
1653     case CODEC_TYPE_VIDEO:
1654         is->video_stream = stream_index;
1655         is->video_st = ic->streams[stream_index];
1656
1657         is->frame_last_delay = 40e-3;
1658         is->frame_timer = (double)av_gettime() / 1000000.0;
1659         is->video_current_pts_time = av_gettime();
1660
1661         packet_queue_init(&is->videoq);
1662         is->video_tid = SDL_CreateThread(video_thread, is);
1663         break;
1664     case CODEC_TYPE_SUBTITLE:
1665         is->subtitle_stream = stream_index;
1666         is->subtitle_st = ic->streams[stream_index];
1667         packet_queue_init(&is->subtitleq);
1668         
1669         is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1670         break;
1671     default:
1672         break;
1673     }
1674     return 0;
1675 }
1676
1677 static void stream_component_close(VideoState *is, int stream_index)
1678 {
1679     AVFormatContext *ic = is->ic;
1680     AVCodecContext *enc;
1681     
1682     if (stream_index < 0 || stream_index >= ic->nb_streams)
1683         return;
1684     enc = ic->streams[stream_index]->codec;
1685
1686     switch(enc->codec_type) {
1687     case CODEC_TYPE_AUDIO:
1688         packet_queue_abort(&is->audioq);
1689
1690         SDL_CloseAudio();
1691
1692         packet_queue_end(&is->audioq);
1693         break;
1694     case CODEC_TYPE_VIDEO:
1695         packet_queue_abort(&is->videoq);
1696
1697         /* note: we also signal this mutex to make sure we deblock the
1698            video thread in all cases */
1699         SDL_LockMutex(is->pictq_mutex);
1700         SDL_CondSignal(is->pictq_cond);
1701         SDL_UnlockMutex(is->pictq_mutex);
1702
1703         SDL_WaitThread(is->video_tid, NULL);
1704
1705         packet_queue_end(&is->videoq);
1706         break;
1707     case CODEC_TYPE_SUBTITLE:
1708         packet_queue_abort(&is->subtitleq);
1709         
1710         /* note: we also signal this mutex to make sure we deblock the
1711            video thread in all cases */
1712         SDL_LockMutex(is->subpq_mutex);
1713         is->subtitle_stream_changed = 1;
1714     
1715         SDL_CondSignal(is->subpq_cond);
1716         SDL_UnlockMutex(is->subpq_mutex);
1717
1718         SDL_WaitThread(is->subtitle_tid, NULL);
1719
1720         packet_queue_end(&is->subtitleq);
1721         break;
1722     default:
1723         break;
1724     }
1725
1726     avcodec_close(enc);
1727     switch(enc->codec_type) {
1728     case CODEC_TYPE_AUDIO:
1729         is->audio_st = NULL;
1730         is->audio_stream = -1;
1731         break;
1732     case CODEC_TYPE_VIDEO:
1733         is->video_st = NULL;
1734         is->video_stream = -1;
1735         break;
1736     case CODEC_TYPE_SUBTITLE:
1737         is->subtitle_st = NULL;
1738         is->subtitle_stream = -1;
1739         break;
1740     default:
1741         break;
1742     }
1743 }
1744
1745 void dump_stream_info(AVFormatContext *s)
1746 {
1747     if (s->track != 0)
1748         fprintf(stderr, "Track: %d\n", s->track);
1749     if (s->title[0] != '\0')
1750         fprintf(stderr, "Title: %s\n", s->title);
1751     if (s->author[0] != '\0')
1752         fprintf(stderr, "Author: %s\n", s->author);
1753     if (s->album[0] != '\0')
1754         fprintf(stderr, "Album: %s\n", s->album);
1755     if (s->year != 0)
1756         fprintf(stderr, "Year: %d\n", s->year);
1757     if (s->genre[0] != '\0')
1758         fprintf(stderr, "Genre: %s\n", s->genre);
1759 }
1760
1761 /* since we have only one decoding thread, we can use a global
1762    variable instead of a thread local variable */
1763 static VideoState *global_video_state;
1764
1765 static int decode_interrupt_cb(void)
1766 {
1767     return (global_video_state && global_video_state->abort_request);
1768 }
1769
1770 /* this thread gets the stream from the disk or the network */
1771 static int decode_thread(void *arg)
1772 {
1773     VideoState *is = arg;
1774     AVFormatContext *ic;
1775     int err, i, ret, video_index, audio_index, use_play;
1776     AVPacket pkt1, *pkt = &pkt1;
1777     AVFormatParameters params, *ap = &params;
1778
1779     video_index = -1;
1780     audio_index = -1;
1781     is->video_stream = -1;
1782     is->audio_stream = -1;
1783     is->subtitle_stream = -1;
1784
1785     global_video_state = is;
1786     url_set_interrupt_cb(decode_interrupt_cb);
1787
1788     memset(ap, 0, sizeof(*ap));
1789     ap->image_format = image_format;
1790     ap->initial_pause = 1; /* we force a pause when starting an RTSP
1791                               stream */
1792     
1793     err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
1794     if (err < 0) {
1795         print_error(is->filename, err);
1796         ret = -1;
1797         goto fail;
1798     }
1799     is->ic = ic;
1800 #ifdef CONFIG_NETWORK
1801     use_play = (ic->iformat == &rtsp_demux);
1802 #else
1803     use_play = 0;
1804 #endif
1805     if (!use_play) {
1806         err = av_find_stream_info(ic);
1807         if (err < 0) {
1808             fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1809             ret = -1;
1810             goto fail;
1811         }
1812         ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
1813     }
1814
1815     /* if seeking requested, we execute it */
1816     if (start_time != AV_NOPTS_VALUE) {
1817         int64_t timestamp;
1818
1819         timestamp = start_time;
1820         /* add the stream start time */
1821         if (ic->start_time != AV_NOPTS_VALUE)
1822             timestamp += ic->start_time;
1823         ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1824         if (ret < 0) {
1825             fprintf(stderr, "%s: could not seek to position %0.3f\n", 
1826                     is->filename, (double)timestamp / AV_TIME_BASE);
1827         }
1828     }
1829
1830     /* now we can begin to play (RTSP stream only) */
1831     av_read_play(ic);
1832
1833     if (use_play) {
1834         err = av_find_stream_info(ic);
1835         if (err < 0) {
1836             fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1837             ret = -1;
1838             goto fail;
1839         }
1840     }
1841
1842     for(i = 0; i < ic->nb_streams; i++) {
1843         AVCodecContext *enc = ic->streams[i]->codec;
1844         switch(enc->codec_type) {
1845         case CODEC_TYPE_AUDIO:
1846             if (audio_index < 0 && !audio_disable)
1847                 audio_index = i;
1848             break;
1849         case CODEC_TYPE_VIDEO:
1850             if (video_index < 0 && !video_disable)
1851                 video_index = i;
1852             break;
1853         default:
1854             break;
1855         }
1856     }
1857     if (show_status) {
1858         dump_format(ic, 0, is->filename, 0);
1859         dump_stream_info(ic);
1860     }
1861
1862     /* open the streams */
1863     if (audio_index >= 0) {
1864         stream_component_open(is, audio_index);
1865     }
1866
1867     if (video_index >= 0) {
1868         stream_component_open(is, video_index);
1869     } else {
1870         if (!display_disable)
1871             is->show_audio = 1;
1872     }
1873
1874     if (is->video_stream < 0 && is->audio_stream < 0) {
1875         fprintf(stderr, "%s: could not open codecs\n", is->filename);
1876         ret = -1;
1877         goto fail;
1878     }
1879
1880     for(;;) {
1881         if (is->abort_request)
1882             break;
1883 #ifdef CONFIG_NETWORK
1884         if (is->paused != is->last_paused) {
1885             is->last_paused = is->paused;
1886             if (is->paused)
1887                 av_read_pause(ic);
1888             else
1889                 av_read_play(ic);
1890         }
1891         if (is->paused && ic->iformat == &rtsp_demux) {
1892             /* wait 10 ms to avoid trying to get another packet */
1893             /* XXX: horrible */
1894             SDL_Delay(10);
1895             continue;
1896         }
1897 #endif
1898         if (is->seek_req) {
1899             /* XXX: must lock decoder threads */
1900             SDL_LockMutex(is->video_decoder_mutex);
1901             SDL_LockMutex(is->audio_decoder_mutex);
1902             SDL_LockMutex(is->subtitle_decoder_mutex);
1903             ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
1904             if (ret < 0) {
1905                 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
1906             }else{
1907                 if (is->audio_stream >= 0) {
1908                     packet_queue_flush(&is->audioq);
1909                 }
1910                 if (is->subtitle_stream >= 0) {
1911                     packet_queue_flush(&is->subtitleq);
1912                 }
1913                 if (is->video_stream >= 0) {
1914                     packet_queue_flush(&is->videoq);
1915                     avcodec_flush_buffers(ic->streams[video_index]->codec);
1916                 }
1917             }
1918             SDL_UnlockMutex(is->subtitle_decoder_mutex);
1919             SDL_UnlockMutex(is->audio_decoder_mutex);
1920             SDL_UnlockMutex(is->video_decoder_mutex);
1921             is->seek_req = 0;
1922         }
1923
1924         /* if the queue are full, no need to read more */
1925         if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1926             is->videoq.size > MAX_VIDEOQ_SIZE || 
1927             is->subtitleq.size > MAX_SUBTITLEQ_SIZE || 
1928             url_feof(&ic->pb)) {
1929             /* wait 10 ms */
1930             SDL_Delay(10);
1931             continue;
1932         }
1933         ret = av_read_frame(ic, pkt);
1934         if (ret < 0) {
1935             if (url_ferror(&ic->pb) == 0) {
1936                 SDL_Delay(100); /* wait for user event */
1937                 continue;
1938             } else
1939                 break;
1940         }
1941         if (pkt->stream_index == is->audio_stream) {
1942             packet_queue_put(&is->audioq, pkt);
1943         } else if (pkt->stream_index == is->video_stream) {
1944             packet_queue_put(&is->videoq, pkt);
1945         } else if (pkt->stream_index == is->subtitle_stream) {
1946             packet_queue_put(&is->subtitleq, pkt);
1947         } else {
1948             av_free_packet(pkt);
1949         }
1950     }
1951     /* wait until the end */
1952     while (!is->abort_request) {
1953         SDL_Delay(100);
1954     }
1955
1956     ret = 0;
1957  fail:
1958     /* disable interrupting */
1959     global_video_state = NULL;
1960
1961     /* close each stream */
1962     if (is->audio_stream >= 0)
1963         stream_component_close(is, is->audio_stream);
1964     if (is->video_stream >= 0)
1965         stream_component_close(is, is->video_stream);
1966     if (is->subtitle_stream >= 0)
1967         stream_component_close(is, is->subtitle_stream);
1968     if (is->ic) {
1969         av_close_input_file(is->ic);
1970         is->ic = NULL; /* safety */
1971     }
1972     url_set_interrupt_cb(NULL);
1973
1974     if (ret != 0) {
1975         SDL_Event event;
1976         
1977         event.type = FF_QUIT_EVENT;
1978         event.user.data1 = is;
1979         SDL_PushEvent(&event);
1980     }
1981     return 0;
1982 }
1983
1984 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
1985 {
1986     VideoState *is;
1987
1988     is = av_mallocz(sizeof(VideoState));
1989     if (!is)
1990         return NULL;
1991     pstrcpy(is->filename, sizeof(is->filename), filename);
1992     is->iformat = iformat;
1993     if (screen) {
1994         is->width = screen->w;
1995         is->height = screen->h;
1996     }
1997     is->ytop = 0;
1998     is->xleft = 0;
1999
2000     /* start video display */
2001     is->pictq_mutex = SDL_CreateMutex();
2002     is->pictq_cond = SDL_CreateCond();
2003     
2004     is->subpq_mutex = SDL_CreateMutex();
2005     is->subpq_cond = SDL_CreateCond();
2006     
2007     is->subtitle_decoder_mutex = SDL_CreateMutex();
2008     is->audio_decoder_mutex = SDL_CreateMutex();
2009     is->video_decoder_mutex = SDL_CreateMutex();
2010
2011     /* add the refresh timer to draw the picture */
2012     schedule_refresh(is, 40);
2013
2014     is->av_sync_type = av_sync_type;
2015     is->parse_tid = SDL_CreateThread(decode_thread, is);
2016     if (!is->parse_tid) {
2017         av_free(is);
2018         return NULL;
2019     }
2020     return is;
2021 }
2022
2023 static void stream_close(VideoState *is)
2024 {
2025     VideoPicture *vp;
2026     int i;
2027     /* XXX: use a special url_shutdown call to abort parse cleanly */
2028     is->abort_request = 1;
2029     SDL_WaitThread(is->parse_tid, NULL);
2030
2031     /* free all pictures */
2032     for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2033         vp = &is->pictq[i];
2034         if (vp->bmp) {
2035             SDL_FreeYUVOverlay(vp->bmp);
2036             vp->bmp = NULL;
2037         }
2038     }
2039     SDL_DestroyMutex(is->pictq_mutex);
2040     SDL_DestroyCond(is->pictq_cond);
2041     SDL_DestroyMutex(is->subpq_mutex);
2042     SDL_DestroyCond(is->subpq_cond);
2043     SDL_DestroyMutex(is->subtitle_decoder_mutex);
2044     SDL_DestroyMutex(is->audio_decoder_mutex);
2045     SDL_DestroyMutex(is->video_decoder_mutex);
2046 }
2047
2048 void stream_cycle_channel(VideoState *is, int codec_type)
2049 {
2050     AVFormatContext *ic = is->ic;
2051     int start_index, stream_index;
2052     AVStream *st;
2053
2054     if (codec_type == CODEC_TYPE_VIDEO)
2055         start_index = is->video_stream;
2056     else if (codec_type == CODEC_TYPE_AUDIO)
2057         start_index = is->audio_stream;
2058     else
2059         start_index = is->subtitle_stream;
2060     if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
2061         return;
2062     stream_index = start_index;
2063     for(;;) {
2064         if (++stream_index >= is->ic->nb_streams)
2065         {
2066             if (codec_type == CODEC_TYPE_SUBTITLE)
2067             {
2068                 stream_index = -1;
2069                 goto the_end;
2070             } else
2071                 stream_index = 0;
2072         }
2073         if (stream_index == start_index)
2074             return;
2075         st = ic->streams[stream_index];
2076         if (st->codec->codec_type == codec_type) {
2077             /* check that parameters are OK */
2078             switch(codec_type) {
2079             case CODEC_TYPE_AUDIO:
2080                 if (st->codec->sample_rate != 0 &&
2081                     st->codec->channels != 0)
2082                     goto the_end;
2083                 break;
2084             case CODEC_TYPE_VIDEO:
2085             case CODEC_TYPE_SUBTITLE:
2086                 goto the_end;
2087             default:
2088                 break;
2089             }
2090         }
2091     }
2092  the_end:
2093     stream_component_close(is, start_index);
2094     stream_component_open(is, stream_index);
2095 }
2096
2097
2098 void toggle_full_screen(void)
2099 {
2100     int w, h, flags;
2101     is_full_screen = !is_full_screen;
2102     if (!fs_screen_width) {
2103         /* use default SDL method */
2104         SDL_WM_ToggleFullScreen(screen);
2105     } else {
2106         /* use the recorded resolution */
2107         flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
2108         if (is_full_screen) {
2109             w = fs_screen_width;
2110             h = fs_screen_height;
2111             flags |= SDL_FULLSCREEN;
2112         } else {
2113             w = screen_width;
2114             h = screen_height;
2115             flags |= SDL_RESIZABLE;
2116         }
2117         screen = SDL_SetVideoMode(w, h, 0, flags);
2118         cur_stream->width = w;
2119         cur_stream->height = h;
2120     }
2121 }
2122
2123 void toggle_pause(void)
2124 {
2125     if (cur_stream)
2126         stream_pause(cur_stream);
2127     step = 0;
2128 }
2129
2130 void step_to_next_frame(void)
2131 {
2132     if (cur_stream) {
2133         if (cur_stream->paused)
2134             cur_stream->paused=0;
2135         cur_stream->video_current_pts = get_video_clock(cur_stream);
2136     }
2137     step = 1;
2138 }
2139
2140 void do_exit(void)
2141 {
2142     if (cur_stream) {
2143         stream_close(cur_stream);
2144         cur_stream = NULL;
2145     }
2146     if (show_status)
2147         printf("\n");
2148     SDL_Quit();
2149     exit(0);
2150 }
2151
2152 void toggle_audio_display(void)
2153 {
2154     if (cur_stream) {
2155         cur_stream->show_audio = !cur_stream->show_audio;
2156     }
2157 }
2158
2159 /* handle an event sent by the GUI */
2160 void event_loop(void)
2161 {
2162     SDL_Event event;
2163     double incr, pos, frac;
2164
2165     for(;;) {
2166         SDL_WaitEvent(&event);
2167         switch(event.type) {
2168         case SDL_KEYDOWN:
2169             switch(event.key.keysym.sym) {
2170             case SDLK_ESCAPE:
2171             case SDLK_q:
2172                 do_exit();
2173                 break;
2174             case SDLK_f:
2175                 toggle_full_screen();
2176                 break;
2177             case SDLK_p:
2178             case SDLK_SPACE:
2179                 toggle_pause();
2180                 break;
2181             case SDLK_s: //S: Step to next frame
2182                 step_to_next_frame();
2183                 break;
2184             case SDLK_a:
2185                 if (cur_stream) 
2186                     stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2187                 break;
2188             case SDLK_v:
2189                 if (cur_stream) 
2190                     stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2191                 break;
2192             case SDLK_t:
2193                 if (cur_stream) 
2194                     stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2195                 break;
2196             case SDLK_w:
2197                 toggle_audio_display();
2198                 break;
2199             case SDLK_LEFT:
2200                 incr = -10.0;
2201                 goto do_seek;
2202             case SDLK_RIGHT:
2203                 incr = 10.0;
2204                 goto do_seek;
2205             case SDLK_UP:
2206                 incr = 60.0;
2207                 goto do_seek;
2208             case SDLK_DOWN:
2209                 incr = -60.0;
2210             do_seek:
2211                 if (cur_stream) {
2212                     pos = get_master_clock(cur_stream);
2213                     pos += incr;
2214                     stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
2215                 }
2216                 break;
2217             default:
2218                 break;
2219             }
2220             break;
2221         case SDL_MOUSEBUTTONDOWN:
2222             if (cur_stream) {
2223                 int ns, hh, mm, ss;
2224                 int tns, thh, tmm, tss;
2225                 tns = cur_stream->ic->duration/1000000LL;
2226                 thh = tns/3600;
2227                 tmm = (tns%3600)/60;
2228                 tss = (tns%60);
2229                 frac = (double)event.button.x/(double)cur_stream->width;
2230                 ns = frac*tns;
2231                 hh = ns/3600;
2232                 mm = (ns%3600)/60;
2233                 ss = (ns%60);
2234                 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n", frac*100,
2235                         hh, mm, ss, thh, tmm, tss);
2236                 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
2237             }
2238             break;
2239         case SDL_VIDEORESIZE:
2240             if (cur_stream) {
2241                 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, 
2242                                           SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2243                 cur_stream->width = event.resize.w;
2244                 cur_stream->height = event.resize.h;
2245             }
2246             break;
2247         case SDL_QUIT:
2248         case FF_QUIT_EVENT:
2249             do_exit();
2250             break;
2251         case FF_ALLOC_EVENT:
2252             alloc_picture(event.user.data1);
2253             break;
2254         case FF_REFRESH_EVENT:
2255             video_refresh_timer(event.user.data1);
2256             break;
2257         default:
2258             break;
2259         }
2260     }
2261 }
2262
2263 void opt_width(const char *arg)
2264 {
2265     screen_width = atoi(arg);
2266 }
2267
2268 void opt_height(const char *arg)
2269 {
2270     screen_height = atoi(arg);
2271 }
2272
2273 static void opt_format(const char *arg)
2274 {
2275     file_iformat = av_find_input_format(arg);
2276     if (!file_iformat) {
2277         fprintf(stderr, "Unknown input format: %s\n", arg);
2278         exit(1);
2279     }
2280 }
2281
2282 static void opt_image_format(const char *arg)
2283 {
2284     AVImageFormat *f;
2285     
2286     for(f = first_image_format; f != NULL; f = f->next) {
2287         if (!strcmp(arg, f->name))
2288             break;
2289     }
2290     if (!f) {
2291         fprintf(stderr, "Unknown image format: '%s'\n", arg);
2292         exit(1);
2293     }
2294     image_format = f;
2295 }
2296
2297 #ifdef CONFIG_NETWORK
2298 void opt_rtp_tcp(void)
2299 {
2300     /* only tcp protocol */
2301     rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
2302 }
2303 #endif
2304
2305 void opt_sync(const char *arg)
2306 {
2307     if (!strcmp(arg, "audio"))
2308         av_sync_type = AV_SYNC_AUDIO_MASTER;
2309     else if (!strcmp(arg, "video"))
2310         av_sync_type = AV_SYNC_VIDEO_MASTER;
2311     else if (!strcmp(arg, "ext"))
2312         av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2313     else
2314         show_help();
2315 }
2316
2317 void opt_seek(const char *arg)
2318 {
2319     start_time = parse_date(arg, 1);
2320 }
2321
2322 static void opt_debug(const char *arg)
2323 {
2324     debug = atoi(arg);
2325 }
2326     
2327 static void opt_vismv(const char *arg)
2328 {
2329     debug_mv = atoi(arg);
2330 }
2331
2332 static void opt_thread_count(const char *arg)
2333 {
2334     thread_count= atoi(arg);
2335 #if !defined(HAVE_THREADS)
2336     fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2337 #endif
2338 }
2339     
2340 const OptionDef options[] = {
2341     { "h", 0, {(void*)show_help}, "show help" },    
2342     { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
2343     { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
2344 #if 0
2345     /* disabled as SDL/X11 does not support it correctly on application launch */
2346     { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
2347 #endif
2348     { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2349     { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
2350     { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
2351     { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2352     { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
2353     { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
2354     { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
2355     { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
2356     { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
2357     { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
2358     { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
2359     { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
2360     { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2361     { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2362     { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
2363     { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo",  "algo" },
2364     { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)",  "threshold" },
2365     { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options",  "bit_mask" },
2366 #ifdef CONFIG_NETWORK
2367     { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
2368 #endif
2369     { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2370     { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
2371     { NULL, },
2372 };
2373
2374 void show_help(void)
2375 {
2376     printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
2377            "usage: ffplay [options] input_file\n"
2378            "Simple media player\n");
2379     printf("\n");
2380     show_help_options(options, "Main options:\n",
2381                       OPT_EXPERT, 0);
2382     show_help_options(options, "\nAdvanced options:\n",
2383                       OPT_EXPERT, OPT_EXPERT);
2384     printf("\nWhile playing:\n"
2385            "q, ESC              quit\n"
2386            "f                   toggle full screen\n"
2387            "p, SPC              pause\n"
2388            "a                   cycle audio channel\n"
2389            "v                   cycle video channel\n"
2390            "t                   cycle subtitle channel\n"
2391            "w                   show audio waves\n"
2392            "left/right          seek backward/forward 10 seconds\n"
2393            "down/up             seek backward/forward 1 minute\n"
2394            "mouse click         seek to percentage in file corresponding to fraction of width\n"
2395            );
2396     exit(1);
2397 }
2398
2399 void parse_arg_file(const char *filename)
2400 {
2401     if (!strcmp(filename, "-"))
2402                     filename = "pipe:";
2403     input_filename = filename;
2404 }
2405
2406 /* Called from the main */
2407 int main(int argc, char **argv)
2408 {
2409     int flags, w, h;
2410     
2411     /* register all codecs, demux and protocols */
2412     av_register_all();
2413
2414     #ifdef CONFIG_OS2
2415       MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
2416  
2417       // Make stdout and stderr unbuffered
2418       setbuf( stdout, NULL );
2419       setbuf( stderr, NULL );
2420     #endif
2421
2422     parse_options(argc, argv, options);
2423
2424     if (!input_filename)
2425         show_help();
2426
2427     if (display_disable) {
2428         video_disable = 1;
2429     }
2430     flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
2431 #ifndef CONFIG_WIN32
2432     flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 */
2433 #endif
2434     if (SDL_Init (flags)) {
2435         fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
2436         exit(1);
2437     }
2438
2439     if (!display_disable) {
2440 #ifdef HAVE_X11
2441         /* save the screen resolution... SDL should allow full screen
2442            by resizing the window */
2443         {
2444             Display *dpy;
2445             dpy = XOpenDisplay(NULL);
2446             if (dpy) {
2447                 fs_screen_width = DisplayWidth(dpy, DefaultScreen(dpy));
2448                 fs_screen_height = DisplayHeight(dpy, DefaultScreen(dpy));
2449                 XCloseDisplay(dpy);
2450             }
2451         }
2452 #endif
2453         flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
2454         if (is_full_screen && fs_screen_width) {
2455             w = fs_screen_width;
2456             h = fs_screen_height;
2457             flags |= SDL_FULLSCREEN;
2458         } else {
2459             w = screen_width;
2460             h = screen_height;
2461             flags |= SDL_RESIZABLE;
2462         }
2463         screen = SDL_SetVideoMode(w, h, 0, flags);
2464         if (!screen) {
2465             fprintf(stderr, "SDL: could not set video mode - exiting\n");
2466             exit(1);
2467         }
2468         SDL_WM_SetCaption("FFplay", "FFplay");
2469     }
2470
2471     SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2472     SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2473     SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2474     SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2475
2476     cur_stream = stream_open(input_filename, file_iformat);
2477
2478     event_loop();
2479
2480     /* never returns */
2481
2482     return 0;
2483 }