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