aarch64: Add assembly support for -fsanitize=hwaddress tagged globals.
[libav.git] / avtools / avplay.c
blobb6dbc52cf7222819714394df262fab3603580beb
1 /*
2 * avplay : Simple Media Player based on the Libav libraries
3 * Copyright (c) 2003 Fabrice Bellard
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "config.h"
23 #include <inttypes.h>
24 #include <math.h>
25 #include <limits.h>
26 #include <stdint.h>
28 #include "libavutil/avstring.h"
29 #include "libavutil/colorspace.h"
30 #include "libavutil/display.h"
31 #include "libavutil/mathematics.h"
32 #include "libavutil/pixdesc.h"
33 #include "libavutil/imgutils.h"
34 #include "libavutil/dict.h"
35 #include "libavutil/parseutils.h"
36 #include "libavutil/samplefmt.h"
37 #include "libavutil/time.h"
38 #include "libavformat/avformat.h"
39 #include "libavdevice/avdevice.h"
40 #include "libavresample/avresample.h"
41 #include "libavutil/opt.h"
42 #include "libavcodec/avfft.h"
44 #include "libavfilter/avfilter.h"
45 #include "libavfilter/buffersink.h"
46 #include "libavfilter/buffersrc.h"
48 #include "cmdutils.h"
50 #include <SDL.h>
51 #include <SDL_thread.h>
53 #ifdef __MINGW32__
54 #undef main /* We don't want SDL to override our main() */
55 #endif
57 #include <assert.h>
59 const char program_name[] = "avplay";
60 const int program_birth_year = 2003;
62 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
63 #define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
64 #define MIN_FRAMES 5
66 /* SDL audio buffer size, in samples. Should be small to have precise
67 A/V sync as SDL does not have hardware buffer fullness info. */
68 #define SDL_AUDIO_BUFFER_SIZE 1024
70 /* no AV sync correction is done if below the AV sync threshold */
71 #define AV_SYNC_THRESHOLD 0.01
72 /* no AV correction is done if too big error */
73 #define AV_NOSYNC_THRESHOLD 10.0
75 #define FRAME_SKIP_FACTOR 0.05
77 /* maximum audio speed change to get correct sync */
78 #define SAMPLE_CORRECTION_PERCENT_MAX 10
80 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
81 #define AUDIO_DIFF_AVG_NB 20
83 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
84 #define SAMPLE_ARRAY_SIZE (2 * 65536)
86 static int64_t sws_flags = SWS_BICUBIC;
88 typedef struct PacketQueue {
89 AVPacketList *first_pkt, *last_pkt;
90 int nb_packets;
91 int size;
92 int abort_request;
93 SDL_mutex *mutex;
94 SDL_cond *cond;
95 } PacketQueue;
97 #define VIDEO_PICTURE_QUEUE_SIZE 2
98 #define SUBPICTURE_QUEUE_SIZE 4
100 typedef struct VideoPicture {
101 double pts; // presentation timestamp for this picture
102 double target_clock; // av_gettime_relative() time at which this should be displayed ideally
103 int64_t pos; // byte position in file
104 SDL_Overlay *bmp;
105 int width, height; /* source height & width */
106 int allocated;
107 int reallocate;
108 enum AVPixelFormat pix_fmt;
110 AVRational sar;
111 } VideoPicture;
113 typedef struct SubPicture {
114 double pts; /* presentation time stamp for this picture */
115 AVSubtitle sub;
116 } SubPicture;
118 enum {
119 AV_SYNC_AUDIO_MASTER, /* default choice */
120 AV_SYNC_VIDEO_MASTER,
121 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
124 typedef struct PlayerState {
125 SDL_Thread *parse_tid;
126 SDL_Thread *video_tid;
127 SDL_Thread *refresh_tid;
128 AVInputFormat *iformat;
129 int no_background;
130 int abort_request;
131 int paused;
132 int last_paused;
133 int seek_req;
134 int seek_flags;
135 int64_t seek_pos;
136 int64_t seek_rel;
137 int read_pause_return;
138 AVFormatContext *ic;
140 int audio_stream;
142 int av_sync_type;
143 double external_clock; /* external clock base */
144 int64_t external_clock_time;
146 double audio_clock;
147 double audio_diff_cum; /* used for AV difference average computation */
148 double audio_diff_avg_coef;
149 double audio_diff_threshold;
150 int audio_diff_avg_count;
151 AVStream *audio_st;
152 AVCodecContext *audio_dec;
153 PacketQueue audioq;
154 int audio_hw_buf_size;
155 uint8_t silence_buf[SDL_AUDIO_BUFFER_SIZE];
156 uint8_t *audio_buf;
157 uint8_t *audio_buf1;
158 unsigned int audio_buf_size; /* in bytes */
159 int audio_buf_index; /* in bytes */
160 AVPacket audio_pkt_temp;
161 AVPacket audio_pkt;
162 enum AVSampleFormat sdl_sample_fmt;
163 uint64_t sdl_channel_layout;
164 int sdl_channels;
165 int sdl_sample_rate;
166 enum AVSampleFormat resample_sample_fmt;
167 uint64_t resample_channel_layout;
168 int resample_sample_rate;
169 AVAudioResampleContext *avr;
170 AVFrame *frame;
172 int show_audio; /* if true, display audio samples */
173 int16_t sample_array[SAMPLE_ARRAY_SIZE];
174 int sample_array_index;
175 int last_i_start;
176 RDFTContext *rdft;
177 int rdft_bits;
178 FFTSample *rdft_data;
179 int xpos;
181 SDL_Thread *subtitle_tid;
182 int subtitle_stream;
183 int subtitle_stream_changed;
184 AVStream *subtitle_st;
185 AVCodecContext *subtitle_dec;
186 PacketQueue subtitleq;
187 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
188 int subpq_size, subpq_rindex, subpq_windex;
189 SDL_mutex *subpq_mutex;
190 SDL_cond *subpq_cond;
192 double frame_timer;
193 double frame_last_pts;
194 double frame_last_delay;
195 double video_clock; // pts of last decoded frame / predicted pts of next decoded frame
196 int video_stream;
197 AVStream *video_st;
198 AVCodecContext *video_dec;
199 PacketQueue videoq;
200 double video_current_pts; // current displayed pts (different from video_clock if frame fifos are used)
201 double video_current_pts_drift; // video_current_pts - time (av_gettime_relative) at which we updated video_current_pts - used to have running video pts
202 int64_t video_current_pos; // current displayed file pos
203 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
204 int pictq_size, pictq_rindex, pictq_windex;
205 SDL_mutex *pictq_mutex;
206 SDL_cond *pictq_cond;
208 // QETimer *video_timer;
209 char filename[1024];
210 int width, height, xleft, ytop;
212 PtsCorrectionContext pts_ctx;
214 AVFilterContext *in_video_filter; // the first filter in the video chain
215 AVFilterContext *out_video_filter; // the last filter in the video chain
216 SDL_mutex *video_filter_mutex;
218 float skip_frames;
219 float skip_frames_index;
220 int refresh;
222 SpecifierOpt *codec_names;
223 int nb_codec_names;
224 } PlayerState;
226 /* options specified by the user */
227 static AVInputFormat *file_iformat;
228 static const char *input_filename;
229 static const char *window_title;
230 static int fs_screen_width;
231 static int fs_screen_height;
232 static int screen_width = 0;
233 static int screen_height = 0;
234 static int audio_disable;
235 static int video_disable;
236 static int wanted_stream[AVMEDIA_TYPE_NB] = {
237 [AVMEDIA_TYPE_AUDIO] = -1,
238 [AVMEDIA_TYPE_VIDEO] = -1,
239 [AVMEDIA_TYPE_SUBTITLE] = -1,
241 static int seek_by_bytes = -1;
242 static int display_disable;
243 static int show_status = 1;
244 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
245 static int64_t start_time = AV_NOPTS_VALUE;
246 static int64_t duration = AV_NOPTS_VALUE;
247 static int step = 0;
248 static int workaround_bugs = 1;
249 static int fast = 0;
250 static int genpts = 0;
251 static int idct = FF_IDCT_AUTO;
252 static enum AVDiscard skip_frame = AVDISCARD_DEFAULT;
253 static enum AVDiscard skip_idct = AVDISCARD_DEFAULT;
254 static enum AVDiscard skip_loop_filter = AVDISCARD_DEFAULT;
255 static int error_concealment = 3;
256 static int decoder_reorder_pts = -1;
257 static int noautoexit;
258 static int exit_on_keydown;
259 static int exit_on_mousedown;
260 static int loop = 1;
261 static int framedrop = 1;
262 static int infinite_buffer = 0;
264 static int rdftspeed = 20;
265 static char *vfilters = NULL;
266 static int autorotate = 1;
268 /* current context */
269 static int is_full_screen;
270 static PlayerState player_state;
271 static PlayerState *player = &player_state;
272 static int64_t audio_callback_time;
274 static AVPacket flush_pkt;
276 #define FF_ALLOC_EVENT (SDL_USEREVENT)
277 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
278 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
280 static SDL_Surface *screen;
282 static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
284 /* packet queue handling */
285 static void packet_queue_init(PacketQueue *q)
287 memset(q, 0, sizeof(PacketQueue));
288 q->mutex = SDL_CreateMutex();
289 q->cond = SDL_CreateCond();
290 packet_queue_put(q, &flush_pkt);
293 static void packet_queue_flush(PacketQueue *q)
295 AVPacketList *pkt, *pkt1;
297 SDL_LockMutex(q->mutex);
298 for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
299 pkt1 = pkt->next;
300 av_packet_unref(&pkt->pkt);
301 av_freep(&pkt);
303 q->last_pkt = NULL;
304 q->first_pkt = NULL;
305 q->nb_packets = 0;
306 q->size = 0;
307 SDL_UnlockMutex(q->mutex);
310 static void packet_queue_end(PacketQueue *q)
312 packet_queue_flush(q);
313 SDL_DestroyMutex(q->mutex);
314 SDL_DestroyCond(q->cond);
317 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
319 AVPacketList *pkt1;
321 pkt1 = av_malloc(sizeof(AVPacketList));
322 if (!pkt1)
323 return -1;
324 pkt1->pkt = *pkt;
325 pkt1->next = NULL;
328 SDL_LockMutex(q->mutex);
330 if (!q->last_pkt)
332 q->first_pkt = pkt1;
333 else
334 q->last_pkt->next = pkt1;
335 q->last_pkt = pkt1;
336 q->nb_packets++;
337 q->size += pkt1->pkt.size + sizeof(*pkt1);
338 /* XXX: should duplicate packet data in DV case */
339 SDL_CondSignal(q->cond);
341 SDL_UnlockMutex(q->mutex);
342 return 0;
345 static void packet_queue_abort(PacketQueue *q)
347 SDL_LockMutex(q->mutex);
349 q->abort_request = 1;
351 SDL_CondSignal(q->cond);
353 SDL_UnlockMutex(q->mutex);
356 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
357 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
359 AVPacketList *pkt1;
360 int ret;
362 SDL_LockMutex(q->mutex);
364 for (;;) {
365 if (q->abort_request) {
366 ret = -1;
367 break;
370 pkt1 = q->first_pkt;
371 if (pkt1) {
372 q->first_pkt = pkt1->next;
373 if (!q->first_pkt)
374 q->last_pkt = NULL;
375 q->nb_packets--;
376 q->size -= pkt1->pkt.size + sizeof(*pkt1);
377 *pkt = pkt1->pkt;
378 av_free(pkt1);
379 ret = 1;
380 break;
381 } else if (!block) {
382 ret = 0;
383 break;
384 } else {
385 SDL_CondWait(q->cond, q->mutex);
388 SDL_UnlockMutex(q->mutex);
389 return ret;
392 static inline void fill_rectangle(SDL_Surface *screen,
393 int x, int y, int w, int h, int color)
395 SDL_Rect rect;
396 rect.x = x;
397 rect.y = y;
398 rect.w = w;
399 rect.h = h;
400 SDL_FillRect(screen, &rect, color);
403 #define ALPHA_BLEND(a, oldp, newp, s)\
404 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
406 #define RGBA_IN(r, g, b, a, s)\
408 unsigned int v = ((const uint32_t *)(s))[0];\
409 a = (v >> 24) & 0xff;\
410 r = (v >> 16) & 0xff;\
411 g = (v >> 8) & 0xff;\
412 b = v & 0xff;\
415 #define YUVA_IN(y, u, v, a, s, pal)\
417 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
418 a = (val >> 24) & 0xff;\
419 y = (val >> 16) & 0xff;\
420 u = (val >> 8) & 0xff;\
421 v = val & 0xff;\
424 #define YUVA_OUT(d, y, u, v, a)\
426 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
430 #define BPP 1
432 static void blend_subrect(uint8_t *dst[4], uint16_t dst_linesize[4],
433 const AVSubtitleRect *rect, int imgw, int imgh)
435 int wrap, wrap3, width2, skip2;
436 int y, u, v, a, u1, v1, a1, w, h;
437 uint8_t *lum, *cb, *cr;
438 const uint8_t *p;
439 const uint32_t *pal;
440 int dstx, dsty, dstw, dsth;
442 dstw = av_clip(rect->w, 0, imgw);
443 dsth = av_clip(rect->h, 0, imgh);
444 dstx = av_clip(rect->x, 0, imgw - dstw);
445 dsty = av_clip(rect->y, 0, imgh - dsth);
446 /* sdl has U and V inverted */
447 lum = dst[0] + dsty * dst_linesize[0];
448 cb = dst[2] + (dsty >> 1) * dst_linesize[2];
449 cr = dst[1] + (dsty >> 1) * dst_linesize[1];
451 width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
452 skip2 = dstx >> 1;
453 wrap = dst_linesize[0];
454 wrap3 = rect->linesize[0];
455 p = rect->data[0];
456 pal = (const uint32_t *)rect->data[1]; /* Now in YCrCb! */
458 if (dsty & 1) {
459 lum += dstx;
460 cb += skip2;
461 cr += skip2;
463 if (dstx & 1) {
464 YUVA_IN(y, u, v, a, p, pal);
465 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
466 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
467 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
468 cb++;
469 cr++;
470 lum++;
471 p += BPP;
473 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
474 YUVA_IN(y, u, v, a, p, pal);
475 u1 = u;
476 v1 = v;
477 a1 = a;
478 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
480 YUVA_IN(y, u, v, a, p + BPP, pal);
481 u1 += u;
482 v1 += v;
483 a1 += a;
484 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
485 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
486 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
487 cb++;
488 cr++;
489 p += 2 * BPP;
490 lum += 2;
492 if (w) {
493 YUVA_IN(y, u, v, a, p, pal);
494 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
495 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
496 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
497 p++;
498 lum++;
500 p += wrap3 - dstw * BPP;
501 lum += wrap - dstw - dstx;
502 cb += dst_linesize[2] - width2 - skip2;
503 cr += dst_linesize[1] - width2 - skip2;
505 for (h = dsth - (dsty & 1); h >= 2; h -= 2) {
506 lum += dstx;
507 cb += skip2;
508 cr += skip2;
510 if (dstx & 1) {
511 YUVA_IN(y, u, v, a, p, pal);
512 u1 = u;
513 v1 = v;
514 a1 = a;
515 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
516 p += wrap3;
517 lum += wrap;
518 YUVA_IN(y, u, v, a, p, pal);
519 u1 += u;
520 v1 += v;
521 a1 += a;
522 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
523 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
524 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
525 cb++;
526 cr++;
527 p += -wrap3 + BPP;
528 lum += -wrap + 1;
530 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
531 YUVA_IN(y, u, v, a, p, pal);
532 u1 = u;
533 v1 = v;
534 a1 = a;
535 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
537 YUVA_IN(y, u, v, a, p + BPP, pal);
538 u1 += u;
539 v1 += v;
540 a1 += a;
541 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
542 p += wrap3;
543 lum += wrap;
545 YUVA_IN(y, u, v, a, p, pal);
546 u1 += u;
547 v1 += v;
548 a1 += a;
549 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
551 YUVA_IN(y, u, v, a, p + BPP, pal);
552 u1 += u;
553 v1 += v;
554 a1 += a;
555 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
557 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
558 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
560 cb++;
561 cr++;
562 p += -wrap3 + 2 * BPP;
563 lum += -wrap + 2;
565 if (w) {
566 YUVA_IN(y, u, v, a, p, pal);
567 u1 = u;
568 v1 = v;
569 a1 = a;
570 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
571 p += wrap3;
572 lum += wrap;
573 YUVA_IN(y, u, v, a, p, pal);
574 u1 += u;
575 v1 += v;
576 a1 += a;
577 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
578 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
579 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
580 cb++;
581 cr++;
582 p += -wrap3 + BPP;
583 lum += -wrap + 1;
585 p += wrap3 + (wrap3 - dstw * BPP);
586 lum += wrap + (wrap - dstw - dstx);
587 cb += dst_linesize[2] - width2 - skip2;
588 cr += dst_linesize[1] - width2 - skip2;
590 /* handle odd height */
591 if (h) {
592 lum += dstx;
593 cb += skip2;
594 cr += skip2;
596 if (dstx & 1) {
597 YUVA_IN(y, u, v, a, p, pal);
598 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
599 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
600 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
601 cb++;
602 cr++;
603 lum++;
604 p += BPP;
606 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
607 YUVA_IN(y, u, v, a, p, pal);
608 u1 = u;
609 v1 = v;
610 a1 = a;
611 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
613 YUVA_IN(y, u, v, a, p + BPP, pal);
614 u1 += u;
615 v1 += v;
616 a1 += a;
617 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
618 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
619 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
620 cb++;
621 cr++;
622 p += 2 * BPP;
623 lum += 2;
625 if (w) {
626 YUVA_IN(y, u, v, a, p, pal);
627 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
628 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
629 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
634 static void free_subpicture(SubPicture *sp)
636 avsubtitle_free(&sp->sub);
639 static void video_image_display(PlayerState *is)
641 VideoPicture *vp;
642 SubPicture *sp;
643 float aspect_ratio;
644 int width, height, x, y;
645 SDL_Rect rect;
646 int i;
648 vp = &is->pictq[is->pictq_rindex];
649 if (vp->bmp) {
650 if (!vp->sar.num)
651 aspect_ratio = 0;
652 else
653 aspect_ratio = av_q2d(vp->sar);
654 if (aspect_ratio <= 0.0)
655 aspect_ratio = 1.0;
656 aspect_ratio *= (float)vp->width / (float)vp->height;
658 if (is->subtitle_st)
660 if (is->subpq_size > 0)
662 sp = &is->subpq[is->subpq_rindex];
664 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
666 SDL_LockYUVOverlay (vp->bmp);
668 for (i = 0; i < sp->sub.num_rects; i++)
669 blend_subrect(vp->bmp->pixels, vp->bmp->pitches,
670 sp->sub.rects[i], vp->bmp->w, vp->bmp->h);
672 SDL_UnlockYUVOverlay (vp->bmp);
678 /* XXX: we suppose the screen has a 1.0 pixel ratio */
679 height = is->height;
680 width = ((int)rint(height * aspect_ratio)) & ~1;
681 if (width > is->width) {
682 width = is->width;
683 height = ((int)rint(width / aspect_ratio)) & ~1;
685 x = (is->width - width) / 2;
686 y = (is->height - height) / 2;
687 is->no_background = 0;
688 rect.x = is->xleft + x;
689 rect.y = is->ytop + y;
690 rect.w = width;
691 rect.h = height;
692 SDL_DisplayYUVOverlay(vp->bmp, &rect);
696 /* get the current audio output buffer size, in samples. With SDL, we
697 cannot have a precise information */
698 static int audio_write_get_buf_size(PlayerState *is)
700 return is->audio_buf_size - is->audio_buf_index;
703 static inline int compute_mod(int a, int b)
705 a = a % b;
706 if (a >= 0)
707 return a;
708 else
709 return a + b;
712 static void video_audio_display(PlayerState *s)
714 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
715 int ch, channels, h, h2, bgcolor, fgcolor;
716 int16_t time_diff;
717 int rdft_bits, nb_freq;
719 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
721 nb_freq = 1 << (rdft_bits - 1);
723 /* compute display index : center on currently output samples */
724 channels = s->sdl_channels;
725 nb_display_channels = channels;
726 if (!s->paused) {
727 int data_used = s->show_audio == 1 ? s->width : (2 * nb_freq);
728 n = 2 * channels;
729 delay = audio_write_get_buf_size(s);
730 delay /= n;
732 /* to be more precise, we take into account the time spent since
733 the last buffer computation */
734 if (audio_callback_time) {
735 time_diff = av_gettime_relative() - audio_callback_time;
736 delay -= (time_diff * s->sdl_sample_rate) / 1000000;
739 delay += 2 * data_used;
740 if (delay < data_used)
741 delay = data_used;
743 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
744 if (s->show_audio == 1) {
745 h = INT_MIN;
746 for (i = 0; i < 1000; i += channels) {
747 int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
748 int a = s->sample_array[idx];
749 int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
750 int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
751 int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
752 int score = a - d;
753 if (h < score && (b ^ c) < 0) {
754 h = score;
755 i_start = idx;
760 s->last_i_start = i_start;
761 } else {
762 i_start = s->last_i_start;
765 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
766 if (s->show_audio == 1) {
767 fill_rectangle(screen,
768 s->xleft, s->ytop, s->width, s->height,
769 bgcolor);
771 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
773 /* total height for one channel */
774 h = s->height / nb_display_channels;
775 /* graph height / 2 */
776 h2 = (h * 9) / 20;
777 for (ch = 0; ch < nb_display_channels; ch++) {
778 i = i_start + ch;
779 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
780 for (x = 0; x < s->width; x++) {
781 y = (s->sample_array[i] * h2) >> 15;
782 if (y < 0) {
783 y = -y;
784 ys = y1 - y;
785 } else {
786 ys = y1;
788 fill_rectangle(screen,
789 s->xleft + x, ys, 1, y,
790 fgcolor);
791 i += channels;
792 if (i >= SAMPLE_ARRAY_SIZE)
793 i -= SAMPLE_ARRAY_SIZE;
797 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
799 for (ch = 1; ch < nb_display_channels; ch++) {
800 y = s->ytop + ch * h;
801 fill_rectangle(screen,
802 s->xleft, y, s->width, 1,
803 fgcolor);
805 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
806 } else {
807 nb_display_channels= FFMIN(nb_display_channels, 2);
808 if (rdft_bits != s->rdft_bits) {
809 av_rdft_end(s->rdft);
810 av_free(s->rdft_data);
811 s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
812 s->rdft_bits = rdft_bits;
813 s->rdft_data = av_malloc(4 * nb_freq * sizeof(*s->rdft_data));
816 FFTSample *data[2];
817 for (ch = 0; ch < nb_display_channels; ch++) {
818 data[ch] = s->rdft_data + 2 * nb_freq * ch;
819 i = i_start + ch;
820 for (x = 0; x < 2 * nb_freq; x++) {
821 double w = (x-nb_freq) * (1.0 / nb_freq);
822 data[ch][x] = s->sample_array[i] * (1.0 - w * w);
823 i += channels;
824 if (i >= SAMPLE_ARRAY_SIZE)
825 i -= SAMPLE_ARRAY_SIZE;
827 av_rdft_calc(s->rdft, data[ch]);
829 /* Least efficient way to do this, we should of course
830 * directly access it but it is more than fast enough. */
831 for (y = 0; y < s->height; y++) {
832 double w = 1 / sqrt(nb_freq);
833 int a = sqrt(w * sqrt(data[0][2 * y + 0] * data[0][2 * y + 0] + data[0][2 * y + 1] * data[0][2 * y + 1]));
834 int b = (nb_display_channels == 2 ) ? sqrt(w * sqrt(data[1][2 * y + 0] * data[1][2 * y + 0]
835 + data[1][2 * y + 1] * data[1][2 * y + 1])) : a;
836 a = FFMIN(a, 255);
837 b = FFMIN(b, 255);
838 fgcolor = SDL_MapRGB(screen->format, a, b, (a + b) / 2);
840 fill_rectangle(screen,
841 s->xpos, s->height-y, 1, 1,
842 fgcolor);
845 SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
846 s->xpos++;
847 if (s->xpos >= s->width)
848 s->xpos= s->xleft;
852 static int video_open(PlayerState *is)
854 int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
855 int w,h;
857 if (is_full_screen) flags |= SDL_FULLSCREEN;
858 else flags |= SDL_RESIZABLE;
860 if (is_full_screen && fs_screen_width) {
861 w = fs_screen_width;
862 h = fs_screen_height;
863 } else if (!is_full_screen && screen_width) {
864 w = screen_width;
865 h = screen_height;
866 } else if (is->out_video_filter && is->out_video_filter->inputs[0]) {
867 w = is->out_video_filter->inputs[0]->w;
868 h = is->out_video_filter->inputs[0]->h;
869 } else {
870 w = 640;
871 h = 480;
873 if (screen && is->width == screen->w && screen->w == w
874 && is->height== screen->h && screen->h == h)
875 return 0;
877 #if defined(__APPLE__) && !SDL_VERSION_ATLEAST(1, 2, 14)
878 /* setting bits_per_pixel = 0 or 32 causes blank video on OS X and older SDL */
879 screen = SDL_SetVideoMode(w, h, 24, flags);
880 #else
881 screen = SDL_SetVideoMode(w, h, 0, flags);
882 #endif
883 if (!screen) {
884 fprintf(stderr, "SDL: could not set video mode - exiting\n");
885 return -1;
887 if (!window_title)
888 window_title = input_filename;
889 SDL_WM_SetCaption(window_title, window_title);
891 is->width = screen->w;
892 is->height = screen->h;
894 return 0;
897 /* display the current picture, if any */
898 static void video_display(PlayerState *is)
900 if (!screen)
901 video_open(player);
902 if (is->audio_st && is->show_audio)
903 video_audio_display(is);
904 else if (is->video_st)
905 video_image_display(is);
908 static int refresh_thread(void *opaque)
910 PlayerState *is= opaque;
911 while (!is->abort_request) {
912 SDL_Event event;
913 event.type = FF_REFRESH_EVENT;
914 event.user.data1 = opaque;
915 if (!is->refresh) {
916 is->refresh = 1;
917 SDL_PushEvent(&event);
919 av_usleep(is->audio_st && is->show_audio ? rdftspeed * 1000 : 5000); // FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly
921 return 0;
924 /* get the current audio clock value */
925 static double get_audio_clock(PlayerState *is)
927 double pts;
928 int hw_buf_size, bytes_per_sec;
929 pts = is->audio_clock;
930 hw_buf_size = audio_write_get_buf_size(is);
931 bytes_per_sec = 0;
932 if (is->audio_st) {
933 bytes_per_sec = is->sdl_sample_rate * is->sdl_channels *
934 av_get_bytes_per_sample(is->sdl_sample_fmt);
936 if (bytes_per_sec)
937 pts -= (double)hw_buf_size / bytes_per_sec;
938 return pts;
941 /* get the current video clock value */
942 static double get_video_clock(PlayerState *is)
944 if (is->paused) {
945 return is->video_current_pts;
946 } else {
947 return is->video_current_pts_drift + av_gettime_relative() / 1000000.0;
951 /* get the current external clock value */
952 static double get_external_clock(PlayerState *is)
954 int64_t ti;
955 ti = av_gettime_relative();
956 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
959 /* get the current master clock value */
960 static double get_master_clock(PlayerState *is)
962 double val;
964 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
965 if (is->video_st)
966 val = get_video_clock(is);
967 else
968 val = get_audio_clock(is);
969 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
970 if (is->audio_st)
971 val = get_audio_clock(is);
972 else
973 val = get_video_clock(is);
974 } else {
975 val = get_external_clock(is);
977 return val;
980 /* seek in the stream */
981 static void stream_seek(PlayerState *is, int64_t pos, int64_t rel, int seek_by_bytes)
983 if (!is->seek_req) {
984 is->seek_pos = pos;
985 is->seek_rel = rel;
986 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
987 if (seek_by_bytes)
988 is->seek_flags |= AVSEEK_FLAG_BYTE;
989 is->seek_req = 1;
993 /* pause or resume the video */
994 static void stream_pause(PlayerState *is)
996 if (is->paused) {
997 is->frame_timer += av_gettime_relative() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts;
998 if (is->read_pause_return != AVERROR(ENOSYS)) {
999 is->video_current_pts = is->video_current_pts_drift + av_gettime_relative() / 1000000.0;
1001 is->video_current_pts_drift = is->video_current_pts - av_gettime_relative() / 1000000.0;
1003 is->paused = !is->paused;
1006 static double compute_target_time(double frame_current_pts, PlayerState *is)
1008 double delay, sync_threshold, diff = 0;
1010 /* compute nominal delay */
1011 delay = frame_current_pts - is->frame_last_pts;
1012 if (delay <= 0 || delay >= 10.0) {
1013 /* if incorrect delay, use previous one */
1014 delay = is->frame_last_delay;
1015 } else {
1016 is->frame_last_delay = delay;
1018 is->frame_last_pts = frame_current_pts;
1020 /* update delay to follow master synchronisation source */
1021 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1022 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1023 /* if video is slave, we try to correct big delays by
1024 duplicating or deleting a frame */
1025 diff = get_video_clock(is) - get_master_clock(is);
1027 /* skip or repeat frame. We take into account the
1028 delay to compute the threshold. I still don't know
1029 if it is the best guess */
1030 sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
1031 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1032 if (diff <= -sync_threshold)
1033 delay = 0;
1034 else if (diff >= sync_threshold)
1035 delay = 2 * delay;
1038 is->frame_timer += delay;
1040 av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f pts=%0.3f A-V=%f\n",
1041 delay, frame_current_pts, -diff);
1043 return is->frame_timer;
1046 /* called to display each frame */
1047 static void video_refresh_timer(void *opaque)
1049 PlayerState *is = opaque;
1050 VideoPicture *vp;
1052 SubPicture *sp, *sp2;
1054 if (is->video_st) {
1055 retry:
1056 if (is->pictq_size == 0) {
1057 // nothing to do, no picture to display in the que
1058 } else {
1059 double time = av_gettime_relative() / 1000000.0;
1060 double next_target;
1061 /* dequeue the picture */
1062 vp = &is->pictq[is->pictq_rindex];
1064 if (time < vp->target_clock)
1065 return;
1066 /* update current video pts */
1067 is->video_current_pts = vp->pts;
1068 is->video_current_pts_drift = is->video_current_pts - time;
1069 is->video_current_pos = vp->pos;
1070 if (is->pictq_size > 1) {
1071 VideoPicture *nextvp = &is->pictq[(is->pictq_rindex + 1) % VIDEO_PICTURE_QUEUE_SIZE];
1072 assert(nextvp->target_clock >= vp->target_clock);
1073 next_target= nextvp->target_clock;
1074 } else {
1075 next_target = vp->target_clock + is->video_clock - vp->pts; // FIXME pass durations cleanly
1077 if (framedrop && time > next_target) {
1078 is->skip_frames *= 1.0 + FRAME_SKIP_FACTOR;
1079 if (is->pictq_size > 1 || time > next_target + 0.5) {
1080 /* update queue size and signal for next picture */
1081 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1082 is->pictq_rindex = 0;
1084 SDL_LockMutex(is->pictq_mutex);
1085 is->pictq_size--;
1086 SDL_CondSignal(is->pictq_cond);
1087 SDL_UnlockMutex(is->pictq_mutex);
1088 goto retry;
1092 if (is->subtitle_st) {
1093 if (is->subtitle_stream_changed) {
1094 SDL_LockMutex(is->subpq_mutex);
1096 while (is->subpq_size) {
1097 free_subpicture(&is->subpq[is->subpq_rindex]);
1099 /* update queue size and signal for next picture */
1100 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1101 is->subpq_rindex = 0;
1103 is->subpq_size--;
1105 is->subtitle_stream_changed = 0;
1107 SDL_CondSignal(is->subpq_cond);
1108 SDL_UnlockMutex(is->subpq_mutex);
1109 } else {
1110 if (is->subpq_size > 0) {
1111 sp = &is->subpq[is->subpq_rindex];
1113 if (is->subpq_size > 1)
1114 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1115 else
1116 sp2 = NULL;
1118 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1119 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1121 free_subpicture(sp);
1123 /* update queue size and signal for next picture */
1124 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1125 is->subpq_rindex = 0;
1127 SDL_LockMutex(is->subpq_mutex);
1128 is->subpq_size--;
1129 SDL_CondSignal(is->subpq_cond);
1130 SDL_UnlockMutex(is->subpq_mutex);
1136 /* display picture */
1137 if (!display_disable)
1138 video_display(is);
1140 /* update queue size and signal for next picture */
1141 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1142 is->pictq_rindex = 0;
1144 SDL_LockMutex(is->pictq_mutex);
1145 is->pictq_size--;
1146 SDL_CondSignal(is->pictq_cond);
1147 SDL_UnlockMutex(is->pictq_mutex);
1149 } else if (is->audio_st) {
1150 /* draw the next audio frame */
1152 /* if only audio stream, then display the audio bars (better
1153 than nothing, just to test the implementation */
1155 /* display picture */
1156 if (!display_disable)
1157 video_display(is);
1159 if (show_status) {
1160 static int64_t last_time;
1161 int64_t cur_time;
1162 int aqsize, vqsize, sqsize;
1163 double av_diff;
1165 cur_time = av_gettime_relative();
1166 if (!last_time || (cur_time - last_time) >= 30000) {
1167 aqsize = 0;
1168 vqsize = 0;
1169 sqsize = 0;
1170 if (is->audio_st)
1171 aqsize = is->audioq.size;
1172 if (is->video_st)
1173 vqsize = is->videoq.size;
1174 if (is->subtitle_st)
1175 sqsize = is->subtitleq.size;
1176 av_diff = 0;
1177 if (is->audio_st && is->video_st)
1178 av_diff = get_audio_clock(is) - get_video_clock(is);
1179 printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
1180 get_master_clock(is), av_diff, FFMAX(is->skip_frames - 1, 0), aqsize / 1024,
1181 vqsize / 1024, sqsize, is->pts_ctx.num_faulty_dts, is->pts_ctx.num_faulty_pts);
1182 fflush(stdout);
1183 last_time = cur_time;
1188 static void player_close(PlayerState *is)
1190 VideoPicture *vp;
1191 int i;
1192 /* XXX: use a special url_shutdown call to abort parse cleanly */
1193 is->abort_request = 1;
1194 SDL_WaitThread(is->parse_tid, NULL);
1195 SDL_WaitThread(is->refresh_tid, NULL);
1197 /* free all pictures */
1198 for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
1199 vp = &is->pictq[i];
1200 if (vp->bmp) {
1201 SDL_FreeYUVOverlay(vp->bmp);
1202 vp->bmp = NULL;
1205 SDL_DestroyMutex(is->video_filter_mutex);
1206 SDL_DestroyMutex(is->pictq_mutex);
1207 SDL_DestroyCond(is->pictq_cond);
1208 SDL_DestroyMutex(is->subpq_mutex);
1209 SDL_DestroyCond(is->subpq_cond);
1212 static void do_exit(void)
1214 if (player) {
1215 player_close(player);
1216 player = NULL;
1218 uninit_opts();
1219 avformat_network_deinit();
1220 if (show_status)
1221 printf("\n");
1222 SDL_Quit();
1223 av_log(NULL, AV_LOG_QUIET, "");
1224 exit(0);
1227 /* allocate a picture (needs to do that in main thread to avoid
1228 potential locking problems */
1229 static void alloc_picture(void *opaque)
1231 PlayerState *is = opaque;
1232 VideoPicture *vp;
1234 vp = &is->pictq[is->pictq_windex];
1236 if (vp->bmp)
1237 SDL_FreeYUVOverlay(vp->bmp);
1239 vp->width = is->out_video_filter->inputs[0]->w;
1240 vp->height = is->out_video_filter->inputs[0]->h;
1241 vp->pix_fmt = is->out_video_filter->inputs[0]->format;
1243 vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
1244 SDL_YV12_OVERLAY,
1245 screen);
1246 if (!vp->bmp || vp->bmp->pitches[0] < vp->width) {
1247 /* SDL allocates a buffer smaller than requested if the video
1248 * overlay hardware is unable to support the requested size. */
1249 fprintf(stderr, "Error: the video system does not support an image\n"
1250 "size of %dx%d pixels. Try using -vf \"scale=w:h\"\n"
1251 "to reduce the image size.\n", vp->width, vp->height );
1252 do_exit();
1255 SDL_LockMutex(is->pictq_mutex);
1256 vp->allocated = 1;
1257 SDL_CondSignal(is->pictq_cond);
1258 SDL_UnlockMutex(is->pictq_mutex);
1261 /* The 'pts' parameter is the dts of the packet / pts of the frame and
1262 * guessed if not known. */
1263 static int queue_picture(PlayerState *is, AVFrame *src_frame, double pts, int64_t pos)
1265 VideoPicture *vp;
1267 /* wait until we have space to put a new picture */
1268 SDL_LockMutex(is->pictq_mutex);
1270 if (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !is->refresh)
1271 is->skip_frames = FFMAX(1.0 - FRAME_SKIP_FACTOR, is->skip_frames * (1.0 - FRAME_SKIP_FACTOR));
1273 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1274 !is->videoq.abort_request) {
1275 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1277 SDL_UnlockMutex(is->pictq_mutex);
1279 if (is->videoq.abort_request)
1280 return -1;
1282 vp = &is->pictq[is->pictq_windex];
1284 vp->sar = src_frame->sample_aspect_ratio;
1286 /* alloc or resize hardware picture buffer */
1287 if (!vp->bmp || vp->reallocate ||
1288 vp->width != is->out_video_filter->inputs[0]->w ||
1289 vp->height != is->out_video_filter->inputs[0]->h) {
1290 SDL_Event event;
1292 vp->allocated = 0;
1293 vp->reallocate = 0;
1295 /* the allocation must be done in the main thread to avoid
1296 locking problems */
1297 event.type = FF_ALLOC_EVENT;
1298 event.user.data1 = is;
1299 SDL_PushEvent(&event);
1301 /* wait until the picture is allocated */
1302 SDL_LockMutex(is->pictq_mutex);
1303 while (!vp->allocated && !is->videoq.abort_request) {
1304 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1306 SDL_UnlockMutex(is->pictq_mutex);
1308 if (is->videoq.abort_request)
1309 return -1;
1312 /* if the frame is not skipped, then display it */
1313 if (vp->bmp) {
1314 uint8_t *data[4];
1315 int linesize[4];
1317 /* get a pointer on the bitmap */
1318 SDL_LockYUVOverlay (vp->bmp);
1320 data[0] = vp->bmp->pixels[0];
1321 data[1] = vp->bmp->pixels[2];
1322 data[2] = vp->bmp->pixels[1];
1324 linesize[0] = vp->bmp->pitches[0];
1325 linesize[1] = vp->bmp->pitches[2];
1326 linesize[2] = vp->bmp->pitches[1];
1328 // FIXME use direct rendering
1329 av_image_copy(data, linesize, src_frame->data, src_frame->linesize,
1330 vp->pix_fmt, vp->width, vp->height);
1332 /* update the bitmap content */
1333 SDL_UnlockYUVOverlay(vp->bmp);
1335 vp->pts = pts;
1336 vp->pos = pos;
1338 /* now we can update the picture count */
1339 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1340 is->pictq_windex = 0;
1341 SDL_LockMutex(is->pictq_mutex);
1342 vp->target_clock = compute_target_time(vp->pts, is);
1344 is->pictq_size++;
1345 SDL_UnlockMutex(is->pictq_mutex);
1347 return 0;
1350 /* Compute the exact PTS for the picture if it is omitted in the stream.
1351 * The 'pts1' parameter is the dts of the packet / pts of the frame. */
1352 static int output_picture2(PlayerState *is, AVFrame *src_frame, double pts1, int64_t pos)
1354 double frame_delay, pts;
1355 int ret;
1357 pts = pts1;
1359 if (pts != 0) {
1360 /* update video clock with pts, if present */
1361 is->video_clock = pts;
1362 } else {
1363 pts = is->video_clock;
1365 /* update video clock for next frame */
1366 frame_delay = av_q2d(is->video_dec->time_base);
1367 /* For MPEG-2, the frame can be repeated, so we update the
1368 clock accordingly */
1369 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
1370 is->video_clock += frame_delay;
1372 ret = queue_picture(is, src_frame, pts, pos);
1373 av_frame_unref(src_frame);
1374 return ret;
1377 static int get_video_frame(PlayerState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt)
1379 int got_picture, i;
1381 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1382 return -1;
1384 if (pkt->data == flush_pkt.data) {
1385 avcodec_flush_buffers(is->video_dec);
1387 SDL_LockMutex(is->pictq_mutex);
1388 // Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
1389 for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
1390 is->pictq[i].target_clock= 0;
1392 while (is->pictq_size && !is->videoq.abort_request) {
1393 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1395 is->video_current_pos = -1;
1396 SDL_UnlockMutex(is->pictq_mutex);
1398 init_pts_correction(&is->pts_ctx);
1399 is->frame_last_pts = AV_NOPTS_VALUE;
1400 is->frame_last_delay = 0;
1401 is->frame_timer = (double)av_gettime_relative() / 1000000.0;
1402 is->skip_frames = 1;
1403 is->skip_frames_index = 0;
1404 return 0;
1407 avcodec_decode_video2(is->video_dec, frame, &got_picture, pkt);
1409 if (got_picture) {
1410 if (decoder_reorder_pts == -1) {
1411 *pts = guess_correct_pts(&is->pts_ctx, frame->pts, frame->pkt_dts);
1412 } else if (decoder_reorder_pts) {
1413 *pts = frame->pts;
1414 } else {
1415 *pts = frame->pkt_dts;
1418 if (*pts == AV_NOPTS_VALUE) {
1419 *pts = 0;
1421 if (is->video_st->sample_aspect_ratio.num) {
1422 frame->sample_aspect_ratio = is->video_st->sample_aspect_ratio;
1425 is->skip_frames_index += 1;
1426 if (is->skip_frames_index >= is->skip_frames) {
1427 is->skip_frames_index -= FFMAX(is->skip_frames, 1.0);
1428 return 1;
1430 av_frame_unref(frame);
1432 return 0;
1435 static int configure_video_filters(AVFilterGraph *graph, PlayerState *is, const char *vfilters)
1437 char sws_flags_str[128];
1438 char buffersrc_args[256];
1439 int ret;
1440 AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter;
1441 AVCodecContext *codec = is->video_dec;
1443 snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%"PRId64, sws_flags);
1444 graph->scale_sws_opts = av_strdup(sws_flags_str);
1446 snprintf(buffersrc_args, sizeof(buffersrc_args),
1447 "width=%d:height=%d:pix_fmt=%d:time_base=%d/%d:sar=%d/%d",
1448 codec->width, codec->height, codec->pix_fmt,
1449 is->video_st->time_base.num, is->video_st->time_base.den,
1450 codec->sample_aspect_ratio.num, codec->sample_aspect_ratio.den);
1453 if ((ret = avfilter_graph_create_filter(&filt_src,
1454 avfilter_get_by_name("buffer"),
1455 "src", buffersrc_args, NULL,
1456 graph)) < 0)
1457 return ret;
1458 if ((ret = avfilter_graph_create_filter(&filt_out,
1459 avfilter_get_by_name("buffersink"),
1460 "out", NULL, NULL, graph)) < 0)
1461 return ret;
1463 last_filter = filt_out;
1465 /* Note: this macro adds a filter before the lastly added filter, so the
1466 * processing order of the filters is in reverse */
1467 #define INSERT_FILT(name, arg) do { \
1468 AVFilterContext *filt_ctx; \
1470 ret = avfilter_graph_create_filter(&filt_ctx, \
1471 avfilter_get_by_name(name), \
1472 "avplay_" name, arg, NULL, graph); \
1473 if (ret < 0) \
1474 return ret; \
1476 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
1477 if (ret < 0) \
1478 return ret; \
1480 last_filter = filt_ctx; \
1481 } while (0)
1483 INSERT_FILT("format", "yuv420p");
1485 if (autorotate) {
1486 uint8_t* displaymatrix = av_stream_get_side_data(is->video_st,
1487 AV_PKT_DATA_DISPLAYMATRIX, NULL);
1488 if (displaymatrix) {
1489 double rot = av_display_rotation_get((int32_t*) displaymatrix);
1490 if (rot < -135 || rot > 135) {
1491 INSERT_FILT("vflip", NULL);
1492 INSERT_FILT("hflip", NULL);
1493 } else if (rot < -45) {
1494 INSERT_FILT("transpose", "dir=clock");
1495 } else if (rot > 45) {
1496 INSERT_FILT("transpose", "dir=cclock");
1501 if (vfilters) {
1502 AVFilterInOut *outputs = avfilter_inout_alloc();
1503 AVFilterInOut *inputs = avfilter_inout_alloc();
1505 outputs->name = av_strdup("in");
1506 outputs->filter_ctx = filt_src;
1507 outputs->pad_idx = 0;
1508 outputs->next = NULL;
1510 inputs->name = av_strdup("out");
1511 inputs->filter_ctx = last_filter;
1512 inputs->pad_idx = 0;
1513 inputs->next = NULL;
1515 if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
1516 return ret;
1517 } else {
1518 if ((ret = avfilter_link(filt_src, 0, last_filter, 0)) < 0)
1519 return ret;
1522 if ((ret = avfilter_graph_config(graph, NULL)) < 0)
1523 return ret;
1525 is->in_video_filter = filt_src;
1526 is->out_video_filter = filt_out;
1528 return ret;
1531 static int video_thread(void *arg)
1533 AVPacket pkt = { 0 };
1534 PlayerState *is = arg;
1535 AVFrame *frame = av_frame_alloc();
1536 int64_t pts_int;
1537 double pts;
1538 int ret;
1540 AVFilterGraph *graph = avfilter_graph_alloc();
1541 AVFilterContext *filt_out = NULL, *filt_in = NULL;
1542 int last_w = is->video_dec->width;
1543 int last_h = is->video_dec->height;
1544 if (!graph) {
1545 av_frame_free(&frame);
1546 return AVERROR(ENOMEM);
1549 if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
1550 goto the_end;
1551 filt_in = is->in_video_filter;
1552 filt_out = is->out_video_filter;
1554 if (!frame) {
1555 avfilter_graph_free(&graph);
1556 return AVERROR(ENOMEM);
1559 for (;;) {
1560 AVRational tb;
1561 while (is->paused && !is->videoq.abort_request)
1562 SDL_Delay(10);
1564 av_packet_unref(&pkt);
1566 ret = get_video_frame(is, frame, &pts_int, &pkt);
1567 if (ret < 0)
1568 goto the_end;
1570 if (!ret)
1571 continue;
1573 if ( last_w != is->video_dec->width
1574 || last_h != is->video_dec->height) {
1575 av_log(NULL, AV_LOG_TRACE, "Changing size %dx%d -> %dx%d\n", last_w, last_h,
1576 is->video_dec->width, is->video_dec->height);
1577 avfilter_graph_free(&graph);
1578 graph = avfilter_graph_alloc();
1579 if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
1580 goto the_end;
1581 filt_in = is->in_video_filter;
1582 filt_out = is->out_video_filter;
1583 last_w = is->video_dec->width;
1584 last_h = is->video_dec->height;
1587 frame->pts = pts_int;
1588 ret = av_buffersrc_add_frame(filt_in, frame);
1589 if (ret < 0)
1590 goto the_end;
1592 while (ret >= 0) {
1593 ret = av_buffersink_get_frame(filt_out, frame);
1594 if (ret < 0) {
1595 ret = 0;
1596 break;
1599 pts_int = frame->pts;
1600 tb = filt_out->inputs[0]->time_base;
1601 if (av_cmp_q(tb, is->video_st->time_base)) {
1602 av_unused int64_t pts1 = pts_int;
1603 pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base);
1604 av_log(NULL, AV_LOG_TRACE, "video_thread(): "
1605 "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
1606 tb.num, tb.den, pts1,
1607 is->video_st->time_base.num, is->video_st->time_base.den, pts_int);
1609 pts = pts_int * av_q2d(is->video_st->time_base);
1610 ret = output_picture2(is, frame, pts, 0);
1613 if (ret < 0)
1614 goto the_end;
1617 if (step)
1618 if (player)
1619 stream_pause(player);
1621 the_end:
1622 SDL_LockMutex(is->video_filter_mutex);
1623 is->out_video_filter = NULL;
1624 SDL_UnlockMutex(is->video_filter_mutex);
1625 av_freep(&vfilters);
1626 avfilter_graph_free(&graph);
1627 av_packet_unref(&pkt);
1628 av_frame_free(&frame);
1629 return 0;
1632 static int subtitle_thread(void *arg)
1634 PlayerState *is = arg;
1635 SubPicture *sp;
1636 AVPacket pkt1, *pkt = &pkt1;
1637 int got_subtitle;
1638 double pts;
1639 int i, j;
1640 int r, g, b, y, u, v, a;
1642 for (;;) {
1643 while (is->paused && !is->subtitleq.abort_request) {
1644 SDL_Delay(10);
1646 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1647 break;
1649 if (pkt->data == flush_pkt.data) {
1650 avcodec_flush_buffers(is->subtitle_dec);
1651 continue;
1653 SDL_LockMutex(is->subpq_mutex);
1654 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1655 !is->subtitleq.abort_request) {
1656 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1658 SDL_UnlockMutex(is->subpq_mutex);
1660 if (is->subtitleq.abort_request)
1661 return 0;
1663 sp = &is->subpq[is->subpq_windex];
1665 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1666 this packet, if any */
1667 pts = 0;
1668 if (pkt->pts != AV_NOPTS_VALUE)
1669 pts = av_q2d(is->subtitle_dec->time_base) * pkt->pts;
1671 avcodec_decode_subtitle2(is->subtitle_dec, &sp->sub,
1672 &got_subtitle, pkt);
1674 if (got_subtitle && sp->sub.format == 0) {
1675 sp->pts = pts;
1677 for (i = 0; i < sp->sub.num_rects; i++)
1679 for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
1681 RGBA_IN(r, g, b, a, (uint32_t *)sp->sub.rects[i]->data[1] + j);
1682 y = RGB_TO_Y_CCIR(r, g, b);
1683 u = RGB_TO_U_CCIR(r, g, b, 0);
1684 v = RGB_TO_V_CCIR(r, g, b, 0);
1685 YUVA_OUT((uint32_t *)sp->sub.rects[i]->data[1] + j, y, u, v, a);
1689 /* now we can update the picture count */
1690 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1691 is->subpq_windex = 0;
1692 SDL_LockMutex(is->subpq_mutex);
1693 is->subpq_size++;
1694 SDL_UnlockMutex(is->subpq_mutex);
1696 av_packet_unref(pkt);
1698 return 0;
1701 /* copy samples for viewing in editor window */
1702 static void update_sample_display(PlayerState *is, short *samples, int samples_size)
1704 int size, len;
1706 size = samples_size / sizeof(short);
1707 while (size > 0) {
1708 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1709 if (len > size)
1710 len = size;
1711 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1712 samples += len;
1713 is->sample_array_index += len;
1714 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1715 is->sample_array_index = 0;
1716 size -= len;
1720 /* return the new audio buffer size (samples can be added or deleted
1721 to get better sync if video or external master clock) */
1722 static int synchronize_audio(PlayerState *is, short *samples,
1723 int samples_size1, double pts)
1725 int n, samples_size;
1726 double ref_clock;
1728 n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
1729 samples_size = samples_size1;
1731 /* if not master, then we try to remove or add samples to correct the clock */
1732 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
1733 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1734 double diff, avg_diff;
1735 int wanted_size, min_size, max_size, nb_samples;
1737 ref_clock = get_master_clock(is);
1738 diff = get_audio_clock(is) - ref_clock;
1740 if (diff < AV_NOSYNC_THRESHOLD) {
1741 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1742 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1743 /* not enough measures to have a correct estimate */
1744 is->audio_diff_avg_count++;
1745 } else {
1746 /* estimate the A-V difference */
1747 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1749 if (fabs(avg_diff) >= is->audio_diff_threshold) {
1750 wanted_size = samples_size + ((int)(diff * is->sdl_sample_rate) * n);
1751 nb_samples = samples_size / n;
1753 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1754 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1755 if (wanted_size < min_size)
1756 wanted_size = min_size;
1757 else if (wanted_size > max_size)
1758 wanted_size = max_size;
1760 /* add or remove samples to correction the synchro */
1761 if (wanted_size < samples_size) {
1762 /* remove samples */
1763 samples_size = wanted_size;
1764 } else if (wanted_size > samples_size) {
1765 uint8_t *samples_end, *q;
1766 int nb;
1768 /* add samples */
1769 nb = (samples_size - wanted_size);
1770 samples_end = (uint8_t *)samples + samples_size - n;
1771 q = samples_end + n;
1772 while (nb > 0) {
1773 memcpy(q, samples_end, n);
1774 q += n;
1775 nb -= n;
1777 samples_size = wanted_size;
1780 av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1781 diff, avg_diff, samples_size - samples_size1,
1782 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1784 } else {
1785 /* too big difference : may be initial PTS errors, so
1786 reset A-V filter */
1787 is->audio_diff_avg_count = 0;
1788 is->audio_diff_cum = 0;
1792 return samples_size;
1795 /* decode one audio frame and returns its uncompressed size */
1796 static int audio_decode_frame(PlayerState *is, double *pts_ptr)
1798 AVPacket *pkt_temp = &is->audio_pkt_temp;
1799 AVPacket *pkt = &is->audio_pkt;
1800 AVCodecContext *dec = is->audio_dec;
1801 int n, len1, data_size, got_frame;
1802 double pts;
1803 int new_packet = 0;
1804 int flush_complete = 0;
1806 for (;;) {
1807 /* NOTE: the audio packet can contain several frames */
1808 while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) {
1809 int resample_changed, audio_resample;
1811 if (!is->frame) {
1812 if (!(is->frame = av_frame_alloc()))
1813 return AVERROR(ENOMEM);
1816 if (flush_complete)
1817 break;
1818 new_packet = 0;
1819 len1 = avcodec_decode_audio4(dec, is->frame, &got_frame, pkt_temp);
1820 if (len1 < 0) {
1821 /* if error, we skip the frame */
1822 pkt_temp->size = 0;
1823 break;
1826 pkt_temp->data += len1;
1827 pkt_temp->size -= len1;
1829 if (!got_frame) {
1830 /* stop sending empty packets if the decoder is finished */
1831 if (!pkt_temp->data && (dec->codec->capabilities & AV_CODEC_CAP_DELAY))
1832 flush_complete = 1;
1833 continue;
1835 data_size = av_samples_get_buffer_size(NULL, dec->channels,
1836 is->frame->nb_samples,
1837 is->frame->format, 1);
1839 audio_resample = is->frame->format != is->sdl_sample_fmt ||
1840 is->frame->channel_layout != is->sdl_channel_layout ||
1841 is->frame->sample_rate != is->sdl_sample_rate;
1843 resample_changed = is->frame->format != is->resample_sample_fmt ||
1844 is->frame->channel_layout != is->resample_channel_layout ||
1845 is->frame->sample_rate != is->resample_sample_rate;
1847 if ((!is->avr && audio_resample) || resample_changed) {
1848 int ret;
1849 if (is->avr)
1850 avresample_close(is->avr);
1851 else if (audio_resample) {
1852 is->avr = avresample_alloc_context();
1853 if (!is->avr) {
1854 fprintf(stderr, "error allocating AVAudioResampleContext\n");
1855 break;
1858 if (audio_resample) {
1859 av_opt_set_int(is->avr, "in_channel_layout", is->frame->channel_layout, 0);
1860 av_opt_set_int(is->avr, "in_sample_fmt", is->frame->format, 0);
1861 av_opt_set_int(is->avr, "in_sample_rate", is->frame->sample_rate, 0);
1862 av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0);
1863 av_opt_set_int(is->avr, "out_sample_fmt", is->sdl_sample_fmt, 0);
1864 av_opt_set_int(is->avr, "out_sample_rate", is->sdl_sample_rate, 0);
1866 if ((ret = avresample_open(is->avr)) < 0) {
1867 fprintf(stderr, "error initializing libavresample\n");
1868 break;
1871 is->resample_sample_fmt = is->frame->format;
1872 is->resample_channel_layout = is->frame->channel_layout;
1873 is->resample_sample_rate = is->frame->sample_rate;
1876 if (audio_resample) {
1877 void *tmp_out;
1878 int out_samples, out_size, out_linesize;
1879 int osize = av_get_bytes_per_sample(is->sdl_sample_fmt);
1880 int nb_samples = is->frame->nb_samples;
1882 out_size = av_samples_get_buffer_size(&out_linesize,
1883 is->sdl_channels,
1884 nb_samples,
1885 is->sdl_sample_fmt, 0);
1886 tmp_out = av_realloc(is->audio_buf1, out_size);
1887 if (!tmp_out)
1888 return AVERROR(ENOMEM);
1889 is->audio_buf1 = tmp_out;
1891 out_samples = avresample_convert(is->avr,
1892 &is->audio_buf1,
1893 out_linesize, nb_samples,
1894 is->frame->data,
1895 is->frame->linesize[0],
1896 is->frame->nb_samples);
1897 if (out_samples < 0) {
1898 fprintf(stderr, "avresample_convert() failed\n");
1899 break;
1901 is->audio_buf = is->audio_buf1;
1902 data_size = out_samples * osize * is->sdl_channels;
1903 } else {
1904 is->audio_buf = is->frame->data[0];
1907 /* if no pts, then compute it */
1908 pts = is->audio_clock;
1909 *pts_ptr = pts;
1910 n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
1911 is->audio_clock += (double)data_size /
1912 (double)(n * is->sdl_sample_rate);
1913 #ifdef DEBUG
1915 static double last_clock;
1916 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1917 is->audio_clock - last_clock,
1918 is->audio_clock, pts);
1919 last_clock = is->audio_clock;
1921 #endif
1922 return data_size;
1925 /* free the current packet */
1926 if (pkt->data)
1927 av_packet_unref(pkt);
1928 memset(pkt_temp, 0, sizeof(*pkt_temp));
1930 if (is->paused || is->audioq.abort_request) {
1931 return -1;
1934 /* read next packet */
1935 if ((new_packet = packet_queue_get(&is->audioq, pkt, 1)) < 0)
1936 return -1;
1938 if (pkt->data == flush_pkt.data) {
1939 avcodec_flush_buffers(dec);
1940 flush_complete = 0;
1943 *pkt_temp = *pkt;
1945 /* if update the audio clock with the pts */
1946 if (pkt->pts != AV_NOPTS_VALUE) {
1947 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
1952 /* prepare a new audio buffer */
1953 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1955 PlayerState *is = opaque;
1956 int audio_size, len1;
1957 double pts;
1959 audio_callback_time = av_gettime_relative();
1961 while (len > 0) {
1962 if (is->audio_buf_index >= is->audio_buf_size) {
1963 audio_size = audio_decode_frame(is, &pts);
1964 if (audio_size < 0) {
1965 /* if error, just output silence */
1966 is->audio_buf = is->silence_buf;
1967 is->audio_buf_size = sizeof(is->silence_buf);
1968 } else {
1969 if (is->show_audio)
1970 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1971 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
1972 pts);
1973 is->audio_buf_size = audio_size;
1975 is->audio_buf_index = 0;
1977 len1 = is->audio_buf_size - is->audio_buf_index;
1978 if (len1 > len)
1979 len1 = len;
1980 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1981 len -= len1;
1982 stream += len1;
1983 is->audio_buf_index += len1;
1987 static AVCodec *find_codec_or_die(const char *name, enum AVMediaType type)
1989 const AVCodecDescriptor *desc;
1990 AVCodec *codec = avcodec_find_decoder_by_name(name);
1992 if (!codec && (desc = avcodec_descriptor_get_by_name(name))) {
1993 codec = avcodec_find_decoder(desc->id);
1994 if (codec)
1995 av_log(NULL, AV_LOG_VERBOSE, "Matched decoder '%s' for codec '%s'.\n",
1996 codec->name, desc->name);
1999 if (!codec) {
2000 av_log(NULL, AV_LOG_FATAL, "Unknown decoder '%s'\n", name);
2001 exit_program(1);
2004 if (codec->type != type) {
2005 av_log(NULL, AV_LOG_FATAL, "Invalid decoder type '%s'\n", name);
2006 exit_program(1);
2009 return codec;
2012 static AVCodec *choose_decoder(PlayerState *is, AVFormatContext *ic, AVStream *st)
2014 char *codec_name = NULL;
2015 int i, ret;
2017 for (i = 0; i < is->nb_codec_names; i++) {
2018 char *spec = is->codec_names[i].specifier;
2019 if ((ret = check_stream_specifier(ic, st, spec)) > 0)
2020 codec_name = is->codec_names[i].u.str;
2021 else if (ret < 0)
2022 exit_program(1);
2025 if (codec_name) {
2026 AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type);
2027 st->codecpar->codec_id = codec->id;
2028 return codec;
2029 } else
2030 return avcodec_find_decoder(st->codecpar->codec_id);
2033 /* open a given stream. Return 0 if OK */
2034 static int stream_component_open(PlayerState *is, int stream_index)
2036 AVFormatContext *ic = is->ic;
2037 AVCodecContext *avctx;
2038 AVCodec *codec;
2039 SDL_AudioSpec wanted_spec, spec;
2040 AVDictionary *opts;
2041 AVDictionaryEntry *t = NULL;
2042 int ret = 0;
2044 if (stream_index < 0 || stream_index >= ic->nb_streams)
2045 return -1;
2047 avctx = avcodec_alloc_context3(NULL);
2048 if (!avctx)
2049 return AVERROR(ENOMEM);
2051 ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
2052 if (ret < 0) {
2053 avcodec_free_context(&avctx);
2054 return ret;
2057 opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], NULL);
2059 codec = choose_decoder(is, ic, ic->streams[stream_index]);
2060 avctx->workaround_bugs = workaround_bugs;
2061 avctx->idct_algo = idct;
2062 avctx->skip_frame = skip_frame;
2063 avctx->skip_idct = skip_idct;
2064 avctx->skip_loop_filter = skip_loop_filter;
2065 avctx->error_concealment = error_concealment;
2067 if (fast)
2068 avctx->flags2 |= AV_CODEC_FLAG2_FAST;
2070 if (!av_dict_get(opts, "threads", NULL, 0))
2071 av_dict_set(&opts, "threads", "auto", 0);
2072 if (avctx->codec_type == AVMEDIA_TYPE_VIDEO)
2073 av_dict_set(&opts, "refcounted_frames", "1", 0);
2074 if (!codec ||
2075 (ret = avcodec_open2(avctx, codec, &opts)) < 0) {
2076 goto fail;
2078 if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
2079 av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
2080 ret = AVERROR_OPTION_NOT_FOUND;
2081 goto fail;
2084 /* prepare audio output */
2085 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
2086 is->sdl_sample_rate = avctx->sample_rate;
2088 if (!avctx->channel_layout)
2089 avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
2090 if (!avctx->channel_layout) {
2091 fprintf(stderr, "unable to guess channel layout\n");
2092 ret = AVERROR_INVALIDDATA;
2093 goto fail;
2095 if (avctx->channels == 1)
2096 is->sdl_channel_layout = AV_CH_LAYOUT_MONO;
2097 else
2098 is->sdl_channel_layout = AV_CH_LAYOUT_STEREO;
2099 is->sdl_channels = av_get_channel_layout_nb_channels(is->sdl_channel_layout);
2101 wanted_spec.format = AUDIO_S16SYS;
2102 wanted_spec.freq = is->sdl_sample_rate;
2103 wanted_spec.channels = is->sdl_channels;
2104 wanted_spec.silence = 0;
2105 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
2106 wanted_spec.callback = sdl_audio_callback;
2107 wanted_spec.userdata = is;
2108 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
2109 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
2110 ret = AVERROR_UNKNOWN;
2111 goto fail;
2113 is->audio_hw_buf_size = spec.size;
2114 is->sdl_sample_fmt = AV_SAMPLE_FMT_S16;
2115 is->resample_sample_fmt = is->sdl_sample_fmt;
2116 is->resample_channel_layout = avctx->channel_layout;
2117 is->resample_sample_rate = avctx->sample_rate;
2120 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2121 switch (avctx->codec_type) {
2122 case AVMEDIA_TYPE_AUDIO:
2123 is->audio_stream = stream_index;
2124 is->audio_st = ic->streams[stream_index];
2125 is->audio_dec = avctx;
2126 is->audio_buf_size = 0;
2127 is->audio_buf_index = 0;
2129 /* init averaging filter */
2130 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2131 is->audio_diff_avg_count = 0;
2132 /* since we do not have a precise enough audio FIFO fullness,
2133 we correct audio sync only if larger than this threshold */
2134 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / avctx->sample_rate;
2136 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
2137 packet_queue_init(&is->audioq);
2138 SDL_PauseAudio(0);
2139 break;
2140 case AVMEDIA_TYPE_VIDEO:
2141 is->video_stream = stream_index;
2142 is->video_st = ic->streams[stream_index];
2143 is->video_dec = avctx;
2145 packet_queue_init(&is->videoq);
2146 is->video_tid = SDL_CreateThread(video_thread, is);
2147 break;
2148 case AVMEDIA_TYPE_SUBTITLE:
2149 is->subtitle_stream = stream_index;
2150 is->subtitle_st = ic->streams[stream_index];
2151 is->subtitle_dec = avctx;
2152 packet_queue_init(&is->subtitleq);
2154 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
2155 break;
2156 default:
2157 break;
2160 fail:
2161 av_dict_free(&opts);
2163 return ret;
2166 static void stream_component_close(PlayerState *is, int stream_index)
2168 AVFormatContext *ic = is->ic;
2169 AVCodecParameters *par;
2171 if (stream_index < 0 || stream_index >= ic->nb_streams)
2172 return;
2173 par = ic->streams[stream_index]->codecpar;
2175 switch (par->codec_type) {
2176 case AVMEDIA_TYPE_AUDIO:
2177 packet_queue_abort(&is->audioq);
2179 SDL_CloseAudio();
2181 packet_queue_end(&is->audioq);
2182 av_packet_unref(&is->audio_pkt);
2183 if (is->avr)
2184 avresample_free(&is->avr);
2185 av_freep(&is->audio_buf1);
2186 is->audio_buf = NULL;
2187 av_frame_free(&is->frame);
2189 if (is->rdft) {
2190 av_rdft_end(is->rdft);
2191 av_freep(&is->rdft_data);
2192 is->rdft = NULL;
2193 is->rdft_bits = 0;
2195 break;
2196 case AVMEDIA_TYPE_VIDEO:
2197 packet_queue_abort(&is->videoq);
2199 /* note: we also signal this mutex to make sure we deblock the
2200 video thread in all cases */
2201 SDL_LockMutex(is->pictq_mutex);
2202 SDL_CondSignal(is->pictq_cond);
2203 SDL_UnlockMutex(is->pictq_mutex);
2205 SDL_WaitThread(is->video_tid, NULL);
2207 packet_queue_end(&is->videoq);
2208 break;
2209 case AVMEDIA_TYPE_SUBTITLE:
2210 packet_queue_abort(&is->subtitleq);
2212 /* note: we also signal this mutex to make sure we deblock the
2213 video thread in all cases */
2214 SDL_LockMutex(is->subpq_mutex);
2215 is->subtitle_stream_changed = 1;
2217 SDL_CondSignal(is->subpq_cond);
2218 SDL_UnlockMutex(is->subpq_mutex);
2220 SDL_WaitThread(is->subtitle_tid, NULL);
2222 packet_queue_end(&is->subtitleq);
2223 break;
2224 default:
2225 break;
2228 ic->streams[stream_index]->discard = AVDISCARD_ALL;
2229 switch (par->codec_type) {
2230 case AVMEDIA_TYPE_AUDIO:
2231 avcodec_free_context(&is->audio_dec);
2232 is->audio_st = NULL;
2233 is->audio_stream = -1;
2234 break;
2235 case AVMEDIA_TYPE_VIDEO:
2236 avcodec_free_context(&is->video_dec);
2237 is->video_st = NULL;
2238 is->video_stream = -1;
2239 break;
2240 case AVMEDIA_TYPE_SUBTITLE:
2241 avcodec_free_context(&is->subtitle_dec);
2242 is->subtitle_st = NULL;
2243 is->subtitle_stream = -1;
2244 break;
2245 default:
2246 break;
2250 /* since we have only one decoding thread, we can use a global
2251 variable instead of a thread local variable */
2252 static PlayerState *global_video_state;
2254 static int decode_interrupt_cb(void *ctx)
2256 return global_video_state && global_video_state->abort_request;
2259 static void stream_close(PlayerState *is)
2261 /* disable interrupting */
2262 global_video_state = NULL;
2264 /* close each stream */
2265 if (is->audio_stream >= 0)
2266 stream_component_close(is, is->audio_stream);
2267 if (is->video_stream >= 0)
2268 stream_component_close(is, is->video_stream);
2269 if (is->subtitle_stream >= 0)
2270 stream_component_close(is, is->subtitle_stream);
2271 if (is->ic) {
2272 avformat_close_input(&is->ic);
2276 static int stream_setup(PlayerState *is)
2278 AVFormatContext *ic = NULL;
2279 int err, i, ret;
2280 int st_index[AVMEDIA_TYPE_NB];
2281 AVDictionaryEntry *t;
2282 AVDictionary **opts;
2283 int orig_nb_streams;
2285 memset(st_index, -1, sizeof(st_index));
2286 is->video_stream = -1;
2287 is->audio_stream = -1;
2288 is->subtitle_stream = -1;
2290 global_video_state = is;
2292 ic = avformat_alloc_context();
2293 if (!ic) {
2294 av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
2295 ret = AVERROR(ENOMEM);
2296 goto fail;
2298 ic->interrupt_callback.callback = decode_interrupt_cb;
2299 err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
2300 if (err < 0) {
2301 print_error(is->filename, err);
2302 ret = -1;
2303 goto fail;
2306 if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
2307 av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
2308 ret = AVERROR_OPTION_NOT_FOUND;
2309 goto fail;
2311 is->ic = ic;
2313 if (genpts)
2314 ic->flags |= AVFMT_FLAG_GENPTS;
2316 opts = setup_find_stream_info_opts(ic, codec_opts);
2317 orig_nb_streams = ic->nb_streams;
2319 for (i = 0; i < ic->nb_streams; i++)
2320 choose_decoder(is, ic, ic->streams[i]);
2322 err = avformat_find_stream_info(ic, opts);
2324 for (i = 0; i < orig_nb_streams; i++)
2325 av_dict_free(&opts[i]);
2326 av_freep(&opts);
2328 if (err < 0) {
2329 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
2330 ret = -1;
2331 goto fail;
2334 if (ic->pb)
2335 ic->pb->eof_reached = 0; // FIXME hack, avplay maybe should not use url_feof() to test for the end
2337 if (seek_by_bytes < 0)
2338 seek_by_bytes = !!(ic->iformat->flags & AVFMT_TS_DISCONT);
2340 /* if seeking requested, we execute it */
2341 if (start_time != AV_NOPTS_VALUE) {
2342 int64_t timestamp;
2344 timestamp = start_time;
2345 /* add the stream start time */
2346 if (ic->start_time != AV_NOPTS_VALUE)
2347 timestamp += ic->start_time;
2348 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
2349 if (ret < 0) {
2350 fprintf(stderr, "%s: could not seek to position %0.3f\n",
2351 is->filename, (double)timestamp / AV_TIME_BASE);
2355 for (i = 0; i < ic->nb_streams; i++)
2356 ic->streams[i]->discard = AVDISCARD_ALL;
2357 if (!video_disable)
2358 st_index[AVMEDIA_TYPE_VIDEO] =
2359 av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
2360 wanted_stream[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
2361 if (!audio_disable)
2362 st_index[AVMEDIA_TYPE_AUDIO] =
2363 av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
2364 wanted_stream[AVMEDIA_TYPE_AUDIO],
2365 st_index[AVMEDIA_TYPE_VIDEO],
2366 NULL, 0);
2367 if (!video_disable)
2368 st_index[AVMEDIA_TYPE_SUBTITLE] =
2369 av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
2370 wanted_stream[AVMEDIA_TYPE_SUBTITLE],
2371 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
2372 st_index[AVMEDIA_TYPE_AUDIO] :
2373 st_index[AVMEDIA_TYPE_VIDEO]),
2374 NULL, 0);
2375 if (show_status) {
2376 av_dump_format(ic, 0, is->filename, 0);
2379 /* open the streams */
2380 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2381 stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
2384 ret = -1;
2385 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2386 ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
2388 if (ret < 0) {
2389 if (!display_disable)
2390 is->show_audio = 2;
2393 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2394 stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
2397 if (is->video_stream < 0 && is->audio_stream < 0) {
2398 fprintf(stderr, "%s: could not open codecs\n", is->filename);
2399 ret = -1;
2400 goto fail;
2403 return 0;
2405 fail:
2406 return ret;
2409 /* this thread gets the stream from the disk or the network */
2410 static int decode_thread(void *arg)
2412 PlayerState *is = arg;
2413 AVPacket pkt1, *pkt = &pkt1;
2414 AVFormatContext *ic = is->ic;
2415 int pkt_in_play_range = 0;
2416 int ret, eof = 0;
2418 for (;;) {
2419 if (is->abort_request)
2420 break;
2421 if (is->paused != is->last_paused) {
2422 is->last_paused = is->paused;
2423 if (is->paused)
2424 is->read_pause_return = av_read_pause(ic);
2425 else
2426 av_read_play(ic);
2428 #if CONFIG_RTSP_DEMUXER
2429 if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
2430 /* wait 10 ms to avoid trying to get another packet */
2431 /* XXX: horrible */
2432 SDL_Delay(10);
2433 continue;
2435 #endif
2436 if (is->seek_req) {
2437 int64_t seek_target = is->seek_pos;
2438 int64_t seek_min = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2439 int64_t seek_max = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2440 // FIXME the +-2 is due to rounding being not done in the correct direction in generation
2441 // of the seek_pos/seek_rel variables
2443 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2444 if (ret < 0) {
2445 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
2446 } else {
2447 if (is->audio_stream >= 0) {
2448 packet_queue_flush(&is->audioq);
2449 packet_queue_put(&is->audioq, &flush_pkt);
2451 if (is->subtitle_stream >= 0) {
2452 packet_queue_flush(&is->subtitleq);
2453 packet_queue_put(&is->subtitleq, &flush_pkt);
2455 if (is->video_stream >= 0) {
2456 packet_queue_flush(&is->videoq);
2457 packet_queue_put(&is->videoq, &flush_pkt);
2460 is->seek_req = 0;
2461 eof = 0;
2464 /* if the queue are full, no need to read more */
2465 if (!infinite_buffer &&
2466 (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2467 || ( (is->audioq .size > MIN_AUDIOQ_SIZE || is->audio_stream < 0)
2468 && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream < 0)
2469 && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0)))) {
2470 /* wait 10 ms */
2471 SDL_Delay(10);
2472 continue;
2474 if (eof) {
2475 if (is->video_stream >= 0) {
2476 av_init_packet(pkt);
2477 pkt->data = NULL;
2478 pkt->size = 0;
2479 pkt->stream_index = is->video_stream;
2480 packet_queue_put(&is->videoq, pkt);
2482 if (is->audio_stream >= 0 &&
2483 (is->audio_dec->codec->capabilities & AV_CODEC_CAP_DELAY)) {
2484 av_init_packet(pkt);
2485 pkt->data = NULL;
2486 pkt->size = 0;
2487 pkt->stream_index = is->audio_stream;
2488 packet_queue_put(&is->audioq, pkt);
2490 SDL_Delay(10);
2491 if (is->audioq.size + is->videoq.size + is->subtitleq.size == 0) {
2492 if (loop != 1 && (!loop || --loop)) {
2493 stream_seek(player, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
2494 } else if (!noautoexit) {
2495 ret = AVERROR_EOF;
2496 goto fail;
2499 continue;
2501 ret = av_read_frame(ic, pkt);
2502 if (ret < 0) {
2503 if (ret == AVERROR_EOF || (ic->pb && ic->pb->eof_reached))
2504 eof = 1;
2505 if (ic->pb && ic->pb->error)
2506 break;
2507 SDL_Delay(100); /* wait for user event */
2508 continue;
2510 /* check if packet is in play range specified by user, then queue, otherwise discard */
2511 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
2512 (pkt->pts - ic->streams[pkt->stream_index]->start_time) *
2513 av_q2d(ic->streams[pkt->stream_index]->time_base) -
2514 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000
2515 <= ((double)duration / 1000000);
2516 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
2517 packet_queue_put(&is->audioq, pkt);
2518 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range) {
2519 packet_queue_put(&is->videoq, pkt);
2520 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
2521 packet_queue_put(&is->subtitleq, pkt);
2522 } else {
2523 av_packet_unref(pkt);
2526 /* wait until the end */
2527 while (!is->abort_request) {
2528 SDL_Delay(100);
2531 ret = 0;
2533 fail:
2534 stream_close(is);
2536 if (ret != 0) {
2537 SDL_Event event;
2539 event.type = FF_QUIT_EVENT;
2540 event.user.data1 = is;
2541 SDL_PushEvent(&event);
2543 return 0;
2546 static int stream_open(PlayerState *is,
2547 const char *filename, AVInputFormat *iformat)
2549 int ret;
2551 av_strlcpy(is->filename, filename, sizeof(is->filename));
2552 is->iformat = iformat;
2553 is->ytop = 0;
2554 is->xleft = 0;
2556 if ((ret = stream_setup(is)) < 0) {
2557 return ret;
2560 is->video_filter_mutex = SDL_CreateMutex();
2562 /* start video display */
2563 is->pictq_mutex = SDL_CreateMutex();
2564 is->pictq_cond = SDL_CreateCond();
2566 is->subpq_mutex = SDL_CreateMutex();
2567 is->subpq_cond = SDL_CreateCond();
2569 is->av_sync_type = av_sync_type;
2570 is->refresh_tid = SDL_CreateThread(refresh_thread, is);
2571 if (!is->refresh_tid)
2572 return -1;
2573 is->parse_tid = SDL_CreateThread(decode_thread, is);
2574 if (!is->parse_tid)
2575 return -1;
2576 return 0;
2579 static void stream_cycle_channel(PlayerState *is, int codec_type)
2581 AVFormatContext *ic = is->ic;
2582 int start_index, stream_index;
2583 AVStream *st;
2585 if (codec_type == AVMEDIA_TYPE_VIDEO)
2586 start_index = is->video_stream;
2587 else if (codec_type == AVMEDIA_TYPE_AUDIO)
2588 start_index = is->audio_stream;
2589 else
2590 start_index = is->subtitle_stream;
2591 if (start_index < (codec_type == AVMEDIA_TYPE_SUBTITLE ? -1 : 0))
2592 return;
2593 stream_index = start_index;
2594 for (;;) {
2595 if (++stream_index >= is->ic->nb_streams)
2597 if (codec_type == AVMEDIA_TYPE_SUBTITLE)
2599 stream_index = -1;
2600 goto the_end;
2601 } else
2602 stream_index = 0;
2604 if (stream_index == start_index)
2605 return;
2606 st = ic->streams[stream_index];
2607 if (st->codecpar->codec_type == codec_type) {
2608 /* check that parameters are OK */
2609 switch (codec_type) {
2610 case AVMEDIA_TYPE_AUDIO:
2611 if (st->codecpar->sample_rate != 0 &&
2612 st->codecpar->channels != 0)
2613 goto the_end;
2614 break;
2615 case AVMEDIA_TYPE_VIDEO:
2616 case AVMEDIA_TYPE_SUBTITLE:
2617 goto the_end;
2618 default:
2619 break;
2623 the_end:
2624 stream_component_close(is, start_index);
2625 stream_component_open(is, stream_index);
2629 static void toggle_full_screen(void)
2631 #if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
2632 /* OS X needs to empty the picture_queue */
2633 int i;
2634 for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++)
2635 player->pictq[i].reallocate = 1;
2636 #endif
2637 is_full_screen = !is_full_screen;
2638 video_open(player);
2641 static void toggle_pause(void)
2643 if (player)
2644 stream_pause(player);
2645 step = 0;
2648 static void step_to_next_frame(void)
2650 if (player) {
2651 /* if the stream is paused unpause it, then step */
2652 if (player->paused)
2653 stream_pause(player);
2655 step = 1;
2658 static void toggle_audio_display(void)
2660 if (player) {
2661 int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
2662 player->show_audio = (player->show_audio + 1) % 3;
2663 fill_rectangle(screen,
2664 player->xleft, player->ytop, player->width, player->height,
2665 bgcolor);
2666 SDL_UpdateRect(screen, player->xleft, player->ytop, player->width, player->height);
2670 static void seek_chapter(PlayerState *is, int incr)
2672 int64_t pos = get_master_clock(is) * AV_TIME_BASE;
2673 int i;
2675 if (!is->ic->nb_chapters)
2676 return;
2678 /* find the current chapter */
2679 for (i = 0; i < is->ic->nb_chapters; i++) {
2680 AVChapter *ch = is->ic->chapters[i];
2681 if (av_compare_ts(pos, AV_TIME_BASE_Q, ch->start, ch->time_base) < 0) {
2682 i--;
2683 break;
2687 i += incr;
2688 i = FFMAX(i, 0);
2689 if (i >= is->ic->nb_chapters)
2690 return;
2692 av_log(NULL, AV_LOG_VERBOSE, "Seeking to chapter %d.\n", i);
2693 stream_seek(is, av_rescale_q(is->ic->chapters[i]->start, is->ic->chapters[i]->time_base,
2694 AV_TIME_BASE_Q), 0, 0);
2697 /* handle an event sent by the GUI */
2698 static void event_loop(void)
2700 SDL_Event event;
2701 double incr, pos, frac;
2703 for (;;) {
2704 double x;
2705 SDL_WaitEvent(&event);
2706 switch (event.type) {
2707 case SDL_KEYDOWN:
2708 if (exit_on_keydown) {
2709 do_exit();
2710 break;
2712 switch (event.key.keysym.sym) {
2713 case SDLK_ESCAPE:
2714 case SDLK_q:
2715 do_exit();
2716 break;
2717 case SDLK_f:
2718 toggle_full_screen();
2719 break;
2720 case SDLK_p:
2721 case SDLK_SPACE:
2722 toggle_pause();
2723 break;
2724 case SDLK_s: // S: Step to next frame
2725 step_to_next_frame();
2726 break;
2727 case SDLK_a:
2728 if (player)
2729 stream_cycle_channel(player, AVMEDIA_TYPE_AUDIO);
2730 break;
2731 case SDLK_v:
2732 if (player)
2733 stream_cycle_channel(player, AVMEDIA_TYPE_VIDEO);
2734 break;
2735 case SDLK_t:
2736 if (player)
2737 stream_cycle_channel(player, AVMEDIA_TYPE_SUBTITLE);
2738 break;
2739 case SDLK_w:
2740 toggle_audio_display();
2741 break;
2742 case SDLK_PAGEUP:
2743 seek_chapter(player, 1);
2744 break;
2745 case SDLK_PAGEDOWN:
2746 seek_chapter(player, -1);
2747 break;
2748 case SDLK_LEFT:
2749 incr = -10.0;
2750 goto do_seek;
2751 case SDLK_RIGHT:
2752 incr = 10.0;
2753 goto do_seek;
2754 case SDLK_UP:
2755 incr = 60.0;
2756 goto do_seek;
2757 case SDLK_DOWN:
2758 incr = -60.0;
2759 do_seek:
2760 if (player) {
2761 if (seek_by_bytes) {
2762 if (player->video_stream >= 0 && player->video_current_pos >= 0) {
2763 pos = player->video_current_pos;
2764 } else if (player->audio_stream >= 0 && player->audio_pkt.pos >= 0) {
2765 pos = player->audio_pkt.pos;
2766 } else
2767 pos = avio_tell(player->ic->pb);
2768 if (player->ic->bit_rate)
2769 incr *= player->ic->bit_rate / 8.0;
2770 else
2771 incr *= 180000.0;
2772 pos += incr;
2773 stream_seek(player, pos, incr, 1);
2774 } else {
2775 pos = get_master_clock(player);
2776 pos += incr;
2777 stream_seek(player, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
2780 break;
2781 default:
2782 break;
2784 break;
2785 case SDL_MOUSEBUTTONDOWN:
2786 if (exit_on_mousedown) {
2787 do_exit();
2788 break;
2790 case SDL_MOUSEMOTION:
2791 if (event.type == SDL_MOUSEBUTTONDOWN) {
2792 x = event.button.x;
2793 } else {
2794 if (event.motion.state != SDL_PRESSED)
2795 break;
2796 x = event.motion.x;
2798 if (player) {
2799 if (seek_by_bytes || player->ic->duration <= 0) {
2800 uint64_t size = avio_size(player->ic->pb);
2801 stream_seek(player, size*x/player->width, 0, 1);
2802 } else {
2803 int64_t ts;
2804 int ns, hh, mm, ss;
2805 int tns, thh, tmm, tss;
2806 tns = player->ic->duration / 1000000LL;
2807 thh = tns / 3600;
2808 tmm = (tns % 3600) / 60;
2809 tss = (tns % 60);
2810 frac = x / player->width;
2811 ns = frac * tns;
2812 hh = ns / 3600;
2813 mm = (ns % 3600) / 60;
2814 ss = (ns % 60);
2815 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2816 hh, mm, ss, thh, tmm, tss);
2817 ts = frac * player->ic->duration;
2818 if (player->ic->start_time != AV_NOPTS_VALUE)
2819 ts += player->ic->start_time;
2820 stream_seek(player, ts, 0, 0);
2823 break;
2824 case SDL_VIDEORESIZE:
2825 if (player) {
2826 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2827 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2828 screen_width = player->width = event.resize.w;
2829 screen_height = player->height = event.resize.h;
2831 break;
2832 case SDL_QUIT:
2833 case FF_QUIT_EVENT:
2834 do_exit();
2835 break;
2836 case FF_ALLOC_EVENT:
2837 SDL_LockMutex(player->video_filter_mutex);
2838 if (player->out_video_filter) {
2839 video_open(event.user.data1);
2840 alloc_picture(event.user.data1);
2842 SDL_UnlockMutex(player->video_filter_mutex);
2843 break;
2844 case FF_REFRESH_EVENT:
2845 video_refresh_timer(event.user.data1);
2846 player->refresh = 0;
2847 break;
2848 default:
2849 break;
2854 static int opt_frame_size(void *optctx, const char *opt, const char *arg)
2856 av_log(NULL, AV_LOG_ERROR,
2857 "Option '%s' has been removed, use private format options instead\n", opt);
2858 return AVERROR(EINVAL);
2861 static int opt_width(void *optctx, const char *opt, const char *arg)
2863 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2864 return 0;
2867 static int opt_height(void *optctx, const char *opt, const char *arg)
2869 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2870 return 0;
2873 static int opt_format(void *optctx, const char *opt, const char *arg)
2875 file_iformat = av_find_input_format(arg);
2876 if (!file_iformat) {
2877 fprintf(stderr, "Unknown input format: %s\n", arg);
2878 return AVERROR(EINVAL);
2880 return 0;
2883 static int opt_frame_pix_fmt(void *optctx, const char *opt, const char *arg)
2885 av_log(NULL, AV_LOG_ERROR,
2886 "Option '%s' has been removed, use private format options instead\n", opt);
2887 return AVERROR(EINVAL);
2890 static int opt_sync(void *optctx, const char *opt, const char *arg)
2892 if (!strcmp(arg, "audio"))
2893 av_sync_type = AV_SYNC_AUDIO_MASTER;
2894 else if (!strcmp(arg, "video"))
2895 av_sync_type = AV_SYNC_VIDEO_MASTER;
2896 else if (!strcmp(arg, "ext"))
2897 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2898 else {
2899 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
2900 exit(1);
2902 return 0;
2905 static int opt_seek(void *optctx, const char *opt, const char *arg)
2907 start_time = parse_time_or_die(opt, arg, 1);
2908 return 0;
2911 static int opt_duration(void *optctx, const char *opt, const char *arg)
2913 duration = parse_time_or_die(opt, arg, 1);
2914 return 0;
2917 #define OFF(x) offsetof(PlayerState, x)
2918 static const OptionDef options[] = {
2919 CMDUTILS_COMMON_OPTIONS
2920 { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
2921 { "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
2922 { "s", HAS_ARG | OPT_VIDEO, { .func_arg = opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },
2923 { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },
2924 { "an", OPT_BOOL, { &audio_disable }, "disable audio" },
2925 { "vn", OPT_BOOL, { &video_disable }, "disable video" },
2926 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_number" },
2927 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_number" },
2928 { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_number" },
2929 { "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" },
2930 { "t", HAS_ARG, { .func_arg = opt_duration }, "play \"duration\" seconds of audio/video", "duration" },
2931 { "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
2932 { "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" },
2933 { "f", HAS_ARG, { .func_arg = opt_format }, "force format", "fmt" },
2934 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_frame_pix_fmt }, "set pixel format", "format" },
2935 { "stats", OPT_BOOL | OPT_EXPERT, { &show_status }, "show status", "" },
2936 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, { &workaround_bugs }, "workaround bugs", "" },
2937 { "fast", OPT_BOOL | OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
2938 { "genpts", OPT_BOOL | OPT_EXPERT, { &genpts }, "generate pts", "" },
2939 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
2940 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_loop_filter }, "", "" },
2941 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_frame }, "", "" },
2942 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_idct }, "", "" },
2943 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, { &idct }, "set idct algo", "algo" },
2944 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, { &error_concealment }, "set error concealment options", "bit_mask" },
2945 { "sync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
2946 { "noautoexit", OPT_BOOL | OPT_EXPERT, { &noautoexit }, "Do not exit at the end of playback", "" },
2947 { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
2948 { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
2949 { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
2950 { "framedrop", OPT_BOOL | OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
2951 { "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
2952 { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
2953 { "vf", OPT_STRING | HAS_ARG, { &vfilters }, "video filters", "filter list" },
2954 { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
2955 { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default }, "generic catchall option", "" },
2956 { "i", 0, { NULL }, "avconv compatibility dummy option", ""},
2957 { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" },
2958 { "c", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT, { .off = OFF(codec_names) }, "codec name", "codec" },
2959 { "codec", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT, { .off = OFF(codec_names) }, "codec name", "codec" },
2961 { NULL, },
2964 static void show_usage(void)
2966 printf("Simple media player\n");
2967 printf("usage: %s [options] input_file\n", program_name);
2968 printf("\n");
2971 void show_help_default(const char *opt, const char *arg)
2973 av_log_set_callback(log_callback_help);
2974 show_usage();
2975 show_help_options(options, "Main options:", 0, OPT_EXPERT, 0);
2976 show_help_options(options, "Advanced options:", OPT_EXPERT, 0, 0);
2977 printf("\n");
2978 show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
2979 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
2980 printf("\nWhile playing:\n"
2981 "q, ESC quit\n"
2982 "f toggle full screen\n"
2983 "p, SPC pause\n"
2984 "a cycle audio channel\n"
2985 "v cycle video channel\n"
2986 "t cycle subtitle channel\n"
2987 "w show audio waves\n"
2988 "s activate frame-step mode\n"
2989 "left/right seek backward/forward 10 seconds\n"
2990 "down/up seek backward/forward 1 minute\n"
2991 "mouse click seek to percentage in file corresponding to fraction of width\n"
2995 static void opt_input_file(void *optctx, const char *filename)
2997 if (input_filename) {
2998 fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
2999 filename, input_filename);
3000 exit(1);
3002 if (!strcmp(filename, "-"))
3003 filename = "pipe:";
3004 input_filename = filename;
3007 /* Called from the main */
3008 int main(int argc, char **argv)
3010 int flags;
3012 av_log_set_flags(AV_LOG_SKIP_REPEATED);
3013 parse_loglevel(argc, argv, options);
3015 /* register all codecs, demux and protocols */
3016 avcodec_register_all();
3017 #if CONFIG_AVDEVICE
3018 avdevice_register_all();
3019 #endif
3020 avfilter_register_all();
3021 av_register_all();
3022 avformat_network_init();
3024 init_opts();
3026 show_banner();
3028 parse_options(player, argc, argv, options, opt_input_file);
3030 if (!input_filename) {
3031 show_usage();
3032 fprintf(stderr, "An input file must be specified\n");
3033 fprintf(stderr, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
3034 exit(1);
3037 if (display_disable) {
3038 video_disable = 1;
3040 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3041 #if !defined(__MINGW32__) && !defined(__APPLE__)
3042 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
3043 #endif
3044 if (SDL_Init (flags)) {
3045 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
3046 exit(1);
3049 if (!display_disable) {
3050 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
3051 fs_screen_width = vi->current_w;
3052 fs_screen_height = vi->current_h;
3055 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
3056 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3057 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3059 av_init_packet(&flush_pkt);
3060 flush_pkt.data = (uint8_t *)&flush_pkt;
3062 if (stream_open(player, input_filename, file_iformat) < 0) {
3063 fprintf(stderr, "Could not setup the player\n");
3064 stream_close(player);
3065 exit(1);
3068 event_loop();
3070 /* never returns */
3072 return 0;