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
90 #define REFRESH_RATE 0.01
94 #define SAMPLE_ARRAY_SIZE (8 * 65536)
96 #define CURSOR_HIDE_DELAY 1000000
116 #define VIDEO_PICTURE_QUEUE_SIZE 4
117 #define SUBPICTURE_QUEUE_SIZE 4
316 static char *vfilters =
NULL;
325 #define FF_ALLOC_EVENT (SDL_USEREVENT)
326 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
344 if (pkt == &flush_pkt)
356 SDL_CondSignal(q->
cond);
368 SDL_LockMutex(q->
mutex);
370 SDL_UnlockMutex(q->
mutex);
372 if (pkt != &flush_pkt && ret < 0)
382 q->
mutex = SDL_CreateMutex();
383 q->
cond = SDL_CreateCond();
391 SDL_LockMutex(q->
mutex);
401 SDL_UnlockMutex(q->
mutex);
407 SDL_DestroyMutex(q->
mutex);
408 SDL_DestroyCond(q->
cond);
413 SDL_LockMutex(q->
mutex);
417 SDL_CondSignal(q->
cond);
419 SDL_UnlockMutex(q->
mutex);
424 SDL_LockMutex(q->
mutex);
427 SDL_UnlockMutex(q->
mutex);
436 SDL_LockMutex(q->
mutex);
464 SDL_UnlockMutex(q->
mutex);
469 int x,
int y,
int w,
int h,
int color,
int update)
476 SDL_FillRect(screen, &rect, color);
477 if (update && w > 0 && h > 0)
478 SDL_UpdateRect(screen, x, y, w, h);
490 w2 = width - (x + w);
496 h2 = height - (y + h);
504 xleft + width - w2, ytop,
512 xleft + w1, ytop + height - h2,
517 #define ALPHA_BLEND(a, oldp, newp, s)\
518 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
520 #define RGBA_IN(r, g, b, a, s)\
522 unsigned int v = ((const uint32_t *)(s))[0];\
523 a = (v >> 24) & 0xff;\
524 r = (v >> 16) & 0xff;\
525 g = (v >> 8) & 0xff;\
529 #define YUVA_IN(y, u, v, a, s, pal)\
531 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
532 a = (val >> 24) & 0xff;\
533 y = (val >> 16) & 0xff;\
534 u = (val >> 8) & 0xff;\
538 #define YUVA_OUT(d, y, u, v, a)\
540 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
548 int wrap, wrap3, width2, skip2;
549 int y,
u,
v,
a, u1, v1,
a1, w, h;
553 int dstx, dsty, dstw, dsth;
555 dstw = av_clip(rect->
w, 0, imgw);
556 dsth = av_clip(rect->
h, 0, imgh);
557 dstx = av_clip(rect->
x, 0, imgw - dstw);
558 dsty = av_clip(rect->
y, 0, imgh - dsth);
563 width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
568 pal = (
const uint32_t *)rect->
pict.
data[1];
585 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
612 p += wrap3 - dstw *
BPP;
613 lum += wrap - dstw - dstx;
614 cb += dst->
linesize[1] - width2 - skip2;
615 cr += dst->
linesize[2] - width2 - skip2;
617 for (h = dsth - (dsty & 1); h >= 2; h -= 2) {
642 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
674 p += -wrap3 + 2 *
BPP;
697 p += wrap3 + (wrap3 - dstw *
BPP);
698 lum += wrap + (wrap - dstw - dstx);
699 cb += dst->
linesize[1] - width2 - skip2;
700 cr += dst->
linesize[2] - width2 - skip2;
718 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
761 if (aspect_ratio <= 0.0)
763 aspect_ratio *= (float)vp->
width / (
float)vp->
height;
767 width = ((int)
rint(height * aspect_ratio)) & ~1;
768 if (width > scr_width) {
770 height = ((int)
rint(width / aspect_ratio)) & ~1;
772 x = (scr_width -
width) / 2;
773 y = (scr_height -
height) / 2;
774 rect->x = scr_xleft + x;
775 rect->y = scr_ytop +
y;
776 rect->w =
FFMAX(width, 1);
777 rect->h =
FFMAX(height, 1);
795 SDL_LockYUVOverlay (vp->
bmp);
797 pict.
data[0] = vp->
bmp->pixels[0];
798 pict.
data[1] = vp->
bmp->pixels[2];
799 pict.
data[2] = vp->
bmp->pixels[1];
809 SDL_UnlockYUVOverlay (vp->
bmp);
816 SDL_DisplayYUVOverlay(vp->
bmp, &rect);
819 int bgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0x00);
828 return a < 0 ? a%b + b : a%
b;
833 int i, i_start, x, y1,
y, ys, delay, n, nb_display_channels;
834 int ch, channels, h, h2, bgcolor, fgcolor;
836 int rdft_bits, nb_freq;
838 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->
height; rdft_bits++)
840 nb_freq = 1 << (rdft_bits - 1);
844 nb_display_channels = channels;
846 int data_used= s->
show_mode == SHOW_MODE_WAVES ? s->
width : (2*nb_freq);
858 delay += 2 * data_used;
859 if (delay < data_used)
865 for (i = 0; i < 1000; i += channels) {
872 if (h < score && (b ^ c) < 0) {
884 bgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0x00);
890 fgcolor = SDL_MapRGB(
screen->format, 0xff, 0xff, 0xff);
893 h = s->
height / nb_display_channels;
896 for (ch = 0; ch < nb_display_channels; ch++) {
898 y1 = s->
ytop + ch * h + (h / 2);
899 for (x = 0; x < s->
width; x++) {
908 s->
xleft + x, ys, 1, y,
916 fgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0xff);
918 for (ch = 1; ch < nb_display_channels; ch++) {
919 y = s->
ytop + ch * h;
926 nb_display_channels=
FFMIN(nb_display_channels, 2);
936 for (ch = 0; ch < nb_display_channels; ch++) {
937 data[ch] = s->
rdft_data + 2 * nb_freq * ch;
939 for (x = 0; x < 2 * nb_freq; x++) {
940 double w = (x-nb_freq) * (1.0 / nb_freq);
949 for (y = 0; y < s->
height; y++) {
950 double w = 1 / sqrt(nb_freq);
951 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]));
952 int b = (nb_display_channels == 2 ) ? sqrt(w * sqrt(data[1][2 * y + 0] * data[1][2 * y + 0]
953 + data[1][2 * y + 1] * data[1][2 * y + 1])) : a;
956 fgcolor = SDL_MapRGB(
screen->format, a, b, (a + b) / 2);
989 SDL_FreeYUVOverlay(vp->
bmp);
1030 int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
1035 else flags |= SDL_RESIZABLE;
1037 if (vp && vp->
width) {
1056 screen = SDL_SetVideoMode(w, h, 0, flags);
1058 fprintf(stderr,
"SDL: could not set video mode - exiting\n");
1229 double sync_threshold,
diff;
1242 if (diff <= -sync_threshold)
1244 else if (diff >= sync_threshold)
1332 double last_duration,
duration, delay;
1347 if (last_duration > 0 && last_duration < is->max_frame_duration) {
1354 if (time < is->frame_timer + delay) {
1368 duration = nextvp->
pts - vp->
pts;
1435 static int64_t last_time;
1437 int aqsize, vqsize, sqsize;
1441 if (!last_time || (cur_time - last_time) >= 30000) {
1454 printf(
"%7.2f A-V:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64
"/%"PRId64
" \r",
1478 SDL_FreeYUVOverlay(vp->
bmp);
1489 if (!vp->
bmp || vp->
bmp->pitches[0] < vp->
width) {
1492 fprintf(stderr,
"Error: the video system does not support an image\n"
1493 "size of %dx%d pixels. Try using -lowres or -vf \"scale=w:h\"\n"
1494 "to reduce the image size.\n", vp->
width, vp->
height );
1507 for (i = 0; i < 3; i++) {
1514 if (bmp->pitches[i] > width) {
1515 maxp = bmp->pixels[i] + bmp->pitches[i] * height - 1;
1516 for (p = bmp->pixels[i] + width - 1; p < maxp; p += bmp->pitches[i])
1526 #if defined(DEBUG_SYNC) && 0
1527 printf(
"frame_type=%c pts=%0.3f\n",
1566 event.user.data1 = is;
1567 SDL_PushEvent(&event);
1591 vp->picref = src_frame->
opaque;
1595 SDL_LockYUVOverlay (vp->
bmp);
1597 pict.
data[0] = vp->
bmp->pixels[0];
1598 pict.
data[1] = vp->
bmp->pixels[2];
1599 pict.
data[2] = vp->
bmp->pixels[1];
1615 fprintf(stderr,
"Cannot initialize the conversion context\n");
1624 SDL_UnlockYUVOverlay(vp->
bmp);
1716 if (!outputs || !inputs) {
1727 inputs->filter_ctx = sink_ctx;
1728 inputs->pad_idx = 0;
1729 inputs->next =
NULL;
1748 char sws_flags_str[128];
1749 char buffersrc_args[256];
1755 if (!buffersink_params)
1762 snprintf(buffersrc_args,
sizeof(buffersrc_args),
1763 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
1770 "ffplay_buffer", buffersrc_args,
NULL,
1777 "ffplay_buffersink",
NULL, buffersink_params, graph);
1785 "ffplay_crop",
"floor(in_w/2)*2:floor(in_h/2)*2",
NULL, graph)) < 0)
1793 is->in_video_filter = filt_src;
1794 is->out_video_filter = filt_out;
1820 int last_serial = -1;
1826 codec->
opaque = &is->buffer_pool;
1849 if ( last_w != frame->
width
1850 || last_h != frame->
height
1851 || last_format != frame->
format
1852 || last_serial != serial) {
1854 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
1861 if ((ret = configure_video_filters(graph, is, vfilters, frame)) < 0) {
1864 event.user.data1 = is;
1865 SDL_PushEvent(&event);
1869 filt_in = is->in_video_filter;
1870 filt_out = is->out_video_filter;
1871 last_w = frame->
width;
1873 last_format = frame->
format;
1874 last_serial = serial;
1877 frame->
pts = pts_int;
1879 if (is->use_dr1 && frame->
opaque) {
1914 pts_int = picref->
pts;
1923 "tb:%d/%d pts:%"PRId64
" -> tb:%d/%d pts:%"PRId64
"\n",
1988 &got_subtitle, pkt);
1989 if (got_subtitle && sp->
sub.
format == 0) {
2023 size = samples_size /
sizeof(short);
2045 double diff, avg_diff;
2046 int min_nb_samples, max_nb_samples;
2060 wanted_nb_samples = nb_samples + (int)(diff * is->
audio_src.
freq);
2063 wanted_nb_samples =
FFMIN(
FFMAX(wanted_nb_samples, min_nb_samples), max_nb_samples);
2065 av_dlog(
NULL,
"diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n",
2066 diff, avg_diff, wanted_nb_samples - nb_samples,
2077 return wanted_nb_samples;
2092 int len1, len2, data_size, resampled_data_size;
2093 int64_t dec_channel_layout;
2097 int flush_complete = 0;
2098 int wanted_nb_samples;
2102 while (pkt_temp->
size > 0 || (!pkt_temp->
data && new_packet)) {
2125 pkt_temp->
data += len1;
2126 pkt_temp->
size -= len1;
2138 dec_channel_layout =
2153 fprintf(stderr,
"Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2172 fprintf(stderr,
"swr_set_compensation() failed\n");
2181 fprintf(stderr,
"swr_convert() failed\n");
2184 if (len2 == out_count) {
2185 fprintf(stderr,
"warning: audio buffer is probably too small\n");
2192 resampled_data_size = data_size;
2200 static double last_clock;
2201 printf(
"audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
2207 return resampled_data_size;
2213 memset(pkt_temp, 0,
sizeof(*pkt_temp));
2254 if (audio_size < 0) {
2282 static int audio_open(
void *opaque, int64_t wanted_channel_layout,
int wanted_nb_channels,
int wanted_sample_rate,
struct AudioParams *audio_hw_params)
2284 SDL_AudioSpec wanted_spec, spec;
2286 const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2288 env = SDL_getenv(
"SDL_AUDIO_CHANNELS");
2290 wanted_nb_channels = atoi(env);
2298 wanted_spec.freq = wanted_sample_rate;
2299 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2300 fprintf(stderr,
"Invalid sample rate or channel count!\n");
2303 wanted_spec.format = AUDIO_S16SYS;
2304 wanted_spec.silence = 0;
2307 wanted_spec.userdata = opaque;
2308 while (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
2309 fprintf(stderr,
"SDL_OpenAudio (%d channels): %s\n", wanted_spec.channels, SDL_GetError());
2310 wanted_spec.channels = next_nb_channels[
FFMIN(7, wanted_spec.channels)];
2311 if (!wanted_spec.channels) {
2312 fprintf(stderr,
"No more channel combinations to try, audio open failed\n");
2317 if (spec.format != AUDIO_S16SYS) {
2318 fprintf(stderr,
"SDL advised audio format %d is not supported!\n", spec.format);
2321 if (spec.channels != wanted_spec.channels) {
2323 if (!wanted_channel_layout) {
2324 fprintf(stderr,
"SDL advised channel count %d is not supported!\n", spec.channels);
2330 audio_hw_params->
freq = spec.freq;
2332 audio_hw_params->
channels = spec.channels;
2342 const char *forced_codec_name =
NULL;
2346 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2357 if (forced_codec_name)
2360 if (forced_codec_name) fprintf(stderr,
"No codec could be found with name '%s'\n", forced_codec_name);
2361 else fprintf(stderr,
"No codec could be found with id %d\n", avctx->
codec_id);
2397 if (audio_hw_buf_size < 0)
2448 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2542 if(s->
pb && ( !strncmp(s->
filename,
"rtp:", 4)
2543 || !strncmp(s->
filename,
"udp:", 4)
2559 int pkt_in_play_range = 0;
2562 int orig_nb_streams;
2563 SDL_mutex *wait_mutex = SDL_CreateMutex();
2565 memset(st_index, -1,
sizeof(st_index));
2594 fprintf(stderr,
"%s: could not find codec parameters\n", is->
filename);
2598 for (i = 0; i < orig_nb_streams; i++)
2620 fprintf(stderr,
"%s: could not seek to position %0.3f\n",
2637 st_index[AVMEDIA_TYPE_VIDEO],
2643 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
2644 st_index[AVMEDIA_TYPE_AUDIO] :
2645 st_index[AVMEDIA_TYPE_VIDEO]),
2654 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2659 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2663 is->
show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
2665 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2670 fprintf(stderr,
"%s: could not open codecs\n", is->
filename);
2675 if (infinite_buffer < 0 && is->realtime)
2688 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
2699 int64_t seek_target = is->
seek_pos;
2700 int64_t seek_min = is->
seek_rel > 0 ? seek_target - is->
seek_rel + 2: INT64_MIN;
2701 int64_t seek_max = is->
seek_rel < 0 ? seek_target - is->
seek_rel - 2: INT64_MAX;
2707 fprintf(stderr,
"%s: error while seeking\n", is->
ic->
filename);
2744 SDL_LockMutex(wait_mutex);
2746 SDL_UnlockMutex(wait_mutex);
2783 SDL_LockMutex(wait_mutex);
2785 SDL_UnlockMutex(wait_mutex);
2826 event.user.data1 = is;
2827 SDL_PushEvent(&event);
2829 SDL_DestroyMutex(wait_mutex);
2876 int start_index, stream_index;
2890 stream_index = start_index;
2900 if (start_index == -1)
2904 if (stream_index == start_index)
2906 st = ic->
streams[stream_index];
2909 switch (codec_type) {
2933 #if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
2945 int bgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0x00);
2948 next = (next + 1) % SHOW_MODE_NB;
2949 }
while (next != is->
show_mode && (next == SHOW_MODE_VIDEO && !is->
video_st || next != SHOW_MODE_VIDEO && !is->
audio_st));
2960 double remaining_time = 0.0;
2962 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS)) {
2967 if (remaining_time > 0.0)
2968 av_usleep((int64_t)(remaining_time * 1000000.0));
2980 double incr, pos, frac;
2985 switch (event.type) {
2991 switch (event.key.keysym.sym) {
3064 case SDL_VIDEOEXPOSE:
3067 case SDL_MOUSEBUTTONDOWN:
3072 case SDL_MOUSEMOTION:
3078 if (event.type == SDL_MOUSEBUTTONDOWN) {
3081 if (event.motion.state != SDL_PRESSED)
3091 int tns, thh, tmm, tss;
3094 tmm = (tns % 3600) / 60;
3096 frac = x / cur_stream->
width;
3099 mm = (ns % 3600) / 60;
3101 fprintf(stderr,
"Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3102 hh, mm, ss, thh, tmm, tss);
3109 case SDL_VIDEORESIZE:
3110 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
3111 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
3150 if (!file_iformat) {
3151 fprintf(stderr,
"Unknown input format: %s\n", arg);
3165 if (!strcmp(arg,
"audio"))
3167 else if (!strcmp(arg,
"video"))
3169 else if (!strcmp(arg,
"ext"))
3172 fprintf(stderr,
"Unknown value for %s: %s\n", opt, arg);
3192 show_mode = !strcmp(arg,
"video") ? SHOW_MODE_VIDEO :
3193 !strcmp(arg,
"waves") ? SHOW_MODE_WAVES :
3194 !strcmp(arg,
"rdft" ) ? SHOW_MODE_RDFT :
3202 fprintf(stderr,
"Argument '%s' provided as input filename, but '%s' was already specified.\n",
3206 if (!strcmp(filename,
"-"))
3213 const char *spec = strchr(opt,
':');
3215 fprintf(stderr,
"No media specifier was specified in '%s' in option '%s'\n",
3225 fprintf(stderr,
"Invalid media specifier '%s' in option '%s'\n", spec, opt);
3235 {
"x",
HAS_ARG, { .func_arg =
opt_width },
"force displayed width",
"width" },
3236 {
"y",
HAS_ARG, { .func_arg =
opt_height },
"force displayed height",
"height" },
3245 {
"ss",
HAS_ARG, { .func_arg =
opt_seek },
"seek to a given position in seconds",
"pos" },
3246 {
"t",
HAS_ARG, { .func_arg =
opt_duration },
"play \"duration\" seconds of audio/video",
"duration" },
3262 {
"sync",
HAS_ARG |
OPT_EXPERT, { .func_arg =
opt_sync },
"set audio-video sync. type (type=audio/video/ext)",
"type" },
3271 {
"vf",
OPT_STRING |
HAS_ARG, { &vfilters },
"set video filters",
"filter_graph" },
3274 {
"showmode",
HAS_ARG, { .func_arg =
opt_show_mode},
"select show mode (0 = video, 1 = waves, 2 = RDFT)",
"mode" },
3276 {
"i",
OPT_BOOL, { &dummy},
"read specified file",
"input_file"},
3277 {
"codec",
HAS_ARG, { .func_arg =
opt_codec},
"force decoder",
"decoder_name" },
3300 #if !CONFIG_AVFILTER
3305 printf(
"\nWhile playing:\n"
3307 "f toggle full screen\n"
3309 "a cycle audio channel\n"
3310 "v cycle video channel\n"
3311 "t cycle subtitle channel\n"
3312 "w show audio waves\n"
3313 "s activate frame-step mode\n"
3314 "left/right seek backward/forward 10 seconds\n"
3315 "down/up seek backward/forward 1 minute\n"
3316 "page down/page up seek backward/forward 10 minutes\n"
3317 "mouse click seek to percentage in file corresponding to fraction of width\n"
3325 *mtx = SDL_CreateMutex();
3330 return !!SDL_LockMutex(*mtx);
3332 return !!SDL_UnlockMutex(*mtx);
3334 SDL_DestroyMutex(*mtx);
3345 char dummy_videodriver[] =
"SDL_VIDEODRIVER=dummy";
3372 fprintf(stderr,
"An input file must be specified\n");
3373 fprintf(stderr,
"Use -h to get full help or, even better, run 'man %s'\n",
program_name);
3380 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3382 flags &= ~SDL_INIT_AUDIO;
3384 SDL_putenv(dummy_videodriver);
3385 #if !defined(__MINGW32__) && !defined(__APPLE__)
3386 flags |= SDL_INIT_EVENTTHREAD;
3388 if (SDL_Init (flags)) {
3389 fprintf(stderr,
"Could not initialize SDL - %s\n", SDL_GetError());
3390 fprintf(stderr,
"(Did you set the DISPLAY variable?)\n");
3395 #if HAVE_SDL_VIDEO_SIZE
3396 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
3402 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
3403 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3404 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3407 fprintf(stderr,
"Could not initialize lock manager!\n");
3412 flush_pkt.
data = (
char *)(intptr_t)
"FLUSH";
3416 fprintf(stderr,
"Failed to initialize VideoState!\n");