27 #include "config_components.h"
55 #include <SDL_thread.h>
64 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
66 #define EXTERNAL_CLOCK_MIN_FRAMES 2
67 #define EXTERNAL_CLOCK_MAX_FRAMES 10
70 #define SDL_AUDIO_MIN_BUFFER_SIZE 512
72 #define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30
75 #define SDL_VOLUME_STEP (0.75)
78 #define AV_SYNC_THRESHOLD_MIN 0.04
80 #define AV_SYNC_THRESHOLD_MAX 0.1
82 #define AV_SYNC_FRAMEDUP_THRESHOLD 0.1
84 #define AV_NOSYNC_THRESHOLD 10.0
87 #define SAMPLE_CORRECTION_PERCENT_MAX 10
90 #define EXTERNAL_CLOCK_SPEED_MIN 0.900
91 #define EXTERNAL_CLOCK_SPEED_MAX 1.010
92 #define EXTERNAL_CLOCK_SPEED_STEP 0.001
95 #define AUDIO_DIFF_AVG_NB 20
98 #define REFRESH_RATE 0.01
102 #define SAMPLE_ARRAY_SIZE (8 * 65536)
104 #define CURSOR_HIDE_DELAY 1000000
106 #define USE_ONEPASS_SUBTITLE_RENDER 1
124 #define VIDEO_PICTURE_QUEUE_SIZE 3
125 #define SUBPICTURE_QUEUE_SIZE 16
126 #define SAMPLE_QUEUE_SIZE 9
127 #define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
359 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
411 if (channel_count1 == 1 && channel_count2 == 1)
414 return channel_count1 != channel_count2 || fmt1 != fmt2;
436 SDL_CondSignal(q->
cond);
452 SDL_LockMutex(q->
mutex);
454 SDL_UnlockMutex(q->
mutex);
475 q->
mutex = SDL_CreateMutex();
480 q->
cond = SDL_CreateCond();
493 SDL_LockMutex(q->
mutex);
500 SDL_UnlockMutex(q->
mutex);
507 SDL_DestroyMutex(q->
mutex);
508 SDL_DestroyCond(q->
cond);
513 SDL_LockMutex(q->
mutex);
517 SDL_CondSignal(q->
cond);
519 SDL_UnlockMutex(q->
mutex);
524 SDL_LockMutex(q->
mutex);
527 SDL_UnlockMutex(q->
mutex);
536 SDL_LockMutex(q->
mutex);
561 SDL_UnlockMutex(q->
mutex);
650 if (got_frame && !d->
pkt->
data) {
668 av_log(d->
avctx,
AV_LOG_ERROR,
"Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
692 if (!(
f->mutex = SDL_CreateMutex())) {
696 if (!(
f->cond = SDL_CreateCond())) {
702 f->keep_last = !!keep_last;
703 for (
i = 0;
i <
f->max_size;
i++)
712 for (
i = 0;
i <
f->max_size;
i++) {
717 SDL_DestroyMutex(
f->mutex);
718 SDL_DestroyCond(
f->cond);
723 SDL_LockMutex(
f->mutex);
724 SDL_CondSignal(
f->cond);
725 SDL_UnlockMutex(
f->mutex);
730 return &
f->queue[(
f->rindex +
f->rindex_shown) %
f->max_size];
735 return &
f->queue[(
f->rindex +
f->rindex_shown + 1) %
f->max_size];
740 return &
f->queue[
f->rindex];
746 SDL_LockMutex(
f->mutex);
747 while (
f->size >=
f->max_size &&
748 !
f->pktq->abort_request) {
749 SDL_CondWait(
f->cond,
f->mutex);
751 SDL_UnlockMutex(
f->mutex);
753 if (
f->pktq->abort_request)
756 return &
f->queue[
f->windex];
762 SDL_LockMutex(
f->mutex);
763 while (
f->size -
f->rindex_shown <= 0 &&
764 !
f->pktq->abort_request) {
765 SDL_CondWait(
f->cond,
f->mutex);
767 SDL_UnlockMutex(
f->mutex);
769 if (
f->pktq->abort_request)
772 return &
f->queue[(
f->rindex +
f->rindex_shown) %
f->max_size];
777 if (++
f->windex ==
f->max_size)
779 SDL_LockMutex(
f->mutex);
781 SDL_CondSignal(
f->cond);
782 SDL_UnlockMutex(
f->mutex);
787 if (
f->keep_last && !
f->rindex_shown) {
792 if (++
f->rindex ==
f->max_size)
794 SDL_LockMutex(
f->mutex);
796 SDL_CondSignal(
f->cond);
797 SDL_UnlockMutex(
f->mutex);
803 return f->size -
f->rindex_shown;
809 Frame *fp = &
f->queue[
f->rindex];
810 if (
f->rindex_shown && fp->
serial ==
f->pktq->serial)
836 static int realloc_texture(SDL_Texture **texture, Uint32 new_format,
int new_width,
int new_height, SDL_BlendMode blendmode,
int init_texture)
840 if (!*texture || SDL_QueryTexture(*texture, &
format, &access, &
w, &
h) < 0 || new_width !=
w || new_height !=
h || new_format !=
format) {
844 SDL_DestroyTexture(*texture);
845 if (!(*texture = SDL_CreateTexture(
renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
847 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
850 if (SDL_LockTexture(*texture,
NULL, &pixels, &pitch) < 0)
852 memset(pixels, 0, pitch * new_height);
853 SDL_UnlockTexture(*texture);
855 av_log(
NULL,
AV_LOG_VERBOSE,
"Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
861 int scr_xleft,
int scr_ytop,
int scr_width,
int scr_height,
862 int pic_width,
int pic_height,
AVRational pic_sar)
875 if (
width > scr_width) {
879 x = (scr_width -
width) / 2;
880 y = (scr_height -
height) / 2;
881 rect->
x = scr_xleft + x;
882 rect->
y = scr_ytop + y;
890 *sdl_blendmode = SDL_BLENDMODE_NONE;
891 *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN;
896 *sdl_blendmode = SDL_BLENDMODE_BLEND;
909 SDL_BlendMode sdl_blendmode;
911 if (
realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt,
frame->width,
frame->height, sdl_blendmode, 0) < 0)
913 switch (sdl_pix_fmt) {
914 case SDL_PIXELFORMAT_IYUV:
915 if (
frame->linesize[0] > 0 &&
frame->linesize[1] > 0 &&
frame->linesize[2] > 0) {
919 }
else if (
frame->linesize[0] < 0 &&
frame->linesize[1] < 0 &&
frame->linesize[2] < 0) {
929 if (
frame->linesize[0] < 0) {
947 #if SDL_VERSION_ATLEAST(2,0,8)
948 SDL_YUV_CONVERSION_MODE
mode = SDL_YUV_CONVERSION_AUTOMATIC;
951 mode = SDL_YUV_CONVERSION_JPEG;
953 mode = SDL_YUV_CONVERSION_BT709;
955 mode = SDL_YUV_CONVERSION_BT601;
957 SDL_SetYUVConversionMode(
mode);
973 if (
is->subtitle_st) {
1001 if (!
is->sub_convert_ctx) {
1005 if (!SDL_LockTexture(
is->sub_texture, (SDL_Rect *)sub_rect, (
void **)pixels, pitch)) {
1006 sws_scale(
is->sub_convert_ctx, (
const uint8_t *
const *)sub_rect->data, sub_rect->linesize,
1007 0, sub_rect->h, pixels, pitch);
1008 SDL_UnlockTexture(
is->sub_texture);
1033 #if USE_ONEPASS_SUBTITLE_RENDER
1040 SDL_Rect *sub_rect = (SDL_Rect*)sp->
sub.
rects[
i];
1041 SDL_Rect target = {.
x =
rect.
x + sub_rect->x * xratio,
1042 .y =
rect.
y + sub_rect->y * yratio,
1043 .w = sub_rect->w * xratio,
1044 .h = sub_rect->h * yratio};
1045 SDL_RenderCopy(
renderer,
is->sub_texture, sub_rect, &target);
1053 return a < 0 ?
a%
b +
b :
a%
b;
1058 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1061 int rdft_bits, nb_freq;
1063 for (rdft_bits = 1; (1 << rdft_bits) < 2 *
s->height; rdft_bits++)
1065 nb_freq = 1 << (rdft_bits - 1);
1068 channels =
s->audio_tgt.ch_layout.nb_channels;
1071 int data_used=
s->show_mode == SHOW_MODE_WAVES ?
s->width : (2*nb_freq);
1073 delay =
s->audio_write_buf_size;
1080 delay -= (time_diff *
s->audio_tgt.freq) / 1000000;
1083 delay += 2 * data_used;
1084 if (delay < data_used)
1088 if (
s->show_mode == SHOW_MODE_WAVES) {
1092 int a =
s->sample_array[idx];
1097 if (
h < score && (
b ^
c) < 0) {
1104 s->last_i_start = i_start;
1106 i_start =
s->last_i_start;
1109 if (
s->show_mode == SHOW_MODE_WAVES) {
1110 SDL_SetRenderDrawColor(
renderer, 255, 255, 255, 255);
1113 h =
s->height / nb_display_channels;
1116 for (ch = 0; ch < nb_display_channels; ch++) {
1118 y1 =
s->ytop + ch *
h + (
h / 2);
1119 for (x = 0; x <
s->width; x++) {
1120 y = (
s->sample_array[
i] * h2) >> 15;
1134 SDL_SetRenderDrawColor(
renderer, 0, 0, 255, 255);
1136 for (ch = 1; ch < nb_display_channels; ch++) {
1137 y =
s->ytop + ch *
h;
1142 if (
realloc_texture(&
s->vis_texture, SDL_PIXELFORMAT_ARGB8888,
s->width,
s->height, SDL_BLENDMODE_NONE, 1) < 0)
1145 if (
s->xpos >=
s->width)
1147 nb_display_channels=
FFMIN(nb_display_channels, 2);
1148 if (rdft_bits !=
s->rdft_bits) {
1149 const float rdft_scale = 1.0;
1153 s->rdft_bits = rdft_bits;
1157 0, 1 << rdft_bits, &rdft_scale, 0);
1159 if (err < 0 || !s->rdft_data) {
1161 s->show_mode = SHOW_MODE_WAVES;
1165 SDL_Rect
rect = {.
x =
s->xpos, .y = 0, .w = 1, .h =
s->height};
1168 for (ch = 0; ch < nb_display_channels; ch++) {
1169 data_in[ch] =
s->real_data + 2 * nb_freq * ch;
1170 data[ch] =
s->rdft_data + nb_freq * ch;
1172 for (x = 0; x < 2 * nb_freq; x++) {
1173 double w = (x-nb_freq) * (1.0 / nb_freq);
1174 data_in[ch][x] =
s->sample_array[
i] * (1.0 -
w *
w);
1179 s->rdft_fn(
s->rdft,
data[ch], data_in[ch],
sizeof(
float));
1180 data[ch][0].im =
data[ch][nb_freq].re;
1181 data[ch][nb_freq].re = 0;
1185 if (!SDL_LockTexture(
s->vis_texture, &
rect, (
void **)&pixels, &pitch)) {
1187 pixels += pitch *
s->height;
1188 for (y = 0; y <
s->height; y++) {
1189 double w = 1 / sqrt(nb_freq);
1190 int a = sqrt(
w * sqrt(
data[0][y].re *
data[0][y].re +
data[0][y].im *
data[0][y].im));
1191 int b = (nb_display_channels == 2 ) ? sqrt(
w *
hypot(
data[1][y].re,
data[1][y].im))
1196 *pixels = (
a << 16) + (
b << 8) + ((
a+
b) >> 1);
1198 SDL_UnlockTexture(
s->vis_texture);
1212 if (stream_index < 0 || stream_index >= ic->
nb_streams)
1223 is->audio_buf1_size = 0;
1250 is->audio_stream = -1;
1254 is->video_stream = -1;
1258 is->subtitle_stream = -1;
1268 is->abort_request = 1;
1269 SDL_WaitThread(
is->read_tid,
NULL);
1272 if (
is->audio_stream >= 0)
1274 if (
is->video_stream >= 0)
1276 if (
is->subtitle_stream >= 0)
1289 SDL_DestroyCond(
is->continue_read_thread);
1292 if (
is->vis_texture)
1293 SDL_DestroyTexture(
is->vis_texture);
1294 if (
is->vid_texture)
1295 SDL_DestroyTexture(
is->vid_texture);
1296 if (
is->sub_texture)
1297 SDL_DestroyTexture(
is->sub_texture);
1311 SDL_DestroyWindow(
window);
1338 if (max_width == INT_MAX && max_height == INT_MAX)
1359 SDL_SetWindowFullscreen(
window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1374 SDL_SetRenderDrawColor(
renderer, 0, 0, 0, 255);
1376 if (
is->audio_st &&
is->show_mode != SHOW_MODE_VIDEO)
1378 else if (
is->video_st)
1385 if (*
c->queue_serial !=
c->serial)
1391 return c->pts_drift + time - (time -
c->last_updated) * (1.0 -
c->speed);
1398 c->last_updated = time;
1399 c->pts_drift =
c->pts - time;
1419 c->queue_serial = queue_serial;
1474 double speed =
is->extclk.speed;
1483 if (!
is->seek_req) {
1490 SDL_CondSignal(
is->continue_read_thread);
1499 if (
is->read_pause_return !=
AVERROR(ENOSYS)) {
1500 is->vidclk.paused = 0;
1505 is->paused =
is->audclk.paused =
is->vidclk.paused =
is->extclk.paused = !
is->paused;
1516 is->muted = !
is->muted;
1521 double volume_level =
is->audio_volume ? (20 *
log(
is->audio_volume / (
double)SDL_MIX_MAXVOLUME) /
log(10)) : -1000.0;
1522 int new_volume =
lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign *
step) / 20.0));
1523 is->audio_volume =
av_clip(
is->audio_volume == new_volume ? (
is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
1536 double sync_threshold,
diff = 0;
1549 if (
diff <= -sync_threshold)
1552 delay = delay +
diff;
1553 else if (
diff >= sync_threshold)
1567 if (
isnan(
duration) || duration <= 0 || duration >
is->max_frame_duration)
1596 if (
is->force_refresh ||
is->last_vis_time +
rdftspeed < time) {
1598 is->last_vis_time = time;
1600 *remaining_time =
FFMIN(*remaining_time,
is->last_vis_time +
rdftspeed - time);
1608 double last_duration,
duration, delay;
1615 if (vp->
serial !=
is->videoq.serial) {
1631 if (time < is->frame_timer + delay) {
1632 *remaining_time =
FFMIN(
is->frame_timer + delay - time, *remaining_time);
1636 is->frame_timer += delay;
1638 is->frame_timer = time;
1640 SDL_LockMutex(
is->pictq.mutex);
1643 SDL_UnlockMutex(
is->pictq.mutex);
1649 is->frame_drops_late++;
1655 if (
is->subtitle_st) {
1664 if (sp->
serial !=
is->subtitleq.serial
1675 if (!SDL_LockTexture(
is->sub_texture, (SDL_Rect *)sub_rect, (
void **)&pixels, &pitch)) {
1676 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
1677 memset(pixels, 0, sub_rect->w << 2);
1678 SDL_UnlockTexture(
is->sub_texture);
1690 is->force_refresh = 1;
1692 if (
is->step && !
is->paused)
1697 if (!
display_disable &&
is->force_refresh &&
is->show_mode == SHOW_MODE_VIDEO &&
is->pictq.rindex_shown)
1700 is->force_refresh = 0;
1705 int aqsize, vqsize, sqsize;
1709 if (!last_time || (cur_time - last_time) >= 30000) {
1714 aqsize =
is->audioq.size;
1716 vqsize =
is->videoq.size;
1717 if (
is->subtitle_st)
1718 sqsize =
is->subtitleq.size;
1720 if (
is->audio_st &&
is->video_st)
1722 else if (
is->video_st)
1724 else if (
is->audio_st)
1729 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB \r",
1731 (
is->audio_st &&
is->video_st) ?
"A-V" : (
is->video_st ?
"M-V" : (
is->audio_st ?
"M-A" :
" ")),
1733 is->frame_drops_early +
is->frame_drops_late,
1739 fprintf(stderr,
"%s", buf.str);
1746 last_time = cur_time;
1755 #if defined(DEBUG_SYNC)
1756 printf(
"frame_type=%c pts=%0.3f\n",
1801 diff -
is->frame_last_filter_delay < 0 &&
1802 is->viddec.pkt_serial ==
is->vidclk.serial &&
1803 is->videoq.nb_packets) {
1804 is->frame_drops_early++;
1831 outputs->filter_ctx = source_ctx;
1836 inputs->filter_ctx = sink_ctx;
1861 char sws_flags_str[512] =
"";
1867 int nb_pix_fmts = 0;
1884 if (!strcmp(e->
key,
"sws_flags")) {
1885 av_strlcatf(sws_flags_str,
sizeof(sws_flags_str),
"%s=%s:",
"flags", e->
value);
1889 if (strlen(sws_flags_str))
1890 sws_flags_str[strlen(sws_flags_str)-1] =
'\0';
1920 "ffplay_buffersink");
1939 last_filter = filt_out;
1943 #define INSERT_FILT(name, arg) do { \
1944 AVFilterContext *filt_ctx; \
1946 ret = avfilter_graph_create_filter(&filt_ctx, \
1947 avfilter_get_by_name(name), \
1948 "ffplay_" name, arg, NULL, graph); \
1952 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
1956 last_filter = filt_ctx; \
1965 if (!displaymatrix) {
1967 is->video_st->codecpar->nb_coded_side_data,
1974 if (
fabs(theta - 90) < 1.0) {
1975 INSERT_FILT(
"transpose", displaymatrix[3] > 0 ?
"cclock_flip" :
"clock");
1976 }
else if (
fabs(theta - 180) < 1.0) {
1977 if (displaymatrix[0] < 0)
1979 if (displaymatrix[4] < 0)
1981 }
else if (
fabs(theta - 270) < 1.0) {
1982 INSERT_FILT(
"transpose", displaymatrix[3] < 0 ?
"clock_flip" :
"cclock");
1983 }
else if (
fabs(theta) > 1.0) {
1984 char rotate_buf[64];
1985 snprintf(rotate_buf,
sizeof(rotate_buf),
"%f*PI/180", theta);
1988 if (displaymatrix && displaymatrix[4] < 0)
1996 is->in_video_filter = filt_src;
1997 is->out_video_filter = filt_out;
2007 char aresample_swr_opts[512] =
"";
2010 char asrc_args[256];
2022 if (strlen(aresample_swr_opts))
2023 aresample_swr_opts[strlen(aresample_swr_opts)-1] =
'\0';
2024 av_opt_set(
is->agraph,
"aresample_swr_opts", aresample_swr_opts, 0);
2029 "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:channel_layout=%s",
2031 1,
is->audio_filter_src.freq, bp.str);
2035 asrc_args,
NULL,
is->agraph);
2040 "ffplay_abuffersink");
2049 if (force_output_format) {
2065 is->in_audio_filter = filt_asrc;
2066 is->out_audio_filter = filt_asink;
2081 int last_serial = -1;
2099 frame->format,
frame->ch_layout.nb_channels) ||
2101 is->audio_filter_src.freq !=
frame->sample_rate ||
2102 is->auddec.pkt_serial != last_serial;
2105 char buf1[1024], buf2[1024];
2109 "Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n",
2110 is->audio_filter_src.freq,
is->audio_filter_src.ch_layout.nb_channels,
av_get_sample_fmt_name(
is->audio_filter_src.fmt), buf1, last_serial,
2113 is->audio_filter_src.fmt =
frame->format;
2117 is->audio_filter_src.freq =
frame->sample_rate;
2118 last_serial =
is->auddec.pkt_serial;
2135 af->
serial =
is->auddec.pkt_serial;
2141 if (
is->audioq.serial !=
is->auddec.pkt_serial)
2145 is->auddec.finished =
is->auddec.pkt_serial;
2180 int last_serial = -1;
2181 int last_vfilter_idx = 0;
2193 if ( last_w !=
frame->width
2194 || last_h !=
frame->height
2195 || last_format !=
frame->format
2196 || last_serial !=
is->viddec.pkt_serial
2197 || last_vfilter_idx !=
is->vfilter_idx) {
2199 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
2214 event.user.data1 =
is;
2215 SDL_PushEvent(&event);
2218 filt_in =
is->in_video_filter;
2219 filt_out =
is->out_video_filter;
2220 last_w =
frame->width;
2221 last_h =
frame->height;
2222 last_format =
frame->format;
2223 last_serial =
is->viddec.pkt_serial;
2224 last_vfilter_idx =
is->vfilter_idx;
2240 is->viddec.finished =
is->viddec.pkt_serial;
2249 is->frame_last_filter_delay = 0;
2255 if (
is->videoq.serial !=
is->viddec.pkt_serial)
2284 if (got_subtitle && sp->
sub.
format == 0) {
2288 sp->
serial =
is->subdec.pkt_serial;
2289 sp->
width =
is->subdec.avctx->width;
2290 sp->
height =
is->subdec.avctx->height;
2295 }
else if (got_subtitle) {
2312 memcpy(
is->sample_array +
is->sample_array_index,
samples,
len *
sizeof(
short));
2314 is->sample_array_index +=
len;
2316 is->sample_array_index = 0;
2325 int wanted_nb_samples = nb_samples;
2329 double diff, avg_diff;
2330 int min_nb_samples, max_nb_samples;
2335 is->audio_diff_cum =
diff +
is->audio_diff_avg_coef *
is->audio_diff_cum;
2338 is->audio_diff_avg_count++;
2341 avg_diff =
is->audio_diff_cum * (1.0 -
is->audio_diff_avg_coef);
2343 if (
fabs(avg_diff) >=
is->audio_diff_threshold) {
2344 wanted_nb_samples = nb_samples + (int)(
diff *
is->audio_src.freq);
2347 wanted_nb_samples =
av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
2350 diff, avg_diff, wanted_nb_samples - nb_samples,
2351 is->audio_clock,
is->audio_diff_threshold);
2356 is->audio_diff_avg_count = 0;
2357 is->audio_diff_cum = 0;
2361 return wanted_nb_samples;
2373 int data_size, resampled_data_size;
2375 int wanted_nb_samples;
2392 }
while (af->
serial !=
is->audioq.serial);
2407 &
is->audio_tgt.ch_layout,
is->audio_tgt.fmt,
is->audio_tgt.freq,
2412 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2426 uint8_t **
out = &
is->audio_buf1;
2442 if (!
is->audio_buf1)
2449 if (len2 == out_count) {
2454 is->audio_buf =
is->audio_buf1;
2458 resampled_data_size = data_size;
2461 audio_clock0 =
is->audio_clock;
2466 is->audio_clock =
NAN;
2467 is->audio_clock_serial = af->
serial;
2470 static double last_clock;
2471 printf(
"audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
2472 is->audio_clock - last_clock,
2473 is->audio_clock, audio_clock0);
2474 last_clock =
is->audio_clock;
2477 return resampled_data_size;
2484 int audio_size, len1;
2489 if (
is->audio_buf_index >=
is->audio_buf_size) {
2491 if (audio_size < 0) {
2496 if (
is->show_mode != SHOW_MODE_VIDEO)
2498 is->audio_buf_size = audio_size;
2500 is->audio_buf_index = 0;
2502 len1 =
is->audio_buf_size -
is->audio_buf_index;
2505 if (!
is->muted &&
is->audio_buf &&
is->audio_volume == SDL_MIX_MAXVOLUME)
2506 memcpy(stream, (uint8_t *)
is->audio_buf +
is->audio_buf_index, len1);
2508 memset(stream, 0, len1);
2509 if (!
is->muted &&
is->audio_buf)
2510 SDL_MixAudioFormat(stream, (uint8_t *)
is->audio_buf +
is->audio_buf_index, AUDIO_S16SYS, len1,
is->audio_volume);
2514 is->audio_buf_index += len1;
2516 is->audio_write_buf_size =
is->audio_buf_size -
is->audio_buf_index;
2518 if (!
isnan(
is->audio_clock)) {
2526 SDL_AudioSpec wanted_spec, spec;
2528 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2529 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
2530 int next_sample_rate_idx =
FF_ARRAY_ELEMS(next_sample_rates) - 1;
2531 int wanted_nb_channels = wanted_channel_layout->
nb_channels;
2533 env = SDL_getenv(
"SDL_AUDIO_CHANNELS");
2535 wanted_nb_channels = atoi(env);
2543 wanted_nb_channels = wanted_channel_layout->
nb_channels;
2544 wanted_spec.channels = wanted_nb_channels;
2545 wanted_spec.freq = wanted_sample_rate;
2546 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2550 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
2551 next_sample_rate_idx--;
2552 wanted_spec.format = AUDIO_S16SYS;
2553 wanted_spec.silence = 0;
2556 wanted_spec.userdata = opaque;
2557 while (!(
audio_dev = SDL_OpenAudioDevice(
NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
2559 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
2560 wanted_spec.channels = next_nb_channels[
FFMIN(7, wanted_spec.channels)];
2561 if (!wanted_spec.channels) {
2562 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
2563 wanted_spec.channels = wanted_nb_channels;
2564 if (!wanted_spec.freq) {
2566 "No more combinations to try, audio open failed\n");
2572 if (spec.format != AUDIO_S16SYS) {
2574 "SDL advised audio format %d is not supported!\n", spec.format);
2577 if (spec.channels != wanted_spec.channels) {
2582 "SDL advised channel count %d is not supported!\n", spec.channels);
2588 audio_hw_params->
freq = spec.freq;
2642 const char *forced_codec_name =
NULL;
2647 int stream_lowres =
lowres;
2649 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2668 if (forced_codec_name)
2672 "No codec could be found with name '%s'\n", forced_codec_name);
2685 avctx->
lowres = stream_lowres;
2729 sink =
is->out_audio_filter;
2739 is->audio_hw_buf_size =
ret;
2740 is->audio_src =
is->audio_tgt;
2741 is->audio_buf_size = 0;
2742 is->audio_buf_index = 0;
2746 is->audio_diff_avg_count = 0;
2749 is->audio_diff_threshold = (
double)(
is->audio_hw_buf_size) /
is->audio_tgt.bytes_per_sec;
2751 is->audio_stream = stream_index;
2752 is->audio_st = ic->
streams[stream_index];
2757 is->auddec.start_pts =
is->audio_st->start_time;
2758 is->auddec.start_pts_tb =
is->audio_st->time_base;
2765 is->video_stream = stream_index;
2766 is->video_st = ic->
streams[stream_index];
2772 is->queue_attachments_req = 1;
2775 is->subtitle_stream = stream_index;
2776 is->subtitle_st = ic->
streams[stream_index];
2800 return is->abort_request;
2804 return stream_id < 0 ||
2812 if( !strcmp(
s->iformat->name,
"rtp")
2813 || !strcmp(
s->iformat->name,
"rtsp")
2814 || !strcmp(
s->iformat->name,
"sdp")
2818 if(
s->pb && ( !strncmp(
s->url,
"rtp:", 4)
2819 || !strncmp(
s->url,
"udp:", 4)
2835 int pkt_in_play_range = 0;
2837 SDL_mutex *wait_mutex = SDL_CreateMutex();
2838 int scan_all_pmts_set = 0;
2847 memset(st_index, -1,
sizeof(st_index));
2866 scan_all_pmts_set = 1;
2874 if (scan_all_pmts_set)
2893 "Error setting up avformat_find_stream_info() options\n");
2900 for (
i = 0;
i < orig_nb_streams;
i++)
2906 "%s: could not find codec parameters\n",
is->filename);
2956 st_index[
i] = INT_MAX;
2984 if (codecpar->
width)
2997 if (
is->show_mode == SHOW_MODE_NONE)
2998 is->show_mode =
ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
3004 if (
is->video_stream < 0 &&
is->audio_stream < 0) {
3011 if (infinite_buffer < 0 && is->realtime)
3015 if (
is->abort_request)
3017 if (
is->paused !=
is->last_paused) {
3018 is->last_paused =
is->paused;
3024 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
3036 int64_t seek_min =
is->seek_rel > 0 ? seek_target -
is->seek_rel + 2: INT64_MIN;
3037 int64_t seek_max =
is->seek_rel < 0 ? seek_target -
is->seek_rel - 2: INT64_MAX;
3044 "%s: error while seeking\n",
is->ic->url);
3046 if (
is->audio_stream >= 0)
3048 if (
is->subtitle_stream >= 0)
3050 if (
is->video_stream >= 0)
3059 is->queue_attachments_req = 1;
3064 if (
is->queue_attachments_req) {
3071 is->queue_attachments_req = 0;
3081 SDL_LockMutex(wait_mutex);
3082 SDL_CondWaitTimeout(
is->continue_read_thread, wait_mutex, 10);
3083 SDL_UnlockMutex(wait_mutex);
3099 if (
is->video_stream >= 0)
3101 if (
is->audio_stream >= 0)
3103 if (
is->subtitle_stream >= 0)
3113 SDL_LockMutex(wait_mutex);
3114 SDL_CondWaitTimeout(
is->continue_read_thread, wait_mutex, 10);
3115 SDL_UnlockMutex(wait_mutex);
3124 (pkt_ts - (stream_start_time !=
AV_NOPTS_VALUE ? stream_start_time : 0)) *
3150 event.user.data1 =
is;
3151 SDL_PushEvent(&event);
3153 SDL_DestroyMutex(wait_mutex);
3165 is->last_video_stream =
is->video_stream = -1;
3166 is->last_audio_stream =
is->audio_stream = -1;
3167 is->last_subtitle_stream =
is->subtitle_stream = -1;
3188 if (!(
is->continue_read_thread = SDL_CreateCond())) {
3196 is->audio_clock_serial = -1;
3207 if (!
is->read_tid) {
3219 int start_index, stream_index;
3226 start_index =
is->last_video_stream;
3227 old_index =
is->video_stream;
3229 start_index =
is->last_audio_stream;
3230 old_index =
is->audio_stream;
3232 start_index =
is->last_subtitle_stream;
3233 old_index =
is->subtitle_stream;
3235 stream_index = start_index;
3241 for (start_index = 0; start_index <
nb_streams; start_index++)
3246 stream_index = start_index;
3256 is->last_subtitle_stream = -1;
3259 if (start_index == -1)
3263 if (stream_index == start_index)
3265 st =
is->ic->streams[p ? p->
stream_index[stream_index] : stream_index];
3283 if (p && stream_index != -1)
3303 int next =
is->show_mode;
3305 next = (next + 1) % SHOW_MODE_NB;
3306 }
while (next !=
is->show_mode && (next == SHOW_MODE_VIDEO && !
is->video_st || next != SHOW_MODE_VIDEO && !
is->audio_st));
3307 if (
is->show_mode != next) {
3308 is->force_refresh = 1;
3309 is->show_mode = next;
3314 double remaining_time = 0.0;
3316 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
3321 if (remaining_time > 0.0)
3324 if (
is->show_mode != SHOW_MODE_NONE && (!
is->paused ||
is->force_refresh))
3335 if (!
is->ic->nb_chapters)
3339 for (
i = 0;
i <
is->ic->nb_chapters;
i++) {
3349 if (
i >=
is->ic->nb_chapters)
3361 double incr,
pos, frac;
3366 switch (event.type) {
3368 if (
exit_on_keydown || event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q) {
3373 if (!cur_stream->
width)
3375 switch (event.key.keysym.sym) {
3387 case SDLK_KP_MULTIPLY:
3391 case SDLK_KP_DIVIDE:
3475 case SDL_MOUSEBUTTONDOWN:
3480 if (event.button.button == SDL_BUTTON_LEFT) {
3481 static int64_t last_mouse_left_click = 0;
3485 last_mouse_left_click = 0;
3490 case SDL_MOUSEMOTION:
3496 if (event.type == SDL_MOUSEBUTTONDOWN) {
3497 if (event.button.button != SDL_BUTTON_RIGHT)
3501 if (!(event.motion.state & SDL_BUTTON_RMASK))
3511 int tns, thh, tmm, tss;
3514 tmm = (tns % 3600) / 60;
3516 frac = x / cur_stream->
width;
3519 mm = (
ns % 3600) / 60;
3522 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3523 hh, mm,
ss, thh, tmm, tss);
3530 case SDL_WINDOWEVENT:
3531 switch (event.window.event) {
3532 case SDL_WINDOWEVENT_SIZE_CHANGED:
3541 case SDL_WINDOWEVENT_EXPOSED:
3589 if (!strcmp(
arg,
"audio"))
3591 else if (!strcmp(
arg,
"video"))
3593 else if (!strcmp(
arg,
"ext"))
3605 !strcmp(
arg,
"waves") ? SHOW_MODE_WAVES :
3606 !strcmp(
arg,
"rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE;
3622 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3626 if (!strcmp(filename,
"-"))
3637 const char *spec = strchr(opt,
':');
3641 "No media specifier was specified in '%s' in option '%s'\n",
3653 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
3710 "read and decode the streams to fill missing information with heuristics" },
3735 printf(
"\nWhile playing:\n"
3737 "f toggle full screen\n"
3740 "9, 0 decrease and increase volume respectively\n"
3741 "/, * decrease and increase volume respectively\n"
3742 "a cycle audio channel in the current program\n"
3743 "v cycle video channel\n"
3744 "t cycle subtitle channel in the current program\n"
3746 "w cycle video filters or show modes\n"
3747 "s activate frame-step mode\n"
3748 "left/right seek backward/forward 10 seconds or to custom interval if -seek_interval is set\n"
3749 "down/up seek backward/forward 1 minute\n"
3750 "page down/page up seek backward/forward 10 minutes\n"
3751 "right mouse click seek to percentage in file corresponding to fraction of width\n"
3752 "left double-click toggle full screen\n"
3786 "Use -h to get full help or, even better, run 'man %s'\n",
program_name);
3793 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3795 flags &= ~SDL_INIT_AUDIO;
3799 if (!SDL_getenv(
"SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
3800 SDL_setenv(
"SDL_AUDIO_ALSA_SET_BUFFER_SIZE",
"1", 1);
3803 flags &= ~SDL_INIT_VIDEO;
3804 if (SDL_Init (
flags)) {
3810 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3811 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3814 int flags = SDL_WINDOW_HIDDEN;
3816 #if SDL_VERSION_ATLEAST(2,0,5)
3817 flags |= SDL_WINDOW_ALWAYS_ON_TOP;
3819 av_log(
NULL,
AV_LOG_WARNING,
"Your SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
3822 flags |= SDL_WINDOW_BORDERLESS;
3824 flags |= SDL_WINDOW_RESIZABLE;
3826 #ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
3827 SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,
"0");
3836 #if SDL_VERSION_ATLEAST(2, 0, 6)
3837 flags |= SDL_WINDOW_VULKAN;
3845 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
"linear");
3868 renderer = SDL_CreateRenderer(
window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);