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;
2637 const char *forced_codec_name =
NULL;
2642 int stream_lowres =
lowres;
2644 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2663 if (forced_codec_name)
2667 "No codec could be found with name '%s'\n", forced_codec_name);
2680 avctx->
lowres = stream_lowres;
2724 sink =
is->out_audio_filter;
2734 is->audio_hw_buf_size =
ret;
2735 is->audio_src =
is->audio_tgt;
2736 is->audio_buf_size = 0;
2737 is->audio_buf_index = 0;
2741 is->audio_diff_avg_count = 0;
2744 is->audio_diff_threshold = (
double)(
is->audio_hw_buf_size) /
is->audio_tgt.bytes_per_sec;
2746 is->audio_stream = stream_index;
2747 is->audio_st = ic->
streams[stream_index];
2752 is->auddec.start_pts =
is->audio_st->start_time;
2753 is->auddec.start_pts_tb =
is->audio_st->time_base;
2760 is->video_stream = stream_index;
2761 is->video_st = ic->
streams[stream_index];
2767 is->queue_attachments_req = 1;
2770 is->subtitle_stream = stream_index;
2771 is->subtitle_st = ic->
streams[stream_index];
2795 return is->abort_request;
2799 return stream_id < 0 ||
2807 if( !strcmp(
s->iformat->name,
"rtp")
2808 || !strcmp(
s->iformat->name,
"rtsp")
2809 || !strcmp(
s->iformat->name,
"sdp")
2813 if(
s->pb && ( !strncmp(
s->url,
"rtp:", 4)
2814 || !strncmp(
s->url,
"udp:", 4)
2830 int pkt_in_play_range = 0;
2832 SDL_mutex *wait_mutex = SDL_CreateMutex();
2833 int scan_all_pmts_set = 0;
2842 memset(st_index, -1,
sizeof(st_index));
2861 scan_all_pmts_set = 1;
2869 if (scan_all_pmts_set)
2888 "Error setting up avformat_find_stream_info() options\n");
2895 for (
i = 0;
i < orig_nb_streams;
i++)
2901 "%s: could not find codec parameters\n",
is->filename);
2951 st_index[
i] = INT_MAX;
2979 if (codecpar->
width)
2992 if (
is->show_mode == SHOW_MODE_NONE)
2993 is->show_mode =
ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
2999 if (
is->video_stream < 0 &&
is->audio_stream < 0) {
3006 if (infinite_buffer < 0 && is->realtime)
3010 if (
is->abort_request)
3012 if (
is->paused !=
is->last_paused) {
3013 is->last_paused =
is->paused;
3019 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
3031 int64_t seek_min =
is->seek_rel > 0 ? seek_target -
is->seek_rel + 2: INT64_MIN;
3032 int64_t seek_max =
is->seek_rel < 0 ? seek_target -
is->seek_rel - 2: INT64_MAX;
3039 "%s: error while seeking\n",
is->ic->url);
3041 if (
is->audio_stream >= 0)
3043 if (
is->subtitle_stream >= 0)
3045 if (
is->video_stream >= 0)
3054 is->queue_attachments_req = 1;
3059 if (
is->queue_attachments_req) {
3066 is->queue_attachments_req = 0;
3076 SDL_LockMutex(wait_mutex);
3077 SDL_CondWaitTimeout(
is->continue_read_thread, wait_mutex, 10);
3078 SDL_UnlockMutex(wait_mutex);
3094 if (
is->video_stream >= 0)
3096 if (
is->audio_stream >= 0)
3098 if (
is->subtitle_stream >= 0)
3108 SDL_LockMutex(wait_mutex);
3109 SDL_CondWaitTimeout(
is->continue_read_thread, wait_mutex, 10);
3110 SDL_UnlockMutex(wait_mutex);
3119 (pkt_ts - (stream_start_time !=
AV_NOPTS_VALUE ? stream_start_time : 0)) *
3145 event.user.data1 =
is;
3146 SDL_PushEvent(&event);
3148 SDL_DestroyMutex(wait_mutex);
3160 is->last_video_stream =
is->video_stream = -1;
3161 is->last_audio_stream =
is->audio_stream = -1;
3162 is->last_subtitle_stream =
is->subtitle_stream = -1;
3183 if (!(
is->continue_read_thread = SDL_CreateCond())) {
3191 is->audio_clock_serial = -1;
3202 if (!
is->read_tid) {
3214 int start_index, stream_index;
3221 start_index =
is->last_video_stream;
3222 old_index =
is->video_stream;
3224 start_index =
is->last_audio_stream;
3225 old_index =
is->audio_stream;
3227 start_index =
is->last_subtitle_stream;
3228 old_index =
is->subtitle_stream;
3230 stream_index = start_index;
3236 for (start_index = 0; start_index <
nb_streams; start_index++)
3241 stream_index = start_index;
3251 is->last_subtitle_stream = -1;
3254 if (start_index == -1)
3258 if (stream_index == start_index)
3260 st =
is->ic->streams[p ? p->
stream_index[stream_index] : stream_index];
3278 if (p && stream_index != -1)
3298 int next =
is->show_mode;
3300 next = (next + 1) % SHOW_MODE_NB;
3301 }
while (next !=
is->show_mode && (next == SHOW_MODE_VIDEO && !
is->video_st || next != SHOW_MODE_VIDEO && !
is->audio_st));
3302 if (
is->show_mode != next) {
3303 is->force_refresh = 1;
3304 is->show_mode = next;
3309 double remaining_time = 0.0;
3311 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
3316 if (remaining_time > 0.0)
3319 if (
is->show_mode != SHOW_MODE_NONE && (!
is->paused ||
is->force_refresh))
3330 if (!
is->ic->nb_chapters)
3334 for (
i = 0;
i <
is->ic->nb_chapters;
i++) {
3344 if (
i >=
is->ic->nb_chapters)
3356 double incr,
pos, frac;
3361 switch (event.type) {
3363 if (
exit_on_keydown || event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q) {
3368 if (!cur_stream->
width)
3370 switch (event.key.keysym.sym) {
3382 case SDLK_KP_MULTIPLY:
3386 case SDLK_KP_DIVIDE:
3470 case SDL_MOUSEBUTTONDOWN:
3475 if (event.button.button == SDL_BUTTON_LEFT) {
3476 static int64_t last_mouse_left_click = 0;
3480 last_mouse_left_click = 0;
3485 case SDL_MOUSEMOTION:
3491 if (event.type == SDL_MOUSEBUTTONDOWN) {
3492 if (event.button.button != SDL_BUTTON_RIGHT)
3496 if (!(event.motion.state & SDL_BUTTON_RMASK))
3506 int tns, thh, tmm, tss;
3509 tmm = (tns % 3600) / 60;
3511 frac = x / cur_stream->
width;
3514 mm = (
ns % 3600) / 60;
3517 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3518 hh, mm,
ss, thh, tmm, tss);
3525 case SDL_WINDOWEVENT:
3526 switch (event.window.event) {
3527 case SDL_WINDOWEVENT_SIZE_CHANGED:
3536 case SDL_WINDOWEVENT_EXPOSED:
3584 if (!strcmp(
arg,
"audio"))
3586 else if (!strcmp(
arg,
"video"))
3588 else if (!strcmp(
arg,
"ext"))
3600 !strcmp(
arg,
"waves") ? SHOW_MODE_WAVES :
3601 !strcmp(
arg,
"rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE;
3617 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3621 if (!strcmp(filename,
"-"))
3632 const char *spec = strchr(opt,
':');
3636 "No media specifier was specified in '%s' in option '%s'\n",
3648 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
3705 "read and decode the streams to fill missing information with heuristics" },
3730 printf(
"\nWhile playing:\n"
3732 "f toggle full screen\n"
3735 "9, 0 decrease and increase volume respectively\n"
3736 "/, * decrease and increase volume respectively\n"
3737 "a cycle audio channel in the current program\n"
3738 "v cycle video channel\n"
3739 "t cycle subtitle channel in the current program\n"
3741 "w cycle video filters or show modes\n"
3742 "s activate frame-step mode\n"
3743 "left/right seek backward/forward 10 seconds or to custom interval if -seek_interval is set\n"
3744 "down/up seek backward/forward 1 minute\n"
3745 "page down/page up seek backward/forward 10 minutes\n"
3746 "right mouse click seek to percentage in file corresponding to fraction of width\n"
3747 "left double-click toggle full screen\n"
3781 "Use -h to get full help or, even better, run 'man %s'\n",
program_name);
3788 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3790 flags &= ~SDL_INIT_AUDIO;
3794 if (!SDL_getenv(
"SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
3795 SDL_setenv(
"SDL_AUDIO_ALSA_SET_BUFFER_SIZE",
"1", 1);
3798 flags &= ~SDL_INIT_VIDEO;
3799 if (SDL_Init (
flags)) {
3805 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3806 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3809 int flags = SDL_WINDOW_HIDDEN;
3811 #if SDL_VERSION_ATLEAST(2,0,5)
3812 flags |= SDL_WINDOW_ALWAYS_ON_TOP;
3814 av_log(
NULL,
AV_LOG_WARNING,
"Your SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
3817 flags |= SDL_WINDOW_BORDERLESS;
3819 flags |= SDL_WINDOW_RESIZABLE;
3821 #ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
3822 SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,
"0");
3831 #if SDL_VERSION_ATLEAST(2, 0, 6)
3832 flags |= SDL_WINDOW_VULKAN;
3840 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
"linear");
3863 renderer = SDL_CreateRenderer(
window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);