53 #include <SDL_thread.h>
64 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
65 #define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
70 #define SDL_AUDIO_BUFFER_SIZE 1024
73 #define AV_SYNC_THRESHOLD 0.01
75 #define AV_NOSYNC_THRESHOLD 10.0
77 #define FRAME_SKIP_FACTOR 0.05
80 #define SAMPLE_CORRECTION_PERCENT_MAX 10
83 #define AUDIO_DIFF_AVG_NB 20
86 #define SAMPLE_ARRAY_SIZE (2 * 65536)
99 #define VIDEO_PICTURE_QUEUE_SIZE 2
100 #define SUBPICTURE_QUEUE_SIZE 4
266 static char *vfilters =
NULL;
276 #define FF_ALLOC_EVENT (SDL_USEREVENT)
277 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
278 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
288 q->
mutex = SDL_CreateMutex();
289 q->
cond = SDL_CreateCond();
297 SDL_LockMutex(q->
mutex);
307 SDL_UnlockMutex(q->
mutex);
313 SDL_DestroyMutex(q->
mutex);
314 SDL_DestroyCond(q->
cond);
332 SDL_LockMutex(q->
mutex);
343 SDL_CondSignal(q->
cond);
345 SDL_UnlockMutex(q->
mutex);
351 SDL_LockMutex(q->
mutex);
355 SDL_CondSignal(q->
cond);
357 SDL_UnlockMutex(q->
mutex);
366 SDL_LockMutex(q->
mutex);
392 SDL_UnlockMutex(q->
mutex);
397 int x,
int y,
int w,
int h,
int color)
404 SDL_FillRect(screen, &rect, color);
407 #define ALPHA_BLEND(a, oldp, newp, s)\
408 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
410 #define RGBA_IN(r, g, b, a, s)\
412 unsigned int v = ((const uint32_t *)(s))[0];\
413 a = (v >> 24) & 0xff;\
414 r = (v >> 16) & 0xff;\
415 g = (v >> 8) & 0xff;\
419 #define YUVA_IN(y, u, v, a, s, pal)\
421 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
422 a = (val >> 24) & 0xff;\
423 y = (val >> 16) & 0xff;\
424 u = (val >> 8) & 0xff;\
428 #define YUVA_OUT(d, y, u, v, a)\
430 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
438 int wrap, wrap3, width2, skip2;
439 int y, u, v, a, u1, v1, a1, w, h;
443 int dstx, dsty, dstw, dsth;
445 dstw = av_clip(rect->
w, 0, imgw);
446 dsth = av_clip(rect->
h, 0, imgh);
447 dstx = av_clip(rect->
x, 0, imgw - dstw);
448 dsty = av_clip(rect->
y, 0, imgh - dsth);
453 width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
458 pal = (
const uint32_t *)rect->
pict.
data[1];
475 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
502 p += wrap3 - dstw *
BPP;
503 lum += wrap - dstw - dstx;
504 cb += dst->
linesize[1] - width2 - skip2;
505 cr += dst->
linesize[2] - width2 - skip2;
507 for (h = dsth - (dsty & 1); h >= 2; h -= 2) {
532 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
564 p += -wrap3 + 2 *
BPP;
587 p += wrap3 + (wrap3 - dstw *
BPP);
588 lum += wrap + (wrap - dstw - dstx);
589 cb += dst->
linesize[1] - width2 - skip2;
590 cr += dst->
linesize[2] - width2 - skip2;
608 for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
668 if (aspect_ratio <= 0.0)
670 aspect_ratio *= (float)vp->
width / (
float)vp->
height;
680 SDL_LockYUVOverlay (vp->
bmp);
682 pict.
data[0] = vp->
bmp->pixels[0];
683 pict.
data[1] = vp->
bmp->pixels[2];
684 pict.
data[2] = vp->
bmp->pixels[1];
694 SDL_UnlockYUVOverlay (vp->
bmp);
702 width = ((int)
rint(height * aspect_ratio)) & ~1;
703 if (width > is->
width) {
705 height = ((int)
rint(width / aspect_ratio)) & ~1;
710 rect.x = is->
xleft + x;
711 rect.y = is->
ytop + y;
714 SDL_DisplayYUVOverlay(vp->
bmp, &rect);
736 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
737 int ch, channels, h, h2, bgcolor, fgcolor;
739 int rdft_bits, nb_freq;
741 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->
height; rdft_bits++)
743 nb_freq = 1 << (rdft_bits - 1);
747 nb_display_channels = channels;
761 delay += 2 * data_used;
762 if (delay < data_used)
768 for (i = 0; i < 1000; i += channels) {
775 if (h < score && (b ^ c) < 0) {
787 bgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0x00);
793 fgcolor = SDL_MapRGB(
screen->format, 0xff, 0xff, 0xff);
796 h = s->
height / nb_display_channels;
799 for (ch = 0; ch < nb_display_channels; ch++) {
801 y1 = s->
ytop + ch * h + (h / 2);
802 for (x = 0; x < s->
width; x++) {
811 s->
xleft + x, ys, 1, y,
819 fgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0xff);
821 for (ch = 1; ch < nb_display_channels; ch++) {
822 y = s->
ytop + ch * h;
829 nb_display_channels=
FFMIN(nb_display_channels, 2);
839 for (ch = 0; ch < nb_display_channels; ch++) {
840 data[ch] = s->
rdft_data + 2 * nb_freq * ch;
842 for (x = 0; x < 2 * nb_freq; x++) {
843 double w = (x-nb_freq) * (1.0 / nb_freq);
853 for (y = 0; y < s->
height; y++) {
854 double w = 1 / sqrt(nb_freq);
855 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]));
856 int b = (nb_display_channels == 2 ) ? sqrt(w * sqrt(data[1][2 * y + 0] * data[1][2 * y + 0]
857 + data[1][2 * y + 1] * data[1][2 * y + 1])) : a;
860 fgcolor = SDL_MapRGB(
screen->format, a, b, (a + b) / 2);
876 int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
880 else flags |= SDL_RESIZABLE;
889 }
else if (is->out_video_filter && is->out_video_filter->inputs[0]) {
890 w = is->out_video_filter->inputs[0]->w;
891 h = is->out_video_filter->inputs[0]->h;
905 #if defined(__APPLE__) && !SDL_VERSION_ATLEAST(1, 2, 14)
907 screen = SDL_SetVideoMode(w, h, 24, flags);
909 screen = SDL_SetVideoMode(w, h, 0, flags);
912 fprintf(stderr,
"SDL: could not set video mode - exiting\n");
942 event.user.data1 = opaque;
945 SDL_PushEvent(&event);
956 int hw_buf_size, bytes_per_sec;
965 pts -= (double)hw_buf_size / bytes_per_sec;
1036 double delay, sync_threshold, diff;
1040 if (delay <= 0 || delay >= 10.0) {
1060 if (diff <= -sync_threshold)
1062 else if (diff >= sync_threshold)
1068 av_dlog(
NULL,
"video: delay=%0.3f pts=%0.3f A-V=%f\n",
1069 delay, frame_current_pts, -diff);
1092 if (time < vp->target_clock)
1107 if (is->
pictq_size > 1 || time > next_target + 0.5) {
1188 static int64_t last_time;
1190 int aqsize, vqsize, sqsize;
1194 if (!last_time || (cur_time - last_time) >= 30000) {
1207 printf(
"%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64
"/%"PRId64
" \r",
1229 SDL_FreeYUVOverlay(vp->
bmp);
1237 #if !CONFIG_AVFILTER
1269 SDL_FreeYUVOverlay(vp->
bmp);
1272 vp->
width = is->out_video_filter->inputs[0]->w;
1273 vp->
height = is->out_video_filter->inputs[0]->h;
1274 vp->
pix_fmt = is->out_video_filter->inputs[0]->format;
1284 if (!vp->
bmp || vp->
bmp->pitches[0] < vp->
width) {
1287 fprintf(stderr,
"Error: the video system does not support an image\n"
1288 "size of %dx%d pixels. Try using -vf \"scale=w:h\"\n"
1289 "to reduce the image size.\n", vp->
width, vp->
height );
1329 vp->
width != is->out_video_filter->inputs[0]->w ||
1330 vp->
height != is->out_video_filter->inputs[0]->h) {
1343 event.user.data1 = is;
1344 SDL_PushEvent(&event);
1362 SDL_LockYUVOverlay (vp->
bmp);
1364 pict.
data[0] = vp->
bmp->pixels[0];
1365 pict.
data[1] = vp->
bmp->pixels[2];
1366 pict.
data[2] = vp->
bmp->pixels[1];
1373 pict_src.
data[0] = src_frame->
data[0];
1374 pict_src.
data[1] = src_frame->
data[1];
1375 pict_src.
data[2] = src_frame->
data[2];
1390 fprintf(stderr,
"Cannot initialize the conversion context\n");
1397 SDL_UnlockYUVOverlay(vp->
bmp);
1418 double frame_delay, pts;
1433 frame_delay += src_frame->
repeat_pict * (frame_delay * 0.5);
1502 char sws_flags_str[128];
1503 char buffersrc_args[256];
1508 snprintf(sws_flags_str,
sizeof(sws_flags_str),
"flags=%"PRId64,
sws_flags);
1511 snprintf(buffersrc_args,
sizeof(buffersrc_args),
"%d:%d:%d:%d:%d:%d:%d",
1519 "src", buffersrc_args,
NULL,
1529 "format",
"yuv420p",
NULL, graph)) < 0)
1559 is->in_video_filter = filt_src;
1560 is->out_video_filter = filt_out;
1582 if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
1584 filt_in = is->in_video_filter;
1585 filt_out = is->out_video_filter;
1607 av_dlog(
NULL,
"Changing size %dx%d -> %dx%d\n", last_w, last_h,
1611 if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
1613 filt_in = is->in_video_filter;
1614 filt_out = is->out_video_filter;
1619 frame->
pts = pts_int;
1631 pts_int = frame->
pts;
1637 "tb:%d/%d pts:%"PRId64
" -> tb:%d/%d pts:%"PRId64
"\n",
1675 int r,
g,
b, y, u, v, a;
1707 &got_subtitle, pkt);
1709 if (got_subtitle && sp->
sub.
format == 0) {
1741 size = samples_size /
sizeof(short);
1758 int samples_size1,
double pts)
1760 int n, samples_size;
1764 samples_size = samples_size1;
1769 double diff, avg_diff;
1770 int wanted_size, min_size, max_size, nb_samples;
1786 nb_samples = samples_size / n;
1790 if (wanted_size < min_size)
1791 wanted_size = min_size;
1792 else if (wanted_size > max_size)
1793 wanted_size = max_size;
1796 if (wanted_size < samples_size) {
1798 samples_size = wanted_size;
1799 }
else if (wanted_size > samples_size) {
1804 nb = (samples_size - wanted_size);
1805 samples_end = (
uint8_t *)samples + samples_size - n;
1806 q = samples_end + n;
1808 memcpy(q, samples_end, n);
1812 samples_size = wanted_size;
1815 av_dlog(
NULL,
"diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1816 diff, avg_diff, samples_size - samples_size1,
1827 return samples_size;
1836 int n, len1, data_size, got_frame;
1839 int flush_complete = 0;
1843 while (pkt_temp->
size > 0 || (!pkt_temp->
data && new_packet)) {
1844 int resample_changed, audio_resample;
1861 pkt_temp->
data += len1;
1862 pkt_temp->
size -= len1;
1882 if ((!is->
avr && audio_resample) || resample_changed) {
1886 else if (audio_resample) {
1889 fprintf(stderr,
"error allocating AVAudioResampleContext\n");
1893 if (audio_resample) {
1902 fprintf(stderr,
"error initializing libavresample\n");
1911 if (audio_resample) {
1913 int out_samples, out_size, out_linesize;
1928 out_linesize, nb_samples,
1932 if (out_samples < 0) {
1933 fprintf(stderr,
"avresample_convert() failed\n");
1950 static double last_clock;
1951 printf(
"audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1963 memset(pkt_temp, 0,
sizeof(*pkt_temp));
1999 if (audio_size < 0) {
2028 SDL_AudioSpec wanted_spec, spec;
2032 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2067 fprintf(stderr,
"unable to guess channel layout\n");
2076 wanted_spec.format = AUDIO_S16SYS;
2079 wanted_spec.silence = 0;
2082 wanted_spec.userdata = is;
2083 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
2084 fprintf(stderr,
"SDL_OpenAudio: %s\n", SDL_GetError());
2138 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2221 return global_video_state && global_video_state->
abort_request;
2233 int pkt_in_play_range = 0;
2236 int orig_nb_streams;
2238 memset(st_index, -1,
sizeof(st_index));
2243 global_video_state = is;
2268 fprintf(stderr,
"%s: could not find codec parameters\n", is->
filename);
2272 for (i = 0; i < orig_nb_streams; i++)
2292 fprintf(stderr,
"%s: could not seek to position %0.3f\n",
2307 st_index[AVMEDIA_TYPE_VIDEO],
2313 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
2314 st_index[AVMEDIA_TYPE_AUDIO] :
2315 st_index[AVMEDIA_TYPE_VIDEO]),
2322 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2327 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2336 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2341 fprintf(stderr,
"%s: could not open codecs\n", is->
filename);
2356 #if CONFIG_RTSP_DEMUXER
2365 int64_t seek_target = is->
seek_pos;
2366 int64_t seek_min = is->
seek_rel > 0 ? seek_target - is->
seek_rel + 2: INT64_MIN;
2367 int64_t seek_max = is->
seek_rel < 0 ? seek_target - is->
seek_rel - 2: INT64_MAX;
2373 fprintf(stderr,
"%s: error while seeking\n", is->
ic->
filename);
2462 global_video_state =
NULL;
2479 event.user.data1 = is;
2480 SDL_PushEvent(&event);
2516 int start_index, stream_index;
2527 stream_index = start_index;
2538 if (stream_index == start_index)
2540 st = ic->
streams[stream_index];
2543 switch (codec_type) {
2565 #if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
2595 int bgcolor = SDL_MapRGB(
screen->format, 0x00, 0x00, 0x00);
2635 double incr, pos, frac;
2639 SDL_WaitEvent(&event);
2640 switch (event.type) {
2646 switch (event.key.keysym.sym) {
2719 case SDL_MOUSEBUTTONDOWN:
2724 case SDL_MOUSEMOTION:
2725 if (event.type == SDL_MOUSEBUTTONDOWN) {
2728 if (event.motion.state != SDL_PRESSED)
2739 int tns, thh, tmm, tss;
2742 tmm = (tns % 3600) / 60;
2744 frac = x / cur_stream->
width;
2747 mm = (ns % 3600) / 60;
2749 fprintf(stderr,
"Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2750 hh, mm, ss, thh, tmm, tss);
2758 case SDL_VIDEORESIZE:
2760 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2761 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2787 "Option '%s' has been removed, use private format options instead\n", opt);
2791 static int opt_width(
void *optctx,
const char *opt,
const char *arg)
2797 static int opt_height(
void *optctx,
const char *opt,
const char *arg)
2803 static int opt_format(
void *optctx,
const char *opt,
const char *arg)
2806 if (!file_iformat) {
2807 fprintf(stderr,
"Unknown input format: %s\n", arg);
2816 "Option '%s' has been removed, use private format options instead\n", opt);
2820 static int opt_sync(
void *optctx,
const char *opt,
const char *arg)
2822 if (!strcmp(arg,
"audio"))
2824 else if (!strcmp(arg,
"video"))
2826 else if (!strcmp(arg,
"ext"))
2829 fprintf(stderr,
"Unknown value for %s: %s\n", opt, arg);
2835 static int opt_seek(
void *optctx,
const char *opt,
const char *arg)
2849 {
"x",
HAS_ARG, { .func_arg =
opt_width },
"force displayed width",
"width" },
2850 {
"y",
HAS_ARG, { .func_arg =
opt_height },
"force displayed height",
"height" },
2858 {
"ss",
HAS_ARG, { .func_arg =
opt_seek },
"seek to a given position in seconds",
"pos" },
2859 {
"t",
HAS_ARG, { .func_arg =
opt_duration },
"play \"duration\" seconds of audio/video",
"duration" },
2874 {
"sync",
HAS_ARG |
OPT_EXPERT, { .func_arg =
opt_sync },
"set audio-video sync. type (type=audio/video/ext)",
"type" },
2887 {
"i", 0, {
NULL },
"avconv compatibility dummy option",
""},
2893 printf(
"Simple media player\n");
2894 printf(
"usage: %s [options] input_file\n",
program_name);
2907 #if !CONFIG_AVFILTER
2910 printf(
"\nWhile playing:\n"
2912 "f toggle full screen\n"
2914 "a cycle audio channel\n"
2915 "v cycle video channel\n"
2916 "t cycle subtitle channel\n"
2917 "w show audio waves\n"
2918 "s activate frame-step mode\n"
2919 "left/right seek backward/forward 10 seconds\n"
2920 "down/up seek backward/forward 1 minute\n"
2921 "mouse click seek to percentage in file corresponding to fraction of width\n"
2928 fprintf(stderr,
"Argument '%s' provided as input filename, but '%s' was already specified.\n",
2932 if (!strcmp(filename,
"-"))
2964 fprintf(stderr,
"An input file must be specified\n");
2965 fprintf(stderr,
"Use -h to get full help or, even better, run 'man %s'\n",
program_name);
2972 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
2973 #if !defined(__MINGW32__) && !defined(__APPLE__)
2974 flags |= SDL_INIT_EVENTTHREAD;
2976 if (SDL_Init (flags)) {
2977 fprintf(stderr,
"Could not initialize SDL - %s\n", SDL_GetError());
2982 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2987 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2988 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2989 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);