Rename av_fill_image_linesizes() internal variables max_plane_step and
[libav.git] / ffplay.c
1 /*
2 * FFplay : Simple Media Player based on the FFmpeg libraries
3 * Copyright (c) 2003 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "config.h"
23 #include <inttypes.h>
24 #include <math.h>
25 #include <limits.h>
26 #include "libavutil/avstring.h"
27 #include "libavutil/colorspace.h"
28 #include "libavutil/pixdesc.h"
29 #include "libavcore/parseutils.h"
30 #include "libavformat/avformat.h"
31 #include "libavdevice/avdevice.h"
32 #include "libswscale/swscale.h"
33 #include "libavcodec/audioconvert.h"
34 #include "libavcodec/opt.h"
35 #include "libavcodec/avfft.h"
36
37 #if CONFIG_AVFILTER
38 # include "libavfilter/avfilter.h"
39 # include "libavfilter/avfiltergraph.h"
40 # include "libavfilter/graphparser.h"
41 #endif
42
43 #include "cmdutils.h"
44
45 #include <SDL.h>
46 #include <SDL_thread.h>
47
48 #ifdef __MINGW32__
49 #undef main /* We don't want SDL to override our main() */
50 #endif
51
52 #include <unistd.h>
53 #include <assert.h>
54
55 const char program_name[] = "FFplay";
56 const int program_birth_year = 2003;
57
58 //#define DEBUG_SYNC
59
60 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
61 #define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
62 #define MIN_FRAMES 5
63
64 /* SDL audio buffer size, in samples. Should be small to have precise
65 A/V sync as SDL does not have hardware buffer fullness info. */
66 #define SDL_AUDIO_BUFFER_SIZE 1024
67
68 /* no AV sync correction is done if below the AV sync threshold */
69 #define AV_SYNC_THRESHOLD 0.01
70 /* no AV correction is done if too big error */
71 #define AV_NOSYNC_THRESHOLD 10.0
72
73 #define FRAME_SKIP_FACTOR 0.05
74
75 /* maximum audio speed change to get correct sync */
76 #define SAMPLE_CORRECTION_PERCENT_MAX 10
77
78 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
79 #define AUDIO_DIFF_AVG_NB 20
80
81 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
82 #define SAMPLE_ARRAY_SIZE (2*65536)
83
84 static int sws_flags = SWS_BICUBIC;
85
86 typedef struct PacketQueue {
87 AVPacketList *first_pkt, *last_pkt;
88 int nb_packets;
89 int size;
90 int abort_request;
91 SDL_mutex *mutex;
92 SDL_cond *cond;
93 } PacketQueue;
94
95 #define VIDEO_PICTURE_QUEUE_SIZE 2
96 #define SUBPICTURE_QUEUE_SIZE 4
97
98 typedef struct VideoPicture {
99 double pts; ///<presentation time stamp for this picture
100 double target_clock; ///<av_gettime() time at which this should be displayed ideally
101 int64_t pos; ///<byte position in file
102 SDL_Overlay *bmp;
103 int width, height; /* source height & width */
104 int allocated;
105 enum PixelFormat pix_fmt;
106
107 #if CONFIG_AVFILTER
108 AVFilterPicRef *picref;
109 #endif
110 } VideoPicture;
111
112 typedef struct SubPicture {
113 double pts; /* presentation time stamp for this picture */
114 AVSubtitle sub;
115 } SubPicture;
116
117 enum {
118 AV_SYNC_AUDIO_MASTER, /* default choice */
119 AV_SYNC_VIDEO_MASTER,
120 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
121 };
122
123 typedef struct VideoState {
124 SDL_Thread *parse_tid;
125 SDL_Thread *video_tid;
126 SDL_Thread *refresh_tid;
127 AVInputFormat *iformat;
128 int no_background;
129 int abort_request;
130 int paused;
131 int last_paused;
132 int seek_req;
133 int seek_flags;
134 int64_t seek_pos;
135 int64_t seek_rel;
136 int read_pause_return;
137 AVFormatContext *ic;
138 int dtg_active_format;
139
140 int audio_stream;
141
142 int av_sync_type;
143 double external_clock; /* external clock base */
144 int64_t external_clock_time;
145
146 double audio_clock;
147 double audio_diff_cum; /* used for AV difference average computation */
148 double audio_diff_avg_coef;
149 double audio_diff_threshold;
150 int audio_diff_avg_count;
151 AVStream *audio_st;
152 PacketQueue audioq;
153 int audio_hw_buf_size;
154 /* samples output by the codec. we reserve more space for avsync
155 compensation */
156 DECLARE_ALIGNED(16,uint8_t,audio_buf1)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
157 DECLARE_ALIGNED(16,uint8_t,audio_buf2)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
158 uint8_t *audio_buf;
159 unsigned int audio_buf_size; /* in bytes */
160 int audio_buf_index; /* in bytes */
161 AVPacket audio_pkt_temp;
162 AVPacket audio_pkt;
163 enum SampleFormat audio_src_fmt;
164 AVAudioConvert *reformat_ctx;
165
166 int show_audio; /* if true, display audio samples */
167 int16_t sample_array[SAMPLE_ARRAY_SIZE];
168 int sample_array_index;
169 int last_i_start;
170 RDFTContext *rdft;
171 int rdft_bits;
172 FFTSample *rdft_data;
173 int xpos;
174
175 SDL_Thread *subtitle_tid;
176 int subtitle_stream;
177 int subtitle_stream_changed;
178 AVStream *subtitle_st;
179 PacketQueue subtitleq;
180 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
181 int subpq_size, subpq_rindex, subpq_windex;
182 SDL_mutex *subpq_mutex;
183 SDL_cond *subpq_cond;
184
185 double frame_timer;
186 double frame_last_pts;
187 double frame_last_delay;
188 double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
189 int video_stream;
190 AVStream *video_st;
191 PacketQueue videoq;
192 double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
193 double video_current_pts_drift; ///<video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts
194 int64_t video_current_pos; ///<current displayed file pos
195 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
196 int pictq_size, pictq_rindex, pictq_windex;
197 SDL_mutex *pictq_mutex;
198 SDL_cond *pictq_cond;
199 #if !CONFIG_AVFILTER
200 struct SwsContext *img_convert_ctx;
201 #endif
202
203 // QETimer *video_timer;
204 char filename[1024];
205 int width, height, xleft, ytop;
206
207 int64_t faulty_pts;
208 int64_t faulty_dts;
209 int64_t last_dts_for_fault_detection;
210 int64_t last_pts_for_fault_detection;
211
212 #if CONFIG_AVFILTER
213 AVFilterContext *out_video_filter; ///<the last filter in the video chain
214 #endif
215
216 float skip_frames;
217 float skip_frames_index;
218 int refresh;
219 } VideoState;
220
221 static void show_help(void);
222 static int audio_write_get_buf_size(VideoState *is);
223
224 /* options specified by the user */
225 static AVInputFormat *file_iformat;
226 static const char *input_filename;
227 static const char *window_title;
228 static int fs_screen_width;
229 static int fs_screen_height;
230 static int screen_width = 0;
231 static int screen_height = 0;
232 static int frame_width = 0;
233 static int frame_height = 0;
234 static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
235 static int audio_disable;
236 static int video_disable;
237 static int wanted_stream[AVMEDIA_TYPE_NB]={
238 [AVMEDIA_TYPE_AUDIO]=-1,
239 [AVMEDIA_TYPE_VIDEO]=-1,
240 [AVMEDIA_TYPE_SUBTITLE]=-1,
241 };
242 static int seek_by_bytes=-1;
243 static int display_disable;
244 static int show_status = 1;
245 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
246 static int64_t start_time = AV_NOPTS_VALUE;
247 static int64_t duration = AV_NOPTS_VALUE;
248 static int debug = 0;
249 static int debug_mv = 0;
250 static int step = 0;
251 static int thread_count = 1;
252 static int workaround_bugs = 1;
253 static int fast = 0;
254 static int genpts = 0;
255 static int lowres = 0;
256 static int idct = FF_IDCT_AUTO;
257 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
258 static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
259 static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
260 static int error_recognition = FF_ER_CAREFUL;
261 static int error_concealment = 3;
262 static int decoder_reorder_pts= -1;
263 static int autoexit;
264 static int exit_on_keydown;
265 static int exit_on_mousedown;
266 static int loop=1;
267 static int framedrop=1;
268
269 static int rdftspeed=20;
270 #if CONFIG_AVFILTER
271 static char *vfilters = NULL;
272 #endif
273
274 /* current context */
275 static int is_full_screen;
276 static VideoState *cur_stream;
277 static int64_t audio_callback_time;
278
279 static AVPacket flush_pkt;
280
281 #define FF_ALLOC_EVENT (SDL_USEREVENT)
282 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
283 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
284
285 static SDL_Surface *screen;
286
287 static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
288
289 /* packet queue handling */
290 static void packet_queue_init(PacketQueue *q)
291 {
292 memset(q, 0, sizeof(PacketQueue));
293 q->mutex = SDL_CreateMutex();
294 q->cond = SDL_CreateCond();
295 packet_queue_put(q, &flush_pkt);
296 }
297
298 static void packet_queue_flush(PacketQueue *q)
299 {
300 AVPacketList *pkt, *pkt1;
301
302 SDL_LockMutex(q->mutex);
303 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
304 pkt1 = pkt->next;
305 av_free_packet(&pkt->pkt);
306 av_freep(&pkt);
307 }
308 q->last_pkt = NULL;
309 q->first_pkt = NULL;
310 q->nb_packets = 0;
311 q->size = 0;
312 SDL_UnlockMutex(q->mutex);
313 }
314
315 static void packet_queue_end(PacketQueue *q)
316 {
317 packet_queue_flush(q);
318 SDL_DestroyMutex(q->mutex);
319 SDL_DestroyCond(q->cond);
320 }
321
322 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
323 {
324 AVPacketList *pkt1;
325
326 /* duplicate the packet */
327 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
328 return -1;
329
330 pkt1 = av_malloc(sizeof(AVPacketList));
331 if (!pkt1)
332 return -1;
333 pkt1->pkt = *pkt;
334 pkt1->next = NULL;
335
336
337 SDL_LockMutex(q->mutex);
338
339 if (!q->last_pkt)
340
341 q->first_pkt = pkt1;
342 else
343 q->last_pkt->next = pkt1;
344 q->last_pkt = pkt1;
345 q->nb_packets++;
346 q->size += pkt1->pkt.size + sizeof(*pkt1);
347 /* XXX: should duplicate packet data in DV case */
348 SDL_CondSignal(q->cond);
349
350 SDL_UnlockMutex(q->mutex);
351 return 0;
352 }
353
354 static void packet_queue_abort(PacketQueue *q)
355 {
356 SDL_LockMutex(q->mutex);
357
358 q->abort_request = 1;
359
360 SDL_CondSignal(q->cond);
361
362 SDL_UnlockMutex(q->mutex);
363 }
364
365 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
366 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
367 {
368 AVPacketList *pkt1;
369 int ret;
370
371 SDL_LockMutex(q->mutex);
372
373 for(;;) {
374 if (q->abort_request) {
375 ret = -1;
376 break;
377 }
378
379 pkt1 = q->first_pkt;
380 if (pkt1) {
381 q->first_pkt = pkt1->next;
382 if (!q->first_pkt)
383 q->last_pkt = NULL;
384 q->nb_packets--;
385 q->size -= pkt1->pkt.size + sizeof(*pkt1);
386 *pkt = pkt1->pkt;
387 av_free(pkt1);
388 ret = 1;
389 break;
390 } else if (!block) {
391 ret = 0;
392 break;
393 } else {
394 SDL_CondWait(q->cond, q->mutex);
395 }
396 }
397 SDL_UnlockMutex(q->mutex);
398 return ret;
399 }
400
401 static inline void fill_rectangle(SDL_Surface *screen,
402 int x, int y, int w, int h, int color)
403 {
404 SDL_Rect rect;
405 rect.x = x;
406 rect.y = y;
407 rect.w = w;
408 rect.h = h;
409 SDL_FillRect(screen, &rect, color);
410 }
411
412 #if 0
413 /* draw only the border of a rectangle */
414 void fill_border(VideoState *s, int x, int y, int w, int h, int color)
415 {
416 int w1, w2, h1, h2;
417
418 /* fill the background */
419 w1 = x;
420 if (w1 < 0)
421 w1 = 0;
422 w2 = s->width - (x + w);
423 if (w2 < 0)
424 w2 = 0;
425 h1 = y;
426 if (h1 < 0)
427 h1 = 0;
428 h2 = s->height - (y + h);
429 if (h2 < 0)
430 h2 = 0;
431 fill_rectangle(screen,
432 s->xleft, s->ytop,
433 w1, s->height,
434 color);
435 fill_rectangle(screen,
436 s->xleft + s->width - w2, s->ytop,
437 w2, s->height,
438 color);
439 fill_rectangle(screen,
440 s->xleft + w1, s->ytop,
441 s->width - w1 - w2, h1,
442 color);
443 fill_rectangle(screen,
444 s->xleft + w1, s->ytop + s->height - h2,
445 s->width - w1 - w2, h2,
446 color);
447 }
448 #endif
449
450 #define ALPHA_BLEND(a, oldp, newp, s)\
451 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
452
453 #define RGBA_IN(r, g, b, a, s)\
454 {\
455 unsigned int v = ((const uint32_t *)(s))[0];\
456 a = (v >> 24) & 0xff;\
457 r = (v >> 16) & 0xff;\
458 g = (v >> 8) & 0xff;\
459 b = v & 0xff;\
460 }
461
462 #define YUVA_IN(y, u, v, a, s, pal)\
463 {\
464 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
465 a = (val >> 24) & 0xff;\
466 y = (val >> 16) & 0xff;\
467 u = (val >> 8) & 0xff;\
468 v = val & 0xff;\
469 }
470
471 #define YUVA_OUT(d, y, u, v, a)\
472 {\
473 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
474 }
475
476
477 #define BPP 1
478
479 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
480 {
481 int wrap, wrap3, width2, skip2;
482 int y, u, v, a, u1, v1, a1, w, h;
483 uint8_t *lum, *cb, *cr;
484 const uint8_t *p;
485 const uint32_t *pal;
486 int dstx, dsty, dstw, dsth;
487
488 dstw = av_clip(rect->w, 0, imgw);
489 dsth = av_clip(rect->h, 0, imgh);
490 dstx = av_clip(rect->x, 0, imgw - dstw);
491 dsty = av_clip(rect->y, 0, imgh - dsth);
492 lum = dst->data[0] + dsty * dst->linesize[0];
493 cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
494 cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
495
496 width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
497 skip2 = dstx >> 1;
498 wrap = dst->linesize[0];
499 wrap3 = rect->pict.linesize[0];
500 p = rect->pict.data[0];
501 pal = (const uint32_t *)rect->pict.data[1]; /* Now in YCrCb! */
502
503 if (dsty & 1) {
504 lum += dstx;
505 cb += skip2;
506 cr += skip2;
507
508 if (dstx & 1) {
509 YUVA_IN(y, u, v, a, p, pal);
510 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
511 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
512 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
513 cb++;
514 cr++;
515 lum++;
516 p += BPP;
517 }
518 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
519 YUVA_IN(y, u, v, a, p, pal);
520 u1 = u;
521 v1 = v;
522 a1 = a;
523 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
524
525 YUVA_IN(y, u, v, a, p + BPP, pal);
526 u1 += u;
527 v1 += v;
528 a1 += a;
529 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
530 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
531 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
532 cb++;
533 cr++;
534 p += 2 * BPP;
535 lum += 2;
536 }
537 if (w) {
538 YUVA_IN(y, u, v, a, p, pal);
539 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
540 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
541 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
542 p++;
543 lum++;
544 }
545 p += wrap3 - dstw * BPP;
546 lum += wrap - dstw - dstx;
547 cb += dst->linesize[1] - width2 - skip2;
548 cr += dst->linesize[2] - width2 - skip2;
549 }
550 for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
551 lum += dstx;
552 cb += skip2;
553 cr += skip2;
554
555 if (dstx & 1) {
556 YUVA_IN(y, u, v, a, p, pal);
557 u1 = u;
558 v1 = v;
559 a1 = a;
560 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
561 p += wrap3;
562 lum += wrap;
563 YUVA_IN(y, u, v, a, p, pal);
564 u1 += u;
565 v1 += v;
566 a1 += a;
567 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
568 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
569 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
570 cb++;
571 cr++;
572 p += -wrap3 + BPP;
573 lum += -wrap + 1;
574 }
575 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
576 YUVA_IN(y, u, v, a, p, pal);
577 u1 = u;
578 v1 = v;
579 a1 = a;
580 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
581
582 YUVA_IN(y, u, v, a, p + BPP, pal);
583 u1 += u;
584 v1 += v;
585 a1 += a;
586 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
587 p += wrap3;
588 lum += wrap;
589
590 YUVA_IN(y, u, v, a, p, pal);
591 u1 += u;
592 v1 += v;
593 a1 += a;
594 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
595
596 YUVA_IN(y, u, v, a, p + BPP, pal);
597 u1 += u;
598 v1 += v;
599 a1 += a;
600 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
601
602 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
603 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
604
605 cb++;
606 cr++;
607 p += -wrap3 + 2 * BPP;
608 lum += -wrap + 2;
609 }
610 if (w) {
611 YUVA_IN(y, u, v, a, p, pal);
612 u1 = u;
613 v1 = v;
614 a1 = a;
615 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
616 p += wrap3;
617 lum += wrap;
618 YUVA_IN(y, u, v, a, p, pal);
619 u1 += u;
620 v1 += v;
621 a1 += a;
622 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
623 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
624 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
625 cb++;
626 cr++;
627 p += -wrap3 + BPP;
628 lum += -wrap + 1;
629 }
630 p += wrap3 + (wrap3 - dstw * BPP);
631 lum += wrap + (wrap - dstw - dstx);
632 cb += dst->linesize[1] - width2 - skip2;
633 cr += dst->linesize[2] - width2 - skip2;
634 }
635 /* handle odd height */
636 if (h) {
637 lum += dstx;
638 cb += skip2;
639 cr += skip2;
640
641 if (dstx & 1) {
642 YUVA_IN(y, u, v, a, p, pal);
643 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
644 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
645 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
646 cb++;
647 cr++;
648 lum++;
649 p += BPP;
650 }
651 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
652 YUVA_IN(y, u, v, a, p, pal);
653 u1 = u;
654 v1 = v;
655 a1 = a;
656 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
657
658 YUVA_IN(y, u, v, a, p + BPP, pal);
659 u1 += u;
660 v1 += v;
661 a1 += a;
662 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
663 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
664 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
665 cb++;
666 cr++;
667 p += 2 * BPP;
668 lum += 2;
669 }
670 if (w) {
671 YUVA_IN(y, u, v, a, p, pal);
672 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
673 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
674 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
675 }
676 }
677 }
678
679 static void free_subpicture(SubPicture *sp)
680 {
681 avsubtitle_free(&sp->sub);
682 }
683
684 static void video_image_display(VideoState *is)
685 {
686 VideoPicture *vp;
687 SubPicture *sp;
688 AVPicture pict;
689 float aspect_ratio;
690 int width, height, x, y;
691 SDL_Rect rect;
692 int i;
693
694 vp = &is->pictq[is->pictq_rindex];
695 if (vp->bmp) {
696 #if CONFIG_AVFILTER
697 if (vp->picref->pixel_aspect.num == 0)
698 aspect_ratio = 0;
699 else
700 aspect_ratio = av_q2d(vp->picref->pixel_aspect);
701 #else
702
703 /* XXX: use variable in the frame */
704 if (is->video_st->sample_aspect_ratio.num)
705 aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
706 else if (is->video_st->codec->sample_aspect_ratio.num)
707 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
708 else
709 aspect_ratio = 0;
710 #endif
711 if (aspect_ratio <= 0.0)
712 aspect_ratio = 1.0;
713 aspect_ratio *= (float)vp->width / (float)vp->height;
714 /* if an active format is indicated, then it overrides the
715 mpeg format */
716 #if 0
717 if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
718 is->dtg_active_format = is->video_st->codec->dtg_active_format;
719 printf("dtg_active_format=%d\n", is->dtg_active_format);
720 }
721 #endif
722 #if 0
723 switch(is->video_st->codec->dtg_active_format) {
724 case FF_DTG_AFD_SAME:
725 default:
726 /* nothing to do */
727 break;
728 case FF_DTG_AFD_4_3:
729 aspect_ratio = 4.0 / 3.0;
730 break;
731 case FF_DTG_AFD_16_9:
732 aspect_ratio = 16.0 / 9.0;
733 break;
734 case FF_DTG_AFD_14_9:
735 aspect_ratio = 14.0 / 9.0;
736 break;
737 case FF_DTG_AFD_4_3_SP_14_9:
738 aspect_ratio = 14.0 / 9.0;
739 break;
740 case FF_DTG_AFD_16_9_SP_14_9:
741 aspect_ratio = 14.0 / 9.0;
742 break;
743 case FF_DTG_AFD_SP_4_3:
744 aspect_ratio = 4.0 / 3.0;
745 break;
746 }
747 #endif
748
749 if (is->subtitle_st)
750 {
751 if (is->subpq_size > 0)
752 {
753 sp = &is->subpq[is->subpq_rindex];
754
755 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
756 {
757 SDL_LockYUVOverlay (vp->bmp);
758
759 pict.data[0] = vp->bmp->pixels[0];
760 pict.data[1] = vp->bmp->pixels[2];
761 pict.data[2] = vp->bmp->pixels[1];
762
763 pict.linesize[0] = vp->bmp->pitches[0];
764 pict.linesize[1] = vp->bmp->pitches[2];
765 pict.linesize[2] = vp->bmp->pitches[1];
766
767 for (i = 0; i < sp->sub.num_rects; i++)
768 blend_subrect(&pict, sp->sub.rects[i],
769 vp->bmp->w, vp->bmp->h);
770
771 SDL_UnlockYUVOverlay (vp->bmp);
772 }
773 }
774 }
775
776
777 /* XXX: we suppose the screen has a 1.0 pixel ratio */
778 height = is->height;
779 width = ((int)rint(height * aspect_ratio)) & ~1;
780 if (width > is->width) {
781 width = is->width;
782 height = ((int)rint(width / aspect_ratio)) & ~1;
783 }
784 x = (is->width - width) / 2;
785 y = (is->height - height) / 2;
786 if (!is->no_background) {
787 /* fill the background */
788 // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
789 } else {
790 is->no_background = 0;
791 }
792 rect.x = is->xleft + x;
793 rect.y = is->ytop + y;
794 rect.w = width;
795 rect.h = height;
796 SDL_DisplayYUVOverlay(vp->bmp, &rect);
797 } else {
798 #if 0
799 fill_rectangle(screen,
800 is->xleft, is->ytop, is->width, is->height,
801 QERGB(0x00, 0x00, 0x00));
802 #endif
803 }
804 }
805
806 static inline int compute_mod(int a, int b)
807 {
808 a = a % b;
809 if (a >= 0)
810 return a;
811 else
812 return a + b;
813 }
814
815 static void video_audio_display(VideoState *s)
816 {
817 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
818 int ch, channels, h, h2, bgcolor, fgcolor;
819 int16_t time_diff;
820 int rdft_bits, nb_freq;
821
822 for(rdft_bits=1; (1<<rdft_bits)<2*s->height; rdft_bits++)
823 ;
824 nb_freq= 1<<(rdft_bits-1);
825
826 /* compute display index : center on currently output samples */
827 channels = s->audio_st->codec->channels;
828 nb_display_channels = channels;
829 if (!s->paused) {
830 int data_used= s->show_audio==1 ? s->width : (2*nb_freq);
831 n = 2 * channels;
832 delay = audio_write_get_buf_size(s);
833 delay /= n;
834
835 /* to be more precise, we take into account the time spent since
836 the last buffer computation */
837 if (audio_callback_time) {
838 time_diff = av_gettime() - audio_callback_time;
839 delay -= (time_diff * s->audio_st->codec->sample_rate) / 1000000;
840 }
841
842 delay += 2*data_used;
843 if (delay < data_used)
844 delay = data_used;
845
846 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
847 if(s->show_audio==1){
848 h= INT_MIN;
849 for(i=0; i<1000; i+=channels){
850 int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
851 int a= s->sample_array[idx];
852 int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
853 int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
854 int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
855 int score= a-d;
856 if(h<score && (b^c)<0){
857 h= score;
858 i_start= idx;
859 }
860 }
861 }
862
863 s->last_i_start = i_start;
864 } else {
865 i_start = s->last_i_start;
866 }
867
868 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
869 if(s->show_audio==1){
870 fill_rectangle(screen,
871 s->xleft, s->ytop, s->width, s->height,
872 bgcolor);
873
874 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
875
876 /* total height for one channel */
877 h = s->height / nb_display_channels;
878 /* graph height / 2 */
879 h2 = (h * 9) / 20;
880 for(ch = 0;ch < nb_display_channels; ch++) {
881 i = i_start + ch;
882 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
883 for(x = 0; x < s->width; x++) {
884 y = (s->sample_array[i] * h2) >> 15;
885 if (y < 0) {
886 y = -y;
887 ys = y1 - y;
888 } else {
889 ys = y1;
890 }
891 fill_rectangle(screen,
892 s->xleft + x, ys, 1, y,
893 fgcolor);
894 i += channels;
895 if (i >= SAMPLE_ARRAY_SIZE)
896 i -= SAMPLE_ARRAY_SIZE;
897 }
898 }
899
900 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
901
902 for(ch = 1;ch < nb_display_channels; ch++) {
903 y = s->ytop + ch * h;
904 fill_rectangle(screen,
905 s->xleft, y, s->width, 1,
906 fgcolor);
907 }
908 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
909 }else{
910 nb_display_channels= FFMIN(nb_display_channels, 2);
911 if(rdft_bits != s->rdft_bits){
912 av_rdft_end(s->rdft);
913 av_free(s->rdft_data);
914 s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
915 s->rdft_bits= rdft_bits;
916 s->rdft_data= av_malloc(4*nb_freq*sizeof(*s->rdft_data));
917 }
918 {
919 FFTSample *data[2];
920 for(ch = 0;ch < nb_display_channels; ch++) {
921 data[ch] = s->rdft_data + 2*nb_freq*ch;
922 i = i_start + ch;
923 for(x = 0; x < 2*nb_freq; x++) {
924 double w= (x-nb_freq)*(1.0/nb_freq);
925 data[ch][x]= s->sample_array[i]*(1.0-w*w);
926 i += channels;
927 if (i >= SAMPLE_ARRAY_SIZE)
928 i -= SAMPLE_ARRAY_SIZE;
929 }
930 av_rdft_calc(s->rdft, data[ch]);
931 }
932 //least efficient way to do this, we should of course directly access it but its more than fast enough
933 for(y=0; y<s->height; y++){
934 double w= 1/sqrt(nb_freq);
935 int a= sqrt(w*sqrt(data[0][2*y+0]*data[0][2*y+0] + data[0][2*y+1]*data[0][2*y+1]));
936 int b= (nb_display_channels == 2 ) ? sqrt(w*sqrt(data[1][2*y+0]*data[1][2*y+0]
937 + data[1][2*y+1]*data[1][2*y+1])) : a;
938 a= FFMIN(a,255);
939 b= FFMIN(b,255);
940 fgcolor = SDL_MapRGB(screen->format, a, b, (a+b)/2);
941
942 fill_rectangle(screen,
943 s->xpos, s->height-y, 1, 1,
944 fgcolor);
945 }
946 }
947 SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
948 s->xpos++;
949 if(s->xpos >= s->width)
950 s->xpos= s->xleft;
951 }
952 }
953
954 static int video_open(VideoState *is){
955 int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
956 int w,h;
957
958 if(is_full_screen) flags |= SDL_FULLSCREEN;
959 else flags |= SDL_RESIZABLE;
960
961 if (is_full_screen && fs_screen_width) {
962 w = fs_screen_width;
963 h = fs_screen_height;
964 } else if(!is_full_screen && screen_width){
965 w = screen_width;
966 h = screen_height;
967 #if CONFIG_AVFILTER
968 }else if (is->out_video_filter && is->out_video_filter->inputs[0]){
969 w = is->out_video_filter->inputs[0]->w;
970 h = is->out_video_filter->inputs[0]->h;
971 #else
972 }else if (is->video_st && is->video_st->codec->width){
973 w = is->video_st->codec->width;
974 h = is->video_st->codec->height;
975 #endif
976 } else {
977 w = 640;
978 h = 480;
979 }
980 if(screen && is->width == screen->w && screen->w == w
981 && is->height== screen->h && screen->h == h)
982 return 0;
983
984 #ifndef __APPLE__
985 screen = SDL_SetVideoMode(w, h, 0, flags);
986 #else
987 /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
988 screen = SDL_SetVideoMode(w, h, 24, flags);
989 #endif
990 if (!screen) {
991 fprintf(stderr, "SDL: could not set video mode - exiting\n");
992 return -1;
993 }
994 if (!window_title)
995 window_title = input_filename;
996 SDL_WM_SetCaption(window_title, window_title);
997
998 is->width = screen->w;
999 is->height = screen->h;
1000
1001 return 0;
1002 }
1003
1004 /* display the current picture, if any */
1005 static void video_display(VideoState *is)
1006 {
1007 if(!screen)
1008 video_open(cur_stream);
1009 if (is->audio_st && is->show_audio)
1010 video_audio_display(is);
1011 else if (is->video_st)
1012 video_image_display(is);
1013 }
1014
1015 static int refresh_thread(void *opaque)
1016 {
1017 VideoState *is= opaque;
1018 while(!is->abort_request){
1019 SDL_Event event;
1020 event.type = FF_REFRESH_EVENT;
1021 event.user.data1 = opaque;
1022 if(!is->refresh){
1023 is->refresh=1;
1024 SDL_PushEvent(&event);
1025 }
1026 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
1027 }
1028 return 0;
1029 }
1030
1031 /* get the current audio clock value */
1032 static double get_audio_clock(VideoState *is)
1033 {
1034 double pts;
1035 int hw_buf_size, bytes_per_sec;
1036 pts = is->audio_clock;
1037 hw_buf_size = audio_write_get_buf_size(is);
1038 bytes_per_sec = 0;
1039 if (is->audio_st) {
1040 bytes_per_sec = is->audio_st->codec->sample_rate *
1041 2 * is->audio_st->codec->channels;
1042 }
1043 if (bytes_per_sec)
1044 pts -= (double)hw_buf_size / bytes_per_sec;
1045 return pts;
1046 }
1047
1048 /* get the current video clock value */
1049 static double get_video_clock(VideoState *is)
1050 {
1051 if (is->paused) {
1052 return is->video_current_pts;
1053 } else {
1054 return is->video_current_pts_drift + av_gettime() / 1000000.0;
1055 }
1056 }
1057
1058 /* get the current external clock value */
1059 static double get_external_clock(VideoState *is)
1060 {
1061 int64_t ti;
1062 ti = av_gettime();
1063 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
1064 }
1065
1066 /* get the current master clock value */
1067 static double get_master_clock(VideoState *is)
1068 {
1069 double val;
1070
1071 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
1072 if (is->video_st)
1073 val = get_video_clock(is);
1074 else
1075 val = get_audio_clock(is);
1076 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
1077 if (is->audio_st)
1078 val = get_audio_clock(is);
1079 else
1080 val = get_video_clock(is);
1081 } else {
1082 val = get_external_clock(is);
1083 }
1084 return val;
1085 }
1086
1087 /* seek in the stream */
1088 static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
1089 {
1090 if (!is->seek_req) {
1091 is->seek_pos = pos;
1092 is->seek_rel = rel;
1093 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
1094 if (seek_by_bytes)
1095 is->seek_flags |= AVSEEK_FLAG_BYTE;
1096 is->seek_req = 1;
1097 }
1098 }
1099
1100 /* pause or resume the video */
1101 static void stream_pause(VideoState *is)
1102 {
1103 if (is->paused) {
1104 is->frame_timer += av_gettime() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts;
1105 if(is->read_pause_return != AVERROR(ENOSYS)){
1106 is->video_current_pts = is->video_current_pts_drift + av_gettime() / 1000000.0;
1107 }
1108 is->video_current_pts_drift = is->video_current_pts - av_gettime() / 1000000.0;
1109 }
1110 is->paused = !is->paused;
1111 }
1112
1113 static double compute_target_time(double frame_current_pts, VideoState *is)
1114 {
1115 double delay, sync_threshold, diff;
1116
1117 /* compute nominal delay */
1118 delay = frame_current_pts - is->frame_last_pts;
1119 if (delay <= 0 || delay >= 10.0) {
1120 /* if incorrect delay, use previous one */
1121 delay = is->frame_last_delay;
1122 } else {
1123 is->frame_last_delay = delay;
1124 }
1125 is->frame_last_pts = frame_current_pts;
1126
1127 /* update delay to follow master synchronisation source */
1128 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1129 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1130 /* if video is slave, we try to correct big delays by
1131 duplicating or deleting a frame */
1132 diff = get_video_clock(is) - get_master_clock(is);
1133
1134 /* skip or repeat frame. We take into account the
1135 delay to compute the threshold. I still don't know
1136 if it is the best guess */
1137 sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
1138 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1139 if (diff <= -sync_threshold)
1140 delay = 0;
1141 else if (diff >= sync_threshold)
1142 delay = 2 * delay;
1143 }
1144 }
1145 is->frame_timer += delay;
1146 #if defined(DEBUG_SYNC)
1147 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
1148 delay, actual_delay, frame_current_pts, -diff);
1149 #endif
1150
1151 return is->frame_timer;
1152 }
1153
1154 /* called to display each frame */
1155 static void video_refresh_timer(void *opaque)
1156 {
1157 VideoState *is = opaque;
1158 VideoPicture *vp;
1159
1160 SubPicture *sp, *sp2;
1161
1162 if (is->video_st) {
1163 retry:
1164 if (is->pictq_size == 0) {
1165 //nothing to do, no picture to display in the que
1166 } else {
1167 double time= av_gettime()/1000000.0;
1168 double next_target;
1169 /* dequeue the picture */
1170 vp = &is->pictq[is->pictq_rindex];
1171
1172 if(time < vp->target_clock)
1173 return;
1174 /* update current video pts */
1175 is->video_current_pts = vp->pts;
1176 is->video_current_pts_drift = is->video_current_pts - time;
1177 is->video_current_pos = vp->pos;
1178 if(is->pictq_size > 1){
1179 VideoPicture *nextvp= &is->pictq[(is->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE];
1180 assert(nextvp->target_clock >= vp->target_clock);
1181 next_target= nextvp->target_clock;
1182 }else{
1183 next_target= vp->target_clock + is->video_clock - vp->pts; //FIXME pass durations cleanly
1184 }
1185 if(framedrop && time > next_target){
1186 is->skip_frames *= 1.0 + FRAME_SKIP_FACTOR;
1187 if(is->pictq_size > 1 || time > next_target + 0.5){
1188 /* update queue size and signal for next picture */
1189 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1190 is->pictq_rindex = 0;
1191
1192 SDL_LockMutex(is->pictq_mutex);
1193 is->pictq_size--;
1194 SDL_CondSignal(is->pictq_cond);
1195 SDL_UnlockMutex(is->pictq_mutex);
1196 goto retry;
1197 }
1198 }
1199
1200 if(is->subtitle_st) {
1201 if (is->subtitle_stream_changed) {
1202 SDL_LockMutex(is->subpq_mutex);
1203
1204 while (is->subpq_size) {
1205 free_subpicture(&is->subpq[is->subpq_rindex]);
1206
1207 /* update queue size and signal for next picture */
1208 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1209 is->subpq_rindex = 0;
1210
1211 is->subpq_size--;
1212 }
1213 is->subtitle_stream_changed = 0;
1214
1215 SDL_CondSignal(is->subpq_cond);
1216 SDL_UnlockMutex(is->subpq_mutex);
1217 } else {
1218 if (is->subpq_size > 0) {
1219 sp = &is->subpq[is->subpq_rindex];
1220
1221 if (is->subpq_size > 1)
1222 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1223 else
1224 sp2 = NULL;
1225
1226 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1227 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1228 {
1229 free_subpicture(sp);
1230
1231 /* update queue size and signal for next picture */
1232 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1233 is->subpq_rindex = 0;
1234
1235 SDL_LockMutex(is->subpq_mutex);
1236 is->subpq_size--;
1237 SDL_CondSignal(is->subpq_cond);
1238 SDL_UnlockMutex(is->subpq_mutex);
1239 }
1240 }
1241 }
1242 }
1243
1244 /* display picture */
1245 video_display(is);
1246
1247 /* update queue size and signal for next picture */
1248 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1249 is->pictq_rindex = 0;
1250
1251 SDL_LockMutex(is->pictq_mutex);
1252 is->pictq_size--;
1253 SDL_CondSignal(is->pictq_cond);
1254 SDL_UnlockMutex(is->pictq_mutex);
1255 }
1256 } else if (is->audio_st) {
1257 /* draw the next audio frame */
1258
1259 /* if only audio stream, then display the audio bars (better
1260 than nothing, just to test the implementation */
1261
1262 /* display picture */
1263 video_display(is);
1264 }
1265 if (show_status) {
1266 static int64_t last_time;
1267 int64_t cur_time;
1268 int aqsize, vqsize, sqsize;
1269 double av_diff;
1270
1271 cur_time = av_gettime();
1272 if (!last_time || (cur_time - last_time) >= 30000) {
1273 aqsize = 0;
1274 vqsize = 0;
1275 sqsize = 0;
1276 if (is->audio_st)
1277 aqsize = is->audioq.size;
1278 if (is->video_st)
1279 vqsize = is->videoq.size;
1280 if (is->subtitle_st)
1281 sqsize = is->subtitleq.size;
1282 av_diff = 0;
1283 if (is->audio_st && is->video_st)
1284 av_diff = get_audio_clock(is) - get_video_clock(is);
1285 printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
1286 get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->faulty_dts, is->faulty_pts);
1287 fflush(stdout);
1288 last_time = cur_time;
1289 }
1290 }
1291 }
1292
1293 /* allocate a picture (needs to do that in main thread to avoid
1294 potential locking problems */
1295 static void alloc_picture(void *opaque)
1296 {
1297 VideoState *is = opaque;
1298 VideoPicture *vp;
1299
1300 vp = &is->pictq[is->pictq_windex];
1301
1302 if (vp->bmp)
1303 SDL_FreeYUVOverlay(vp->bmp);
1304
1305 #if CONFIG_AVFILTER
1306 if (vp->picref)
1307 avfilter_unref_pic(vp->picref);
1308 vp->picref = NULL;
1309
1310 vp->width = is->out_video_filter->inputs[0]->w;
1311 vp->height = is->out_video_filter->inputs[0]->h;
1312 vp->pix_fmt = is->out_video_filter->inputs[0]->format;
1313 #else
1314 vp->width = is->video_st->codec->width;
1315 vp->height = is->video_st->codec->height;
1316 vp->pix_fmt = is->video_st->codec->pix_fmt;
1317 #endif
1318
1319 vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
1320 SDL_YV12_OVERLAY,
1321 screen);
1322
1323 SDL_LockMutex(is->pictq_mutex);
1324 vp->allocated = 1;
1325 SDL_CondSignal(is->pictq_cond);
1326 SDL_UnlockMutex(is->pictq_mutex);
1327 }
1328
1329 /**
1330 *
1331 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1332 */
1333 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos)
1334 {
1335 VideoPicture *vp;
1336 int dst_pix_fmt;
1337 #if CONFIG_AVFILTER
1338 AVPicture pict_src;
1339 #endif
1340 /* wait until we have space to put a new picture */
1341 SDL_LockMutex(is->pictq_mutex);
1342
1343 if(is->pictq_size>=VIDEO_PICTURE_QUEUE_SIZE && !is->refresh)
1344 is->skip_frames= FFMAX(1.0 - FRAME_SKIP_FACTOR, is->skip_frames * (1.0-FRAME_SKIP_FACTOR));
1345
1346 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1347 !is->videoq.abort_request) {
1348 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1349 }
1350 SDL_UnlockMutex(is->pictq_mutex);
1351
1352 if (is->videoq.abort_request)
1353 return -1;
1354
1355 vp = &is->pictq[is->pictq_windex];
1356
1357 /* alloc or resize hardware picture buffer */
1358 if (!vp->bmp ||
1359 #if CONFIG_AVFILTER
1360 vp->width != is->out_video_filter->inputs[0]->w ||
1361 vp->height != is->out_video_filter->inputs[0]->h) {
1362 #else
1363 vp->width != is->video_st->codec->width ||
1364 vp->height != is->video_st->codec->height) {
1365 #endif
1366 SDL_Event event;
1367
1368 vp->allocated = 0;
1369
1370 /* the allocation must be done in the main thread to avoid
1371 locking problems */
1372 event.type = FF_ALLOC_EVENT;
1373 event.user.data1 = is;
1374 SDL_PushEvent(&event);
1375
1376 /* wait until the picture is allocated */
1377 SDL_LockMutex(is->pictq_mutex);
1378 while (!vp->allocated && !is->videoq.abort_request) {
1379 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1380 }
1381 SDL_UnlockMutex(is->pictq_mutex);
1382
1383 if (is->videoq.abort_request)
1384 return -1;
1385 }
1386
1387 /* if the frame is not skipped, then display it */
1388 if (vp->bmp) {
1389 AVPicture pict;
1390 #if CONFIG_AVFILTER
1391 if(vp->picref)
1392 avfilter_unref_pic(vp->picref);
1393 vp->picref = src_frame->opaque;
1394 #endif
1395
1396 /* get a pointer on the bitmap */
1397 SDL_LockYUVOverlay (vp->bmp);
1398
1399 dst_pix_fmt = PIX_FMT_YUV420P;
1400 memset(&pict,0,sizeof(AVPicture));
1401 pict.data[0] = vp->bmp->pixels[0];
1402 pict.data[1] = vp->bmp->pixels[2];
1403 pict.data[2] = vp->bmp->pixels[1];
1404
1405 pict.linesize[0] = vp->bmp->pitches[0];
1406 pict.linesize[1] = vp->bmp->pitches[2];
1407 pict.linesize[2] = vp->bmp->pitches[1];
1408
1409 #if CONFIG_AVFILTER
1410 pict_src.data[0] = src_frame->data[0];
1411 pict_src.data[1] = src_frame->data[1];
1412 pict_src.data[2] = src_frame->data[2];
1413
1414 pict_src.linesize[0] = src_frame->linesize[0];
1415 pict_src.linesize[1] = src_frame->linesize[1];
1416 pict_src.linesize[2] = src_frame->linesize[2];
1417
1418 //FIXME use direct rendering
1419 av_picture_copy(&pict, &pict_src,
1420 vp->pix_fmt, vp->width, vp->height);
1421 #else
1422 sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
1423 is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
1424 vp->width, vp->height, vp->pix_fmt, vp->width, vp->height,
1425 dst_pix_fmt, sws_flags, NULL, NULL, NULL);
1426 if (is->img_convert_ctx == NULL) {
1427 fprintf(stderr, "Cannot initialize the conversion context\n");
1428 exit(1);
1429 }
1430 sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
1431 0, vp->height, pict.data, pict.linesize);
1432 #endif
1433 /* update the bitmap content */
1434 SDL_UnlockYUVOverlay(vp->bmp);
1435
1436 vp->pts = pts;
1437 vp->pos = pos;
1438
1439 /* now we can update the picture count */
1440 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1441 is->pictq_windex = 0;
1442 SDL_LockMutex(is->pictq_mutex);
1443 vp->target_clock= compute_target_time(vp->pts, is);
1444
1445 is->pictq_size++;
1446 SDL_UnlockMutex(is->pictq_mutex);
1447 }
1448 return 0;
1449 }
1450
1451 /**
1452 * compute the exact PTS for the picture if it is omitted in the stream
1453 * @param pts1 the dts of the pkt / pts of the frame
1454 */
1455 static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
1456 {
1457 double frame_delay, pts;
1458
1459 pts = pts1;
1460
1461 if (pts != 0) {
1462 /* update video clock with pts, if present */
1463 is->video_clock = pts;
1464 } else {
1465 pts = is->video_clock;
1466 }
1467 /* update video clock for next frame */
1468 frame_delay = av_q2d(is->video_st->codec->time_base);
1469 /* for MPEG2, the frame can be repeated, so we update the
1470 clock accordingly */
1471 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
1472 is->video_clock += frame_delay;
1473
1474 #if defined(DEBUG_SYNC) && 0
1475 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
1476 av_get_pict_type_char(src_frame->pict_type), pts, pts1);
1477 #endif
1478 return queue_picture(is, src_frame, pts, pos);
1479 }
1480
1481 static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt)
1482 {
1483 int len1, got_picture, i;
1484
1485 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1486 return -1;
1487
1488 if(pkt->data == flush_pkt.data){
1489 avcodec_flush_buffers(is->video_st->codec);
1490
1491 SDL_LockMutex(is->pictq_mutex);
1492 //Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
1493 for(i=0; i<VIDEO_PICTURE_QUEUE_SIZE; i++){
1494 is->pictq[i].target_clock= 0;
1495 }
1496 while (is->pictq_size && !is->videoq.abort_request) {
1497 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1498 }
1499 is->video_current_pos= -1;
1500 SDL_UnlockMutex(is->pictq_mutex);
1501
1502 is->last_dts_for_fault_detection=
1503 is->last_pts_for_fault_detection= INT64_MIN;
1504 is->frame_last_pts= AV_NOPTS_VALUE;
1505 is->frame_last_delay = 0;
1506 is->frame_timer = (double)av_gettime() / 1000000.0;
1507 is->skip_frames= 1;
1508 is->skip_frames_index= 0;
1509 return 0;
1510 }
1511
1512 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1513 this packet, if any */
1514 is->video_st->codec->reordered_opaque= pkt->pts;
1515 len1 = avcodec_decode_video2(is->video_st->codec,
1516 frame, &got_picture,
1517 pkt);
1518
1519 if (got_picture) {
1520 if(pkt->dts != AV_NOPTS_VALUE){
1521 is->faulty_dts += pkt->dts <= is->last_dts_for_fault_detection;
1522 is->last_dts_for_fault_detection= pkt->dts;
1523 }
1524 if(frame->reordered_opaque != AV_NOPTS_VALUE){
1525 is->faulty_pts += frame->reordered_opaque <= is->last_pts_for_fault_detection;
1526 is->last_pts_for_fault_detection= frame->reordered_opaque;
1527 }
1528 }
1529
1530 if( ( decoder_reorder_pts==1
1531 || (decoder_reorder_pts && is->faulty_pts<is->faulty_dts)
1532 || pkt->dts == AV_NOPTS_VALUE)
1533 && frame->reordered_opaque != AV_NOPTS_VALUE)
1534 *pts= frame->reordered_opaque;
1535 else if(pkt->dts != AV_NOPTS_VALUE)
1536 *pts= pkt->dts;
1537 else
1538 *pts= 0;
1539
1540 // if (len1 < 0)
1541 // break;
1542 if (got_picture){
1543 is->skip_frames_index += 1;
1544 if(is->skip_frames_index >= is->skip_frames){
1545 is->skip_frames_index -= FFMAX(is->skip_frames, 1.0);
1546 return 1;
1547 }
1548
1549 }
1550 return 0;
1551 }
1552
1553 #if CONFIG_AVFILTER
1554 typedef struct {
1555 VideoState *is;
1556 AVFrame *frame;
1557 int use_dr1;
1558 } FilterPriv;
1559
1560 static int input_get_buffer(AVCodecContext *codec, AVFrame *pic)
1561 {
1562 AVFilterContext *ctx = codec->opaque;
1563 AVFilterPicRef *ref;
1564 int perms = AV_PERM_WRITE;
1565 int i, w, h, stride[4];
1566 unsigned edge;
1567
1568 if(pic->buffer_hints & FF_BUFFER_HINTS_VALID) {
1569 if(pic->buffer_hints & FF_BUFFER_HINTS_READABLE) perms |= AV_PERM_READ;
1570 if(pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE) perms |= AV_PERM_PRESERVE;
1571 if(pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) perms |= AV_PERM_REUSE2;
1572 }
1573 if(pic->reference) perms |= AV_PERM_READ | AV_PERM_PRESERVE;
1574
1575 w = codec->width;
1576 h = codec->height;
1577 avcodec_align_dimensions2(codec, &w, &h, stride);
1578 edge = codec->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width();
1579 w += edge << 1;
1580 h += edge << 1;
1581
1582 if(!(ref = avfilter_get_video_buffer(ctx->outputs[0], perms, w, h)))
1583 return -1;
1584
1585 ref->w = codec->width;
1586 ref->h = codec->height;
1587 for(i = 0; i < 4; i ++) {
1588 unsigned hshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->pic->format].log2_chroma_w : 0;
1589 unsigned vshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->pic->format].log2_chroma_h : 0;
1590
1591 if (ref->data[i]) {
1592 ref->data[i] += (edge >> hshift) + ((edge * ref->linesize[i]) >> vshift);
1593 }
1594 pic->data[i] = ref->data[i];
1595 pic->linesize[i] = ref->linesize[i];
1596 }
1597 pic->opaque = ref;
1598 pic->age = INT_MAX;
1599 pic->type = FF_BUFFER_TYPE_USER;
1600 pic->reordered_opaque = codec->reordered_opaque;
1601 return 0;
1602 }
1603
1604 static void input_release_buffer(AVCodecContext *codec, AVFrame *pic)
1605 {
1606 memset(pic->data, 0, sizeof(pic->data));
1607 avfilter_unref_pic(pic->opaque);
1608 }
1609
1610 static int input_reget_buffer(AVCodecContext *codec, AVFrame *pic)
1611 {
1612 AVFilterPicRef *ref = pic->opaque;
1613
1614 if (pic->data[0] == NULL) {
1615 pic->buffer_hints |= FF_BUFFER_HINTS_READABLE;
1616 return codec->get_buffer(codec, pic);
1617 }
1618
1619 if ((codec->width != ref->w) || (codec->height != ref->h) ||
1620 (codec->pix_fmt != ref->pic->format)) {
1621 av_log(codec, AV_LOG_ERROR, "Picture properties changed.\n");
1622 return -1;
1623 }
1624
1625 pic->reordered_opaque = codec->reordered_opaque;
1626 return 0;
1627 }
1628
1629 static int input_init(AVFilterContext *ctx, const char *args, void *opaque)
1630 {
1631 FilterPriv *priv = ctx->priv;
1632 AVCodecContext *codec;
1633 if(!opaque) return -1;
1634
1635 priv->is = opaque;
1636 codec = priv->is->video_st->codec;
1637 codec->opaque = ctx;
1638 if(codec->codec->capabilities & CODEC_CAP_DR1) {
1639 priv->use_dr1 = 1;
1640 codec->get_buffer = input_get_buffer;
1641 codec->release_buffer = input_release_buffer;
1642 codec->reget_buffer = input_reget_buffer;
1643 }
1644
1645 priv->frame = avcodec_alloc_frame();
1646
1647 return 0;
1648 }
1649
1650 static void input_uninit(AVFilterContext *ctx)
1651 {
1652 FilterPriv *priv = ctx->priv;
1653 av_free(priv->frame);
1654 }
1655
1656 static int input_request_frame(AVFilterLink *link)
1657 {
1658 FilterPriv *priv = link->src->priv;
1659 AVFilterPicRef *picref;
1660 int64_t pts = 0;
1661 AVPacket pkt;
1662 int ret;
1663
1664 while (!(ret = get_video_frame(priv->is, priv->frame, &pts, &pkt)))
1665 av_free_packet(&pkt);
1666 if (ret < 0)
1667 return -1;
1668
1669 if(priv->use_dr1) {
1670 picref = avfilter_ref_pic(priv->frame->opaque, ~0);
1671 } else {
1672 picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h);
1673 av_picture_copy((AVPicture *)&picref->data, (AVPicture *)priv->frame,
1674 picref->pic->format, link->w, link->h);
1675 }
1676 av_free_packet(&pkt);
1677
1678 picref->pts = pts;
1679 picref->pos = pkt.pos;
1680 picref->pixel_aspect = priv->is->video_st->codec->sample_aspect_ratio;
1681 avfilter_start_frame(link, picref);
1682 avfilter_draw_slice(link, 0, link->h, 1);
1683 avfilter_end_frame(link);
1684
1685 return 0;
1686 }
1687
1688 static int input_query_formats(AVFilterContext *ctx)
1689 {
1690 FilterPriv *priv = ctx->priv;
1691 enum PixelFormat pix_fmts[] = {
1692 priv->is->video_st->codec->pix_fmt, PIX_FMT_NONE
1693 };
1694
1695 avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
1696 return 0;
1697 }
1698
1699 static int input_config_props(AVFilterLink *link)
1700 {
1701 FilterPriv *priv = link->src->priv;
1702 AVCodecContext *c = priv->is->video_st->codec;
1703
1704 link->w = c->width;
1705 link->h = c->height;
1706
1707 return 0;
1708 }
1709
1710 static AVFilter input_filter =
1711 {
1712 .name = "ffplay_input",
1713
1714 .priv_size = sizeof(FilterPriv),
1715
1716 .init = input_init,
1717 .uninit = input_uninit,
1718
1719 .query_formats = input_query_formats,
1720
1721 .inputs = (AVFilterPad[]) {{ .name = NULL }},
1722 .outputs = (AVFilterPad[]) {{ .name = "default",
1723 .type = AVMEDIA_TYPE_VIDEO,
1724 .request_frame = input_request_frame,
1725 .config_props = input_config_props, },
1726 { .name = NULL }},
1727 };
1728
1729 static void output_end_frame(AVFilterLink *link)
1730 {
1731 }
1732
1733 static int output_query_formats(AVFilterContext *ctx)
1734 {
1735 enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
1736
1737 avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
1738 return 0;
1739 }
1740
1741 static int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame,
1742 int64_t *pts, int64_t *pos)
1743 {
1744 AVFilterPicRef *pic;
1745
1746 if(avfilter_request_frame(ctx->inputs[0]))
1747 return -1;
1748 if(!(pic = ctx->inputs[0]->cur_pic))
1749 return -1;
1750 ctx->inputs[0]->cur_pic = NULL;
1751
1752 frame->opaque = pic;
1753 *pts = pic->pts;
1754 *pos = pic->pos;
1755
1756 memcpy(frame->data, pic->data, sizeof(frame->data));
1757 memcpy(frame->linesize, pic->linesize, sizeof(frame->linesize));
1758
1759 return 1;
1760 }
1761
1762 static AVFilter output_filter =
1763 {
1764 .name = "ffplay_output",
1765
1766 .query_formats = output_query_formats,
1767
1768 .inputs = (AVFilterPad[]) {{ .name = "default",
1769 .type = AVMEDIA_TYPE_VIDEO,
1770 .end_frame = output_end_frame,
1771 .min_perms = AV_PERM_READ, },
1772 { .name = NULL }},
1773 .outputs = (AVFilterPad[]) {{ .name = NULL }},
1774 };
1775 #endif /* CONFIG_AVFILTER */
1776
1777 static int video_thread(void *arg)
1778 {
1779 VideoState *is = arg;
1780 AVFrame *frame= avcodec_alloc_frame();
1781 int64_t pts_int;
1782 double pts;
1783 int ret;
1784
1785 #if CONFIG_AVFILTER
1786 int64_t pos;
1787 char sws_flags_str[128];
1788 AVFilterContext *filt_src = NULL, *filt_out = NULL;
1789 AVFilterGraph *graph = av_mallocz(sizeof(AVFilterGraph));
1790 snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags);
1791 graph->scale_sws_opts = av_strdup(sws_flags_str);
1792
1793 if(!(filt_src = avfilter_open(&input_filter, "src"))) goto the_end;
1794 if(!(filt_out = avfilter_open(&output_filter, "out"))) goto the_end;
1795
1796 if(avfilter_init_filter(filt_src, NULL, is)) goto the_end;
1797 if(avfilter_init_filter(filt_out, NULL, frame)) goto the_end;
1798
1799
1800 if(vfilters) {
1801 AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
1802 AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut));
1803
1804 outputs->name = av_strdup("in");
1805 outputs->filter = filt_src;
1806 outputs->pad_idx = 0;
1807 outputs->next = NULL;
1808
1809 inputs->name = av_strdup("out");
1810 inputs->filter = filt_out;
1811 inputs->pad_idx = 0;
1812 inputs->next = NULL;
1813
1814 if (avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL) < 0)
1815 goto the_end;
1816 av_freep(&vfilters);
1817 } else {
1818 if(avfilter_link(filt_src, 0, filt_out, 0) < 0) goto the_end;
1819 }
1820 avfilter_graph_add_filter(graph, filt_src);
1821 avfilter_graph_add_filter(graph, filt_out);
1822
1823 if(avfilter_graph_check_validity(graph, NULL)) goto the_end;
1824 if(avfilter_graph_config_formats(graph, NULL)) goto the_end;
1825 if(avfilter_graph_config_links(graph, NULL)) goto the_end;
1826
1827 is->out_video_filter = filt_out;
1828 #endif
1829
1830 for(;;) {
1831 #if !CONFIG_AVFILTER
1832 AVPacket pkt;
1833 #endif
1834 while (is->paused && !is->videoq.abort_request)
1835 SDL_Delay(10);
1836 #if CONFIG_AVFILTER
1837 ret = get_filtered_video_frame(filt_out, frame, &pts_int, &pos);
1838 #else
1839 ret = get_video_frame(is, frame, &pts_int, &pkt);
1840 #endif
1841
1842 if (ret < 0) goto the_end;
1843
1844 if (!ret)
1845 continue;
1846
1847 pts = pts_int*av_q2d(is->video_st->time_base);
1848
1849 #if CONFIG_AVFILTER
1850 ret = output_picture2(is, frame, pts, pos);
1851 #else
1852 ret = output_picture2(is, frame, pts, pkt.pos);
1853 av_free_packet(&pkt);
1854 #endif
1855 if (ret < 0)
1856 goto the_end;
1857
1858 if (step)
1859 if (cur_stream)
1860 stream_pause(cur_stream);
1861 }
1862 the_end:
1863 #if CONFIG_AVFILTER
1864 avfilter_graph_destroy(graph);
1865 av_freep(&graph);
1866 #endif
1867 av_free(frame);
1868 return 0;
1869 }
1870
1871 static int subtitle_thread(void *arg)
1872 {
1873 VideoState *is = arg;
1874 SubPicture *sp;
1875 AVPacket pkt1, *pkt = &pkt1;
1876 int len1, got_subtitle;
1877 double pts;
1878 int i, j;
1879 int r, g, b, y, u, v, a;
1880
1881 for(;;) {
1882 while (is->paused && !is->subtitleq.abort_request) {
1883 SDL_Delay(10);
1884 }
1885 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1886 break;
1887
1888 if(pkt->data == flush_pkt.data){
1889 avcodec_flush_buffers(is->subtitle_st->codec);
1890 continue;
1891 }
1892 SDL_LockMutex(is->subpq_mutex);
1893 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1894 !is->subtitleq.abort_request) {
1895 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1896 }
1897 SDL_UnlockMutex(is->subpq_mutex);
1898
1899 if (is->subtitleq.abort_request)
1900 goto the_end;
1901
1902 sp = &is->subpq[is->subpq_windex];
1903
1904 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1905 this packet, if any */
1906 pts = 0;
1907 if (pkt->pts != AV_NOPTS_VALUE)
1908 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1909
1910 len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
1911 &sp->sub, &got_subtitle,
1912 pkt);
1913 // if (len1 < 0)
1914 // break;
1915 if (got_subtitle && sp->sub.format == 0) {
1916 sp->pts = pts;
1917
1918 for (i = 0; i < sp->sub.num_rects; i++)
1919 {
1920 for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
1921 {
1922 RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j);
1923 y = RGB_TO_Y_CCIR(r, g, b);
1924 u = RGB_TO_U_CCIR(r, g, b, 0);
1925 v = RGB_TO_V_CCIR(r, g, b, 0);
1926 YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a);
1927 }
1928 }
1929
1930 /* now we can update the picture count */
1931 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1932 is->subpq_windex = 0;
1933 SDL_LockMutex(is->subpq_mutex);
1934 is->subpq_size++;
1935 SDL_UnlockMutex(is->subpq_mutex);
1936 }
1937 av_free_packet(pkt);
1938 // if (step)
1939 // if (cur_stream)
1940 // stream_pause(cur_stream);
1941 }
1942 the_end:
1943 return 0;
1944 }
1945
1946 /* copy samples for viewing in editor window */
1947 static void update_sample_display(VideoState *is, short *samples, int samples_size)
1948 {
1949 int size, len, channels;
1950
1951 channels = is->audio_st->codec->channels;
1952
1953 size = samples_size / sizeof(short);
1954 while (size > 0) {
1955 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1956 if (len > size)
1957 len = size;
1958 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1959 samples += len;
1960 is->sample_array_index += len;
1961 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1962 is->sample_array_index = 0;
1963 size -= len;
1964 }
1965 }
1966
1967 /* return the new audio buffer size (samples can be added or deleted
1968 to get better sync if video or external master clock) */
1969 static int synchronize_audio(VideoState *is, short *samples,
1970 int samples_size1, double pts)
1971 {
1972 int n, samples_size;
1973 double ref_clock;
1974
1975 n = 2 * is->audio_st->codec->channels;
1976 samples_size = samples_size1;
1977
1978 /* if not master, then we try to remove or add samples to correct the clock */
1979 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
1980 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1981 double diff, avg_diff;
1982 int wanted_size, min_size, max_size, nb_samples;
1983
1984 ref_clock = get_master_clock(is);
1985 diff = get_audio_clock(is) - ref_clock;
1986
1987 if (diff < AV_NOSYNC_THRESHOLD) {
1988 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1989 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1990 /* not enough measures to have a correct estimate */
1991 is->audio_diff_avg_count++;
1992 } else {
1993 /* estimate the A-V difference */
1994 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1995
1996 if (fabs(avg_diff) >= is->audio_diff_threshold) {
1997 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
1998 nb_samples = samples_size / n;
1999
2000 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
2001 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
2002 if (wanted_size < min_size)
2003 wanted_size = min_size;
2004 else if (wanted_size > max_size)
2005 wanted_size = max_size;
2006
2007 /* add or remove samples to correction the synchro */
2008 if (wanted_size < samples_size) {
2009 /* remove samples */
2010 samples_size = wanted_size;
2011 } else if (wanted_size > samples_size) {
2012 uint8_t *samples_end, *q;
2013 int nb;
2014
2015 /* add samples */
2016 nb = (samples_size - wanted_size);
2017 samples_end = (uint8_t *)samples + samples_size - n;
2018 q = samples_end + n;
2019 while (nb > 0) {
2020 memcpy(q, samples_end, n);
2021 q += n;
2022 nb -= n;
2023 }
2024 samples_size = wanted_size;
2025 }
2026 }
2027 #if 0
2028 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
2029 diff, avg_diff, samples_size - samples_size1,
2030 is->audio_clock, is->video_clock, is->audio_diff_threshold);
2031 #endif
2032 }
2033 } else {
2034 /* too big difference : may be initial PTS errors, so
2035 reset A-V filter */
2036 is->audio_diff_avg_count = 0;
2037 is->audio_diff_cum = 0;
2038 }
2039 }
2040
2041 return samples_size;
2042 }
2043
2044 /* decode one audio frame and returns its uncompressed size */
2045 static int audio_decode_frame(VideoState *is, double *pts_ptr)
2046 {
2047 AVPacket *pkt_temp = &is->audio_pkt_temp;
2048 AVPacket *pkt = &is->audio_pkt;
2049 AVCodecContext *dec= is->audio_st->codec;
2050 int n, len1, data_size;
2051 double pts;
2052
2053 for(;;) {
2054 /* NOTE: the audio packet can contain several frames */
2055 while (pkt_temp->size > 0) {
2056 data_size = sizeof(is->audio_buf1);
2057 len1 = avcodec_decode_audio3(dec,
2058 (int16_t *)is->audio_buf1, &data_size,
2059 pkt_temp);
2060 if (len1 < 0) {
2061 /* if error, we skip the frame */
2062 pkt_temp->size = 0;
2063 break;
2064 }
2065
2066 pkt_temp->data += len1;
2067 pkt_temp->size -= len1;
2068 if (data_size <= 0)
2069 continue;
2070
2071 if (dec->sample_fmt != is->audio_src_fmt) {
2072 if (is->reformat_ctx)
2073 av_audio_convert_free(is->reformat_ctx);
2074 is->reformat_ctx= av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
2075 dec->sample_fmt, 1, NULL, 0);
2076 if (!is->reformat_ctx) {
2077 fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
2078 avcodec_get_sample_fmt_name(dec->sample_fmt),
2079 avcodec_get_sample_fmt_name(SAMPLE_FMT_S16));
2080 break;
2081 }
2082 is->audio_src_fmt= dec->sample_fmt;
2083 }
2084
2085 if (is->reformat_ctx) {
2086 const void *ibuf[6]= {is->audio_buf1};
2087 void *obuf[6]= {is->audio_buf2};
2088 int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
2089 int ostride[6]= {2};
2090 int len= data_size/istride[0];
2091 if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
2092 printf("av_audio_convert() failed\n");
2093 break;
2094 }
2095 is->audio_buf= is->audio_buf2;
2096 /* FIXME: existing code assume that data_size equals framesize*channels*2
2097 remove this legacy cruft */
2098 data_size= len*2;
2099 }else{
2100 is->audio_buf= is->audio_buf1;
2101 }
2102
2103 /* if no pts, then compute it */
2104 pts = is->audio_clock;
2105 *pts_ptr = pts;
2106 n = 2 * dec->channels;
2107 is->audio_clock += (double)data_size /
2108 (double)(n * dec->sample_rate);
2109 #if defined(DEBUG_SYNC)
2110 {
2111 static double last_clock;
2112 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
2113 is->audio_clock - last_clock,
2114 is->audio_clock, pts);
2115 last_clock = is->audio_clock;
2116 }
2117 #endif
2118 return data_size;
2119 }
2120
2121 /* free the current packet */
2122 if (pkt->data)
2123 av_free_packet(pkt);
2124
2125 if (is->paused || is->audioq.abort_request) {
2126 return -1;
2127 }
2128
2129 /* read next packet */
2130 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
2131 return -1;
2132 if(pkt->data == flush_pkt.data){
2133 avcodec_flush_buffers(dec);
2134 continue;
2135 }
2136
2137 pkt_temp->data = pkt->data;
2138 pkt_temp->size = pkt->size;
2139
2140 /* if update the audio clock with the pts */
2141 if (pkt->pts != AV_NOPTS_VALUE) {
2142 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
2143 }
2144 }
2145 }
2146
2147 /* get the current audio output buffer size, in samples. With SDL, we
2148 cannot have a precise information */
2149 static int audio_write_get_buf_size(VideoState *is)
2150 {
2151 return is->audio_buf_size - is->audio_buf_index;
2152 }
2153
2154
2155 /* prepare a new audio buffer */
2156 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
2157 {
2158 VideoState *is = opaque;
2159 int audio_size, len1;
2160 double pts;
2161
2162 audio_callback_time = av_gettime();
2163
2164 while (len > 0) {
2165 if (is->audio_buf_index >= is->audio_buf_size) {
2166 audio_size = audio_decode_frame(is, &pts);
2167 if (audio_size < 0) {
2168 /* if error, just output silence */
2169 is->audio_buf = is->audio_buf1;
2170 is->audio_buf_size = 1024;
2171 memset(is->audio_buf, 0, is->audio_buf_size);
2172 } else {
2173 if (is->show_audio)
2174 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
2175 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
2176 pts);
2177 is->audio_buf_size = audio_size;
2178 }
2179 is->audio_buf_index = 0;
2180 }
2181 len1 = is->audio_buf_size - is->audio_buf_index;
2182 if (len1 > len)
2183 len1 = len;
2184 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
2185 len -= len1;
2186 stream += len1;
2187 is->audio_buf_index += len1;
2188 }
2189 }
2190
2191 /* open a given stream. Return 0 if OK */
2192 static int stream_component_open(VideoState *is, int stream_index)
2193 {
2194 AVFormatContext *ic = is->ic;
2195 AVCodecContext *avctx;
2196 AVCodec *codec;
2197 SDL_AudioSpec wanted_spec, spec;
2198
2199 if (stream_index < 0 || stream_index >= ic->nb_streams)
2200 return -1;
2201 avctx = ic->streams[stream_index]->codec;
2202
2203 /* prepare audio output */
2204 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
2205 if (avctx->channels > 0) {
2206 avctx->request_channels = FFMIN(2, avctx->channels);
2207 } else {
2208 avctx->request_channels = 2;
2209 }
2210 }
2211
2212 codec = avcodec_find_decoder(avctx->codec_id);
2213 avctx->debug_mv = debug_mv;
2214 avctx->debug = debug;
2215 avctx->workaround_bugs = workaround_bugs;
2216 avctx->lowres = lowres;
2217 if(lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
2218 avctx->idct_algo= idct;
2219 if(fast) avctx->flags2 |= CODEC_FLAG2_FAST;
2220 avctx->skip_frame= skip_frame;
2221 avctx->skip_idct= skip_idct;
2222 avctx->skip_loop_filter= skip_loop_filter;
2223 avctx->error_recognition= error_recognition;
2224 avctx->error_concealment= error_concealment;
2225 avcodec_thread_init(avctx, thread_count);
2226
2227 set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0);
2228
2229 if (!codec ||
2230 avcodec_open(avctx, codec) < 0)
2231 return -1;
2232
2233 /* prepare audio output */
2234 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
2235 wanted_spec.freq = avctx->sample_rate;
2236 wanted_spec.format = AUDIO_S16SYS;
2237 wanted_spec.channels = avctx->channels;
2238 wanted_spec.silence = 0;
2239 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
2240 wanted_spec.callback = sdl_audio_callback;
2241 wanted_spec.userdata = is;
2242 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
2243 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
2244 return -1;
2245 }
2246 is->audio_hw_buf_size = spec.size;
2247 is->audio_src_fmt= SAMPLE_FMT_S16;
2248 }
2249
2250 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2251 switch(avctx->codec_type) {
2252 case AVMEDIA_TYPE_AUDIO:
2253 is->audio_stream = stream_index;
2254 is->audio_st = ic->streams[stream_index];
2255 is->audio_buf_size = 0;
2256 is->audio_buf_index = 0;
2257
2258 /* init averaging filter */
2259 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2260 is->audio_diff_avg_count = 0;
2261 /* since we do not have a precise anough audio fifo fullness,
2262 we correct audio sync only if larger than this threshold */
2263 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / avctx->sample_rate;
2264
2265 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
2266 packet_queue_init(&is->audioq);
2267 SDL_PauseAudio(0);
2268 break;
2269 case AVMEDIA_TYPE_VIDEO:
2270 is->video_stream = stream_index;
2271 is->video_st = ic->streams[stream_index];
2272
2273 // is->video_current_pts_time = av_gettime();
2274
2275 packet_queue_init(&is->videoq);
2276 is->video_tid = SDL_CreateThread(video_thread, is);
2277 break;
2278 case AVMEDIA_TYPE_SUBTITLE:
2279 is->subtitle_stream = stream_index;
2280 is->subtitle_st = ic->streams[stream_index];
2281 packet_queue_init(&is->subtitleq);
2282
2283 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
2284 break;
2285 default:
2286 break;
2287 }
2288 return 0;
2289 }
2290
2291 static void stream_component_close(VideoState *is, int stream_index)
2292 {
2293 AVFormatContext *ic = is->ic;
2294 AVCodecContext *avctx;
2295
2296 if (stream_index < 0 || stream_index >= ic->nb_streams)
2297 return;
2298 avctx = ic->streams[stream_index]->codec;
2299
2300 switch(avctx->codec_type) {
2301 case AVMEDIA_TYPE_AUDIO:
2302 packet_queue_abort(&is->audioq);
2303
2304 SDL_CloseAudio();
2305
2306 packet_queue_end(&is->audioq);
2307 if (is->reformat_ctx)
2308 av_audio_convert_free(is->reformat_ctx);
2309 is->reformat_ctx = NULL;
2310 break;
2311 case AVMEDIA_TYPE_VIDEO:
2312 packet_queue_abort(&is->videoq);
2313
2314 /* note: we also signal this mutex to make sure we deblock the
2315 video thread in all cases */
2316 SDL_LockMutex(is->pictq_mutex);
2317 SDL_CondSignal(is->pictq_cond);
2318 SDL_UnlockMutex(is->pictq_mutex);
2319
2320 SDL_WaitThread(is->video_tid, NULL);
2321
2322 packet_queue_end(&is->videoq);
2323 break;
2324 case AVMEDIA_TYPE_SUBTITLE:
2325 packet_queue_abort(&is->subtitleq);
2326
2327 /* note: we also signal this mutex to make sure we deblock the
2328 video thread in all cases */
2329 SDL_LockMutex(is->subpq_mutex);
2330 is->subtitle_stream_changed = 1;
2331
2332 SDL_CondSignal(is->subpq_cond);
2333 SDL_UnlockMutex(is->subpq_mutex);
2334
2335 SDL_WaitThread(is->subtitle_tid, NULL);
2336
2337 packet_queue_end(&is->subtitleq);
2338 break;
2339 default:
2340 break;
2341 }
2342
2343 ic->streams[stream_index]->discard = AVDISCARD_ALL;
2344 avcodec_close(avctx);
2345 switch(avctx->codec_type) {
2346 case AVMEDIA_TYPE_AUDIO:
2347 is->audio_st = NULL;
2348 is->audio_stream = -1;
2349 break;
2350 case AVMEDIA_TYPE_VIDEO:
2351 is->video_st = NULL;
2352 is->video_stream = -1;
2353 break;
2354 case AVMEDIA_TYPE_SUBTITLE:
2355 is->subtitle_st = NULL;
2356 is->subtitle_stream = -1;
2357 break;
2358 default:
2359 break;
2360 }
2361 }
2362
2363 /* since we have only one decoding thread, we can use a global
2364 variable instead of a thread local variable */
2365 static VideoState *global_video_state;
2366
2367 static int decode_interrupt_cb(void)
2368 {
2369 return (global_video_state && global_video_state->abort_request);
2370 }
2371
2372 /* this thread gets the stream from the disk or the network */
2373 static int decode_thread(void *arg)
2374 {
2375 VideoState *is = arg;
2376 AVFormatContext *ic;
2377 int err, i, ret;
2378 int st_index[AVMEDIA_TYPE_NB];
2379 int st_count[AVMEDIA_TYPE_NB]={0};
2380 int st_best_packet_count[AVMEDIA_TYPE_NB];
2381 AVPacket pkt1, *pkt = &pkt1;
2382 AVFormatParameters params, *ap = &params;
2383 int eof=0;
2384 int pkt_in_play_range = 0;
2385
2386 ic = avformat_alloc_context();
2387
2388 memset(st_index, -1, sizeof(st_index));
2389 memset(st_best_packet_count, -1, sizeof(st_best_packet_count));
2390 is->video_stream = -1;
2391 is->audio_stream = -1;
2392 is->subtitle_stream = -1;
2393
2394 global_video_state = is;
2395 url_set_interrupt_cb(decode_interrupt_cb);
2396
2397 memset(ap, 0, sizeof(*ap));
2398
2399 ap->prealloced_context = 1;
2400 ap->width = frame_width;
2401 ap->height= frame_height;
2402 ap->time_base= (AVRational){1, 25};
2403 ap->pix_fmt = frame_pix_fmt;
2404
2405 set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM);
2406
2407 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
2408 if (err < 0) {
2409 print_error(is->filename, err);
2410 ret = -1;
2411 goto fail;
2412 }
2413 is->ic = ic;
2414
2415 if(genpts)
2416 ic->flags |= AVFMT_FLAG_GENPTS;
2417
2418 err = av_find_stream_info(ic);
2419 if (err < 0) {
2420 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
2421 ret = -1;
2422 goto fail;
2423 }
2424 if(ic->pb)
2425 ic->pb->eof_reached= 0; //FIXME hack, ffplay maybe should not use url_feof() to test for the end
2426
2427 if(seek_by_bytes<0)
2428 seek_by_bytes= !!(ic->iformat->flags & AVFMT_TS_DISCONT);
2429
2430 /* if seeking requested, we execute it */
2431 if (start_time != AV_NOPTS_VALUE) {
2432 int64_t timestamp;
2433
2434 timestamp = start_time;
2435 /* add the stream start time */
2436 if (ic->start_time != AV_NOPTS_VALUE)
2437 timestamp += ic->start_time;
2438 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
2439 if (ret < 0) {
2440 fprintf(stderr, "%s: could not seek to position %0.3f\n",
2441 is->filename, (double)timestamp / AV_TIME_BASE);
2442 }
2443 }
2444
2445 for(i = 0; i < ic->nb_streams; i++) {
2446 AVStream *st= ic->streams[i];
2447 AVCodecContext *avctx = st->codec;
2448 ic->streams[i]->discard = AVDISCARD_ALL;
2449 if(avctx->codec_type >= (unsigned)AVMEDIA_TYPE_NB)
2450 continue;
2451 if(st_count[avctx->codec_type]++ != wanted_stream[avctx->codec_type] && wanted_stream[avctx->codec_type] >= 0)
2452 continue;
2453
2454 if(st_best_packet_count[avctx->codec_type] >= st->codec_info_nb_frames)
2455 continue;
2456 st_best_packet_count[avctx->codec_type]= st->codec_info_nb_frames;
2457
2458 switch(avctx->codec_type) {
2459 case AVMEDIA_TYPE_AUDIO:
2460 if (!audio_disable)
2461 st_index[AVMEDIA_TYPE_AUDIO] = i;
2462 break;
2463 case AVMEDIA_TYPE_VIDEO:
2464 case AVMEDIA_TYPE_SUBTITLE:
2465 if (!video_disable)
2466 st_index[avctx->codec_type] = i;
2467 break;
2468 default:
2469 break;
2470 }
2471 }
2472 if (show_status) {
2473 dump_format(ic, 0, is->filename, 0);
2474 }
2475
2476 /* open the streams */
2477 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2478 stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
2479 }
2480
2481 ret=-1;
2482 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2483 ret= stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
2484 }
2485 is->refresh_tid = SDL_CreateThread(refresh_thread, is);
2486 if(ret<0) {
2487 if (!display_disable)
2488 is->show_audio = 2;
2489 }
2490
2491 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2492 stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
2493 }
2494
2495 if (is->video_stream < 0 && is->audio_stream < 0) {
2496 fprintf(stderr, "%s: could not open codecs\n", is->filename);
2497 ret = -1;
2498 goto fail;
2499 }
2500
2501 for(;;) {
2502 if (is->abort_request)
2503 break;
2504 if (is->paused != is->last_paused) {
2505 is->last_paused = is->paused;
2506 if (is->paused)
2507 is->read_pause_return= av_read_pause(ic);
2508 else
2509 av_read_play(ic);
2510 }
2511 #if CONFIG_RTSP_DEMUXER
2512 if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
2513 /* wait 10 ms to avoid trying to get another packet */
2514 /* XXX: horrible */
2515 SDL_Delay(10);
2516 continue;
2517 }
2518 #endif
2519 if (is->seek_req) {
2520 int64_t seek_target= is->seek_pos;
2521 int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2522 int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2523 //FIXME the +-2 is due to rounding being not done in the correct direction in generation
2524 // of the seek_pos/seek_rel variables
2525
2526 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2527 if (ret < 0) {
2528 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
2529 }else{
2530 if (is->audio_stream >= 0) {
2531 packet_queue_flush(&is->audioq);
2532 packet_queue_put(&is->audioq, &flush_pkt);
2533 }
2534 if (is->subtitle_stream >= 0) {
2535 packet_queue_flush(&is->subtitleq);
2536 packet_queue_put(&is->subtitleq, &flush_pkt);
2537 }
2538 if (is->video_stream >= 0) {
2539 packet_queue_flush(&is->videoq);
2540 packet_queue_put(&is->videoq, &flush_pkt);
2541 }
2542 }
2543 is->seek_req = 0;
2544 eof= 0;
2545 }
2546
2547 /* if the queue are full, no need to read more */
2548 if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2549 || ( (is->audioq .size > MIN_AUDIOQ_SIZE || is->audio_stream<0)
2550 && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream<0)
2551 && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream<0))) {
2552 /* wait 10 ms */
2553 SDL_Delay(10);
2554 continue;
2555 }
2556 if(url_feof(ic->pb) || eof) {
2557 if(is->video_stream >= 0){
2558 av_init_packet(pkt);
2559 pkt->data=NULL;
2560 pkt->size=0;
2561 pkt->stream_index= is->video_stream;
2562 packet_queue_put(&is->videoq, pkt);
2563 }
2564 SDL_Delay(10);
2565 if(is->audioq.size + is->videoq.size + is->subtitleq.size ==0){
2566 if(loop!=1 && (!loop || --loop)){
2567 stream_seek(cur_stream, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
2568 }else if(autoexit){
2569 ret=AVERROR_EOF;
2570 goto fail;
2571 }
2572 }
2573 continue;
2574 }
2575 ret = av_read_frame(ic, pkt);
2576 if (ret < 0) {
2577 if (ret == AVERROR_EOF)
2578 eof=1;
2579 if (url_ferror(ic->pb))
2580 break;
2581 SDL_Delay(100); /* wait for user event */
2582 continue;
2583 }
2584 /* check if packet is in play range specified by user, then queue, otherwise discard */
2585 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
2586 (pkt->pts - ic->streams[pkt->stream_index]->start_time) *
2587 av_q2d(ic->streams[pkt->stream_index]->time_base) -
2588 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0)/1000000
2589 <= ((double)duration/1000000);
2590 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
2591 packet_queue_put(&is->audioq, pkt);
2592 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range) {
2593 packet_queue_put(&is->videoq, pkt);
2594 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
2595 packet_queue_put(&is->subtitleq, pkt);
2596 } else {
2597 av_free_packet(pkt);
2598 }
2599 }
2600 /* wait until the end */
2601 while (!is->abort_request) {
2602 SDL_Delay(100);
2603 }
2604
2605 ret = 0;
2606 fail:
2607 /* disable interrupting */
2608 global_video_state = NULL;
2609
2610 /* close each stream */
2611 if (is->audio_stream >= 0)
2612 stream_component_close(is, is->audio_stream);
2613 if (is->video_stream >= 0)
2614 stream_component_close(is, is->video_stream);
2615 if (is->subtitle_stream >= 0)
2616 stream_component_close(is, is->subtitle_stream);
2617 if (is->ic) {
2618 av_close_input_file(is->ic);
2619 is->ic = NULL; /* safety */
2620 }
2621 url_set_interrupt_cb(NULL);
2622
2623 if (ret != 0) {
2624 SDL_Event event;
2625
2626 event.type = FF_QUIT_EVENT;
2627 event.user.data1 = is;
2628 SDL_PushEvent(&event);
2629 }
2630 return 0;
2631 }
2632
2633 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
2634 {
2635 VideoState *is;
2636
2637 is = av_mallocz(sizeof(VideoState));
2638 if (!is)
2639 return NULL;
2640 av_strlcpy(is->filename, filename, sizeof(is->filename));
2641 is->iformat = iformat;
2642 is->ytop = 0;
2643 is->xleft = 0;
2644
2645 /* start video display */
2646 is->pictq_mutex = SDL_CreateMutex();
2647 is->pictq_cond = SDL_CreateCond();
2648
2649 is->subpq_mutex = SDL_CreateMutex();
2650 is->subpq_cond = SDL_CreateCond();
2651
2652 is->av_sync_type = av_sync_type;
2653 is->parse_tid = SDL_CreateThread(decode_thread, is);
2654 if (!is->parse_tid) {
2655 av_free(is);
2656 return NULL;
2657 }
2658 return is;
2659 }
2660
2661 static void stream_close(VideoState *is)
2662 {
2663 VideoPicture *vp;
2664 int i;
2665 /* XXX: use a special url_shutdown call to abort parse cleanly */
2666 is->abort_request = 1;
2667 SDL_WaitThread(is->parse_tid, NULL);
2668 SDL_WaitThread(is->refresh_tid, NULL);
2669
2670 /* free all pictures */
2671 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2672 vp = &is->pictq[i];
2673 #if CONFIG_AVFILTER
2674 if (vp->picref) {
2675 avfilter_unref_pic(vp->picref);
2676 vp->picref = NULL;
2677 }
2678 #endif
2679 if (vp->bmp) {
2680 SDL_FreeYUVOverlay(vp->bmp);
2681 vp->bmp = NULL;
2682 }
2683 }
2684 SDL_DestroyMutex(is->pictq_mutex);
2685 SDL_DestroyCond(is->pictq_cond);
2686 SDL_DestroyMutex(is->subpq_mutex);
2687 SDL_DestroyCond(is->subpq_cond);
2688 #if !CONFIG_AVFILTER
2689 if (is->img_convert_ctx)
2690 sws_freeContext(is->img_convert_ctx);
2691 #endif
2692 av_free(is);
2693 }
2694
2695 static void stream_cycle_channel(VideoState *is, int codec_type)
2696 {
2697 AVFormatContext *ic = is->ic;
2698 int start_index, stream_index;
2699 AVStream *st;
2700
2701 if (codec_type == AVMEDIA_TYPE_VIDEO)
2702 start_index = is->video_stream;
2703 else if (codec_type == AVMEDIA_TYPE_AUDIO)
2704 start_index = is->audio_stream;
2705 else
2706 start_index = is->subtitle_stream;
2707 if (start_index < (codec_type == AVMEDIA_TYPE_SUBTITLE ? -1 : 0))
2708 return;
2709 stream_index = start_index;
2710 for(;;) {
2711 if (++stream_index >= is->ic->nb_streams)
2712 {
2713 if (codec_type == AVMEDIA_TYPE_SUBTITLE)
2714 {
2715 stream_index = -1;
2716 goto the_end;
2717 } else
2718 stream_index = 0;
2719 }
2720 if (stream_index == start_index)
2721 return;
2722 st = ic->streams[stream_index];
2723 if (st->codec->codec_type == codec_type) {
2724 /* check that parameters are OK */
2725 switch(codec_type) {
2726 case AVMEDIA_TYPE_AUDIO:
2727 if (st->codec->sample_rate != 0 &&
2728 st->codec->channels != 0)
2729 goto the_end;
2730 break;
2731 case AVMEDIA_TYPE_VIDEO:
2732 case AVMEDIA_TYPE_SUBTITLE:
2733 goto the_end;
2734 default:
2735 break;
2736 }
2737 }
2738 }
2739 the_end:
2740 stream_component_close(is, start_index);
2741 stream_component_open(is, stream_index);
2742 }
2743
2744
2745 static void toggle_full_screen(void)
2746 {
2747 is_full_screen = !is_full_screen;
2748 if (!fs_screen_width) {
2749 /* use default SDL method */
2750 // SDL_WM_ToggleFullScreen(screen);
2751 }
2752 video_open(cur_stream);
2753 }
2754
2755 static void toggle_pause(void)
2756 {
2757 if (cur_stream)
2758 stream_pause(cur_stream);
2759 step = 0;
2760 }
2761
2762 static void step_to_next_frame(void)
2763 {
2764 if (cur_stream) {
2765 /* if the stream is paused unpause it, then step */
2766 if (cur_stream->paused)
2767 stream_pause(cur_stream);
2768 }
2769 step = 1;
2770 }
2771
2772 static void do_exit(void)
2773 {
2774 int i;
2775 if (cur_stream) {
2776 stream_close(cur_stream);
2777 cur_stream = NULL;
2778 }
2779 for (i = 0; i < AVMEDIA_TYPE_NB; i++)
2780 av_free(avcodec_opts[i]);
2781 av_free(avformat_opts);
2782 av_free(sws_opts);
2783 #if CONFIG_AVFILTER
2784 avfilter_uninit();
2785 #endif
2786 if (show_status)
2787 printf("\n");
2788 SDL_Quit();
2789 exit(0);
2790 }
2791
2792 static void toggle_audio_display(void)
2793 {
2794 if (cur_stream) {
2795 int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
2796 cur_stream->show_audio = (cur_stream->show_audio + 1) % 3;
2797 fill_rectangle(screen,
2798 cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height,
2799 bgcolor);
2800 SDL_UpdateRect(screen, cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height);
2801 }
2802 }
2803
2804 /* handle an event sent by the GUI */
2805 static void event_loop(void)
2806 {
2807 SDL_Event event;
2808 double incr, pos, frac;
2809
2810 for(;;) {
2811 double x;
2812 SDL_WaitEvent(&event);
2813 switch(event.type) {
2814 case SDL_KEYDOWN:
2815 if (exit_on_keydown) {
2816 do_exit();
2817 break;
2818 }
2819 switch(event.key.keysym.sym) {
2820 case SDLK_ESCAPE:
2821 case SDLK_q:
2822 do_exit();
2823 break;
2824 case SDLK_f:
2825 toggle_full_screen();
2826 break;
2827 case SDLK_p:
2828 case SDLK_SPACE:
2829 toggle_pause();
2830 break;
2831 case SDLK_s: //S: Step to next frame
2832 step_to_next_frame();
2833 break;
2834 case SDLK_a:
2835 if (cur_stream)
2836 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
2837 break;
2838 case SDLK_v:
2839 if (cur_stream)
2840 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
2841 break;
2842 case SDLK_t:
2843 if (cur_stream)
2844 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
2845 break;
2846 case SDLK_w:
2847 toggle_audio_display();
2848 break;
2849 case SDLK_LEFT:
2850 incr = -10.0;
2851 goto do_seek;
2852 case SDLK_RIGHT:
2853 incr = 10.0;
2854 goto do_seek;
2855 case SDLK_UP:
2856 incr = 60.0;
2857 goto do_seek;
2858 case SDLK_DOWN:
2859 incr = -60.0;
2860 do_seek:
2861 if (cur_stream) {
2862 if (seek_by_bytes) {
2863 if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos>=0){
2864 pos= cur_stream->video_current_pos;
2865 }else if(cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos>=0){
2866 pos= cur_stream->audio_pkt.pos;
2867 }else
2868 pos = url_ftell(cur_stream->ic->pb);
2869 if (cur_stream->ic->bit_rate)
2870 incr *= cur_stream->ic->bit_rate / 8.0;
2871 else
2872 incr *= 180000.0;
2873 pos += incr;
2874 stream_seek(cur_stream, pos, incr, 1);
2875 } else {
2876 pos = get_master_clock(cur_stream);
2877 pos += incr;
2878 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
2879 }
2880 }
2881 break;
2882 default:
2883 break;
2884 }
2885 break;
2886 case SDL_MOUSEBUTTONDOWN:
2887 if (exit_on_mousedown) {
2888 do_exit();
2889 break;
2890 }
2891 case SDL_MOUSEMOTION:
2892 if(event.type ==SDL_MOUSEBUTTONDOWN){
2893 x= event.button.x;
2894 }else{
2895 if(event.motion.state != SDL_PRESSED)
2896 break;
2897 x= event.motion.x;
2898 }
2899 if (cur_stream) {
2900 if(seek_by_bytes || cur_stream->ic->duration<=0){
2901 uint64_t size= url_fsize(cur_stream->ic->pb);
2902 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
2903 }else{
2904 int64_t ts;
2905 int ns, hh, mm, ss;
2906 int tns, thh, tmm, tss;
2907 tns = cur_stream->ic->duration/1000000LL;
2908 thh = tns/3600;
2909 tmm = (tns%3600)/60;
2910 tss = (tns%60);
2911 frac = x/cur_stream->width;
2912 ns = frac*tns;
2913 hh = ns/3600;
2914 mm = (ns%3600)/60;
2915 ss = (ns%60);
2916 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2917 hh, mm, ss, thh, tmm, tss);
2918 ts = frac*cur_stream->ic->duration;
2919 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
2920 ts += cur_stream->ic->start_time;
2921 stream_seek(cur_stream, ts, 0, 0);
2922 }
2923 }
2924 break;
2925 case SDL_VIDEORESIZE:
2926 if (cur_stream) {
2927 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2928 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2929 screen_width = cur_stream->width = event.resize.w;
2930 screen_height= cur_stream->height= event.resize.h;
2931 }
2932 break;
2933 case SDL_QUIT:
2934 case FF_QUIT_EVENT:
2935 do_exit();
2936 break;
2937 case FF_ALLOC_EVENT:
2938 video_open(event.user.data1);
2939 alloc_picture(event.user.data1);
2940 break;
2941 case FF_REFRESH_EVENT:
2942 video_refresh_timer(event.user.data1);
2943 cur_stream->refresh=0;
2944 break;
2945 default:
2946 break;
2947 }
2948 }
2949 }
2950
2951 static void opt_frame_size(const char *arg)
2952 {
2953 if (av_parse_video_size(&frame_width, &frame_height, arg) < 0) {
2954 fprintf(stderr, "Incorrect frame size\n");
2955 exit(1);
2956 }
2957 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2958 fprintf(stderr, "Frame size must be a multiple of 2\n");
2959 exit(1);
2960 }
2961 }
2962
2963 static int opt_width(const char *opt, const char *arg)
2964 {
2965 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2966 return 0;
2967 }
2968
2969 static int opt_height(const char *opt, const char *arg)
2970 {
2971 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2972 return 0;
2973 }
2974
2975 static void opt_format(const char *arg)
2976 {
2977 file_iformat = av_find_input_format(arg);
2978 if (!file_iformat) {
2979 fprintf(stderr, "Unknown input format: %s\n", arg);
2980 exit(1);
2981 }
2982 }
2983
2984 static void opt_frame_pix_fmt(const char *arg)
2985 {
2986 frame_pix_fmt = av_get_pix_fmt(arg);
2987 }
2988
2989 static int opt_sync(const char *opt, const char *arg)
2990 {
2991 if (!strcmp(arg, "audio"))
2992 av_sync_type = AV_SYNC_AUDIO_MASTER;
2993 else if (!strcmp(arg, "video"))
2994 av_sync_type = AV_SYNC_VIDEO_MASTER;
2995 else if (!strcmp(arg, "ext"))
2996 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2997 else {
2998 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
2999 exit(1);
3000 }
3001 return 0;
3002 }
3003
3004 static int opt_seek(const char *opt, const char *arg)
3005 {
3006 start_time = parse_time_or_die(opt, arg, 1);
3007 return 0;
3008 }
3009
3010 static int opt_duration(const char *opt, const char *arg)
3011 {
3012 duration = parse_time_or_die(opt, arg, 1);
3013 return 0;
3014 }
3015
3016 static int opt_debug(const char *opt, const char *arg)
3017 {
3018 av_log_set_level(99);
3019 debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
3020 return 0;
3021 }
3022
3023 static int opt_vismv(const char *opt, const char *arg)
3024 {
3025 debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
3026 return 0;
3027 }
3028
3029 static int opt_thread_count(const char *opt, const char *arg)
3030 {
3031 thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
3032 #if !HAVE_THREADS
3033 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
3034 #endif
3035 return 0;
3036 }
3037
3038 static const OptionDef options[] = {
3039 #include "cmdutils_common_opts.h"
3040 { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
3041 { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
3042 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
3043 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
3044 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
3045 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
3046 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_AUDIO]}, "select desired audio stream", "stream_number" },
3047 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_VIDEO]}, "select desired video stream", "stream_number" },
3048 { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_SUBTITLE]}, "select desired subtitle stream", "stream_number" },
3049 { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
3050 { "t", HAS_ARG | OPT_FUNC2, {(void*)&opt_duration}, "play \"duration\" seconds of audio/video", "duration" },
3051 { "bytes", OPT_INT | HAS_ARG, {(void*)&seek_by_bytes}, "seek by bytes 0=off 1=on -1=auto", "val" },
3052 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
3053 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
3054 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
3055 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
3056 { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
3057 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
3058 { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
3059 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
3060 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
3061 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts 0=off 1=on -1=auto", ""},
3062 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
3063 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
3064 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
3065 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
3066 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
3067 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)", "threshold" },
3068 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
3069 { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
3070 { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
3071 { "autoexit", OPT_BOOL | OPT_EXPERT, {(void*)&autoexit}, "exit at the end", "" },
3072 { "exitonkeydown", OPT_BOOL | OPT_EXPERT, {(void*)&exit_on_keydown}, "exit on key down", "" },
3073 { "exitonmousedown", OPT_BOOL | OPT_EXPERT, {(void*)&exit_on_mousedown}, "exit on mouse down", "" },
3074 { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&loop}, "set number of times the playback shall be looped", "loop count" },
3075 { "framedrop", OPT_BOOL | OPT_EXPERT, {(void*)&framedrop}, "drop frames when cpu is too slow", "" },
3076 { "window_title", OPT_STRING | HAS_ARG, {(void*)&window_title}, "set window title", "window title" },
3077 #if CONFIG_AVFILTER
3078 { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
3079 #endif
3080 { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, {(void*)&rdftspeed}, "rdft speed", "msecs" },
3081 { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
3082 { NULL, },
3083 };
3084
3085 static void show_usage(void)
3086 {
3087 printf("Simple media player\n");
3088 printf("usage: ffplay [options] input_file\n");
3089 printf("\n");
3090 }
3091
3092 static void show_help(void)
3093 {
3094 show_usage();
3095 show_help_options(options, "Main options:\n",
3096 OPT_EXPERT, 0);
3097 show_help_options(options, "\nAdvanced options:\n",
3098 OPT_EXPERT, OPT_EXPERT);
3099 printf("\nWhile playing:\n"
3100 "q, ESC quit\n"
3101 "f toggle full screen\n"
3102 "p, SPC pause\n"
3103 "a cycle audio channel\n"
3104 "v cycle video channel\n"
3105 "t cycle subtitle channel\n"
3106 "w show audio waves\n"
3107 "s activate frame-step mode\n"
3108 "left/right seek backward/forward 10 seconds\n"
3109 "down/up seek backward/forward 1 minute\n"
3110 "mouse click seek to percentage in file corresponding to fraction of width\n"
3111 );
3112 }
3113
3114 static void opt_input_file(const char *filename)
3115 {
3116 if (input_filename) {
3117 fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3118 filename, input_filename);
3119 exit(1);
3120 }
3121 if (!strcmp(filename, "-"))
3122 filename = "pipe:";
3123 input_filename = filename;
3124 }
3125
3126 /* Called from the main */
3127 int main(int argc, char **argv)
3128 {
3129 int flags, i;
3130
3131 /* register all codecs, demux and protocols */
3132 avcodec_register_all();
3133 #if CONFIG_AVDEVICE
3134 avdevice_register_all();
3135 #endif
3136 #if CONFIG_AVFILTER
3137 avfilter_register_all();
3138 #endif
3139 av_register_all();
3140
3141 for(i=0; i<AVMEDIA_TYPE_NB; i++){
3142 avcodec_opts[i]= avcodec_alloc_context2(i);
3143 }
3144 avformat_opts = avformat_alloc_context();
3145 #if !CONFIG_AVFILTER
3146 sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
3147 #endif
3148
3149 show_banner();
3150
3151 parse_options(argc, argv, options, opt_input_file);
3152
3153 if (!input_filename) {
3154 show_usage();
3155 fprintf(stderr, "An input file must be specified\n");
3156 fprintf(stderr, "Use -h to get full help or, even better, run 'man ffplay'\n");
3157 exit(1);
3158 }
3159
3160 if (display_disable) {
3161 video_disable = 1;
3162 }
3163 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3164 #if !defined(__MINGW32__) && !defined(__APPLE__)
3165 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
3166 #endif
3167 if (SDL_Init (flags)) {
3168 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
3169 exit(1);
3170 }
3171
3172 if (!display_disable) {
3173 #if HAVE_SDL_VIDEO_SIZE
3174 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
3175 fs_screen_width = vi->current_w;
3176 fs_screen_height = vi->current_h;
3177 #endif
3178 }
3179
3180 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
3181 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3182 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3183
3184 av_init_packet(&flush_pkt);
3185 flush_pkt.data= "FLUSH";
3186
3187 cur_stream = stream_open(input_filename, file_iformat);
3188
3189 event_loop();
3190
3191 /* never returns */
3192
3193 return 0;
3194 }