57 #include <SDL_thread.h>
66 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
71 #define SDL_AUDIO_BUFFER_SIZE 1024
74 #define AV_SYNC_THRESHOLD 0.01
76 #define AV_NOSYNC_THRESHOLD 10.0
79 #define SAMPLE_CORRECTION_PERCENT_MAX 10
82 #define EXTERNAL_CLOCK_SPEED_MIN 0.900
83 #define EXTERNAL_CLOCK_SPEED_MAX 1.010
84 #define EXTERNAL_CLOCK_SPEED_STEP 0.001
87 #define AUDIO_DIFF_AVG_NB 20
91 #define SAMPLE_ARRAY_SIZE (8 * 65536)
93 #define CURSOR_HIDE_DELAY 1000000
113 #define VIDEO_PICTURE_QUEUE_SIZE 4
114 #define SUBPICTURE_QUEUE_SIZE 4
311 static char *vfilters =
NULL;
320 #define FF_ALLOC_EVENT (SDL_USEREVENT)
321 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
322 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
340 if (pkt == &flush_pkt)
352 SDL_CondSignal(q->
cond);
364 SDL_LockMutex(q->
mutex);
366 SDL_UnlockMutex(q->
mutex);
368 if (pkt != &flush_pkt && ret < 0)
378 q->
mutex = SDL_CreateMutex();
379 q->
cond = SDL_CreateCond();
387 SDL_LockMutex(q->
mutex);
397 SDL_UnlockMutex(q->
mutex);
403 SDL_DestroyMutex(q->
mutex);
404 SDL_DestroyCond(q->
cond);
409 SDL_LockMutex(q->
mutex);
413 SDL_CondSignal(q->
cond);
415 SDL_UnlockMutex(q->
mutex);
420 SDL_LockMutex(q->
mutex);
423 SDL_UnlockMutex(q->
mutex);
432 SDL_LockMutex(q->
mutex);
460 SDL_UnlockMutex(q->
mutex);
465 int x,
int y,
int w,
int h,
int color,
int update)
472 SDL_FillRect(screen, &rect, color);
473 if (update && w > 0 && h > 0)
474 SDL_UpdateRect(screen, x, y, w, h);
486 w2 = width - (x + w);
492 h2 = height - (y + h);
500 xleft + width - w2, ytop,
508 xleft + w1, ytop + height - h2,
513 #define ALPHA_BLEND(a, oldp, newp, s)\
514 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
516 #define RGBA_IN(r, g, b, a, s)\
518 unsigned int v = ((const uint32_t *)(s))[0];\
519 a = (v >> 24) & 0xff;\
520 r = (v >> 16) & 0xff;\
521 g = (v >> 8) & 0xff;\
525 #define YUVA_IN(y, u, v, a, s, pal)\
527 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
528 a = (val >> 24) & 0xff;\
529 y = (val >> 16) & 0xff;\
530 u = (val >> 8) & 0xff;\
534 #define YUVA_OUT(d, y, u, v, a)\
536 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
544 int wrap, wrap3, width2, skip2;
545 int y, u, v,
a, u1, v1,
a1, w, h;
549 int dstx, dsty, dstw, dsth;
551 dstw = av_clip(rect->
w, 0, imgw);
552 dsth = av_clip(rect->
h, 0, imgh);
553 dstx = av_clip(rect->
x, 0, imgw - dstw);
554 dsty = av_clip(rect->
y, 0, imgh - dsth);
559 width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
564 pal = (
const uint32_t *)rect->
pict.
data[1];
581 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
608 p += wrap3 - dstw *
BPP;
609 lum += wrap - dstw - dstx;
610 cb += dst->
linesize[1] - width2 - skip2;
611 cr += dst->
linesize[2] - width2 - skip2;
613 for (h = dsth - (dsty & 1); h >= 2; h -= 2) {
638 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
670 p += -wrap3 + 2 *
BPP;
693 p += wrap3 + (wrap3 - dstw *
BPP);
694 lum += wrap + (wrap - dstw - dstx);
695 cb += dst->
linesize[1] - width2 - skip2;
696 cr += dst->
linesize[2] - width2 - skip2;
714 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
757 if (aspect_ratio <= 0.0)
759 aspect_ratio *= (float)vp->
width / (
float)vp->
height;
763 width = ((int)
rint(height * aspect_ratio)) & ~1;
764 if (width > scr_width) {
766 height = ((int)
rint(width / aspect_ratio)) & ~1;
768 x = (scr_width -
width) / 2;
769 y = (scr_height -
height) / 2;
770 rect->x = scr_xleft + x;
771 rect->y = scr_ytop + y;
772 rect->w =
FFMAX(width, 1);
773 rect->h =
FFMAX(height, 1);
791 SDL_LockYUVOverlay (vp->
bmp);
793 pict.
data[0] = vp->
bmp->pixels[0];
794 pict.
data[1] = vp->
bmp->pixels[2];
795 pict.
data[2] = vp->
bmp->pixels[1];
805 SDL_UnlockYUVOverlay (vp->
bmp);
812 SDL_DisplayYUVOverlay(vp->
bmp, &rect);
815 int bgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0x00);
824 return a < 0 ? a%b + b : a%
b;
829 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
830 int ch, channels, h, h2, bgcolor, fgcolor;
832 int rdft_bits, nb_freq;
834 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->
height; rdft_bits++)
836 nb_freq = 1 << (rdft_bits - 1);
840 nb_display_channels = channels;
842 int data_used= s->
show_mode == SHOW_MODE_WAVES ? s->
width : (2*nb_freq);
854 delay += 2 * data_used;
855 if (delay < data_used)
861 for (i = 0; i < 1000; i += channels) {
868 if (h < score && (b ^ c) < 0) {
880 bgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0x00);
886 fgcolor = SDL_MapRGB(
screen->format, 0xff, 0xff, 0xff);
889 h = s->
height / nb_display_channels;
892 for (ch = 0; ch < nb_display_channels; ch++) {
894 y1 = s->
ytop + ch * h + (h / 2);
895 for (x = 0; x < s->
width; x++) {
904 s->
xleft + x, ys, 1, y,
912 fgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0xff);
914 for (ch = 1; ch < nb_display_channels; ch++) {
915 y = s->
ytop + ch * h;
922 nb_display_channels=
FFMIN(nb_display_channels, 2);
932 for (ch = 0; ch < nb_display_channels; ch++) {
933 data[ch] = s->
rdft_data + 2 * nb_freq * ch;
935 for (x = 0; x < 2 * nb_freq; x++) {
936 double w = (x-nb_freq) * (1.0 / nb_freq);
945 for (y = 0; y < s->
height; y++) {
946 double w = 1 / sqrt(nb_freq);
947 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]));
948 int b = (nb_display_channels == 2 ) ? sqrt(w * sqrt(data[1][2 * y + 0] * data[1][2 * y + 0]
949 + data[1][2 * y + 1] * data[1][2 * y + 1])) : a;
952 fgcolor = SDL_MapRGB(
screen->format, a, b, (a + b) / 2);
986 SDL_FreeYUVOverlay(vp->
bmp);
1028 int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
1034 else flags |= SDL_RESIZABLE;
1042 }
else if (vp->
width) {
1053 screen = SDL_SetVideoMode(w, h, 0, flags);
1055 fprintf(stderr,
"SDL: could not set video mode - exiting\n");
1085 event.user.data1 = opaque;
1088 SDL_PushEvent(&event);
1223 double sync_threshold,
diff;
1236 if (diff <= -sync_threshold)
1238 else if (diff >= sync_threshold)
1315 double last_duration,
duration, delay;
1329 if (last_duration > 0 && last_duration < is->max_frame_duration) {
1336 if (time < is->frame_timer + delay)
1348 duration = nextvp->
pts - vp->
pts;
1413 static int64_t last_time;
1415 int aqsize, vqsize, sqsize;
1419 if (!last_time || (cur_time - last_time) >= 30000) {
1432 printf(
"%7.2f A-V:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64
"/%"PRId64
" \r",
1456 SDL_FreeYUVOverlay(vp->
bmp);
1467 if (!vp->
bmp || vp->
bmp->pitches[0] < vp->
width) {
1470 fprintf(stderr,
"Error: the video system does not support an image\n"
1471 "size of %dx%d pixels. Try using -lowres or -vf \"scale=w:h\"\n"
1472 "to reduce the image size.\n", vp->
width, vp->
height );
1485 for (i = 0; i < 3; i++) {
1492 if (bmp->pitches[i] > width) {
1493 maxp = bmp->pixels[i] + bmp->pitches[i] * height - 1;
1494 for (p = bmp->pixels[i] + width - 1; p < maxp; p += bmp->pitches[i])
1503 double frame_delay, pts = pts1;
1517 frame_delay += src_frame->
repeat_pict * (frame_delay * 0.5);
1520 #if defined(DEBUG_SYNC) && 0
1521 printf(
"frame_type=%c clock=%0.3f pts=%0.3f\n",
1560 event.user.data1 = is;
1561 SDL_PushEvent(&event);
1585 vp->picref = src_frame->
opaque;
1589 SDL_LockYUVOverlay (vp->
bmp);
1591 pict.
data[0] = vp->
bmp->pixels[0];
1592 pict.
data[1] = vp->
bmp->pixels[2];
1593 pict.
data[2] = vp->
bmp->pixels[1];
1609 fprintf(stderr,
"Cannot initialize the conversion context\n");
1618 SDL_UnlockYUVOverlay(vp->
bmp);
1714 if (!outputs || !inputs) {
1725 inputs->filter_ctx = sink_ctx;
1726 inputs->pad_idx = 0;
1727 inputs->next =
NULL;
1746 char sws_flags_str[128];
1747 char buffersrc_args[256];
1753 if (!buffersink_params)
1759 snprintf(buffersrc_args,
sizeof(buffersrc_args),
1760 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
1767 "ffplay_buffer", buffersrc_args,
NULL,
1774 "ffplay_buffersink",
NULL, buffersink_params, graph);
1782 "ffplay_crop",
"floor(in_w/2)*2:floor(in_h/2)*2",
NULL, graph)) < 0)
1790 is->in_video_filter = filt_src;
1791 is->out_video_filter = filt_out;
1822 codec->
opaque = &is->buffer_pool;
1845 if ( last_w != frame->
width
1846 || last_h != frame->
height
1847 || last_format != frame->
format) {
1852 if ((ret = configure_video_filters(graph, is, vfilters, frame)) < 0) {
1855 event.user.data1 = is;
1856 SDL_PushEvent(&event);
1860 filt_in = is->in_video_filter;
1861 filt_out = is->out_video_filter;
1862 last_w = frame->
width;
1864 last_format = frame->
format;
1867 frame->
pts = pts_int;
1869 if (is->use_dr1 && frame->
opaque) {
1904 pts_int = picref->
pts;
1913 "tb:%d/%d pts:%"PRId64
" -> tb:%d/%d pts:%"PRId64
"\n",
1946 int r,
g,
b, y, u, v,
a;
1978 &got_subtitle, pkt);
1979 if (got_subtitle && sp->
sub.
format == 0) {
2013 size = samples_size /
sizeof(short);
2035 double diff, avg_diff;
2036 int min_nb_samples, max_nb_samples;
2050 wanted_nb_samples = nb_samples + (int)(diff * is->
audio_src.
freq);
2053 wanted_nb_samples =
FFMIN(
FFMAX(wanted_nb_samples, min_nb_samples), max_nb_samples);
2055 av_dlog(
NULL,
"diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
2056 diff, avg_diff, wanted_nb_samples - nb_samples,
2067 return wanted_nb_samples;
2076 int len1, len2, data_size, resampled_data_size;
2077 int64_t dec_channel_layout;
2081 int flush_complete = 0;
2082 int wanted_nb_samples;
2086 while (pkt_temp->
size > 0 || (!pkt_temp->
data && new_packet)) {
2106 pkt_temp->
data += len1;
2107 pkt_temp->
size -= len1;
2119 dec_channel_layout =
2134 fprintf(stderr,
"Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2152 fprintf(stderr,
"swr_set_compensation() failed\n");
2158 fprintf(stderr,
"swr_convert() failed\n");
2161 if (len2 == out_count) {
2162 fprintf(stderr,
"warning: audio buffer is probably too small\n");
2169 resampled_data_size = data_size;
2179 static double last_clock;
2180 printf(
"audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
2186 return resampled_data_size;
2192 memset(pkt_temp, 0,
sizeof(*pkt_temp));
2233 if (audio_size < 0) {
2261 static int audio_open(
void *opaque, int64_t wanted_channel_layout,
int wanted_nb_channels,
int wanted_sample_rate,
struct AudioParams *audio_hw_params)
2263 SDL_AudioSpec wanted_spec, spec;
2265 const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2267 env = SDL_getenv(
"SDL_AUDIO_CHANNELS");
2269 wanted_nb_channels = atoi(env);
2277 wanted_spec.freq = wanted_sample_rate;
2278 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2279 fprintf(stderr,
"Invalid sample rate or channel count!\n");
2282 wanted_spec.format = AUDIO_S16SYS;
2283 wanted_spec.silence = 0;
2286 wanted_spec.userdata = opaque;
2287 while (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
2288 fprintf(stderr,
"SDL_OpenAudio (%d channels): %s\n", wanted_spec.channels, SDL_GetError());
2289 wanted_spec.channels = next_nb_channels[
FFMIN(7, wanted_spec.channels)];
2290 if (!wanted_spec.channels) {
2291 fprintf(stderr,
"No more channel combinations to try, audio open failed\n");
2296 if (spec.format != AUDIO_S16SYS) {
2297 fprintf(stderr,
"SDL advised audio format %d is not supported!\n", spec.format);
2300 if (spec.channels != wanted_spec.channels) {
2302 if (!wanted_channel_layout) {
2303 fprintf(stderr,
"SDL advised channel count %d is not supported!\n", spec.channels);
2309 audio_hw_params->
freq = spec.freq;
2311 audio_hw_params->
channels = spec.channels;
2321 const char *forced_codec_name =
NULL;
2325 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2336 if (forced_codec_name)
2339 if (forced_codec_name) fprintf(stderr,
"No codec could be found with name '%s'\n", forced_codec_name);
2340 else fprintf(stderr,
"No codec could be found with id %d\n", avctx->
codec_id);
2376 if (audio_hw_buf_size < 0)
2427 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2520 if(s->
pb && ( !strncmp(s->
filename,
"rtp:", 4)
2521 || !strncmp(s->
filename,
"udp:", 4)
2537 int pkt_in_play_range = 0;
2540 int orig_nb_streams;
2541 SDL_mutex *wait_mutex = SDL_CreateMutex();
2543 memset(st_index, -1,
sizeof(st_index));
2572 fprintf(stderr,
"%s: could not find codec parameters\n", is->
filename);
2576 for (i = 0; i < orig_nb_streams; i++)
2598 fprintf(stderr,
"%s: could not seek to position %0.3f\n",
2615 st_index[AVMEDIA_TYPE_VIDEO],
2621 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
2622 st_index[AVMEDIA_TYPE_AUDIO] :
2623 st_index[AVMEDIA_TYPE_VIDEO]),
2632 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2637 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2642 is->
show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
2644 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2649 fprintf(stderr,
"%s: could not open codecs\n", is->
filename);
2654 if (infinite_buffer < 0 && is->realtime)
2667 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
2678 int64_t seek_target = is->
seek_pos;
2679 int64_t seek_min = is->
seek_rel > 0 ? seek_target - is->
seek_rel + 2: INT64_MIN;
2680 int64_t seek_max = is->
seek_rel < 0 ? seek_target - is->
seek_rel - 2: INT64_MAX;
2686 fprintf(stderr,
"%s: error while seeking\n", is->
ic->
filename);
2722 SDL_LockMutex(wait_mutex);
2724 SDL_UnlockMutex(wait_mutex);
2761 SDL_LockMutex(wait_mutex);
2763 SDL_UnlockMutex(wait_mutex);
2804 event.user.data1 = is;
2805 SDL_PushEvent(&event);
2807 SDL_DestroyMutex(wait_mutex);
2853 int start_index, stream_index;
2867 stream_index = start_index;
2877 if (start_index == -1)
2881 if (stream_index == start_index)
2883 st = ic->
streams[stream_index];
2886 switch (codec_type) {
2910 #if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
2936 int bgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0x00);
2947 double incr, pos, frac;
2951 SDL_WaitEvent(&event);
2952 switch (event.type) {
2958 switch (event.key.keysym.sym) {
3022 pos = cur_stream->
ic->
start_time / (double)AV_TIME_BASE;
3023 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
3030 case SDL_VIDEOEXPOSE:
3033 case SDL_MOUSEBUTTONDOWN:
3038 case SDL_MOUSEMOTION:
3044 if (event.type == SDL_MOUSEBUTTONDOWN) {
3047 if (event.motion.state != SDL_PRESSED)
3057 int tns, thh, tmm, tss;
3060 tmm = (tns % 3600) / 60;
3062 frac = x / cur_stream->
width;
3065 mm = (ns % 3600) / 60;
3067 fprintf(stderr,
"Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3068 hh, mm, ss, thh, tmm, tss);
3075 case SDL_VIDEORESIZE:
3076 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
3077 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
3124 if (!file_iformat) {
3125 fprintf(stderr,
"Unknown input format: %s\n", arg);
3139 if (!strcmp(arg,
"audio"))
3141 else if (!strcmp(arg,
"video"))
3143 else if (!strcmp(arg,
"ext"))
3146 fprintf(stderr,
"Unknown value for %s: %s\n", opt, arg);
3166 show_mode = !strcmp(arg,
"video") ? SHOW_MODE_VIDEO :
3167 !strcmp(arg,
"waves") ? SHOW_MODE_WAVES :
3168 !strcmp(arg,
"rdft" ) ? SHOW_MODE_RDFT :
3176 fprintf(stderr,
"Argument '%s' provided as input filename, but '%s' was already specified.\n",
3180 if (!strcmp(filename,
"-"))
3187 const char *spec = strchr(opt,
':');
3189 fprintf(stderr,
"No media specifier was specified in '%s' in option '%s'\n",
3199 fprintf(stderr,
"Invalid media specifier '%s' in option '%s'\n", spec, opt);
3209 {
"x",
HAS_ARG, { .func_arg =
opt_width },
"force displayed width",
"width" },
3210 {
"y",
HAS_ARG, { .func_arg =
opt_height },
"force displayed height",
"height" },
3218 {
"ss",
HAS_ARG, { .func_arg =
opt_seek },
"seek to a given position in seconds",
"pos" },
3219 {
"t",
HAS_ARG, { .func_arg =
opt_duration },
"play \"duration\" seconds of audio/video",
"duration" },
3235 {
"sync",
HAS_ARG |
OPT_EXPERT, { .func_arg =
opt_sync },
"set audio-video sync. type (type=audio/video/ext)",
"type" },
3247 {
"showmode",
HAS_ARG, { .func_arg =
opt_show_mode},
"select show mode (0 = video, 1 = waves, 2 = RDFT)",
"mode" },
3249 {
"i",
OPT_BOOL, { &dummy},
"read specified file",
"input_file"},
3250 {
"codec",
HAS_ARG, { .func_arg =
opt_codec},
"force decoder",
"decoder_name" },
3273 #if !CONFIG_AVFILTER
3278 printf(
"\nWhile playing:\n"
3280 "f toggle full screen\n"
3282 "a cycle audio channel\n"
3283 "v cycle video channel\n"
3284 "t cycle subtitle channel\n"
3285 "w show audio waves\n"
3286 "s activate frame-step mode\n"
3287 "left/right seek backward/forward 10 seconds\n"
3288 "down/up seek backward/forward 1 minute\n"
3289 "page down/page up seek backward/forward 10 minutes\n"
3290 "mouse click seek to percentage in file corresponding to fraction of width\n"
3298 *mtx = SDL_CreateMutex();
3303 return !!SDL_LockMutex(*mtx);
3305 return !!SDL_UnlockMutex(*mtx);
3307 SDL_DestroyMutex(*mtx);
3318 char dummy_videodriver[] =
"SDL_VIDEODRIVER=dummy";
3345 fprintf(stderr,
"An input file must be specified\n");
3346 fprintf(stderr,
"Use -h to get full help or, even better, run 'man %s'\n",
program_name);
3353 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3355 flags &= ~SDL_INIT_AUDIO;
3357 SDL_putenv(dummy_videodriver);
3358 #if !defined(__MINGW32__) && !defined(__APPLE__)
3359 flags |= SDL_INIT_EVENTTHREAD;
3361 if (SDL_Init (flags)) {
3362 fprintf(stderr,
"Could not initialize SDL - %s\n", SDL_GetError());
3363 fprintf(stderr,
"(Did you set the DISPLAY variable?)\n");
3368 #if HAVE_SDL_VIDEO_SIZE
3369 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
3375 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
3376 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3377 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3380 fprintf(stderr,
"Could not initialize lock manager!\n");
3385 flush_pkt.
data = (
char *)(intptr_t)
"FLUSH";
3389 fprintf(stderr,
"Failed to initialize VideoState!\n");