Merge commit 'origin/master' into ordered_chapters
[FFMpeg-mirror/ordered_chapters.git] / ffplay.c
blob814efc521541639186c9e0de7e37f0256833f877
1 /*
2 * FFplay : Simple Media Player based on the ffmpeg libraries
3 * Copyright (c) 2003 Fabrice Bellard
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <math.h>
23 #include <limits.h>
24 #include "libavutil/avstring.h"
25 #include "libavformat/avformat.h"
26 #include "libavdevice/avdevice.h"
27 #include "libswscale/swscale.h"
28 #include "libavcodec/audioconvert.h"
29 #include "libavcodec/colorspace.h"
30 #include "libavcodec/opt.h"
32 #include "cmdutils.h"
34 #include <SDL.h>
35 #include <SDL_thread.h>
37 #ifdef __MINGW32__
38 #undef main /* We don't want SDL to override our main() */
39 #endif
41 #undef exit
43 const char program_name[] = "FFplay";
44 const int program_birth_year = 2003;
46 //#define DEBUG_SYNC
48 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
49 #define MAX_AUDIOQ_SIZE (20 * 16 * 1024)
50 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
52 /* SDL audio buffer size, in samples. Should be small to have precise
53 A/V sync as SDL does not have hardware buffer fullness info. */
54 #define SDL_AUDIO_BUFFER_SIZE 1024
56 /* no AV sync correction is done if below the AV sync threshold */
57 #define AV_SYNC_THRESHOLD 0.01
58 /* no AV correction is done if too big error */
59 #define AV_NOSYNC_THRESHOLD 10.0
61 /* maximum audio speed change to get correct sync */
62 #define SAMPLE_CORRECTION_PERCENT_MAX 10
64 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
65 #define AUDIO_DIFF_AVG_NB 20
67 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
68 #define SAMPLE_ARRAY_SIZE (2*65536)
70 static int sws_flags = SWS_BICUBIC;
72 typedef struct PacketQueue {
73 AVPacketList *first_pkt, *last_pkt;
74 int nb_packets;
75 int size;
76 int abort_request;
77 SDL_mutex *mutex;
78 SDL_cond *cond;
79 } PacketQueue;
81 #define VIDEO_PICTURE_QUEUE_SIZE 1
82 #define SUBPICTURE_QUEUE_SIZE 4
84 typedef struct VideoPicture {
85 double pts; ///<presentation time stamp for this picture
86 SDL_Overlay *bmp;
87 int width, height; /* source height & width */
88 int allocated;
89 } VideoPicture;
91 typedef struct SubPicture {
92 double pts; /* presentation time stamp for this picture */
93 AVSubtitle sub;
94 } SubPicture;
96 enum {
97 AV_SYNC_AUDIO_MASTER, /* default choice */
98 AV_SYNC_VIDEO_MASTER,
99 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
102 typedef struct VideoState {
103 SDL_Thread *parse_tid;
104 SDL_Thread *video_tid;
105 AVInputFormat *iformat;
106 int no_background;
107 int abort_request;
108 int paused;
109 int last_paused;
110 int seek_req;
111 int seek_flags;
112 int64_t seek_pos;
113 int64_t seek_rel;
114 AVFormatContext *ic;
115 int dtg_active_format;
117 int audio_stream;
119 int av_sync_type;
120 double external_clock; /* external clock base */
121 int64_t external_clock_time;
123 double audio_clock;
124 double audio_diff_cum; /* used for AV difference average computation */
125 double audio_diff_avg_coef;
126 double audio_diff_threshold;
127 int audio_diff_avg_count;
128 AVStream *audio_st;
129 PacketQueue audioq;
130 int audio_hw_buf_size;
131 /* samples output by the codec. we reserve more space for avsync
132 compensation */
133 DECLARE_ALIGNED(16,uint8_t,audio_buf1[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
134 DECLARE_ALIGNED(16,uint8_t,audio_buf2[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
135 uint8_t *audio_buf;
136 unsigned int audio_buf_size; /* in bytes */
137 int audio_buf_index; /* in bytes */
138 AVPacket audio_pkt_temp;
139 AVPacket audio_pkt;
140 enum SampleFormat audio_src_fmt;
141 AVAudioConvert *reformat_ctx;
143 int show_audio; /* if true, display audio samples */
144 int16_t sample_array[SAMPLE_ARRAY_SIZE];
145 int sample_array_index;
146 int last_i_start;
148 SDL_Thread *subtitle_tid;
149 int subtitle_stream;
150 int subtitle_stream_changed;
151 AVStream *subtitle_st;
152 PacketQueue subtitleq;
153 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
154 int subpq_size, subpq_rindex, subpq_windex;
155 SDL_mutex *subpq_mutex;
156 SDL_cond *subpq_cond;
158 double frame_timer;
159 double frame_last_pts;
160 double frame_last_delay;
161 double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
162 int video_stream;
163 AVStream *video_st;
164 PacketQueue videoq;
165 double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
166 int64_t video_current_pts_time; ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts
167 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
168 int pictq_size, pictq_rindex, pictq_windex;
169 SDL_mutex *pictq_mutex;
170 SDL_cond *pictq_cond;
171 struct SwsContext *img_convert_ctx;
173 // QETimer *video_timer;
174 char filename[1024];
175 int width, height, xleft, ytop;
176 } VideoState;
178 static void show_help(void);
179 static int audio_write_get_buf_size(VideoState *is);
181 /* options specified by the user */
182 static AVInputFormat *file_iformat;
183 static const char *input_filename;
184 static int fs_screen_width;
185 static int fs_screen_height;
186 static int screen_width = 0;
187 static int screen_height = 0;
188 static int frame_width = 0;
189 static int frame_height = 0;
190 static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
191 static int audio_disable;
192 static int video_disable;
193 static int wanted_audio_stream= 0;
194 static int wanted_video_stream= 0;
195 static int wanted_subtitle_stream= -1;
196 static int seek_by_bytes;
197 static int display_disable;
198 static int show_status = 1;
199 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
200 static int64_t start_time = AV_NOPTS_VALUE;
201 static int debug = 0;
202 static int debug_mv = 0;
203 static int step = 0;
204 static int thread_count = 1;
205 static int workaround_bugs = 1;
206 static int fast = 0;
207 static int genpts = 0;
208 static int lowres = 0;
209 static int idct = FF_IDCT_AUTO;
210 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
211 static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
212 static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
213 static int error_recognition = FF_ER_CAREFUL;
214 static int error_concealment = 3;
215 static int decoder_reorder_pts= 0;
217 /* current context */
218 static int is_full_screen;
219 static VideoState *cur_stream;
220 static int64_t audio_callback_time;
222 static AVPacket flush_pkt;
224 #define FF_ALLOC_EVENT (SDL_USEREVENT)
225 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
226 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
228 static SDL_Surface *screen;
230 /* packet queue handling */
231 static void packet_queue_init(PacketQueue *q)
233 memset(q, 0, sizeof(PacketQueue));
234 q->mutex = SDL_CreateMutex();
235 q->cond = SDL_CreateCond();
238 static void packet_queue_flush(PacketQueue *q)
240 AVPacketList *pkt, *pkt1;
242 SDL_LockMutex(q->mutex);
243 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
244 pkt1 = pkt->next;
245 av_free_packet(&pkt->pkt);
246 av_freep(&pkt);
248 q->last_pkt = NULL;
249 q->first_pkt = NULL;
250 q->nb_packets = 0;
251 q->size = 0;
252 SDL_UnlockMutex(q->mutex);
255 static void packet_queue_end(PacketQueue *q)
257 packet_queue_flush(q);
258 SDL_DestroyMutex(q->mutex);
259 SDL_DestroyCond(q->cond);
262 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
264 AVPacketList *pkt1;
266 /* duplicate the packet */
267 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
268 return -1;
270 pkt1 = av_malloc(sizeof(AVPacketList));
271 if (!pkt1)
272 return -1;
273 pkt1->pkt = *pkt;
274 pkt1->next = NULL;
277 SDL_LockMutex(q->mutex);
279 if (!q->last_pkt)
281 q->first_pkt = pkt1;
282 else
283 q->last_pkt->next = pkt1;
284 q->last_pkt = pkt1;
285 q->nb_packets++;
286 q->size += pkt1->pkt.size + sizeof(*pkt1);
287 /* XXX: should duplicate packet data in DV case */
288 SDL_CondSignal(q->cond);
290 SDL_UnlockMutex(q->mutex);
291 return 0;
294 static void packet_queue_abort(PacketQueue *q)
296 SDL_LockMutex(q->mutex);
298 q->abort_request = 1;
300 SDL_CondSignal(q->cond);
302 SDL_UnlockMutex(q->mutex);
305 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
306 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
308 AVPacketList *pkt1;
309 int ret;
311 SDL_LockMutex(q->mutex);
313 for(;;) {
314 if (q->abort_request) {
315 ret = -1;
316 break;
319 pkt1 = q->first_pkt;
320 if (pkt1) {
321 q->first_pkt = pkt1->next;
322 if (!q->first_pkt)
323 q->last_pkt = NULL;
324 q->nb_packets--;
325 q->size -= pkt1->pkt.size + sizeof(*pkt1);
326 *pkt = pkt1->pkt;
327 av_free(pkt1);
328 ret = 1;
329 break;
330 } else if (!block) {
331 ret = 0;
332 break;
333 } else {
334 SDL_CondWait(q->cond, q->mutex);
337 SDL_UnlockMutex(q->mutex);
338 return ret;
341 static inline void fill_rectangle(SDL_Surface *screen,
342 int x, int y, int w, int h, int color)
344 SDL_Rect rect;
345 rect.x = x;
346 rect.y = y;
347 rect.w = w;
348 rect.h = h;
349 SDL_FillRect(screen, &rect, color);
352 #if 0
353 /* draw only the border of a rectangle */
354 void fill_border(VideoState *s, int x, int y, int w, int h, int color)
356 int w1, w2, h1, h2;
358 /* fill the background */
359 w1 = x;
360 if (w1 < 0)
361 w1 = 0;
362 w2 = s->width - (x + w);
363 if (w2 < 0)
364 w2 = 0;
365 h1 = y;
366 if (h1 < 0)
367 h1 = 0;
368 h2 = s->height - (y + h);
369 if (h2 < 0)
370 h2 = 0;
371 fill_rectangle(screen,
372 s->xleft, s->ytop,
373 w1, s->height,
374 color);
375 fill_rectangle(screen,
376 s->xleft + s->width - w2, s->ytop,
377 w2, s->height,
378 color);
379 fill_rectangle(screen,
380 s->xleft + w1, s->ytop,
381 s->width - w1 - w2, h1,
382 color);
383 fill_rectangle(screen,
384 s->xleft + w1, s->ytop + s->height - h2,
385 s->width - w1 - w2, h2,
386 color);
388 #endif
390 #define ALPHA_BLEND(a, oldp, newp, s)\
391 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
393 #define RGBA_IN(r, g, b, a, s)\
395 unsigned int v = ((const uint32_t *)(s))[0];\
396 a = (v >> 24) & 0xff;\
397 r = (v >> 16) & 0xff;\
398 g = (v >> 8) & 0xff;\
399 b = v & 0xff;\
402 #define YUVA_IN(y, u, v, a, s, pal)\
404 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
405 a = (val >> 24) & 0xff;\
406 y = (val >> 16) & 0xff;\
407 u = (val >> 8) & 0xff;\
408 v = val & 0xff;\
411 #define YUVA_OUT(d, y, u, v, a)\
413 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
417 #define BPP 1
419 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
421 int wrap, wrap3, width2, skip2;
422 int y, u, v, a, u1, v1, a1, w, h;
423 uint8_t *lum, *cb, *cr;
424 const uint8_t *p;
425 const uint32_t *pal;
426 int dstx, dsty, dstw, dsth;
428 dstw = av_clip(rect->w, 0, imgw);
429 dsth = av_clip(rect->h, 0, imgh);
430 dstx = av_clip(rect->x, 0, imgw - dstw);
431 dsty = av_clip(rect->y, 0, imgh - dsth);
432 lum = dst->data[0] + dsty * dst->linesize[0];
433 cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
434 cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
436 width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
437 skip2 = dstx >> 1;
438 wrap = dst->linesize[0];
439 wrap3 = rect->pict.linesize[0];
440 p = rect->pict.data[0];
441 pal = (const uint32_t *)rect->pict.data[1]; /* Now in YCrCb! */
443 if (dsty & 1) {
444 lum += dstx;
445 cb += skip2;
446 cr += skip2;
448 if (dstx & 1) {
449 YUVA_IN(y, u, v, a, p, pal);
450 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
451 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
452 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
453 cb++;
454 cr++;
455 lum++;
456 p += BPP;
458 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
459 YUVA_IN(y, u, v, a, p, pal);
460 u1 = u;
461 v1 = v;
462 a1 = a;
463 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
465 YUVA_IN(y, u, v, a, p + BPP, pal);
466 u1 += u;
467 v1 += v;
468 a1 += a;
469 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
470 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
471 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
472 cb++;
473 cr++;
474 p += 2 * BPP;
475 lum += 2;
477 if (w) {
478 YUVA_IN(y, u, v, a, p, pal);
479 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
480 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
481 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
482 p++;
483 lum++;
485 p += wrap3 - dstw * BPP;
486 lum += wrap - dstw - dstx;
487 cb += dst->linesize[1] - width2 - skip2;
488 cr += dst->linesize[2] - width2 - skip2;
490 for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
491 lum += dstx;
492 cb += skip2;
493 cr += skip2;
495 if (dstx & 1) {
496 YUVA_IN(y, u, v, a, p, pal);
497 u1 = u;
498 v1 = v;
499 a1 = a;
500 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
501 p += wrap3;
502 lum += wrap;
503 YUVA_IN(y, u, v, a, p, pal);
504 u1 += u;
505 v1 += v;
506 a1 += a;
507 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
508 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
509 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
510 cb++;
511 cr++;
512 p += -wrap3 + BPP;
513 lum += -wrap + 1;
515 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
516 YUVA_IN(y, u, v, a, p, pal);
517 u1 = u;
518 v1 = v;
519 a1 = a;
520 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
522 YUVA_IN(y, u, v, a, p + BPP, pal);
523 u1 += u;
524 v1 += v;
525 a1 += a;
526 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
527 p += wrap3;
528 lum += wrap;
530 YUVA_IN(y, u, v, a, p, pal);
531 u1 += u;
532 v1 += v;
533 a1 += a;
534 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
536 YUVA_IN(y, u, v, a, p + BPP, pal);
537 u1 += u;
538 v1 += v;
539 a1 += a;
540 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
542 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
543 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
545 cb++;
546 cr++;
547 p += -wrap3 + 2 * BPP;
548 lum += -wrap + 2;
550 if (w) {
551 YUVA_IN(y, u, v, a, p, pal);
552 u1 = u;
553 v1 = v;
554 a1 = a;
555 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
556 p += wrap3;
557 lum += wrap;
558 YUVA_IN(y, u, v, a, p, pal);
559 u1 += u;
560 v1 += v;
561 a1 += a;
562 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
563 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
564 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
565 cb++;
566 cr++;
567 p += -wrap3 + BPP;
568 lum += -wrap + 1;
570 p += wrap3 + (wrap3 - dstw * BPP);
571 lum += wrap + (wrap - dstw - dstx);
572 cb += dst->linesize[1] - width2 - skip2;
573 cr += dst->linesize[2] - width2 - skip2;
575 /* handle odd height */
576 if (h) {
577 lum += dstx;
578 cb += skip2;
579 cr += skip2;
581 if (dstx & 1) {
582 YUVA_IN(y, u, v, a, p, pal);
583 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
584 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
585 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
586 cb++;
587 cr++;
588 lum++;
589 p += BPP;
591 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
592 YUVA_IN(y, u, v, a, p, pal);
593 u1 = u;
594 v1 = v;
595 a1 = a;
596 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
598 YUVA_IN(y, u, v, a, p + BPP, pal);
599 u1 += u;
600 v1 += v;
601 a1 += a;
602 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
603 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
604 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
605 cb++;
606 cr++;
607 p += 2 * BPP;
608 lum += 2;
610 if (w) {
611 YUVA_IN(y, u, v, a, p, pal);
612 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
613 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
614 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
619 static void free_subpicture(SubPicture *sp)
621 int i;
623 for (i = 0; i < sp->sub.num_rects; i++)
625 av_freep(&sp->sub.rects[i]->pict.data[0]);
626 av_freep(&sp->sub.rects[i]->pict.data[1]);
627 av_freep(&sp->sub.rects[i]);
630 av_free(sp->sub.rects);
632 memset(&sp->sub, 0, sizeof(AVSubtitle));
635 static void video_image_display(VideoState *is)
637 VideoPicture *vp;
638 SubPicture *sp;
639 AVPicture pict;
640 float aspect_ratio;
641 int width, height, x, y;
642 SDL_Rect rect;
643 int i;
645 vp = &is->pictq[is->pictq_rindex];
646 if (vp->bmp) {
647 /* XXX: use variable in the frame */
648 if (is->video_st->sample_aspect_ratio.num)
649 aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
650 else if (is->video_st->codec->sample_aspect_ratio.num)
651 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
652 else
653 aspect_ratio = 0;
654 if (aspect_ratio <= 0.0)
655 aspect_ratio = 1.0;
656 aspect_ratio *= (float)is->video_st->codec->width / is->video_st->codec->height;
657 /* if an active format is indicated, then it overrides the
658 mpeg format */
659 #if 0
660 if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
661 is->dtg_active_format = is->video_st->codec->dtg_active_format;
662 printf("dtg_active_format=%d\n", is->dtg_active_format);
664 #endif
665 #if 0
666 switch(is->video_st->codec->dtg_active_format) {
667 case FF_DTG_AFD_SAME:
668 default:
669 /* nothing to do */
670 break;
671 case FF_DTG_AFD_4_3:
672 aspect_ratio = 4.0 / 3.0;
673 break;
674 case FF_DTG_AFD_16_9:
675 aspect_ratio = 16.0 / 9.0;
676 break;
677 case FF_DTG_AFD_14_9:
678 aspect_ratio = 14.0 / 9.0;
679 break;
680 case FF_DTG_AFD_4_3_SP_14_9:
681 aspect_ratio = 14.0 / 9.0;
682 break;
683 case FF_DTG_AFD_16_9_SP_14_9:
684 aspect_ratio = 14.0 / 9.0;
685 break;
686 case FF_DTG_AFD_SP_4_3:
687 aspect_ratio = 4.0 / 3.0;
688 break;
690 #endif
692 if (is->subtitle_st)
694 if (is->subpq_size > 0)
696 sp = &is->subpq[is->subpq_rindex];
698 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
700 SDL_LockYUVOverlay (vp->bmp);
702 pict.data[0] = vp->bmp->pixels[0];
703 pict.data[1] = vp->bmp->pixels[2];
704 pict.data[2] = vp->bmp->pixels[1];
706 pict.linesize[0] = vp->bmp->pitches[0];
707 pict.linesize[1] = vp->bmp->pitches[2];
708 pict.linesize[2] = vp->bmp->pitches[1];
710 for (i = 0; i < sp->sub.num_rects; i++)
711 blend_subrect(&pict, sp->sub.rects[i],
712 vp->bmp->w, vp->bmp->h);
714 SDL_UnlockYUVOverlay (vp->bmp);
720 /* XXX: we suppose the screen has a 1.0 pixel ratio */
721 height = is->height;
722 width = ((int)rint(height * aspect_ratio)) & ~1;
723 if (width > is->width) {
724 width = is->width;
725 height = ((int)rint(width / aspect_ratio)) & ~1;
727 x = (is->width - width) / 2;
728 y = (is->height - height) / 2;
729 if (!is->no_background) {
730 /* fill the background */
731 // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
732 } else {
733 is->no_background = 0;
735 rect.x = is->xleft + x;
736 rect.y = is->ytop + y;
737 rect.w = width;
738 rect.h = height;
739 SDL_DisplayYUVOverlay(vp->bmp, &rect);
740 } else {
741 #if 0
742 fill_rectangle(screen,
743 is->xleft, is->ytop, is->width, is->height,
744 QERGB(0x00, 0x00, 0x00));
745 #endif
749 static inline int compute_mod(int a, int b)
751 a = a % b;
752 if (a >= 0)
753 return a;
754 else
755 return a + b;
758 static void video_audio_display(VideoState *s)
760 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
761 int ch, channels, h, h2, bgcolor, fgcolor;
762 int16_t time_diff;
764 /* compute display index : center on currently output samples */
765 channels = s->audio_st->codec->channels;
766 nb_display_channels = channels;
767 if (!s->paused) {
768 n = 2 * channels;
769 delay = audio_write_get_buf_size(s);
770 delay /= n;
772 /* to be more precise, we take into account the time spent since
773 the last buffer computation */
774 if (audio_callback_time) {
775 time_diff = av_gettime() - audio_callback_time;
776 delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
779 delay -= s->width / 2;
780 if (delay < s->width)
781 delay = s->width;
783 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
785 h= INT_MIN;
786 for(i=0; i<1000; i+=channels){
787 int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
788 int a= s->sample_array[idx];
789 int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
790 int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
791 int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
792 int score= a-d;
793 if(h<score && (b^c)<0){
794 h= score;
795 i_start= idx;
799 s->last_i_start = i_start;
800 } else {
801 i_start = s->last_i_start;
804 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
805 fill_rectangle(screen,
806 s->xleft, s->ytop, s->width, s->height,
807 bgcolor);
809 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
811 /* total height for one channel */
812 h = s->height / nb_display_channels;
813 /* graph height / 2 */
814 h2 = (h * 9) / 20;
815 for(ch = 0;ch < nb_display_channels; ch++) {
816 i = i_start + ch;
817 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
818 for(x = 0; x < s->width; x++) {
819 y = (s->sample_array[i] * h2) >> 15;
820 if (y < 0) {
821 y = -y;
822 ys = y1 - y;
823 } else {
824 ys = y1;
826 fill_rectangle(screen,
827 s->xleft + x, ys, 1, y,
828 fgcolor);
829 i += channels;
830 if (i >= SAMPLE_ARRAY_SIZE)
831 i -= SAMPLE_ARRAY_SIZE;
835 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
837 for(ch = 1;ch < nb_display_channels; ch++) {
838 y = s->ytop + ch * h;
839 fill_rectangle(screen,
840 s->xleft, y, s->width, 1,
841 fgcolor);
843 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
846 static int video_open(VideoState *is){
847 int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
848 int w,h;
850 if(is_full_screen) flags |= SDL_FULLSCREEN;
851 else flags |= SDL_RESIZABLE;
853 if (is_full_screen && fs_screen_width) {
854 w = fs_screen_width;
855 h = fs_screen_height;
856 } else if(!is_full_screen && screen_width){
857 w = screen_width;
858 h = screen_height;
859 }else if (is->video_st && is->video_st->codec->width){
860 w = is->video_st->codec->width;
861 h = is->video_st->codec->height;
862 } else {
863 w = 640;
864 h = 480;
866 #ifndef __APPLE__
867 screen = SDL_SetVideoMode(w, h, 0, flags);
868 #else
869 /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
870 screen = SDL_SetVideoMode(w, h, 24, flags);
871 #endif
872 if (!screen) {
873 fprintf(stderr, "SDL: could not set video mode - exiting\n");
874 return -1;
876 SDL_WM_SetCaption("FFplay", "FFplay");
878 is->width = screen->w;
879 is->height = screen->h;
881 return 0;
884 /* display the current picture, if any */
885 static void video_display(VideoState *is)
887 if(!screen)
888 video_open(cur_stream);
889 if (is->audio_st && is->show_audio)
890 video_audio_display(is);
891 else if (is->video_st)
892 video_image_display(is);
895 static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
897 SDL_Event event;
898 event.type = FF_REFRESH_EVENT;
899 event.user.data1 = opaque;
900 SDL_PushEvent(&event);
901 return 0; /* 0 means stop timer */
904 /* schedule a video refresh in 'delay' ms */
905 static void schedule_refresh(VideoState *is, int delay)
907 if(!delay) delay=1; //SDL seems to be buggy when the delay is 0
908 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
911 /* get the current audio clock value */
912 static double get_audio_clock(VideoState *is)
914 double pts;
915 int hw_buf_size, bytes_per_sec;
916 pts = is->audio_clock;
917 hw_buf_size = audio_write_get_buf_size(is);
918 bytes_per_sec = 0;
919 if (is->audio_st) {
920 bytes_per_sec = is->audio_st->codec->sample_rate *
921 2 * is->audio_st->codec->channels;
923 if (bytes_per_sec)
924 pts -= (double)hw_buf_size / bytes_per_sec;
925 return pts;
928 /* get the current video clock value */
929 static double get_video_clock(VideoState *is)
931 double delta;
932 if (is->paused) {
933 delta = 0;
934 } else {
935 delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
937 return is->video_current_pts + delta;
940 /* get the current external clock value */
941 static double get_external_clock(VideoState *is)
943 int64_t ti;
944 ti = av_gettime();
945 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
948 /* get the current master clock value */
949 static double get_master_clock(VideoState *is)
951 double val;
953 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
954 if (is->video_st)
955 val = get_video_clock(is);
956 else
957 val = get_audio_clock(is);
958 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
959 if (is->audio_st)
960 val = get_audio_clock(is);
961 else
962 val = get_video_clock(is);
963 } else {
964 val = get_external_clock(is);
966 return val;
969 /* seek in the stream */
970 static void stream_seek(VideoState *is, int64_t pos, int64_t rel)
972 if (!is->seek_req) {
973 is->seek_pos = pos;
974 is->seek_rel = rel;
975 if (seek_by_bytes)
976 is->seek_flags |= AVSEEK_FLAG_BYTE;
977 is->seek_req = 1;
981 /* pause or resume the video */
982 static void stream_pause(VideoState *is)
984 is->paused = !is->paused;
985 if (!is->paused) {
986 is->video_current_pts = get_video_clock(is);
987 is->frame_timer += (av_gettime() - is->video_current_pts_time) / 1000000.0;
991 static double compute_frame_delay(double frame_current_pts, VideoState *is)
993 double actual_delay, delay, sync_threshold, ref_clock, diff;
995 /* compute nominal delay */
996 delay = frame_current_pts - is->frame_last_pts;
997 if (delay <= 0 || delay >= 10.0) {
998 /* if incorrect delay, use previous one */
999 delay = is->frame_last_delay;
1000 } else {
1001 is->frame_last_delay = delay;
1003 is->frame_last_pts = frame_current_pts;
1005 /* update delay to follow master synchronisation source */
1006 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1007 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1008 /* if video is slave, we try to correct big delays by
1009 duplicating or deleting a frame */
1010 ref_clock = get_master_clock(is);
1011 diff = frame_current_pts - ref_clock;
1013 /* skip or repeat frame. We take into account the
1014 delay to compute the threshold. I still don't know
1015 if it is the best guess */
1016 sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
1017 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1018 if (diff <= -sync_threshold)
1019 delay = 0;
1020 else if (diff >= sync_threshold)
1021 delay = 2 * delay;
1025 is->frame_timer += delay;
1026 /* compute the REAL delay (we need to do that to avoid
1027 long term errors */
1028 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
1029 if (actual_delay < 0.010) {
1030 /* XXX: should skip picture */
1031 actual_delay = 0.010;
1034 #if defined(DEBUG_SYNC)
1035 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
1036 delay, actual_delay, frame_current_pts, -diff);
1037 #endif
1039 return actual_delay;
1042 /* called to display each frame */
1043 static void video_refresh_timer(void *opaque)
1045 VideoState *is = opaque;
1046 VideoPicture *vp;
1048 SubPicture *sp, *sp2;
1050 if (is->video_st) {
1051 if (is->pictq_size == 0) {
1052 /* if no picture, need to wait */
1053 schedule_refresh(is, 1);
1054 } else {
1055 /* dequeue the picture */
1056 vp = &is->pictq[is->pictq_rindex];
1058 /* update current video pts */
1059 is->video_current_pts = vp->pts;
1060 is->video_current_pts_time = av_gettime();
1062 /* launch timer for next picture */
1063 schedule_refresh(is, (int)(compute_frame_delay(vp->pts, is) * 1000 + 0.5));
1065 if(is->subtitle_st) {
1066 if (is->subtitle_stream_changed) {
1067 SDL_LockMutex(is->subpq_mutex);
1069 while (is->subpq_size) {
1070 free_subpicture(&is->subpq[is->subpq_rindex]);
1072 /* update queue size and signal for next picture */
1073 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1074 is->subpq_rindex = 0;
1076 is->subpq_size--;
1078 is->subtitle_stream_changed = 0;
1080 SDL_CondSignal(is->subpq_cond);
1081 SDL_UnlockMutex(is->subpq_mutex);
1082 } else {
1083 if (is->subpq_size > 0) {
1084 sp = &is->subpq[is->subpq_rindex];
1086 if (is->subpq_size > 1)
1087 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1088 else
1089 sp2 = NULL;
1091 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1092 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1094 free_subpicture(sp);
1096 /* update queue size and signal for next picture */
1097 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1098 is->subpq_rindex = 0;
1100 SDL_LockMutex(is->subpq_mutex);
1101 is->subpq_size--;
1102 SDL_CondSignal(is->subpq_cond);
1103 SDL_UnlockMutex(is->subpq_mutex);
1109 /* display picture */
1110 video_display(is);
1112 /* update queue size and signal for next picture */
1113 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1114 is->pictq_rindex = 0;
1116 SDL_LockMutex(is->pictq_mutex);
1117 is->pictq_size--;
1118 SDL_CondSignal(is->pictq_cond);
1119 SDL_UnlockMutex(is->pictq_mutex);
1121 } else if (is->audio_st) {
1122 /* draw the next audio frame */
1124 schedule_refresh(is, 40);
1126 /* if only audio stream, then display the audio bars (better
1127 than nothing, just to test the implementation */
1129 /* display picture */
1130 video_display(is);
1131 } else {
1132 schedule_refresh(is, 100);
1134 if (show_status) {
1135 static int64_t last_time;
1136 int64_t cur_time;
1137 int aqsize, vqsize, sqsize;
1138 double av_diff;
1140 cur_time = av_gettime();
1141 if (!last_time || (cur_time - last_time) >= 30000) {
1142 aqsize = 0;
1143 vqsize = 0;
1144 sqsize = 0;
1145 if (is->audio_st)
1146 aqsize = is->audioq.size;
1147 if (is->video_st)
1148 vqsize = is->videoq.size;
1149 if (is->subtitle_st)
1150 sqsize = is->subtitleq.size;
1151 av_diff = 0;
1152 if (is->audio_st && is->video_st)
1153 av_diff = get_audio_clock(is) - get_video_clock(is);
1154 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
1155 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
1156 fflush(stdout);
1157 last_time = cur_time;
1162 /* allocate a picture (needs to do that in main thread to avoid
1163 potential locking problems */
1164 static void alloc_picture(void *opaque)
1166 VideoState *is = opaque;
1167 VideoPicture *vp;
1169 vp = &is->pictq[is->pictq_windex];
1171 if (vp->bmp)
1172 SDL_FreeYUVOverlay(vp->bmp);
1174 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1175 is->video_st->codec->height,
1176 SDL_YV12_OVERLAY,
1177 screen);
1178 vp->width = is->video_st->codec->width;
1179 vp->height = is->video_st->codec->height;
1181 SDL_LockMutex(is->pictq_mutex);
1182 vp->allocated = 1;
1183 SDL_CondSignal(is->pictq_cond);
1184 SDL_UnlockMutex(is->pictq_mutex);
1189 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1191 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
1193 VideoPicture *vp;
1194 int dst_pix_fmt;
1196 /* wait until we have space to put a new picture */
1197 SDL_LockMutex(is->pictq_mutex);
1198 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1199 !is->videoq.abort_request) {
1200 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1202 SDL_UnlockMutex(is->pictq_mutex);
1204 if (is->videoq.abort_request)
1205 return -1;
1207 vp = &is->pictq[is->pictq_windex];
1209 /* alloc or resize hardware picture buffer */
1210 if (!vp->bmp ||
1211 vp->width != is->video_st->codec->width ||
1212 vp->height != is->video_st->codec->height) {
1213 SDL_Event event;
1215 vp->allocated = 0;
1217 /* the allocation must be done in the main thread to avoid
1218 locking problems */
1219 event.type = FF_ALLOC_EVENT;
1220 event.user.data1 = is;
1221 SDL_PushEvent(&event);
1223 /* wait until the picture is allocated */
1224 SDL_LockMutex(is->pictq_mutex);
1225 while (!vp->allocated && !is->videoq.abort_request) {
1226 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1228 SDL_UnlockMutex(is->pictq_mutex);
1230 if (is->videoq.abort_request)
1231 return -1;
1234 /* if the frame is not skipped, then display it */
1235 if (vp->bmp) {
1236 AVPicture pict;
1238 /* get a pointer on the bitmap */
1239 SDL_LockYUVOverlay (vp->bmp);
1241 dst_pix_fmt = PIX_FMT_YUV420P;
1242 memset(&pict,0,sizeof(AVPicture));
1243 pict.data[0] = vp->bmp->pixels[0];
1244 pict.data[1] = vp->bmp->pixels[2];
1245 pict.data[2] = vp->bmp->pixels[1];
1247 pict.linesize[0] = vp->bmp->pitches[0];
1248 pict.linesize[1] = vp->bmp->pitches[2];
1249 pict.linesize[2] = vp->bmp->pitches[1];
1250 sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
1251 is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
1252 is->video_st->codec->width, is->video_st->codec->height,
1253 is->video_st->codec->pix_fmt,
1254 is->video_st->codec->width, is->video_st->codec->height,
1255 dst_pix_fmt, sws_flags, NULL, NULL, NULL);
1256 if (is->img_convert_ctx == NULL) {
1257 fprintf(stderr, "Cannot initialize the conversion context\n");
1258 exit(1);
1260 sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
1261 0, is->video_st->codec->height, pict.data, pict.linesize);
1262 /* update the bitmap content */
1263 SDL_UnlockYUVOverlay(vp->bmp);
1265 vp->pts = pts;
1267 /* now we can update the picture count */
1268 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1269 is->pictq_windex = 0;
1270 SDL_LockMutex(is->pictq_mutex);
1271 is->pictq_size++;
1272 SDL_UnlockMutex(is->pictq_mutex);
1274 return 0;
1278 * compute the exact PTS for the picture if it is omitted in the stream
1279 * @param pts1 the dts of the pkt / pts of the frame
1281 static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
1283 double frame_delay, pts;
1285 pts = pts1;
1287 if (pts != 0) {
1288 /* update video clock with pts, if present */
1289 is->video_clock = pts;
1290 } else {
1291 pts = is->video_clock;
1293 /* update video clock for next frame */
1294 frame_delay = av_q2d(is->video_st->codec->time_base);
1295 /* for MPEG2, the frame can be repeated, so we update the
1296 clock accordingly */
1297 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
1298 is->video_clock += frame_delay;
1300 #if defined(DEBUG_SYNC) && 0
1302 int ftype;
1303 if (src_frame->pict_type == FF_B_TYPE)
1304 ftype = 'B';
1305 else if (src_frame->pict_type == FF_I_TYPE)
1306 ftype = 'I';
1307 else
1308 ftype = 'P';
1309 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
1310 ftype, pts, pts1);
1312 #endif
1313 return queue_picture(is, src_frame, pts);
1316 static int video_thread(void *arg)
1318 VideoState *is = arg;
1319 AVPacket pkt1, *pkt = &pkt1;
1320 int len1, got_picture;
1321 AVFrame *frame= avcodec_alloc_frame();
1322 double pts;
1324 for(;;) {
1325 while (is->paused && !is->videoq.abort_request) {
1326 SDL_Delay(10);
1328 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1329 break;
1331 if(pkt->data == flush_pkt.data){
1332 avcodec_flush_buffers(is->video_st->codec);
1333 continue;
1336 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1337 this packet, if any */
1338 is->video_st->codec->reordered_opaque= pkt->pts;
1339 len1 = avcodec_decode_video2(is->video_st->codec,
1340 frame, &got_picture,
1341 pkt);
1343 if( (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE)
1344 && frame->reordered_opaque != AV_NOPTS_VALUE)
1345 pts= frame->reordered_opaque;
1346 else if(pkt->dts != AV_NOPTS_VALUE)
1347 pts= pkt->dts;
1348 else
1349 pts= 0;
1350 pts *= av_q2d(is->video_st->time_base);
1352 // if (len1 < 0)
1353 // break;
1354 if (got_picture) {
1355 if (output_picture2(is, frame, pts) < 0)
1356 goto the_end;
1358 av_free_packet(pkt);
1359 if (step)
1360 if (cur_stream)
1361 stream_pause(cur_stream);
1363 the_end:
1364 av_free(frame);
1365 return 0;
1368 static int subtitle_thread(void *arg)
1370 VideoState *is = arg;
1371 SubPicture *sp;
1372 AVPacket pkt1, *pkt = &pkt1;
1373 int len1, got_subtitle;
1374 double pts;
1375 int i, j;
1376 int r, g, b, y, u, v, a;
1378 for(;;) {
1379 while (is->paused && !is->subtitleq.abort_request) {
1380 SDL_Delay(10);
1382 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1383 break;
1385 if(pkt->data == flush_pkt.data){
1386 avcodec_flush_buffers(is->subtitle_st->codec);
1387 continue;
1389 SDL_LockMutex(is->subpq_mutex);
1390 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1391 !is->subtitleq.abort_request) {
1392 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1394 SDL_UnlockMutex(is->subpq_mutex);
1396 if (is->subtitleq.abort_request)
1397 goto the_end;
1399 sp = &is->subpq[is->subpq_windex];
1401 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1402 this packet, if any */
1403 pts = 0;
1404 if (pkt->pts != AV_NOPTS_VALUE)
1405 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1407 len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
1408 &sp->sub, &got_subtitle,
1409 pkt);
1410 // if (len1 < 0)
1411 // break;
1412 if (got_subtitle && sp->sub.format == 0) {
1413 sp->pts = pts;
1415 for (i = 0; i < sp->sub.num_rects; i++)
1417 for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
1419 RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j);
1420 y = RGB_TO_Y_CCIR(r, g, b);
1421 u = RGB_TO_U_CCIR(r, g, b, 0);
1422 v = RGB_TO_V_CCIR(r, g, b, 0);
1423 YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a);
1427 /* now we can update the picture count */
1428 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1429 is->subpq_windex = 0;
1430 SDL_LockMutex(is->subpq_mutex);
1431 is->subpq_size++;
1432 SDL_UnlockMutex(is->subpq_mutex);
1434 av_free_packet(pkt);
1435 // if (step)
1436 // if (cur_stream)
1437 // stream_pause(cur_stream);
1439 the_end:
1440 return 0;
1443 /* copy samples for viewing in editor window */
1444 static void update_sample_display(VideoState *is, short *samples, int samples_size)
1446 int size, len, channels;
1448 channels = is->audio_st->codec->channels;
1450 size = samples_size / sizeof(short);
1451 while (size > 0) {
1452 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1453 if (len > size)
1454 len = size;
1455 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1456 samples += len;
1457 is->sample_array_index += len;
1458 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1459 is->sample_array_index = 0;
1460 size -= len;
1464 /* return the new audio buffer size (samples can be added or deleted
1465 to get better sync if video or external master clock) */
1466 static int synchronize_audio(VideoState *is, short *samples,
1467 int samples_size1, double pts)
1469 int n, samples_size;
1470 double ref_clock;
1472 n = 2 * is->audio_st->codec->channels;
1473 samples_size = samples_size1;
1475 /* if not master, then we try to remove or add samples to correct the clock */
1476 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
1477 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1478 double diff, avg_diff;
1479 int wanted_size, min_size, max_size, nb_samples;
1481 ref_clock = get_master_clock(is);
1482 diff = get_audio_clock(is) - ref_clock;
1484 if (diff < AV_NOSYNC_THRESHOLD) {
1485 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1486 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1487 /* not enough measures to have a correct estimate */
1488 is->audio_diff_avg_count++;
1489 } else {
1490 /* estimate the A-V difference */
1491 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1493 if (fabs(avg_diff) >= is->audio_diff_threshold) {
1494 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
1495 nb_samples = samples_size / n;
1497 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1498 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1499 if (wanted_size < min_size)
1500 wanted_size = min_size;
1501 else if (wanted_size > max_size)
1502 wanted_size = max_size;
1504 /* add or remove samples to correction the synchro */
1505 if (wanted_size < samples_size) {
1506 /* remove samples */
1507 samples_size = wanted_size;
1508 } else if (wanted_size > samples_size) {
1509 uint8_t *samples_end, *q;
1510 int nb;
1512 /* add samples */
1513 nb = (samples_size - wanted_size);
1514 samples_end = (uint8_t *)samples + samples_size - n;
1515 q = samples_end + n;
1516 while (nb > 0) {
1517 memcpy(q, samples_end, n);
1518 q += n;
1519 nb -= n;
1521 samples_size = wanted_size;
1524 #if 0
1525 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1526 diff, avg_diff, samples_size - samples_size1,
1527 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1528 #endif
1530 } else {
1531 /* too big difference : may be initial PTS errors, so
1532 reset A-V filter */
1533 is->audio_diff_avg_count = 0;
1534 is->audio_diff_cum = 0;
1538 return samples_size;
1541 /* decode one audio frame and returns its uncompressed size */
1542 static int audio_decode_frame(VideoState *is, double *pts_ptr)
1544 AVPacket *pkt_temp = &is->audio_pkt_temp;
1545 AVPacket *pkt = &is->audio_pkt;
1546 AVCodecContext *dec= is->audio_st->codec;
1547 int n, len1, data_size;
1548 double pts;
1550 for(;;) {
1551 /* NOTE: the audio packet can contain several frames */
1552 while (pkt_temp->size > 0) {
1553 data_size = sizeof(is->audio_buf1);
1554 len1 = avcodec_decode_audio3(dec,
1555 (int16_t *)is->audio_buf1, &data_size,
1556 pkt_temp);
1557 if (len1 < 0) {
1558 /* if error, we skip the frame */
1559 pkt_temp->size = 0;
1560 break;
1563 pkt_temp->data += len1;
1564 pkt_temp->size -= len1;
1565 if (data_size <= 0)
1566 continue;
1568 if (dec->sample_fmt != is->audio_src_fmt) {
1569 if (is->reformat_ctx)
1570 av_audio_convert_free(is->reformat_ctx);
1571 is->reformat_ctx= av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
1572 dec->sample_fmt, 1, NULL, 0);
1573 if (!is->reformat_ctx) {
1574 fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
1575 avcodec_get_sample_fmt_name(dec->sample_fmt),
1576 avcodec_get_sample_fmt_name(SAMPLE_FMT_S16));
1577 break;
1579 is->audio_src_fmt= dec->sample_fmt;
1582 if (is->reformat_ctx) {
1583 const void *ibuf[6]= {is->audio_buf1};
1584 void *obuf[6]= {is->audio_buf2};
1585 int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
1586 int ostride[6]= {2};
1587 int len= data_size/istride[0];
1588 if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
1589 printf("av_audio_convert() failed\n");
1590 break;
1592 is->audio_buf= is->audio_buf2;
1593 /* FIXME: existing code assume that data_size equals framesize*channels*2
1594 remove this legacy cruft */
1595 data_size= len*2;
1596 }else{
1597 is->audio_buf= is->audio_buf1;
1600 /* if no pts, then compute it */
1601 pts = is->audio_clock;
1602 *pts_ptr = pts;
1603 n = 2 * dec->channels;
1604 is->audio_clock += (double)data_size /
1605 (double)(n * dec->sample_rate);
1606 #if defined(DEBUG_SYNC)
1608 static double last_clock;
1609 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1610 is->audio_clock - last_clock,
1611 is->audio_clock, pts);
1612 last_clock = is->audio_clock;
1614 #endif
1615 return data_size;
1618 /* free the current packet */
1619 if (pkt->data)
1620 av_free_packet(pkt);
1622 if (is->paused || is->audioq.abort_request) {
1623 return -1;
1626 /* read next packet */
1627 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1628 return -1;
1629 if(pkt->data == flush_pkt.data){
1630 avcodec_flush_buffers(dec);
1631 continue;
1634 pkt_temp->data = pkt->data;
1635 pkt_temp->size = pkt->size;
1637 /* if update the audio clock with the pts */
1638 if (pkt->pts != AV_NOPTS_VALUE) {
1639 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
1644 /* get the current audio output buffer size, in samples. With SDL, we
1645 cannot have a precise information */
1646 static int audio_write_get_buf_size(VideoState *is)
1648 return is->audio_buf_size - is->audio_buf_index;
1652 /* prepare a new audio buffer */
1653 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1655 VideoState *is = opaque;
1656 int audio_size, len1;
1657 double pts;
1659 audio_callback_time = av_gettime();
1661 while (len > 0) {
1662 if (is->audio_buf_index >= is->audio_buf_size) {
1663 audio_size = audio_decode_frame(is, &pts);
1664 if (audio_size < 0) {
1665 /* if error, just output silence */
1666 is->audio_buf = is->audio_buf1;
1667 is->audio_buf_size = 1024;
1668 memset(is->audio_buf, 0, is->audio_buf_size);
1669 } else {
1670 if (is->show_audio)
1671 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1672 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
1673 pts);
1674 is->audio_buf_size = audio_size;
1676 is->audio_buf_index = 0;
1678 len1 = is->audio_buf_size - is->audio_buf_index;
1679 if (len1 > len)
1680 len1 = len;
1681 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1682 len -= len1;
1683 stream += len1;
1684 is->audio_buf_index += len1;
1688 /* open a given stream. Return 0 if OK */
1689 static int stream_component_open(VideoState *is, int stream_index)
1691 AVFormatContext *ic = is->ic;
1692 AVCodecContext *enc;
1693 AVCodec *codec;
1694 SDL_AudioSpec wanted_spec, spec;
1696 if (stream_index < 0 || stream_index >= ic->nb_streams)
1697 return -1;
1698 enc = ic->streams[stream_index]->codec;
1700 /* prepare audio output */
1701 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1702 if (enc->channels > 0) {
1703 enc->request_channels = FFMIN(2, enc->channels);
1704 } else {
1705 enc->request_channels = 2;
1709 codec = avcodec_find_decoder(enc->codec_id);
1710 enc->debug_mv = debug_mv;
1711 enc->debug = debug;
1712 enc->workaround_bugs = workaround_bugs;
1713 enc->lowres = lowres;
1714 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
1715 enc->idct_algo= idct;
1716 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
1717 enc->skip_frame= skip_frame;
1718 enc->skip_idct= skip_idct;
1719 enc->skip_loop_filter= skip_loop_filter;
1720 enc->error_recognition= error_recognition;
1721 enc->error_concealment= error_concealment;
1723 set_context_opts(enc, avcodec_opts[enc->codec_type], 0);
1725 if (!codec ||
1726 avcodec_open(enc, codec) < 0)
1727 return -1;
1729 /* prepare audio output */
1730 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1731 wanted_spec.freq = enc->sample_rate;
1732 wanted_spec.format = AUDIO_S16SYS;
1733 wanted_spec.channels = enc->channels;
1734 wanted_spec.silence = 0;
1735 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1736 wanted_spec.callback = sdl_audio_callback;
1737 wanted_spec.userdata = is;
1738 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1739 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1740 return -1;
1742 is->audio_hw_buf_size = spec.size;
1743 is->audio_src_fmt= SAMPLE_FMT_S16;
1746 if(thread_count>1)
1747 avcodec_thread_init(enc, thread_count);
1748 enc->thread_count= thread_count;
1749 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
1750 switch(enc->codec_type) {
1751 case CODEC_TYPE_AUDIO:
1752 is->audio_stream = stream_index;
1753 is->audio_st = ic->streams[stream_index];
1754 is->audio_buf_size = 0;
1755 is->audio_buf_index = 0;
1757 /* init averaging filter */
1758 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1759 is->audio_diff_avg_count = 0;
1760 /* since we do not have a precise anough audio fifo fullness,
1761 we correct audio sync only if larger than this threshold */
1762 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1764 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1765 packet_queue_init(&is->audioq);
1766 SDL_PauseAudio(0);
1767 break;
1768 case CODEC_TYPE_VIDEO:
1769 is->video_stream = stream_index;
1770 is->video_st = ic->streams[stream_index];
1772 is->frame_last_delay = 40e-3;
1773 is->frame_timer = (double)av_gettime() / 1000000.0;
1774 is->video_current_pts_time = av_gettime();
1776 packet_queue_init(&is->videoq);
1777 is->video_tid = SDL_CreateThread(video_thread, is);
1778 break;
1779 case CODEC_TYPE_SUBTITLE:
1780 is->subtitle_stream = stream_index;
1781 is->subtitle_st = ic->streams[stream_index];
1782 packet_queue_init(&is->subtitleq);
1784 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1785 break;
1786 default:
1787 break;
1789 return 0;
1792 static void stream_component_close(VideoState *is, int stream_index)
1794 AVFormatContext *ic = is->ic;
1795 AVCodecContext *enc;
1797 if (stream_index < 0 || stream_index >= ic->nb_streams)
1798 return;
1799 enc = ic->streams[stream_index]->codec;
1801 switch(enc->codec_type) {
1802 case CODEC_TYPE_AUDIO:
1803 packet_queue_abort(&is->audioq);
1805 SDL_CloseAudio();
1807 packet_queue_end(&is->audioq);
1808 if (is->reformat_ctx)
1809 av_audio_convert_free(is->reformat_ctx);
1810 break;
1811 case CODEC_TYPE_VIDEO:
1812 packet_queue_abort(&is->videoq);
1814 /* note: we also signal this mutex to make sure we deblock the
1815 video thread in all cases */
1816 SDL_LockMutex(is->pictq_mutex);
1817 SDL_CondSignal(is->pictq_cond);
1818 SDL_UnlockMutex(is->pictq_mutex);
1820 SDL_WaitThread(is->video_tid, NULL);
1822 packet_queue_end(&is->videoq);
1823 break;
1824 case CODEC_TYPE_SUBTITLE:
1825 packet_queue_abort(&is->subtitleq);
1827 /* note: we also signal this mutex to make sure we deblock the
1828 video thread in all cases */
1829 SDL_LockMutex(is->subpq_mutex);
1830 is->subtitle_stream_changed = 1;
1832 SDL_CondSignal(is->subpq_cond);
1833 SDL_UnlockMutex(is->subpq_mutex);
1835 SDL_WaitThread(is->subtitle_tid, NULL);
1837 packet_queue_end(&is->subtitleq);
1838 break;
1839 default:
1840 break;
1843 ic->streams[stream_index]->discard = AVDISCARD_ALL;
1844 avcodec_close(enc);
1845 switch(enc->codec_type) {
1846 case CODEC_TYPE_AUDIO:
1847 is->audio_st = NULL;
1848 is->audio_stream = -1;
1849 break;
1850 case CODEC_TYPE_VIDEO:
1851 is->video_st = NULL;
1852 is->video_stream = -1;
1853 break;
1854 case CODEC_TYPE_SUBTITLE:
1855 is->subtitle_st = NULL;
1856 is->subtitle_stream = -1;
1857 break;
1858 default:
1859 break;
1863 /* since we have only one decoding thread, we can use a global
1864 variable instead of a thread local variable */
1865 static VideoState *global_video_state;
1867 static int decode_interrupt_cb(void)
1869 return (global_video_state && global_video_state->abort_request);
1872 /* this thread gets the stream from the disk or the network */
1873 static int decode_thread(void *arg)
1875 VideoState *is = arg;
1876 AVFormatContext *ic;
1877 int err, i, ret, video_index, audio_index, subtitle_index;
1878 AVPacket pkt1, *pkt = &pkt1;
1879 AVFormatParameters params, *ap = &params;
1880 int eof=0;
1882 video_index = -1;
1883 audio_index = -1;
1884 subtitle_index = -1;
1885 is->video_stream = -1;
1886 is->audio_stream = -1;
1887 is->subtitle_stream = -1;
1889 global_video_state = is;
1890 url_set_interrupt_cb(decode_interrupt_cb);
1892 memset(ap, 0, sizeof(*ap));
1894 ap->width = frame_width;
1895 ap->height= frame_height;
1896 ap->time_base= (AVRational){1, 25};
1897 ap->pix_fmt = frame_pix_fmt;
1899 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
1900 if (err < 0) {
1901 print_error(is->filename, err);
1902 ret = -1;
1903 goto fail;
1905 is->ic = ic;
1907 if(genpts)
1908 ic->flags |= AVFMT_FLAG_GENPTS;
1910 err = av_find_stream_info(ic);
1911 if (err < 0) {
1912 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1913 ret = -1;
1914 goto fail;
1916 if(ic->pb)
1917 ic->pb->eof_reached= 0; //FIXME hack, ffplay maybe should not use url_feof() to test for the end
1919 /* if seeking requested, we execute it */
1920 if (start_time != AV_NOPTS_VALUE) {
1921 int64_t timestamp;
1923 timestamp = start_time;
1924 /* add the stream start time */
1925 if (ic->start_time != AV_NOPTS_VALUE)
1926 timestamp += ic->start_time;
1927 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
1928 if (ret < 0) {
1929 fprintf(stderr, "%s: could not seek to position %0.3f\n",
1930 is->filename, (double)timestamp / AV_TIME_BASE);
1934 for(i = 0; i < ic->nb_streams; i++) {
1935 AVCodecContext *enc = ic->streams[i]->codec;
1936 ic->streams[i]->discard = AVDISCARD_ALL;
1937 switch(enc->codec_type) {
1938 case CODEC_TYPE_AUDIO:
1939 if (wanted_audio_stream-- >= 0 && !audio_disable)
1940 audio_index = i;
1941 break;
1942 case CODEC_TYPE_VIDEO:
1943 if (wanted_video_stream-- >= 0 && !video_disable)
1944 video_index = i;
1945 break;
1946 case CODEC_TYPE_SUBTITLE:
1947 if (wanted_subtitle_stream-- >= 0 && !video_disable)
1948 subtitle_index = i;
1949 break;
1950 default:
1951 break;
1954 if (show_status) {
1955 dump_format(ic, 0, is->filename, 0);
1958 /* open the streams */
1959 if (audio_index >= 0) {
1960 stream_component_open(is, audio_index);
1963 if (video_index >= 0) {
1964 stream_component_open(is, video_index);
1965 } else {
1966 if (!display_disable)
1967 is->show_audio = 1;
1970 if (subtitle_index >= 0) {
1971 stream_component_open(is, subtitle_index);
1974 if (is->video_stream < 0 && is->audio_stream < 0) {
1975 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1976 ret = -1;
1977 goto fail;
1980 for(;;) {
1981 if (is->abort_request)
1982 break;
1983 if (is->paused != is->last_paused) {
1984 is->last_paused = is->paused;
1985 if (is->paused)
1986 av_read_pause(ic);
1987 else
1988 av_read_play(ic);
1990 #if CONFIG_RTSP_DEMUXER
1991 if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
1992 /* wait 10 ms to avoid trying to get another packet */
1993 /* XXX: horrible */
1994 SDL_Delay(10);
1995 continue;
1997 #endif
1998 if (is->seek_req) {
1999 int64_t seek_target= is->seek_pos;
2000 int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2001 int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2002 //FIXME the +-2 is due to rounding being not done in the correct direction in generation
2003 // of the seek_pos/seek_rel variables
2005 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2006 if (ret < 0) {
2007 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
2008 }else{
2009 if (is->audio_stream >= 0) {
2010 packet_queue_flush(&is->audioq);
2011 packet_queue_put(&is->audioq, &flush_pkt);
2013 if (is->subtitle_stream >= 0) {
2014 packet_queue_flush(&is->subtitleq);
2015 packet_queue_put(&is->subtitleq, &flush_pkt);
2017 if (is->video_stream >= 0) {
2018 packet_queue_flush(&is->videoq);
2019 packet_queue_put(&is->videoq, &flush_pkt);
2022 is->seek_req = 0;
2023 eof= 0;
2026 /* if the queue are full, no need to read more */
2027 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
2028 is->videoq.size > MAX_VIDEOQ_SIZE ||
2029 is->subtitleq.size > MAX_SUBTITLEQ_SIZE) {
2030 /* wait 10 ms */
2031 SDL_Delay(10);
2032 continue;
2034 if(url_feof(ic->pb) || eof) {
2035 if(is->video_stream >= 0){
2036 av_init_packet(pkt);
2037 pkt->data=NULL;
2038 pkt->size=0;
2039 pkt->stream_index= is->video_stream;
2040 packet_queue_put(&is->videoq, pkt);
2042 SDL_Delay(10);
2043 continue;
2045 ret = av_read_frame(ic, pkt);
2046 if (ret < 0) {
2047 if (ret == AVERROR_EOF)
2048 eof=1;
2049 if (url_ferror(ic->pb))
2050 break;
2051 SDL_Delay(100); /* wait for user event */
2052 continue;
2054 if (pkt->stream_index == is->audio_stream) {
2055 packet_queue_put(&is->audioq, pkt);
2056 } else if (pkt->stream_index == is->video_stream) {
2057 packet_queue_put(&is->videoq, pkt);
2058 } else if (pkt->stream_index == is->subtitle_stream) {
2059 packet_queue_put(&is->subtitleq, pkt);
2060 } else {
2061 av_free_packet(pkt);
2064 /* wait until the end */
2065 while (!is->abort_request) {
2066 SDL_Delay(100);
2069 ret = 0;
2070 fail:
2071 /* disable interrupting */
2072 global_video_state = NULL;
2074 /* close each stream */
2075 if (is->audio_stream >= 0)
2076 stream_component_close(is, is->audio_stream);
2077 if (is->video_stream >= 0)
2078 stream_component_close(is, is->video_stream);
2079 if (is->subtitle_stream >= 0)
2080 stream_component_close(is, is->subtitle_stream);
2081 if (is->ic) {
2082 av_close_input_file(is->ic);
2083 is->ic = NULL; /* safety */
2085 url_set_interrupt_cb(NULL);
2087 if (ret != 0) {
2088 SDL_Event event;
2090 event.type = FF_QUIT_EVENT;
2091 event.user.data1 = is;
2092 SDL_PushEvent(&event);
2094 return 0;
2097 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
2099 VideoState *is;
2101 is = av_mallocz(sizeof(VideoState));
2102 if (!is)
2103 return NULL;
2104 av_strlcpy(is->filename, filename, sizeof(is->filename));
2105 is->iformat = iformat;
2106 is->ytop = 0;
2107 is->xleft = 0;
2109 /* start video display */
2110 is->pictq_mutex = SDL_CreateMutex();
2111 is->pictq_cond = SDL_CreateCond();
2113 is->subpq_mutex = SDL_CreateMutex();
2114 is->subpq_cond = SDL_CreateCond();
2116 /* add the refresh timer to draw the picture */
2117 schedule_refresh(is, 40);
2119 is->av_sync_type = av_sync_type;
2120 is->parse_tid = SDL_CreateThread(decode_thread, is);
2121 if (!is->parse_tid) {
2122 av_free(is);
2123 return NULL;
2125 return is;
2128 static void stream_close(VideoState *is)
2130 VideoPicture *vp;
2131 int i;
2132 /* XXX: use a special url_shutdown call to abort parse cleanly */
2133 is->abort_request = 1;
2134 SDL_WaitThread(is->parse_tid, NULL);
2136 /* free all pictures */
2137 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2138 vp = &is->pictq[i];
2139 if (vp->bmp) {
2140 SDL_FreeYUVOverlay(vp->bmp);
2141 vp->bmp = NULL;
2144 SDL_DestroyMutex(is->pictq_mutex);
2145 SDL_DestroyCond(is->pictq_cond);
2146 SDL_DestroyMutex(is->subpq_mutex);
2147 SDL_DestroyCond(is->subpq_cond);
2148 if (is->img_convert_ctx)
2149 sws_freeContext(is->img_convert_ctx);
2150 av_free(is);
2153 static void stream_cycle_channel(VideoState *is, int codec_type)
2155 AVFormatContext *ic = is->ic;
2156 int start_index, stream_index;
2157 AVStream *st;
2159 if (codec_type == CODEC_TYPE_VIDEO)
2160 start_index = is->video_stream;
2161 else if (codec_type == CODEC_TYPE_AUDIO)
2162 start_index = is->audio_stream;
2163 else
2164 start_index = is->subtitle_stream;
2165 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
2166 return;
2167 stream_index = start_index;
2168 for(;;) {
2169 if (++stream_index >= is->ic->nb_streams)
2171 if (codec_type == CODEC_TYPE_SUBTITLE)
2173 stream_index = -1;
2174 goto the_end;
2175 } else
2176 stream_index = 0;
2178 if (stream_index == start_index)
2179 return;
2180 st = ic->streams[stream_index];
2181 if (st->codec->codec_type == codec_type) {
2182 /* check that parameters are OK */
2183 switch(codec_type) {
2184 case CODEC_TYPE_AUDIO:
2185 if (st->codec->sample_rate != 0 &&
2186 st->codec->channels != 0)
2187 goto the_end;
2188 break;
2189 case CODEC_TYPE_VIDEO:
2190 case CODEC_TYPE_SUBTITLE:
2191 goto the_end;
2192 default:
2193 break;
2197 the_end:
2198 stream_component_close(is, start_index);
2199 stream_component_open(is, stream_index);
2203 static void toggle_full_screen(void)
2205 is_full_screen = !is_full_screen;
2206 if (!fs_screen_width) {
2207 /* use default SDL method */
2208 // SDL_WM_ToggleFullScreen(screen);
2210 video_open(cur_stream);
2213 static void toggle_pause(void)
2215 if (cur_stream)
2216 stream_pause(cur_stream);
2217 step = 0;
2220 static void step_to_next_frame(void)
2222 if (cur_stream) {
2223 /* if the stream is paused unpause it, then step */
2224 if (cur_stream->paused)
2225 stream_pause(cur_stream);
2227 step = 1;
2230 static void do_exit(void)
2232 int i;
2233 if (cur_stream) {
2234 stream_close(cur_stream);
2235 cur_stream = NULL;
2237 for (i = 0; i < CODEC_TYPE_NB; i++)
2238 av_free(avcodec_opts[i]);
2239 av_free(avformat_opts);
2240 av_free(sws_opts);
2241 if (show_status)
2242 printf("\n");
2243 SDL_Quit();
2244 exit(0);
2247 static void toggle_audio_display(void)
2249 if (cur_stream) {
2250 cur_stream->show_audio = !cur_stream->show_audio;
2254 /* handle an event sent by the GUI */
2255 static void event_loop(void)
2257 SDL_Event event;
2258 double incr, pos, frac;
2260 for(;;) {
2261 SDL_WaitEvent(&event);
2262 switch(event.type) {
2263 case SDL_KEYDOWN:
2264 switch(event.key.keysym.sym) {
2265 case SDLK_ESCAPE:
2266 case SDLK_q:
2267 do_exit();
2268 break;
2269 case SDLK_f:
2270 toggle_full_screen();
2271 break;
2272 case SDLK_p:
2273 case SDLK_SPACE:
2274 toggle_pause();
2275 break;
2276 case SDLK_s: //S: Step to next frame
2277 step_to_next_frame();
2278 break;
2279 case SDLK_a:
2280 if (cur_stream)
2281 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2282 break;
2283 case SDLK_v:
2284 if (cur_stream)
2285 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2286 break;
2287 case SDLK_t:
2288 if (cur_stream)
2289 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2290 break;
2291 case SDLK_w:
2292 toggle_audio_display();
2293 break;
2294 case SDLK_LEFT:
2295 incr = -10.0;
2296 goto do_seek;
2297 case SDLK_RIGHT:
2298 incr = 10.0;
2299 goto do_seek;
2300 case SDLK_UP:
2301 incr = 60.0;
2302 goto do_seek;
2303 case SDLK_DOWN:
2304 incr = -60.0;
2305 do_seek:
2306 if (cur_stream) {
2307 if (seek_by_bytes) {
2308 pos = url_ftell(cur_stream->ic->pb);
2309 if (cur_stream->ic->bit_rate)
2310 incr *= cur_stream->ic->bit_rate / 60.0;
2311 else
2312 incr *= 180000.0;
2313 pos += incr;
2314 stream_seek(cur_stream, pos, incr);
2315 } else {
2316 pos = get_master_clock(cur_stream);
2317 pos += incr;
2318 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE));
2321 break;
2322 default:
2323 break;
2325 break;
2326 case SDL_MOUSEBUTTONDOWN:
2327 if (cur_stream) {
2328 int64_t ts;
2329 int ns, hh, mm, ss;
2330 int tns, thh, tmm, tss;
2331 tns = cur_stream->ic->duration/1000000LL;
2332 thh = tns/3600;
2333 tmm = (tns%3600)/60;
2334 tss = (tns%60);
2335 frac = (double)event.button.x/(double)cur_stream->width;
2336 ns = frac*tns;
2337 hh = ns/3600;
2338 mm = (ns%3600)/60;
2339 ss = (ns%60);
2340 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2341 hh, mm, ss, thh, tmm, tss);
2342 ts = frac*cur_stream->ic->duration;
2343 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
2344 ts += cur_stream->ic->start_time;
2345 stream_seek(cur_stream, ts, 0);
2347 break;
2348 case SDL_VIDEORESIZE:
2349 if (cur_stream) {
2350 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2351 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2352 screen_width = cur_stream->width = event.resize.w;
2353 screen_height= cur_stream->height= event.resize.h;
2355 break;
2356 case SDL_QUIT:
2357 case FF_QUIT_EVENT:
2358 do_exit();
2359 break;
2360 case FF_ALLOC_EVENT:
2361 video_open(event.user.data1);
2362 alloc_picture(event.user.data1);
2363 break;
2364 case FF_REFRESH_EVENT:
2365 video_refresh_timer(event.user.data1);
2366 break;
2367 default:
2368 break;
2373 static void opt_frame_size(const char *arg)
2375 if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
2376 fprintf(stderr, "Incorrect frame size\n");
2377 exit(1);
2379 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2380 fprintf(stderr, "Frame size must be a multiple of 2\n");
2381 exit(1);
2385 static int opt_width(const char *opt, const char *arg)
2387 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2388 return 0;
2391 static int opt_height(const char *opt, const char *arg)
2393 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2394 return 0;
2397 static void opt_format(const char *arg)
2399 file_iformat = av_find_input_format(arg);
2400 if (!file_iformat) {
2401 fprintf(stderr, "Unknown input format: %s\n", arg);
2402 exit(1);
2406 static void opt_frame_pix_fmt(const char *arg)
2408 frame_pix_fmt = avcodec_get_pix_fmt(arg);
2411 static int opt_sync(const char *opt, const char *arg)
2413 if (!strcmp(arg, "audio"))
2414 av_sync_type = AV_SYNC_AUDIO_MASTER;
2415 else if (!strcmp(arg, "video"))
2416 av_sync_type = AV_SYNC_VIDEO_MASTER;
2417 else if (!strcmp(arg, "ext"))
2418 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2419 else {
2420 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
2421 exit(1);
2423 return 0;
2426 static int opt_seek(const char *opt, const char *arg)
2428 start_time = parse_time_or_die(opt, arg, 1);
2429 return 0;
2432 static int opt_debug(const char *opt, const char *arg)
2434 av_log_set_level(99);
2435 debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2436 return 0;
2439 static int opt_vismv(const char *opt, const char *arg)
2441 debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
2442 return 0;
2445 static int opt_thread_count(const char *opt, const char *arg)
2447 thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2448 #if !HAVE_THREADS
2449 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2450 #endif
2451 return 0;
2454 static const OptionDef options[] = {
2455 { "h", OPT_EXIT, {(void*)show_help}, "show help" },
2456 { "version", OPT_EXIT, {(void*)show_version}, "show version" },
2457 { "L", OPT_EXIT, {(void*)show_license}, "show license" },
2458 { "formats", OPT_EXIT, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
2459 { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
2460 { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
2461 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
2462 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
2463 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2464 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
2465 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "select desired audio stream", "stream_number" },
2466 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "select desired video stream", "stream_number" },
2467 { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_subtitle_stream}, "select desired subtitle stream", "stream_number" },
2468 { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
2469 { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
2470 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2471 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
2472 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
2473 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
2474 { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
2475 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
2476 { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
2477 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
2478 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
2479 { "drp", OPT_BOOL |OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts", ""},
2480 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
2481 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2482 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2483 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
2484 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
2485 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)", "threshold" },
2486 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
2487 { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2488 { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
2489 { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
2490 { NULL, },
2493 static void show_help(void)
2495 printf("usage: ffplay [options] input_file\n"
2496 "Simple media player\n");
2497 printf("\n");
2498 show_help_options(options, "Main options:\n",
2499 OPT_EXPERT, 0);
2500 show_help_options(options, "\nAdvanced options:\n",
2501 OPT_EXPERT, OPT_EXPERT);
2502 printf("\nWhile playing:\n"
2503 "q, ESC quit\n"
2504 "f toggle full screen\n"
2505 "p, SPC pause\n"
2506 "a cycle audio channel\n"
2507 "v cycle video channel\n"
2508 "t cycle subtitle channel\n"
2509 "w show audio waves\n"
2510 "left/right seek backward/forward 10 seconds\n"
2511 "down/up seek backward/forward 1 minute\n"
2512 "mouse click seek to percentage in file corresponding to fraction of width\n"
2516 static void opt_input_file(const char *filename)
2518 if (!strcmp(filename, "-"))
2519 filename = "pipe:";
2520 input_filename = filename;
2523 /* Called from the main */
2524 int main(int argc, char **argv)
2526 int flags, i;
2528 /* register all codecs, demux and protocols */
2529 avcodec_register_all();
2530 avdevice_register_all();
2531 av_register_all();
2533 for(i=0; i<CODEC_TYPE_NB; i++){
2534 avcodec_opts[i]= avcodec_alloc_context2(i);
2536 avformat_opts = avformat_alloc_context();
2537 sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
2539 show_banner();
2541 parse_options(argc, argv, options, opt_input_file);
2543 if (!input_filename) {
2544 fprintf(stderr, "An input file must be specified\n");
2545 exit(1);
2548 if (display_disable) {
2549 video_disable = 1;
2551 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
2552 #if !defined(__MINGW32__) && !defined(__APPLE__)
2553 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
2554 #endif
2555 if (SDL_Init (flags)) {
2556 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
2557 exit(1);
2560 if (!display_disable) {
2561 #if HAVE_SDL_VIDEO_SIZE
2562 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2563 fs_screen_width = vi->current_w;
2564 fs_screen_height = vi->current_h;
2565 #endif
2568 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2569 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2570 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2571 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2573 av_init_packet(&flush_pkt);
2574 flush_pkt.data= "FLUSH";
2576 cur_stream = stream_open(input_filename, file_iformat);
2578 event_loop();
2580 /* never returns */
2582 return 0;