Use FFABS instead of abs.
[FFMpeg-mirror/ordered_chapters.git] / ffplay.c
blob23917ac1c0d9ca44d0c216c5e38e39ebe08d4b4e
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
21 #define HAVE_AV_CONFIG_H
22 #include "avformat.h"
23 #include "swscale.h"
25 #include "version.h"
26 #include "cmdutils.h"
28 #include <SDL.h>
29 #include <SDL_thread.h>
31 #ifdef __MINGW32__
32 #undef main /* We don't want SDL to override our main() */
33 #endif
35 #ifdef CONFIG_OS2
36 #define INCL_DOS
37 #include <os2.h>
38 #include <stdio.h>
40 void MorphToPM()
42 PPIB pib;
43 PTIB tib;
45 DosGetInfoBlocks(&tib, &pib);
47 // Change flag from VIO to PM:
48 if (pib->pib_ultype==2) pib->pib_ultype = 3;
50 #endif
52 #undef exit
54 //#define DEBUG_SYNC
56 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
57 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
58 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
60 /* SDL audio buffer size, in samples. Should be small to have precise
61 A/V sync as SDL does not have hardware buffer fullness info. */
62 #define SDL_AUDIO_BUFFER_SIZE 1024
64 /* no AV sync correction is done if below the AV sync threshold */
65 #define AV_SYNC_THRESHOLD 0.01
66 /* no AV correction is done if too big error */
67 #define AV_NOSYNC_THRESHOLD 10.0
69 /* maximum audio speed change to get correct sync */
70 #define SAMPLE_CORRECTION_PERCENT_MAX 10
72 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
73 #define AUDIO_DIFF_AVG_NB 20
75 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
76 #define SAMPLE_ARRAY_SIZE (2*65536)
78 static int sws_flags = SWS_BICUBIC;
80 typedef struct PacketQueue {
81 AVPacketList *first_pkt, *last_pkt;
82 int nb_packets;
83 int size;
84 int abort_request;
85 SDL_mutex *mutex;
86 SDL_cond *cond;
87 } PacketQueue;
89 #define VIDEO_PICTURE_QUEUE_SIZE 1
90 #define SUBPICTURE_QUEUE_SIZE 4
92 typedef struct VideoPicture {
93 double pts; ///<presentation time stamp for this picture
94 SDL_Overlay *bmp;
95 int width, height; /* source height & width */
96 int allocated;
97 } VideoPicture;
99 typedef struct SubPicture {
100 double pts; /* presentation time stamp for this picture */
101 AVSubtitle sub;
102 } SubPicture;
104 enum {
105 AV_SYNC_AUDIO_MASTER, /* default choice */
106 AV_SYNC_VIDEO_MASTER,
107 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
110 typedef struct VideoState {
111 SDL_Thread *parse_tid;
112 SDL_Thread *video_tid;
113 AVInputFormat *iformat;
114 int no_background;
115 int abort_request;
116 int paused;
117 int last_paused;
118 int seek_req;
119 int seek_flags;
120 int64_t seek_pos;
121 AVFormatContext *ic;
122 int dtg_active_format;
124 int audio_stream;
126 int av_sync_type;
127 double external_clock; /* external clock base */
128 int64_t external_clock_time;
130 double audio_clock;
131 double audio_diff_cum; /* used for AV difference average computation */
132 double audio_diff_avg_coef;
133 double audio_diff_threshold;
134 int audio_diff_avg_count;
135 AVStream *audio_st;
136 PacketQueue audioq;
137 int audio_hw_buf_size;
138 /* samples output by the codec. we reserve more space for avsync
139 compensation */
140 DECLARE_ALIGNED(16,uint8_t,audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
141 unsigned int audio_buf_size; /* in bytes */
142 int audio_buf_index; /* in bytes */
143 AVPacket audio_pkt;
144 uint8_t *audio_pkt_data;
145 int audio_pkt_size;
147 int show_audio; /* if true, display audio samples */
148 int16_t sample_array[SAMPLE_ARRAY_SIZE];
149 int sample_array_index;
150 int last_i_start;
152 SDL_Thread *subtitle_tid;
153 int subtitle_stream;
154 int subtitle_stream_changed;
155 AVStream *subtitle_st;
156 PacketQueue subtitleq;
157 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
158 int subpq_size, subpq_rindex, subpq_windex;
159 SDL_mutex *subpq_mutex;
160 SDL_cond *subpq_cond;
162 double frame_timer;
163 double frame_last_pts;
164 double frame_last_delay;
165 double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
166 int video_stream;
167 AVStream *video_st;
168 PacketQueue videoq;
169 double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
170 int64_t video_current_pts_time; ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts
171 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
172 int pictq_size, pictq_rindex, pictq_windex;
173 SDL_mutex *pictq_mutex;
174 SDL_cond *pictq_cond;
176 // QETimer *video_timer;
177 char filename[1024];
178 int width, height, xleft, ytop;
179 } VideoState;
181 void show_help(void);
182 static int audio_write_get_buf_size(VideoState *is);
184 /* options specified by the user */
185 static AVInputFormat *file_iformat;
186 static const char *input_filename;
187 static int fs_screen_width;
188 static int fs_screen_height;
189 static int screen_width = 0;
190 static int screen_height = 0;
191 static int frame_width = 0;
192 static int frame_height = 0;
193 static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
194 static int audio_disable;
195 static int video_disable;
196 static int wanted_audio_stream= 0;
197 static int seek_by_bytes;
198 static int display_disable;
199 static int show_status;
200 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
201 static int64_t start_time = AV_NOPTS_VALUE;
202 static int debug = 0;
203 static int debug_mv = 0;
204 static int step = 0;
205 static int thread_count = 1;
206 static int workaround_bugs = 1;
207 static int fast = 0;
208 static int genpts = 0;
209 static int lowres = 0;
210 static int idct = FF_IDCT_AUTO;
211 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
212 static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
213 static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
214 static int error_resilience = FF_ER_CAREFUL;
215 static int error_concealment = 3;
216 static int decoder_reorder_pts= 0;
218 /* current context */
219 static int is_full_screen;
220 static VideoState *cur_stream;
221 static int64_t audio_callback_time;
223 AVPacket flush_pkt;
225 #define FF_ALLOC_EVENT (SDL_USEREVENT)
226 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
227 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
229 SDL_Surface *screen;
231 /* packet queue handling */
232 static void packet_queue_init(PacketQueue *q)
234 memset(q, 0, sizeof(PacketQueue));
235 q->mutex = SDL_CreateMutex();
236 q->cond = SDL_CreateCond();
239 static void packet_queue_flush(PacketQueue *q)
241 AVPacketList *pkt, *pkt1;
243 SDL_LockMutex(q->mutex);
244 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
245 pkt1 = pkt->next;
246 av_free_packet(&pkt->pkt);
247 av_freep(&pkt);
249 q->last_pkt = NULL;
250 q->first_pkt = NULL;
251 q->nb_packets = 0;
252 q->size = 0;
253 SDL_UnlockMutex(q->mutex);
256 static void packet_queue_end(PacketQueue *q)
258 packet_queue_flush(q);
259 SDL_DestroyMutex(q->mutex);
260 SDL_DestroyCond(q->cond);
263 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
265 AVPacketList *pkt1;
267 /* duplicate the packet */
268 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
269 return -1;
271 pkt1 = av_malloc(sizeof(AVPacketList));
272 if (!pkt1)
273 return -1;
274 pkt1->pkt = *pkt;
275 pkt1->next = NULL;
278 SDL_LockMutex(q->mutex);
280 if (!q->last_pkt)
282 q->first_pkt = pkt1;
283 else
284 q->last_pkt->next = pkt1;
285 q->last_pkt = pkt1;
286 q->nb_packets++;
287 q->size += pkt1->pkt.size;
288 /* XXX: should duplicate packet data in DV case */
289 SDL_CondSignal(q->cond);
291 SDL_UnlockMutex(q->mutex);
292 return 0;
295 static void packet_queue_abort(PacketQueue *q)
297 SDL_LockMutex(q->mutex);
299 q->abort_request = 1;
301 SDL_CondSignal(q->cond);
303 SDL_UnlockMutex(q->mutex);
306 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
307 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
309 AVPacketList *pkt1;
310 int ret;
312 SDL_LockMutex(q->mutex);
314 for(;;) {
315 if (q->abort_request) {
316 ret = -1;
317 break;
320 pkt1 = q->first_pkt;
321 if (pkt1) {
322 q->first_pkt = pkt1->next;
323 if (!q->first_pkt)
324 q->last_pkt = NULL;
325 q->nb_packets--;
326 q->size -= pkt1->pkt.size;
327 *pkt = pkt1->pkt;
328 av_free(pkt1);
329 ret = 1;
330 break;
331 } else if (!block) {
332 ret = 0;
333 break;
334 } else {
335 SDL_CondWait(q->cond, q->mutex);
338 SDL_UnlockMutex(q->mutex);
339 return ret;
342 static inline void fill_rectangle(SDL_Surface *screen,
343 int x, int y, int w, int h, int color)
345 SDL_Rect rect;
346 rect.x = x;
347 rect.y = y;
348 rect.w = w;
349 rect.h = h;
350 SDL_FillRect(screen, &rect, color);
353 #if 0
354 /* draw only the border of a rectangle */
355 void fill_border(VideoState *s, int x, int y, int w, int h, int color)
357 int w1, w2, h1, h2;
359 /* fill the background */
360 w1 = x;
361 if (w1 < 0)
362 w1 = 0;
363 w2 = s->width - (x + w);
364 if (w2 < 0)
365 w2 = 0;
366 h1 = y;
367 if (h1 < 0)
368 h1 = 0;
369 h2 = s->height - (y + h);
370 if (h2 < 0)
371 h2 = 0;
372 fill_rectangle(screen,
373 s->xleft, s->ytop,
374 w1, s->height,
375 color);
376 fill_rectangle(screen,
377 s->xleft + s->width - w2, s->ytop,
378 w2, s->height,
379 color);
380 fill_rectangle(screen,
381 s->xleft + w1, s->ytop,
382 s->width - w1 - w2, h1,
383 color);
384 fill_rectangle(screen,
385 s->xleft + w1, s->ytop + s->height - h2,
386 s->width - w1 - w2, h2,
387 color);
389 #endif
393 #define SCALEBITS 10
394 #define ONE_HALF (1 << (SCALEBITS - 1))
395 #define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
397 #define RGB_TO_Y_CCIR(r, g, b) \
398 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
399 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
401 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
402 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
403 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
405 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
406 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
407 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
409 #define ALPHA_BLEND(a, oldp, newp, s)\
410 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
412 #define RGBA_IN(r, g, b, a, s)\
414 unsigned int v = ((const uint32_t *)(s))[0];\
415 a = (v >> 24) & 0xff;\
416 r = (v >> 16) & 0xff;\
417 g = (v >> 8) & 0xff;\
418 b = v & 0xff;\
421 #define YUVA_IN(y, u, v, a, s, pal)\
423 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)s];\
424 a = (val >> 24) & 0xff;\
425 y = (val >> 16) & 0xff;\
426 u = (val >> 8) & 0xff;\
427 v = val & 0xff;\
430 #define YUVA_OUT(d, y, u, v, a)\
432 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
436 #define BPP 1
438 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
440 int wrap, wrap3, width2, skip2;
441 int y, u, v, a, u1, v1, a1, w, h;
442 uint8_t *lum, *cb, *cr;
443 const uint8_t *p;
444 const uint32_t *pal;
446 lum = dst->data[0] + rect->y * dst->linesize[0];
447 cb = dst->data[1] + (rect->y >> 1) * dst->linesize[1];
448 cr = dst->data[2] + (rect->y >> 1) * dst->linesize[2];
450 width2 = (rect->w + 1) >> 1;
451 skip2 = rect->x >> 1;
452 wrap = dst->linesize[0];
453 wrap3 = rect->linesize;
454 p = rect->bitmap;
455 pal = rect->rgba_palette; /* Now in YCrCb! */
457 if (rect->y & 1) {
458 lum += rect->x;
459 cb += skip2;
460 cr += skip2;
462 if (rect->x & 1) {
463 YUVA_IN(y, u, v, a, p, pal);
464 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
465 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
466 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
467 cb++;
468 cr++;
469 lum++;
470 p += BPP;
472 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
473 YUVA_IN(y, u, v, a, p, pal);
474 u1 = u;
475 v1 = v;
476 a1 = a;
477 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
479 YUVA_IN(y, u, v, a, p + BPP, pal);
480 u1 += u;
481 v1 += v;
482 a1 += a;
483 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
484 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
485 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
486 cb++;
487 cr++;
488 p += 2 * BPP;
489 lum += 2;
491 if (w) {
492 YUVA_IN(y, u, v, a, p, pal);
493 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
494 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
495 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
497 p += wrap3 + (wrap3 - rect->w * BPP);
498 lum += wrap + (wrap - rect->w - rect->x);
499 cb += dst->linesize[1] - width2 - skip2;
500 cr += dst->linesize[2] - width2 - skip2;
502 for(h = rect->h - (rect->y & 1); h >= 2; h -= 2) {
503 lum += rect->x;
504 cb += skip2;
505 cr += skip2;
507 if (rect->x & 1) {
508 YUVA_IN(y, u, v, a, p, pal);
509 u1 = u;
510 v1 = v;
511 a1 = a;
512 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
513 p += wrap3;
514 lum += wrap;
515 YUVA_IN(y, u, v, a, p, pal);
516 u1 += u;
517 v1 += v;
518 a1 += a;
519 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
520 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
521 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
522 cb++;
523 cr++;
524 p += -wrap3 + BPP;
525 lum += -wrap + 1;
527 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
528 YUVA_IN(y, u, v, a, p, pal);
529 u1 = u;
530 v1 = v;
531 a1 = a;
532 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
534 YUVA_IN(y, u, v, a, p, pal);
535 u1 += u;
536 v1 += v;
537 a1 += a;
538 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
539 p += wrap3;
540 lum += wrap;
542 YUVA_IN(y, u, v, a, p, pal);
543 u1 += u;
544 v1 += v;
545 a1 += a;
546 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
548 YUVA_IN(y, u, v, a, p, pal);
549 u1 += u;
550 v1 += v;
551 a1 += a;
552 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
554 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
555 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
557 cb++;
558 cr++;
559 p += -wrap3 + 2 * BPP;
560 lum += -wrap + 2;
562 if (w) {
563 YUVA_IN(y, u, v, a, p, pal);
564 u1 = u;
565 v1 = v;
566 a1 = a;
567 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
568 p += wrap3;
569 lum += wrap;
570 YUVA_IN(y, u, v, a, p, pal);
571 u1 += u;
572 v1 += v;
573 a1 += a;
574 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
575 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
576 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
577 cb++;
578 cr++;
579 p += -wrap3 + BPP;
580 lum += -wrap + 1;
582 p += wrap3 + (wrap3 - rect->w * BPP);
583 lum += wrap + (wrap - rect->w - rect->x);
584 cb += dst->linesize[1] - width2 - skip2;
585 cr += dst->linesize[2] - width2 - skip2;
587 /* handle odd height */
588 if (h) {
589 lum += rect->x;
590 cb += skip2;
591 cr += skip2;
593 if (rect->x & 1) {
594 YUVA_IN(y, u, v, a, p, pal);
595 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
596 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
597 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
598 cb++;
599 cr++;
600 lum++;
601 p += BPP;
603 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
604 YUVA_IN(y, u, v, a, p, pal);
605 u1 = u;
606 v1 = v;
607 a1 = a;
608 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
610 YUVA_IN(y, u, v, a, p + BPP, pal);
611 u1 += u;
612 v1 += v;
613 a1 += a;
614 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
615 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
616 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
617 cb++;
618 cr++;
619 p += 2 * BPP;
620 lum += 2;
622 if (w) {
623 YUVA_IN(y, u, v, a, p, pal);
624 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
625 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
626 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
631 static void free_subpicture(SubPicture *sp)
633 int i;
635 for (i = 0; i < sp->sub.num_rects; i++)
637 av_free(sp->sub.rects[i].bitmap);
638 av_free(sp->sub.rects[i].rgba_palette);
641 av_free(sp->sub.rects);
643 memset(&sp->sub, 0, sizeof(AVSubtitle));
646 static void video_image_display(VideoState *is)
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;
656 vp = &is->pictq[is->pictq_rindex];
657 if (vp->bmp) {
658 /* XXX: use variable in the frame */
659 if (is->video_st->codec->sample_aspect_ratio.num == 0)
660 aspect_ratio = 0;
661 else
662 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio)
663 * is->video_st->codec->width / is->video_st->codec->height;;
664 if (aspect_ratio <= 0.0)
665 aspect_ratio = (float)is->video_st->codec->width /
666 (float)is->video_st->codec->height;
667 /* if an active format is indicated, then it overrides the
668 mpeg format */
669 #if 0
670 if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
671 is->dtg_active_format = is->video_st->codec->dtg_active_format;
672 printf("dtg_active_format=%d\n", is->dtg_active_format);
674 #endif
675 #if 0
676 switch(is->video_st->codec->dtg_active_format) {
677 case FF_DTG_AFD_SAME:
678 default:
679 /* nothing to do */
680 break;
681 case FF_DTG_AFD_4_3:
682 aspect_ratio = 4.0 / 3.0;
683 break;
684 case FF_DTG_AFD_16_9:
685 aspect_ratio = 16.0 / 9.0;
686 break;
687 case FF_DTG_AFD_14_9:
688 aspect_ratio = 14.0 / 9.0;
689 break;
690 case FF_DTG_AFD_4_3_SP_14_9:
691 aspect_ratio = 14.0 / 9.0;
692 break;
693 case FF_DTG_AFD_16_9_SP_14_9:
694 aspect_ratio = 14.0 / 9.0;
695 break;
696 case FF_DTG_AFD_SP_4_3:
697 aspect_ratio = 4.0 / 3.0;
698 break;
700 #endif
702 if (is->subtitle_st)
704 if (is->subpq_size > 0)
706 sp = &is->subpq[is->subpq_rindex];
708 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
710 SDL_LockYUVOverlay (vp->bmp);
712 pict.data[0] = vp->bmp->pixels[0];
713 pict.data[1] = vp->bmp->pixels[2];
714 pict.data[2] = vp->bmp->pixels[1];
716 pict.linesize[0] = vp->bmp->pitches[0];
717 pict.linesize[1] = vp->bmp->pitches[2];
718 pict.linesize[2] = vp->bmp->pitches[1];
720 for (i = 0; i < sp->sub.num_rects; i++)
721 blend_subrect(&pict, &sp->sub.rects[i]);
723 SDL_UnlockYUVOverlay (vp->bmp);
729 /* XXX: we suppose the screen has a 1.0 pixel ratio */
730 height = is->height;
731 width = ((int)rint(height * aspect_ratio)) & -3;
732 if (width > is->width) {
733 width = is->width;
734 height = ((int)rint(width / aspect_ratio)) & -3;
736 x = (is->width - width) / 2;
737 y = (is->height - height) / 2;
738 if (!is->no_background) {
739 /* fill the background */
740 // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
741 } else {
742 is->no_background = 0;
744 rect.x = is->xleft + x;
745 rect.y = is->ytop + y;
746 rect.w = width;
747 rect.h = height;
748 SDL_DisplayYUVOverlay(vp->bmp, &rect);
749 } else {
750 #if 0
751 fill_rectangle(screen,
752 is->xleft, is->ytop, is->width, is->height,
753 QERGB(0x00, 0x00, 0x00));
754 #endif
758 static inline int compute_mod(int a, int b)
760 a = a % b;
761 if (a >= 0)
762 return a;
763 else
764 return a + b;
767 static void video_audio_display(VideoState *s)
769 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
770 int ch, channels, h, h2, bgcolor, fgcolor;
771 int16_t time_diff;
773 /* compute display index : center on currently output samples */
774 channels = s->audio_st->codec->channels;
775 nb_display_channels = channels;
776 if (!s->paused) {
777 n = 2 * channels;
778 delay = audio_write_get_buf_size(s);
779 delay /= n;
781 /* to be more precise, we take into account the time spent since
782 the last buffer computation */
783 if (audio_callback_time) {
784 time_diff = av_gettime() - audio_callback_time;
785 delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
788 delay -= s->width / 2;
789 if (delay < s->width)
790 delay = s->width;
792 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
794 h= INT_MIN;
795 for(i=0; i<1000; i+=channels){
796 int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
797 int a= s->sample_array[idx];
798 int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
799 int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
800 int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
801 int score= a-d;
802 if(h<score && (b^c)<0){
803 h= score;
804 i_start= idx;
808 s->last_i_start = i_start;
809 } else {
810 i_start = s->last_i_start;
813 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
814 fill_rectangle(screen,
815 s->xleft, s->ytop, s->width, s->height,
816 bgcolor);
818 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
820 /* total height for one channel */
821 h = s->height / nb_display_channels;
822 /* graph height / 2 */
823 h2 = (h * 9) / 20;
824 for(ch = 0;ch < nb_display_channels; ch++) {
825 i = i_start + ch;
826 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
827 for(x = 0; x < s->width; x++) {
828 y = (s->sample_array[i] * h2) >> 15;
829 if (y < 0) {
830 y = -y;
831 ys = y1 - y;
832 } else {
833 ys = y1;
835 fill_rectangle(screen,
836 s->xleft + x, ys, 1, y,
837 fgcolor);
838 i += channels;
839 if (i >= SAMPLE_ARRAY_SIZE)
840 i -= SAMPLE_ARRAY_SIZE;
844 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
846 for(ch = 1;ch < nb_display_channels; ch++) {
847 y = s->ytop + ch * h;
848 fill_rectangle(screen,
849 s->xleft, y, s->width, 1,
850 fgcolor);
852 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
855 static int video_open(VideoState *is){
856 int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
857 int w,h;
859 if(is_full_screen) flags |= SDL_FULLSCREEN;
860 else flags |= SDL_RESIZABLE;
862 if (is_full_screen && fs_screen_width) {
863 w = fs_screen_width;
864 h = fs_screen_height;
865 } else if(!is_full_screen && screen_width){
866 w = screen_width;
867 h = screen_height;
868 }else if (is->video_st && is->video_st->codec->width){
869 w = is->video_st->codec->width;
870 h = is->video_st->codec->height;
871 } else {
872 w = 640;
873 h = 480;
875 #ifndef CONFIG_DARWIN
876 screen = SDL_SetVideoMode(w, h, 0, flags);
877 #else
878 /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
879 screen = SDL_SetVideoMode(w, h, 24, flags);
880 #endif
881 if (!screen) {
882 fprintf(stderr, "SDL: could not set video mode - exiting\n");
883 return -1;
885 SDL_WM_SetCaption("FFplay", "FFplay");
887 is->width = screen->w;
888 is->height = screen->h;
890 return 0;
893 /* display the current picture, if any */
894 static void video_display(VideoState *is)
896 if(!screen)
897 video_open(cur_stream);
898 if (is->audio_st && is->show_audio)
899 video_audio_display(is);
900 else if (is->video_st)
901 video_image_display(is);
904 static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
906 SDL_Event event;
907 event.type = FF_REFRESH_EVENT;
908 event.user.data1 = opaque;
909 SDL_PushEvent(&event);
910 return 0; /* 0 means stop timer */
913 /* schedule a video refresh in 'delay' ms */
914 static void schedule_refresh(VideoState *is, int delay)
916 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
919 /* get the current audio clock value */
920 static double get_audio_clock(VideoState *is)
922 double pts;
923 int hw_buf_size, bytes_per_sec;
924 pts = is->audio_clock;
925 hw_buf_size = audio_write_get_buf_size(is);
926 bytes_per_sec = 0;
927 if (is->audio_st) {
928 bytes_per_sec = is->audio_st->codec->sample_rate *
929 2 * is->audio_st->codec->channels;
931 if (bytes_per_sec)
932 pts -= (double)hw_buf_size / bytes_per_sec;
933 return pts;
936 /* get the current video clock value */
937 static double get_video_clock(VideoState *is)
939 double delta;
940 if (is->paused) {
941 delta = 0;
942 } else {
943 delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
945 return is->video_current_pts + delta;
948 /* get the current external clock value */
949 static double get_external_clock(VideoState *is)
951 int64_t ti;
952 ti = av_gettime();
953 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
956 /* get the current master clock value */
957 static double get_master_clock(VideoState *is)
959 double val;
961 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
962 if (is->video_st)
963 val = get_video_clock(is);
964 else
965 val = get_audio_clock(is);
966 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
967 if (is->audio_st)
968 val = get_audio_clock(is);
969 else
970 val = get_video_clock(is);
971 } else {
972 val = get_external_clock(is);
974 return val;
977 /* seek in the stream */
978 static void stream_seek(VideoState *is, int64_t pos, int rel)
980 if (!is->seek_req) {
981 is->seek_pos = pos;
982 is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
983 if (seek_by_bytes)
984 is->seek_flags |= AVSEEK_FLAG_BYTE;
985 is->seek_req = 1;
989 /* pause or resume the video */
990 static void stream_pause(VideoState *is)
992 is->paused = !is->paused;
993 if (!is->paused) {
994 is->video_current_pts = get_video_clock(is);
995 is->frame_timer += (av_gettime() - is->video_current_pts_time) / 1000000.0;
999 /* called to display each frame */
1000 static void video_refresh_timer(void *opaque)
1002 VideoState *is = opaque;
1003 VideoPicture *vp;
1004 double actual_delay, delay, sync_threshold, ref_clock, diff;
1006 SubPicture *sp, *sp2;
1008 if (is->video_st) {
1009 if (is->pictq_size == 0) {
1010 /* if no picture, need to wait */
1011 schedule_refresh(is, 1);
1012 } else {
1013 /* dequeue the picture */
1014 vp = &is->pictq[is->pictq_rindex];
1016 /* update current video pts */
1017 is->video_current_pts = vp->pts;
1018 is->video_current_pts_time = av_gettime();
1020 /* compute nominal delay */
1021 delay = vp->pts - is->frame_last_pts;
1022 if (delay <= 0 || delay >= 1.0) {
1023 /* if incorrect delay, use previous one */
1024 delay = is->frame_last_delay;
1026 is->frame_last_delay = delay;
1027 is->frame_last_pts = vp->pts;
1029 /* update delay to follow master synchronisation source */
1030 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1031 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1032 /* if video is slave, we try to correct big delays by
1033 duplicating or deleting a frame */
1034 ref_clock = get_master_clock(is);
1035 diff = vp->pts - ref_clock;
1037 /* skip or repeat frame. We take into account the
1038 delay to compute the threshold. I still don't know
1039 if it is the best guess */
1040 sync_threshold = AV_SYNC_THRESHOLD;
1041 if (delay > sync_threshold)
1042 sync_threshold = delay;
1043 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1044 if (diff <= -sync_threshold)
1045 delay = 0;
1046 else if (diff >= sync_threshold)
1047 delay = 2 * delay;
1051 is->frame_timer += delay;
1052 /* compute the REAL delay (we need to do that to avoid
1053 long term errors */
1054 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
1055 if (actual_delay < 0.010) {
1056 /* XXX: should skip picture */
1057 actual_delay = 0.010;
1059 /* launch timer for next picture */
1060 schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
1062 #if defined(DEBUG_SYNC)
1063 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
1064 delay, actual_delay, vp->pts, -diff);
1065 #endif
1067 if(is->subtitle_st) {
1068 if (is->subtitle_stream_changed) {
1069 SDL_LockMutex(is->subpq_mutex);
1071 while (is->subpq_size) {
1072 free_subpicture(&is->subpq[is->subpq_rindex]);
1074 /* update queue size and signal for next picture */
1075 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1076 is->subpq_rindex = 0;
1078 is->subpq_size--;
1080 is->subtitle_stream_changed = 0;
1082 SDL_CondSignal(is->subpq_cond);
1083 SDL_UnlockMutex(is->subpq_mutex);
1084 } else {
1085 if (is->subpq_size > 0) {
1086 sp = &is->subpq[is->subpq_rindex];
1088 if (is->subpq_size > 1)
1089 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1090 else
1091 sp2 = NULL;
1093 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1094 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1096 free_subpicture(sp);
1098 /* update queue size and signal for next picture */
1099 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1100 is->subpq_rindex = 0;
1102 SDL_LockMutex(is->subpq_mutex);
1103 is->subpq_size--;
1104 SDL_CondSignal(is->subpq_cond);
1105 SDL_UnlockMutex(is->subpq_mutex);
1111 /* display picture */
1112 video_display(is);
1114 /* update queue size and signal for next picture */
1115 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1116 is->pictq_rindex = 0;
1118 SDL_LockMutex(is->pictq_mutex);
1119 is->pictq_size--;
1120 SDL_CondSignal(is->pictq_cond);
1121 SDL_UnlockMutex(is->pictq_mutex);
1123 } else if (is->audio_st) {
1124 /* draw the next audio frame */
1126 schedule_refresh(is, 40);
1128 /* if only audio stream, then display the audio bars (better
1129 than nothing, just to test the implementation */
1131 /* display picture */
1132 video_display(is);
1133 } else {
1134 schedule_refresh(is, 100);
1136 if (show_status) {
1137 static int64_t last_time;
1138 int64_t cur_time;
1139 int aqsize, vqsize, sqsize;
1140 double av_diff;
1142 cur_time = av_gettime();
1143 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
1144 aqsize = 0;
1145 vqsize = 0;
1146 sqsize = 0;
1147 if (is->audio_st)
1148 aqsize = is->audioq.size;
1149 if (is->video_st)
1150 vqsize = is->videoq.size;
1151 if (is->subtitle_st)
1152 sqsize = is->subtitleq.size;
1153 av_diff = 0;
1154 if (is->audio_st && is->video_st)
1155 av_diff = get_audio_clock(is) - get_video_clock(is);
1156 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
1157 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
1158 fflush(stdout);
1159 last_time = cur_time;
1164 /* allocate a picture (needs to do that in main thread to avoid
1165 potential locking problems */
1166 static void alloc_picture(void *opaque)
1168 VideoState *is = opaque;
1169 VideoPicture *vp;
1171 vp = &is->pictq[is->pictq_windex];
1173 if (vp->bmp)
1174 SDL_FreeYUVOverlay(vp->bmp);
1176 #if 0
1177 /* XXX: use generic function */
1178 /* XXX: disable overlay if no hardware acceleration or if RGB format */
1179 switch(is->video_st->codec->pix_fmt) {
1180 case PIX_FMT_YUV420P:
1181 case PIX_FMT_YUV422P:
1182 case PIX_FMT_YUV444P:
1183 case PIX_FMT_YUYV422:
1184 case PIX_FMT_YUV410P:
1185 case PIX_FMT_YUV411P:
1186 is_yuv = 1;
1187 break;
1188 default:
1189 is_yuv = 0;
1190 break;
1192 #endif
1193 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1194 is->video_st->codec->height,
1195 SDL_YV12_OVERLAY,
1196 screen);
1197 vp->width = is->video_st->codec->width;
1198 vp->height = is->video_st->codec->height;
1200 SDL_LockMutex(is->pictq_mutex);
1201 vp->allocated = 1;
1202 SDL_CondSignal(is->pictq_cond);
1203 SDL_UnlockMutex(is->pictq_mutex);
1208 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1210 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
1212 VideoPicture *vp;
1213 int dst_pix_fmt;
1214 AVPicture pict;
1215 static struct SwsContext *img_convert_ctx;
1217 /* wait until we have space to put a new picture */
1218 SDL_LockMutex(is->pictq_mutex);
1219 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1220 !is->videoq.abort_request) {
1221 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1223 SDL_UnlockMutex(is->pictq_mutex);
1225 if (is->videoq.abort_request)
1226 return -1;
1228 vp = &is->pictq[is->pictq_windex];
1230 /* alloc or resize hardware picture buffer */
1231 if (!vp->bmp ||
1232 vp->width != is->video_st->codec->width ||
1233 vp->height != is->video_st->codec->height) {
1234 SDL_Event event;
1236 vp->allocated = 0;
1238 /* the allocation must be done in the main thread to avoid
1239 locking problems */
1240 event.type = FF_ALLOC_EVENT;
1241 event.user.data1 = is;
1242 SDL_PushEvent(&event);
1244 /* wait until the picture is allocated */
1245 SDL_LockMutex(is->pictq_mutex);
1246 while (!vp->allocated && !is->videoq.abort_request) {
1247 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1249 SDL_UnlockMutex(is->pictq_mutex);
1251 if (is->videoq.abort_request)
1252 return -1;
1255 /* if the frame is not skipped, then display it */
1256 if (vp->bmp) {
1257 /* get a pointer on the bitmap */
1258 SDL_LockYUVOverlay (vp->bmp);
1260 dst_pix_fmt = PIX_FMT_YUV420P;
1261 pict.data[0] = vp->bmp->pixels[0];
1262 pict.data[1] = vp->bmp->pixels[2];
1263 pict.data[2] = vp->bmp->pixels[1];
1265 pict.linesize[0] = vp->bmp->pitches[0];
1266 pict.linesize[1] = vp->bmp->pitches[2];
1267 pict.linesize[2] = vp->bmp->pitches[1];
1268 if (img_convert_ctx == NULL) {
1269 img_convert_ctx = sws_getContext(is->video_st->codec->width,
1270 is->video_st->codec->height, is->video_st->codec->pix_fmt,
1271 is->video_st->codec->width, is->video_st->codec->height,
1272 dst_pix_fmt, sws_flags, NULL, NULL, NULL);
1273 if (img_convert_ctx == NULL) {
1274 fprintf(stderr, "Cannot initialize the conversion context\n");
1275 exit(1);
1278 sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize,
1279 0, is->video_st->codec->height, pict.data, pict.linesize);
1280 /* update the bitmap content */
1281 SDL_UnlockYUVOverlay(vp->bmp);
1283 vp->pts = pts;
1285 /* now we can update the picture count */
1286 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1287 is->pictq_windex = 0;
1288 SDL_LockMutex(is->pictq_mutex);
1289 is->pictq_size++;
1290 SDL_UnlockMutex(is->pictq_mutex);
1292 return 0;
1296 * compute the exact PTS for the picture if it is omitted in the stream
1297 * @param pts1 the dts of the pkt / pts of the frame
1299 static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
1301 double frame_delay, pts;
1303 pts = pts1;
1305 if (pts != 0) {
1306 /* update video clock with pts, if present */
1307 is->video_clock = pts;
1308 } else {
1309 pts = is->video_clock;
1311 /* update video clock for next frame */
1312 frame_delay = av_q2d(is->video_st->codec->time_base);
1313 /* for MPEG2, the frame can be repeated, so we update the
1314 clock accordingly */
1315 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
1316 is->video_clock += frame_delay;
1318 #if defined(DEBUG_SYNC) && 0
1320 int ftype;
1321 if (src_frame->pict_type == FF_B_TYPE)
1322 ftype = 'B';
1323 else if (src_frame->pict_type == FF_I_TYPE)
1324 ftype = 'I';
1325 else
1326 ftype = 'P';
1327 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
1328 ftype, pts, pts1);
1330 #endif
1331 return queue_picture(is, src_frame, pts);
1334 static uint64_t global_video_pkt_pts= AV_NOPTS_VALUE;
1336 static int my_get_buffer(struct AVCodecContext *c, AVFrame *pic){
1337 int ret= avcodec_default_get_buffer(c, pic);
1338 uint64_t *pts= av_malloc(sizeof(uint64_t));
1339 *pts= global_video_pkt_pts;
1340 pic->opaque= pts;
1341 return ret;
1344 static void my_release_buffer(struct AVCodecContext *c, AVFrame *pic){
1345 if(pic) av_freep(&pic->opaque);
1346 avcodec_default_release_buffer(c, pic);
1349 static int video_thread(void *arg)
1351 VideoState *is = arg;
1352 AVPacket pkt1, *pkt = &pkt1;
1353 int len1, got_picture;
1354 AVFrame *frame= avcodec_alloc_frame();
1355 double pts;
1357 for(;;) {
1358 while (is->paused && !is->videoq.abort_request) {
1359 SDL_Delay(10);
1361 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1362 break;
1364 if(pkt->data == flush_pkt.data){
1365 avcodec_flush_buffers(is->video_st->codec);
1366 continue;
1369 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1370 this packet, if any */
1371 global_video_pkt_pts= pkt->pts;
1372 len1 = avcodec_decode_video(is->video_st->codec,
1373 frame, &got_picture,
1374 pkt->data, pkt->size);
1376 if( (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE)
1377 && frame->opaque && *(uint64_t*)frame->opaque != AV_NOPTS_VALUE)
1378 pts= *(uint64_t*)frame->opaque;
1379 else if(pkt->dts != AV_NOPTS_VALUE)
1380 pts= pkt->dts;
1381 else
1382 pts= 0;
1383 pts *= av_q2d(is->video_st->time_base);
1385 // if (len1 < 0)
1386 // break;
1387 if (got_picture) {
1388 if (output_picture2(is, frame, pts) < 0)
1389 goto the_end;
1391 av_free_packet(pkt);
1392 if (step)
1393 if (cur_stream)
1394 stream_pause(cur_stream);
1396 the_end:
1397 av_free(frame);
1398 return 0;
1401 static int subtitle_thread(void *arg)
1403 VideoState *is = arg;
1404 SubPicture *sp;
1405 AVPacket pkt1, *pkt = &pkt1;
1406 int len1, got_subtitle;
1407 double pts;
1408 int i, j;
1409 int r, g, b, y, u, v, a;
1411 for(;;) {
1412 while (is->paused && !is->subtitleq.abort_request) {
1413 SDL_Delay(10);
1415 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1416 break;
1418 if(pkt->data == flush_pkt.data){
1419 avcodec_flush_buffers(is->subtitle_st->codec);
1420 continue;
1422 SDL_LockMutex(is->subpq_mutex);
1423 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1424 !is->subtitleq.abort_request) {
1425 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1427 SDL_UnlockMutex(is->subpq_mutex);
1429 if (is->subtitleq.abort_request)
1430 goto the_end;
1432 sp = &is->subpq[is->subpq_windex];
1434 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1435 this packet, if any */
1436 pts = 0;
1437 if (pkt->pts != AV_NOPTS_VALUE)
1438 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1440 len1 = avcodec_decode_subtitle(is->subtitle_st->codec,
1441 &sp->sub, &got_subtitle,
1442 pkt->data, pkt->size);
1443 // if (len1 < 0)
1444 // break;
1445 if (got_subtitle && sp->sub.format == 0) {
1446 sp->pts = pts;
1448 for (i = 0; i < sp->sub.num_rects; i++)
1450 for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
1452 RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
1453 y = RGB_TO_Y_CCIR(r, g, b);
1454 u = RGB_TO_U_CCIR(r, g, b, 0);
1455 v = RGB_TO_V_CCIR(r, g, b, 0);
1456 YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
1460 /* now we can update the picture count */
1461 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1462 is->subpq_windex = 0;
1463 SDL_LockMutex(is->subpq_mutex);
1464 is->subpq_size++;
1465 SDL_UnlockMutex(is->subpq_mutex);
1467 av_free_packet(pkt);
1468 // if (step)
1469 // if (cur_stream)
1470 // stream_pause(cur_stream);
1472 the_end:
1473 return 0;
1476 /* copy samples for viewing in editor window */
1477 static void update_sample_display(VideoState *is, short *samples, int samples_size)
1479 int size, len, channels;
1481 channels = is->audio_st->codec->channels;
1483 size = samples_size / sizeof(short);
1484 while (size > 0) {
1485 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1486 if (len > size)
1487 len = size;
1488 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1489 samples += len;
1490 is->sample_array_index += len;
1491 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1492 is->sample_array_index = 0;
1493 size -= len;
1497 /* return the new audio buffer size (samples can be added or deleted
1498 to get better sync if video or external master clock) */
1499 static int synchronize_audio(VideoState *is, short *samples,
1500 int samples_size1, double pts)
1502 int n, samples_size;
1503 double ref_clock;
1505 n = 2 * is->audio_st->codec->channels;
1506 samples_size = samples_size1;
1508 /* if not master, then we try to remove or add samples to correct the clock */
1509 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
1510 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1511 double diff, avg_diff;
1512 int wanted_size, min_size, max_size, nb_samples;
1514 ref_clock = get_master_clock(is);
1515 diff = get_audio_clock(is) - ref_clock;
1517 if (diff < AV_NOSYNC_THRESHOLD) {
1518 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1519 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1520 /* not enough measures to have a correct estimate */
1521 is->audio_diff_avg_count++;
1522 } else {
1523 /* estimate the A-V difference */
1524 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1526 if (fabs(avg_diff) >= is->audio_diff_threshold) {
1527 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
1528 nb_samples = samples_size / n;
1530 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1531 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1532 if (wanted_size < min_size)
1533 wanted_size = min_size;
1534 else if (wanted_size > max_size)
1535 wanted_size = max_size;
1537 /* add or remove samples to correction the synchro */
1538 if (wanted_size < samples_size) {
1539 /* remove samples */
1540 samples_size = wanted_size;
1541 } else if (wanted_size > samples_size) {
1542 uint8_t *samples_end, *q;
1543 int nb;
1545 /* add samples */
1546 nb = (samples_size - wanted_size);
1547 samples_end = (uint8_t *)samples + samples_size - n;
1548 q = samples_end + n;
1549 while (nb > 0) {
1550 memcpy(q, samples_end, n);
1551 q += n;
1552 nb -= n;
1554 samples_size = wanted_size;
1557 #if 0
1558 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1559 diff, avg_diff, samples_size - samples_size1,
1560 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1561 #endif
1563 } else {
1564 /* too big difference : may be initial PTS errors, so
1565 reset A-V filter */
1566 is->audio_diff_avg_count = 0;
1567 is->audio_diff_cum = 0;
1571 return samples_size;
1574 /* decode one audio frame and returns its uncompressed size */
1575 static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, int buf_size, double *pts_ptr)
1577 AVPacket *pkt = &is->audio_pkt;
1578 int n, len1, data_size;
1579 double pts;
1581 for(;;) {
1582 /* NOTE: the audio packet can contain several frames */
1583 while (is->audio_pkt_size > 0) {
1584 data_size = buf_size;
1585 len1 = avcodec_decode_audio2(is->audio_st->codec,
1586 (int16_t *)audio_buf, &data_size,
1587 is->audio_pkt_data, is->audio_pkt_size);
1588 if (len1 < 0) {
1589 /* if error, we skip the frame */
1590 is->audio_pkt_size = 0;
1591 break;
1594 is->audio_pkt_data += len1;
1595 is->audio_pkt_size -= len1;
1596 if (data_size <= 0)
1597 continue;
1598 /* if no pts, then compute it */
1599 pts = is->audio_clock;
1600 *pts_ptr = pts;
1601 n = 2 * is->audio_st->codec->channels;
1602 is->audio_clock += (double)data_size /
1603 (double)(n * is->audio_st->codec->sample_rate);
1604 #if defined(DEBUG_SYNC)
1606 static double last_clock;
1607 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1608 is->audio_clock - last_clock,
1609 is->audio_clock, pts);
1610 last_clock = is->audio_clock;
1612 #endif
1613 return data_size;
1616 /* free the current packet */
1617 if (pkt->data)
1618 av_free_packet(pkt);
1620 if (is->paused || is->audioq.abort_request) {
1621 return -1;
1624 /* read next packet */
1625 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1626 return -1;
1627 if(pkt->data == flush_pkt.data){
1628 avcodec_flush_buffers(is->audio_st->codec);
1629 continue;
1632 is->audio_pkt_data = pkt->data;
1633 is->audio_pkt_size = pkt->size;
1635 /* if update the audio clock with the pts */
1636 if (pkt->pts != AV_NOPTS_VALUE) {
1637 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
1642 /* get the current audio output buffer size, in samples. With SDL, we
1643 cannot have a precise information */
1644 static int audio_write_get_buf_size(VideoState *is)
1646 return is->audio_buf_size - is->audio_buf_index;
1650 /* prepare a new audio buffer */
1651 void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1653 VideoState *is = opaque;
1654 int audio_size, len1;
1655 double pts;
1657 audio_callback_time = av_gettime();
1659 while (len > 0) {
1660 if (is->audio_buf_index >= is->audio_buf_size) {
1661 audio_size = audio_decode_frame(is, is->audio_buf, sizeof(is->audio_buf), &pts);
1662 if (audio_size < 0) {
1663 /* if error, just output silence */
1664 is->audio_buf_size = 1024;
1665 memset(is->audio_buf, 0, is->audio_buf_size);
1666 } else {
1667 if (is->show_audio)
1668 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1669 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
1670 pts);
1671 is->audio_buf_size = audio_size;
1673 is->audio_buf_index = 0;
1675 len1 = is->audio_buf_size - is->audio_buf_index;
1676 if (len1 > len)
1677 len1 = len;
1678 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1679 len -= len1;
1680 stream += len1;
1681 is->audio_buf_index += len1;
1685 /* open a given stream. Return 0 if OK */
1686 static int stream_component_open(VideoState *is, int stream_index)
1688 AVFormatContext *ic = is->ic;
1689 AVCodecContext *enc;
1690 AVCodec *codec;
1691 SDL_AudioSpec wanted_spec, spec;
1693 if (stream_index < 0 || stream_index >= ic->nb_streams)
1694 return -1;
1695 enc = ic->streams[stream_index]->codec;
1697 /* prepare audio output */
1698 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1699 wanted_spec.freq = enc->sample_rate;
1700 wanted_spec.format = AUDIO_S16SYS;
1701 /* hack for AC3. XXX: suppress that */
1702 if (enc->channels > 2)
1703 enc->channels = 2;
1704 wanted_spec.channels = enc->channels;
1705 wanted_spec.silence = 0;
1706 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1707 wanted_spec.callback = sdl_audio_callback;
1708 wanted_spec.userdata = is;
1709 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1710 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1711 return -1;
1713 is->audio_hw_buf_size = spec.size;
1716 codec = avcodec_find_decoder(enc->codec_id);
1717 enc->debug_mv = debug_mv;
1718 enc->debug = debug;
1719 enc->workaround_bugs = workaround_bugs;
1720 enc->lowres = lowres;
1721 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
1722 enc->idct_algo= idct;
1723 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
1724 enc->skip_frame= skip_frame;
1725 enc->skip_idct= skip_idct;
1726 enc->skip_loop_filter= skip_loop_filter;
1727 enc->error_resilience= error_resilience;
1728 enc->error_concealment= error_concealment;
1729 if (!codec ||
1730 avcodec_open(enc, codec) < 0)
1731 return -1;
1732 if(thread_count>1)
1733 avcodec_thread_init(enc, thread_count);
1734 enc->thread_count= thread_count;
1735 switch(enc->codec_type) {
1736 case CODEC_TYPE_AUDIO:
1737 is->audio_stream = stream_index;
1738 is->audio_st = ic->streams[stream_index];
1739 is->audio_buf_size = 0;
1740 is->audio_buf_index = 0;
1742 /* init averaging filter */
1743 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1744 is->audio_diff_avg_count = 0;
1745 /* since we do not have a precise anough audio fifo fullness,
1746 we correct audio sync only if larger than this threshold */
1747 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1749 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1750 packet_queue_init(&is->audioq);
1751 SDL_PauseAudio(0);
1752 break;
1753 case CODEC_TYPE_VIDEO:
1754 is->video_stream = stream_index;
1755 is->video_st = ic->streams[stream_index];
1757 is->frame_last_delay = 40e-3;
1758 is->frame_timer = (double)av_gettime() / 1000000.0;
1759 is->video_current_pts_time = av_gettime();
1761 packet_queue_init(&is->videoq);
1762 is->video_tid = SDL_CreateThread(video_thread, is);
1764 enc-> get_buffer= my_get_buffer;
1765 enc->release_buffer= my_release_buffer;
1766 break;
1767 case CODEC_TYPE_SUBTITLE:
1768 is->subtitle_stream = stream_index;
1769 is->subtitle_st = ic->streams[stream_index];
1770 packet_queue_init(&is->subtitleq);
1772 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1773 break;
1774 default:
1775 break;
1777 return 0;
1780 static void stream_component_close(VideoState *is, int stream_index)
1782 AVFormatContext *ic = is->ic;
1783 AVCodecContext *enc;
1785 if (stream_index < 0 || stream_index >= ic->nb_streams)
1786 return;
1787 enc = ic->streams[stream_index]->codec;
1789 switch(enc->codec_type) {
1790 case CODEC_TYPE_AUDIO:
1791 packet_queue_abort(&is->audioq);
1793 SDL_CloseAudio();
1795 packet_queue_end(&is->audioq);
1796 break;
1797 case CODEC_TYPE_VIDEO:
1798 packet_queue_abort(&is->videoq);
1800 /* note: we also signal this mutex to make sure we deblock the
1801 video thread in all cases */
1802 SDL_LockMutex(is->pictq_mutex);
1803 SDL_CondSignal(is->pictq_cond);
1804 SDL_UnlockMutex(is->pictq_mutex);
1806 SDL_WaitThread(is->video_tid, NULL);
1808 packet_queue_end(&is->videoq);
1809 break;
1810 case CODEC_TYPE_SUBTITLE:
1811 packet_queue_abort(&is->subtitleq);
1813 /* note: we also signal this mutex to make sure we deblock the
1814 video thread in all cases */
1815 SDL_LockMutex(is->subpq_mutex);
1816 is->subtitle_stream_changed = 1;
1818 SDL_CondSignal(is->subpq_cond);
1819 SDL_UnlockMutex(is->subpq_mutex);
1821 SDL_WaitThread(is->subtitle_tid, NULL);
1823 packet_queue_end(&is->subtitleq);
1824 break;
1825 default:
1826 break;
1829 avcodec_close(enc);
1830 switch(enc->codec_type) {
1831 case CODEC_TYPE_AUDIO:
1832 is->audio_st = NULL;
1833 is->audio_stream = -1;
1834 break;
1835 case CODEC_TYPE_VIDEO:
1836 is->video_st = NULL;
1837 is->video_stream = -1;
1838 break;
1839 case CODEC_TYPE_SUBTITLE:
1840 is->subtitle_st = NULL;
1841 is->subtitle_stream = -1;
1842 break;
1843 default:
1844 break;
1848 static void dump_stream_info(const AVFormatContext *s)
1850 if (s->track != 0)
1851 fprintf(stderr, "Track: %d\n", s->track);
1852 if (s->title[0] != '\0')
1853 fprintf(stderr, "Title: %s\n", s->title);
1854 if (s->author[0] != '\0')
1855 fprintf(stderr, "Author: %s\n", s->author);
1856 if (s->copyright[0] != '\0')
1857 fprintf(stderr, "Copyright: %s\n", s->copyright);
1858 if (s->comment[0] != '\0')
1859 fprintf(stderr, "Comment: %s\n", s->comment);
1860 if (s->album[0] != '\0')
1861 fprintf(stderr, "Album: %s\n", s->album);
1862 if (s->year != 0)
1863 fprintf(stderr, "Year: %d\n", s->year);
1864 if (s->genre[0] != '\0')
1865 fprintf(stderr, "Genre: %s\n", s->genre);
1868 /* since we have only one decoding thread, we can use a global
1869 variable instead of a thread local variable */
1870 static VideoState *global_video_state;
1872 static int decode_interrupt_cb(void)
1874 return (global_video_state && global_video_state->abort_request);
1877 /* this thread gets the stream from the disk or the network */
1878 static int decode_thread(void *arg)
1880 VideoState *is = arg;
1881 AVFormatContext *ic;
1882 int err, i, ret, video_index, audio_index, use_play;
1883 AVPacket pkt1, *pkt = &pkt1;
1884 AVFormatParameters params, *ap = &params;
1886 video_index = -1;
1887 audio_index = -1;
1888 is->video_stream = -1;
1889 is->audio_stream = -1;
1890 is->subtitle_stream = -1;
1892 global_video_state = is;
1893 url_set_interrupt_cb(decode_interrupt_cb);
1895 memset(ap, 0, sizeof(*ap));
1896 ap->initial_pause = 1; /* we force a pause when starting an RTSP
1897 stream */
1899 ap->width = frame_width;
1900 ap->height= frame_height;
1901 ap->time_base= (AVRational){1, 25};
1902 ap->pix_fmt = frame_pix_fmt;
1904 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
1905 if (err < 0) {
1906 print_error(is->filename, err);
1907 ret = -1;
1908 goto fail;
1910 is->ic = ic;
1911 #ifdef CONFIG_RTSP_DEMUXER
1912 use_play = (ic->iformat == &rtsp_demuxer);
1913 #else
1914 use_play = 0;
1915 #endif
1917 if(genpts)
1918 ic->flags |= AVFMT_FLAG_GENPTS;
1920 if (!use_play) {
1921 err = av_find_stream_info(ic);
1922 if (err < 0) {
1923 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1924 ret = -1;
1925 goto fail;
1927 ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
1930 /* if seeking requested, we execute it */
1931 if (start_time != AV_NOPTS_VALUE) {
1932 int64_t timestamp;
1934 timestamp = start_time;
1935 /* add the stream start time */
1936 if (ic->start_time != AV_NOPTS_VALUE)
1937 timestamp += ic->start_time;
1938 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1939 if (ret < 0) {
1940 fprintf(stderr, "%s: could not seek to position %0.3f\n",
1941 is->filename, (double)timestamp / AV_TIME_BASE);
1945 /* now we can begin to play (RTSP stream only) */
1946 av_read_play(ic);
1948 if (use_play) {
1949 err = av_find_stream_info(ic);
1950 if (err < 0) {
1951 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1952 ret = -1;
1953 goto fail;
1957 for(i = 0; i < ic->nb_streams; i++) {
1958 AVCodecContext *enc = ic->streams[i]->codec;
1959 switch(enc->codec_type) {
1960 case CODEC_TYPE_AUDIO:
1961 if ((audio_index < 0 || wanted_audio_stream-- > 0) && !audio_disable)
1962 audio_index = i;
1963 break;
1964 case CODEC_TYPE_VIDEO:
1965 if (video_index < 0 && !video_disable)
1966 video_index = i;
1967 break;
1968 default:
1969 break;
1972 if (show_status) {
1973 dump_format(ic, 0, is->filename, 0);
1974 dump_stream_info(ic);
1977 /* open the streams */
1978 if (audio_index >= 0) {
1979 stream_component_open(is, audio_index);
1982 if (video_index >= 0) {
1983 stream_component_open(is, video_index);
1984 } else {
1985 if (!display_disable)
1986 is->show_audio = 1;
1989 if (is->video_stream < 0 && is->audio_stream < 0) {
1990 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1991 ret = -1;
1992 goto fail;
1995 for(;;) {
1996 if (is->abort_request)
1997 break;
1998 if (is->paused != is->last_paused) {
1999 is->last_paused = is->paused;
2000 if (is->paused)
2001 av_read_pause(ic);
2002 else
2003 av_read_play(ic);
2005 #ifdef CONFIG_RTSP_DEMUXER
2006 if (is->paused && ic->iformat == &rtsp_demuxer) {
2007 /* wait 10 ms to avoid trying to get another packet */
2008 /* XXX: horrible */
2009 SDL_Delay(10);
2010 continue;
2012 #endif
2013 if (is->seek_req) {
2014 int stream_index= -1;
2015 int64_t seek_target= is->seek_pos;
2017 if (is-> video_stream >= 0) stream_index= is-> video_stream;
2018 else if(is-> audio_stream >= 0) stream_index= is-> audio_stream;
2019 else if(is->subtitle_stream >= 0) stream_index= is->subtitle_stream;
2021 if(stream_index>=0){
2022 seek_target= av_rescale_q(seek_target, AV_TIME_BASE_Q, ic->streams[stream_index]->time_base);
2025 ret = av_seek_frame(is->ic, stream_index, seek_target, is->seek_flags);
2026 if (ret < 0) {
2027 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
2028 }else{
2029 if (is->audio_stream >= 0) {
2030 packet_queue_flush(&is->audioq);
2031 packet_queue_put(&is->audioq, &flush_pkt);
2033 if (is->subtitle_stream >= 0) {
2034 packet_queue_flush(&is->subtitleq);
2035 packet_queue_put(&is->subtitleq, &flush_pkt);
2037 if (is->video_stream >= 0) {
2038 packet_queue_flush(&is->videoq);
2039 packet_queue_put(&is->videoq, &flush_pkt);
2042 is->seek_req = 0;
2045 /* if the queue are full, no need to read more */
2046 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
2047 is->videoq.size > MAX_VIDEOQ_SIZE ||
2048 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
2049 url_feof(&ic->pb)) {
2050 /* wait 10 ms */
2051 SDL_Delay(10);
2052 continue;
2054 ret = av_read_frame(ic, pkt);
2055 if (ret < 0) {
2056 if (url_ferror(&ic->pb) == 0) {
2057 SDL_Delay(100); /* wait for user event */
2058 continue;
2059 } else
2060 break;
2062 if (pkt->stream_index == is->audio_stream) {
2063 packet_queue_put(&is->audioq, pkt);
2064 } else if (pkt->stream_index == is->video_stream) {
2065 packet_queue_put(&is->videoq, pkt);
2066 } else if (pkt->stream_index == is->subtitle_stream) {
2067 packet_queue_put(&is->subtitleq, pkt);
2068 } else {
2069 av_free_packet(pkt);
2072 /* wait until the end */
2073 while (!is->abort_request) {
2074 SDL_Delay(100);
2077 ret = 0;
2078 fail:
2079 /* disable interrupting */
2080 global_video_state = NULL;
2082 /* close each stream */
2083 if (is->audio_stream >= 0)
2084 stream_component_close(is, is->audio_stream);
2085 if (is->video_stream >= 0)
2086 stream_component_close(is, is->video_stream);
2087 if (is->subtitle_stream >= 0)
2088 stream_component_close(is, is->subtitle_stream);
2089 if (is->ic) {
2090 av_close_input_file(is->ic);
2091 is->ic = NULL; /* safety */
2093 url_set_interrupt_cb(NULL);
2095 if (ret != 0) {
2096 SDL_Event event;
2098 event.type = FF_QUIT_EVENT;
2099 event.user.data1 = is;
2100 SDL_PushEvent(&event);
2102 return 0;
2105 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
2107 VideoState *is;
2109 is = av_mallocz(sizeof(VideoState));
2110 if (!is)
2111 return NULL;
2112 pstrcpy(is->filename, sizeof(is->filename), filename);
2113 is->iformat = iformat;
2114 is->ytop = 0;
2115 is->xleft = 0;
2117 /* start video display */
2118 is->pictq_mutex = SDL_CreateMutex();
2119 is->pictq_cond = SDL_CreateCond();
2121 is->subpq_mutex = SDL_CreateMutex();
2122 is->subpq_cond = SDL_CreateCond();
2124 /* add the refresh timer to draw the picture */
2125 schedule_refresh(is, 40);
2127 is->av_sync_type = av_sync_type;
2128 is->parse_tid = SDL_CreateThread(decode_thread, is);
2129 if (!is->parse_tid) {
2130 av_free(is);
2131 return NULL;
2133 return is;
2136 static void stream_close(VideoState *is)
2138 VideoPicture *vp;
2139 int i;
2140 /* XXX: use a special url_shutdown call to abort parse cleanly */
2141 is->abort_request = 1;
2142 SDL_WaitThread(is->parse_tid, NULL);
2144 /* free all pictures */
2145 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2146 vp = &is->pictq[i];
2147 if (vp->bmp) {
2148 SDL_FreeYUVOverlay(vp->bmp);
2149 vp->bmp = NULL;
2152 SDL_DestroyMutex(is->pictq_mutex);
2153 SDL_DestroyCond(is->pictq_cond);
2154 SDL_DestroyMutex(is->subpq_mutex);
2155 SDL_DestroyCond(is->subpq_cond);
2158 static void stream_cycle_channel(VideoState *is, int codec_type)
2160 AVFormatContext *ic = is->ic;
2161 int start_index, stream_index;
2162 AVStream *st;
2164 if (codec_type == CODEC_TYPE_VIDEO)
2165 start_index = is->video_stream;
2166 else if (codec_type == CODEC_TYPE_AUDIO)
2167 start_index = is->audio_stream;
2168 else
2169 start_index = is->subtitle_stream;
2170 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
2171 return;
2172 stream_index = start_index;
2173 for(;;) {
2174 if (++stream_index >= is->ic->nb_streams)
2176 if (codec_type == CODEC_TYPE_SUBTITLE)
2178 stream_index = -1;
2179 goto the_end;
2180 } else
2181 stream_index = 0;
2183 if (stream_index == start_index)
2184 return;
2185 st = ic->streams[stream_index];
2186 if (st->codec->codec_type == codec_type) {
2187 /* check that parameters are OK */
2188 switch(codec_type) {
2189 case CODEC_TYPE_AUDIO:
2190 if (st->codec->sample_rate != 0 &&
2191 st->codec->channels != 0)
2192 goto the_end;
2193 break;
2194 case CODEC_TYPE_VIDEO:
2195 case CODEC_TYPE_SUBTITLE:
2196 goto the_end;
2197 default:
2198 break;
2202 the_end:
2203 stream_component_close(is, start_index);
2204 stream_component_open(is, stream_index);
2208 static void toggle_full_screen(void)
2210 is_full_screen = !is_full_screen;
2211 if (!fs_screen_width) {
2212 /* use default SDL method */
2213 // SDL_WM_ToggleFullScreen(screen);
2215 video_open(cur_stream);
2218 static void toggle_pause(void)
2220 if (cur_stream)
2221 stream_pause(cur_stream);
2222 step = 0;
2225 static void step_to_next_frame(void)
2227 if (cur_stream) {
2228 if (cur_stream->paused)
2229 cur_stream->paused=0;
2230 cur_stream->video_current_pts = get_video_clock(cur_stream);
2232 step = 1;
2235 static void do_exit(void)
2237 if (cur_stream) {
2238 stream_close(cur_stream);
2239 cur_stream = NULL;
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), incr);
2321 break;
2322 default:
2323 break;
2325 break;
2326 case SDL_MOUSEBUTTONDOWN:
2327 if (cur_stream) {
2328 int ns, hh, mm, ss;
2329 int tns, thh, tmm, tss;
2330 tns = cur_stream->ic->duration/1000000LL;
2331 thh = tns/3600;
2332 tmm = (tns%3600)/60;
2333 tss = (tns%60);
2334 frac = (double)event.button.x/(double)cur_stream->width;
2335 ns = frac*tns;
2336 hh = ns/3600;
2337 mm = (ns%3600)/60;
2338 ss = (ns%60);
2339 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2340 hh, mm, ss, thh, tmm, tss);
2341 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
2343 break;
2344 case SDL_VIDEORESIZE:
2345 if (cur_stream) {
2346 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2347 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2348 screen_width = cur_stream->width = event.resize.w;
2349 screen_height= cur_stream->height= event.resize.h;
2351 break;
2352 case SDL_QUIT:
2353 case FF_QUIT_EVENT:
2354 do_exit();
2355 break;
2356 case FF_ALLOC_EVENT:
2357 video_open(event.user.data1);
2358 alloc_picture(event.user.data1);
2359 break;
2360 case FF_REFRESH_EVENT:
2361 video_refresh_timer(event.user.data1);
2362 break;
2363 default:
2364 break;
2369 static void opt_frame_size(const char *arg)
2371 if (parse_image_size(&frame_width, &frame_height, arg) < 0) {
2372 fprintf(stderr, "Incorrect frame size\n");
2373 exit(1);
2375 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2376 fprintf(stderr, "Frame size must be a multiple of 2\n");
2377 exit(1);
2381 static void opt_width(const char *arg)
2383 screen_width = atoi(arg);
2384 if(screen_width<=0){
2385 fprintf(stderr, "invalid width\n");
2386 exit(1);
2390 static void opt_height(const char *arg)
2392 screen_height = atoi(arg);
2393 if(screen_height<=0){
2394 fprintf(stderr, "invalid height\n");
2395 exit(1);
2399 static void opt_format(const char *arg)
2401 file_iformat = av_find_input_format(arg);
2402 if (!file_iformat) {
2403 fprintf(stderr, "Unknown input format: %s\n", arg);
2404 exit(1);
2408 static void opt_frame_pix_fmt(const char *arg)
2410 frame_pix_fmt = avcodec_get_pix_fmt(arg);
2413 #ifdef CONFIG_RTSP_DEMUXER
2414 static void opt_rtp_tcp(void)
2416 /* only tcp protocol */
2417 rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
2419 #endif
2421 static void opt_sync(const char *arg)
2423 if (!strcmp(arg, "audio"))
2424 av_sync_type = AV_SYNC_AUDIO_MASTER;
2425 else if (!strcmp(arg, "video"))
2426 av_sync_type = AV_SYNC_VIDEO_MASTER;
2427 else if (!strcmp(arg, "ext"))
2428 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2429 else
2430 show_help();
2433 static void opt_seek(const char *arg)
2435 start_time = parse_date(arg, 1);
2438 static void opt_debug(const char *arg)
2440 av_log_level = 99;
2441 debug = atoi(arg);
2444 static void opt_vismv(const char *arg)
2446 debug_mv = atoi(arg);
2449 static void opt_thread_count(const char *arg)
2451 thread_count= atoi(arg);
2452 #if !defined(HAVE_THREADS)
2453 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2454 #endif
2457 const OptionDef options[] = {
2458 { "h", 0, {(void*)show_help}, "show help" },
2459 { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
2460 { "y", HAS_ARG, {(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}, "", "" },
2466 { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
2467 { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
2468 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2469 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
2470 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
2471 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
2472 { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
2473 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
2474 { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
2475 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
2476 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
2477 { "drp", OPT_BOOL |OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts", ""},
2478 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
2479 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2480 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2481 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
2482 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
2483 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
2484 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
2485 #ifdef CONFIG_RTSP_DEMUXER
2486 { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
2487 #endif
2488 { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2489 { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
2490 { NULL, },
2493 void show_help(void)
2495 printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003-2006 Fabrice Bellard, et al.\n"
2496 "usage: ffplay [options] input_file\n"
2497 "Simple media player\n");
2498 printf("\n");
2499 show_help_options(options, "Main options:\n",
2500 OPT_EXPERT, 0);
2501 show_help_options(options, "\nAdvanced options:\n",
2502 OPT_EXPERT, OPT_EXPERT);
2503 printf("\nWhile playing:\n"
2504 "q, ESC quit\n"
2505 "f toggle full screen\n"
2506 "p, SPC pause\n"
2507 "a cycle audio channel\n"
2508 "v cycle video channel\n"
2509 "t cycle subtitle channel\n"
2510 "w show audio waves\n"
2511 "left/right seek backward/forward 10 seconds\n"
2512 "down/up seek backward/forward 1 minute\n"
2513 "mouse click seek to percentage in file corresponding to fraction of width\n"
2515 exit(1);
2518 void parse_arg_file(const char *filename)
2520 if (!strcmp(filename, "-"))
2521 filename = "pipe:";
2522 input_filename = filename;
2525 /* Called from the main */
2526 int main(int argc, char **argv)
2528 int flags;
2530 /* register all codecs, demux and protocols */
2531 av_register_all();
2533 #ifdef CONFIG_OS2
2534 MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
2536 // Make stdout and stderr unbuffered
2537 setbuf( stdout, NULL );
2538 setbuf( stderr, NULL );
2539 #endif
2541 parse_options(argc, argv, options);
2543 if (!input_filename)
2544 show_help();
2546 if (display_disable) {
2547 video_disable = 1;
2549 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
2550 #if !defined(__MINGW32__) && !defined(CONFIG_DARWIN)
2551 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 or darwin */
2552 #endif
2553 if (SDL_Init (flags)) {
2554 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
2555 exit(1);
2558 if (!display_disable) {
2559 #ifdef HAVE_SDL_VIDEO_SIZE
2560 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2561 fs_screen_width = vi->current_w;
2562 fs_screen_height = vi->current_h;
2563 #endif
2566 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2567 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2568 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2569 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2571 av_init_packet(&flush_pkt);
2572 flush_pkt.data= "FLUSH";
2574 cur_stream = stream_open(input_filename, file_iformat);
2576 event_loop();
2578 /* never returns */
2580 return 0;