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)
412 if (channel_count1 == 1 && channel_count2 == 1)
415 return channel_count1 != channel_count2 || fmt1 != fmt2;
437 SDL_CondSignal(q->
cond);
453 SDL_LockMutex(q->
mutex);
455 SDL_UnlockMutex(q->
mutex);
476 q->
mutex = SDL_CreateMutex();
481 q->
cond = SDL_CreateCond();
494 SDL_LockMutex(q->
mutex);
501 SDL_UnlockMutex(q->
mutex);
508 SDL_DestroyMutex(q->
mutex);
509 SDL_DestroyCond(q->
cond);
514 SDL_LockMutex(q->
mutex);
518 SDL_CondSignal(q->
cond);
520 SDL_UnlockMutex(q->
mutex);
525 SDL_LockMutex(q->
mutex);
528 SDL_UnlockMutex(q->
mutex);
537 SDL_LockMutex(q->
mutex);
562 SDL_UnlockMutex(q->
mutex);
651 if (got_frame && !d->
pkt->
data) {
669 av_log(d->
avctx,
AV_LOG_ERROR,
"Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
693 if (!(
f->mutex = SDL_CreateMutex())) {
697 if (!(
f->cond = SDL_CreateCond())) {
703 f->keep_last = !!keep_last;
704 for (
i = 0;
i <
f->max_size;
i++)
713 for (
i = 0;
i <
f->max_size;
i++) {
718 SDL_DestroyMutex(
f->mutex);
719 SDL_DestroyCond(
f->cond);
724 SDL_LockMutex(
f->mutex);
725 SDL_CondSignal(
f->cond);
726 SDL_UnlockMutex(
f->mutex);
731 return &
f->queue[(
f->rindex +
f->rindex_shown) %
f->max_size];
736 return &
f->queue[(
f->rindex +
f->rindex_shown + 1) %
f->max_size];
741 return &
f->queue[
f->rindex];
747 SDL_LockMutex(
f->mutex);
748 while (
f->size >=
f->max_size &&
749 !
f->pktq->abort_request) {
750 SDL_CondWait(
f->cond,
f->mutex);
752 SDL_UnlockMutex(
f->mutex);
754 if (
f->pktq->abort_request)
757 return &
f->queue[
f->windex];
763 SDL_LockMutex(
f->mutex);
764 while (
f->size -
f->rindex_shown <= 0 &&
765 !
f->pktq->abort_request) {
766 SDL_CondWait(
f->cond,
f->mutex);
768 SDL_UnlockMutex(
f->mutex);
770 if (
f->pktq->abort_request)
773 return &
f->queue[(
f->rindex +
f->rindex_shown) %
f->max_size];
778 if (++
f->windex ==
f->max_size)
780 SDL_LockMutex(
f->mutex);
782 SDL_CondSignal(
f->cond);
783 SDL_UnlockMutex(
f->mutex);
788 if (
f->keep_last && !
f->rindex_shown) {
793 if (++
f->rindex ==
f->max_size)
795 SDL_LockMutex(
f->mutex);
797 SDL_CondSignal(
f->cond);
798 SDL_UnlockMutex(
f->mutex);
804 return f->size -
f->rindex_shown;
810 Frame *fp = &
f->queue[
f->rindex];
811 if (
f->rindex_shown && fp->
serial ==
f->pktq->serial)
837 static int realloc_texture(SDL_Texture **texture, Uint32 new_format,
int new_width,
int new_height, SDL_BlendMode blendmode,
int init_texture)
841 if (!*texture || SDL_QueryTexture(*texture, &
format, &access, &
w, &
h) < 0 || new_width !=
w || new_height !=
h || new_format !=
format) {
845 SDL_DestroyTexture(*texture);
846 if (!(*texture = SDL_CreateTexture(
renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
848 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
851 if (SDL_LockTexture(*texture,
NULL, &pixels, &pitch) < 0)
853 memset(pixels, 0, pitch * new_height);
854 SDL_UnlockTexture(*texture);
856 av_log(
NULL,
AV_LOG_VERBOSE,
"Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
862 int scr_xleft,
int scr_ytop,
int scr_width,
int scr_height,
863 int pic_width,
int pic_height,
AVRational pic_sar)
876 if (
width > scr_width) {
880 x = (scr_width -
width) / 2;
881 y = (scr_height -
height) / 2;
882 rect->
x = scr_xleft + x;
883 rect->
y = scr_ytop + y;
891 *sdl_blendmode = SDL_BLENDMODE_NONE;
892 *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN;
897 *sdl_blendmode = SDL_BLENDMODE_BLEND;
910 SDL_BlendMode sdl_blendmode;
912 if (
realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt,
frame->width,
frame->height, sdl_blendmode, 0) < 0)
914 switch (sdl_pix_fmt) {
915 case SDL_PIXELFORMAT_IYUV:
916 if (
frame->linesize[0] > 0 &&
frame->linesize[1] > 0 &&
frame->linesize[2] > 0) {
920 }
else if (
frame->linesize[0] < 0 &&
frame->linesize[1] < 0 &&
frame->linesize[2] < 0) {
930 if (
frame->linesize[0] < 0) {
949 #if SDL_VERSION_ATLEAST(2,0,8)
950 SDL_YUV_CONVERSION_MODE
mode = SDL_YUV_CONVERSION_AUTOMATIC;
953 mode = SDL_YUV_CONVERSION_JPEG;
955 mode = SDL_YUV_CONVERSION_BT709;
957 mode = SDL_YUV_CONVERSION_BT601;
959 SDL_SetYUVConversionMode(
mode);
975 if (
is->subtitle_st) {
1003 if (!
is->sub_convert_ctx) {
1007 if (!SDL_LockTexture(
is->sub_texture, (SDL_Rect *)sub_rect, (
void **)pixels, pitch)) {
1008 sws_scale(
is->sub_convert_ctx, (
const uint8_t *
const *)sub_rect->data, sub_rect->linesize,
1009 0, sub_rect->h, pixels, pitch);
1010 SDL_UnlockTexture(
is->sub_texture);
1035 #if USE_ONEPASS_SUBTITLE_RENDER
1042 SDL_Rect *sub_rect = (SDL_Rect*)sp->
sub.
rects[
i];
1043 SDL_Rect target = {.
x =
rect.
x + sub_rect->x * xratio,
1044 .y =
rect.
y + sub_rect->y * yratio,
1045 .w = sub_rect->w * xratio,
1046 .h = sub_rect->h * yratio};
1047 SDL_RenderCopy(
renderer,
is->sub_texture, sub_rect, &target);
1055 return a < 0 ?
a%
b +
b :
a%
b;
1060 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1063 int rdft_bits, nb_freq;
1065 for (rdft_bits = 1; (1 << rdft_bits) < 2 *
s->height; rdft_bits++)
1067 nb_freq = 1 << (rdft_bits - 1);
1070 channels =
s->audio_tgt.ch_layout.nb_channels;
1073 int data_used=
s->show_mode == SHOW_MODE_WAVES ?
s->width : (2*nb_freq);
1075 delay =
s->audio_write_buf_size;
1082 delay -= (time_diff *
s->audio_tgt.freq) / 1000000;
1085 delay += 2 * data_used;
1086 if (delay < data_used)
1090 if (
s->show_mode == SHOW_MODE_WAVES) {
1094 int a =
s->sample_array[idx];
1099 if (
h < score && (
b ^
c) < 0) {
1106 s->last_i_start = i_start;
1108 i_start =
s->last_i_start;
1111 if (
s->show_mode == SHOW_MODE_WAVES) {
1112 SDL_SetRenderDrawColor(
renderer, 255, 255, 255, 255);
1115 h =
s->height / nb_display_channels;
1118 for (ch = 0; ch < nb_display_channels; ch++) {
1120 y1 =
s->ytop + ch *
h + (
h / 2);
1121 for (x = 0; x <
s->width; x++) {
1122 y = (
s->sample_array[
i] * h2) >> 15;
1136 SDL_SetRenderDrawColor(
renderer, 0, 0, 255, 255);
1138 for (ch = 1; ch < nb_display_channels; ch++) {
1139 y =
s->ytop + ch *
h;
1144 if (
realloc_texture(&
s->vis_texture, SDL_PIXELFORMAT_ARGB8888,
s->width,
s->height, SDL_BLENDMODE_NONE, 1) < 0)
1147 if (
s->xpos >=
s->width)
1149 nb_display_channels=
FFMIN(nb_display_channels, 2);
1150 if (rdft_bits !=
s->rdft_bits) {
1151 const float rdft_scale = 1.0;
1155 s->rdft_bits = rdft_bits;
1159 0, 1 << rdft_bits, &rdft_scale, 0);
1161 if (err < 0 || !s->rdft_data) {
1163 s->show_mode = SHOW_MODE_WAVES;
1167 SDL_Rect
rect = {.
x =
s->xpos, .y = 0, .w = 1, .h =
s->height};
1170 for (ch = 0; ch < nb_display_channels; ch++) {
1171 data_in[ch] =
s->real_data + 2 * nb_freq * ch;
1172 data[ch] =
s->rdft_data + nb_freq * ch;
1174 for (x = 0; x < 2 * nb_freq; x++) {
1175 double w = (x-nb_freq) * (1.0 / nb_freq);
1176 data_in[ch][x] =
s->sample_array[
i] * (1.0 -
w *
w);
1181 s->rdft_fn(
s->rdft,
data[ch], data_in[ch],
sizeof(
float));
1182 data[ch][0].im =
data[ch][nb_freq].re;
1183 data[ch][nb_freq].re = 0;
1187 if (!SDL_LockTexture(
s->vis_texture, &
rect, (
void **)&pixels, &pitch)) {
1189 pixels += pitch *
s->height;
1190 for (y = 0; y <
s->height; y++) {
1191 double w = 1 / sqrt(nb_freq);
1192 int a = sqrt(
w * sqrt(
data[0][y].re *
data[0][y].re +
data[0][y].im *
data[0][y].im));
1193 int b = (nb_display_channels == 2 ) ? sqrt(
w *
hypot(
data[1][y].re,
data[1][y].im))
1198 *pixels = (
a << 16) + (
b << 8) + ((
a+
b) >> 1);
1200 SDL_UnlockTexture(
s->vis_texture);
1214 if (stream_index < 0 || stream_index >= ic->
nb_streams)
1225 is->audio_buf1_size = 0;
1252 is->audio_stream = -1;
1256 is->video_stream = -1;
1260 is->subtitle_stream = -1;
1270 is->abort_request = 1;
1271 SDL_WaitThread(
is->read_tid,
NULL);
1274 if (
is->audio_stream >= 0)
1276 if (
is->video_stream >= 0)
1278 if (
is->subtitle_stream >= 0)
1291 SDL_DestroyCond(
is->continue_read_thread);
1294 if (
is->vis_texture)
1295 SDL_DestroyTexture(
is->vis_texture);
1296 if (
is->vid_texture)
1297 SDL_DestroyTexture(
is->vid_texture);
1298 if (
is->sub_texture)
1299 SDL_DestroyTexture(
is->sub_texture);
1313 SDL_DestroyWindow(
window);
1340 if (max_width == INT_MAX && max_height == INT_MAX)
1361 SDL_SetWindowFullscreen(
window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1376 SDL_SetRenderDrawColor(
renderer, 0, 0, 0, 255);
1378 if (
is->audio_st &&
is->show_mode != SHOW_MODE_VIDEO)
1380 else if (
is->video_st)
1387 if (*
c->queue_serial !=
c->serial)
1393 return c->pts_drift + time - (time -
c->last_updated) * (1.0 -
c->speed);
1400 c->last_updated = time;
1401 c->pts_drift =
c->pts - time;
1421 c->queue_serial = queue_serial;
1476 double speed =
is->extclk.speed;
1485 if (!
is->seek_req) {
1492 SDL_CondSignal(
is->continue_read_thread);
1501 if (
is->read_pause_return !=
AVERROR(ENOSYS)) {
1502 is->vidclk.paused = 0;
1507 is->paused =
is->audclk.paused =
is->vidclk.paused =
is->extclk.paused = !
is->paused;
1518 is->muted = !
is->muted;
1523 double volume_level =
is->audio_volume ? (20 *
log(
is->audio_volume / (
double)SDL_MIX_MAXVOLUME) /
log(10)) : -1000.0;
1524 int new_volume =
lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign *
step) / 20.0));
1525 is->audio_volume =
av_clip(
is->audio_volume == new_volume ? (
is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
1538 double sync_threshold,
diff = 0;
1551 if (
diff <= -sync_threshold)
1554 delay = delay +
diff;
1555 else if (
diff >= sync_threshold)
1569 if (
isnan(
duration) || duration <= 0 || duration >
is->max_frame_duration)
1598 if (
is->force_refresh ||
is->last_vis_time +
rdftspeed < time) {
1600 is->last_vis_time = time;
1602 *remaining_time =
FFMIN(*remaining_time,
is->last_vis_time +
rdftspeed - time);
1610 double last_duration,
duration, delay;
1617 if (vp->
serial !=
is->videoq.serial) {
1633 if (time < is->frame_timer + delay) {
1634 *remaining_time =
FFMIN(
is->frame_timer + delay - time, *remaining_time);
1638 is->frame_timer += delay;
1640 is->frame_timer = time;
1642 SDL_LockMutex(
is->pictq.mutex);
1645 SDL_UnlockMutex(
is->pictq.mutex);
1651 is->frame_drops_late++;
1657 if (
is->subtitle_st) {
1666 if (sp->
serial !=
is->subtitleq.serial
1677 if (!SDL_LockTexture(
is->sub_texture, (SDL_Rect *)sub_rect, (
void **)&pixels, &pitch)) {
1678 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
1679 memset(pixels, 0, sub_rect->w << 2);
1680 SDL_UnlockTexture(
is->sub_texture);
1692 is->force_refresh = 1;
1694 if (
is->step && !
is->paused)
1699 if (!
display_disable &&
is->force_refresh &&
is->show_mode == SHOW_MODE_VIDEO &&
is->pictq.rindex_shown)
1702 is->force_refresh = 0;
1707 int aqsize, vqsize, sqsize;
1711 if (!last_time || (cur_time - last_time) >= 30000) {
1716 aqsize =
is->audioq.size;
1718 vqsize =
is->videoq.size;
1719 if (
is->subtitle_st)
1720 sqsize =
is->subtitleq.size;
1722 if (
is->audio_st &&
is->video_st)
1724 else if (
is->video_st)
1726 else if (
is->audio_st)
1731 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB \r",
1733 (
is->audio_st &&
is->video_st) ?
"A-V" : (
is->video_st ?
"M-V" : (
is->audio_st ?
"M-A" :
" ")),
1735 is->frame_drops_early +
is->frame_drops_late,
1741 fprintf(stderr,
"%s", buf.str);
1748 last_time = cur_time;
1757 #if defined(DEBUG_SYNC)
1758 printf(
"frame_type=%c pts=%0.3f\n",
1803 diff -
is->frame_last_filter_delay < 0 &&
1804 is->viddec.pkt_serial ==
is->vidclk.serial &&
1805 is->videoq.nb_packets) {
1806 is->frame_drops_early++;
1833 outputs->filter_ctx = source_ctx;
1838 inputs->filter_ctx = sink_ctx;
1863 char sws_flags_str[512] =
"";
1864 char buffersrc_args[256];
1870 int nb_pix_fmts = 0;
1888 if (!strcmp(e->
key,
"sws_flags")) {
1889 av_strlcatf(sws_flags_str,
sizeof(sws_flags_str),
"%s=%s:",
"flags", e->
value);
1893 if (strlen(sws_flags_str))
1894 sws_flags_str[strlen(sws_flags_str)-1] =
'\0';
1898 snprintf(buffersrc_args,
sizeof(buffersrc_args),
1899 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:"
1900 "colorspace=%d:range=%d",
1902 is->video_st->time_base.num,
is->video_st->time_base.den,
1906 av_strlcatf(buffersrc_args,
sizeof(buffersrc_args),
":frame_rate=%d/%d", fr.
num, fr.
den);
1910 "ffplay_buffer", buffersrc_args,
NULL,
1920 "ffplay_buffersink",
NULL,
NULL, graph);
1930 last_filter = filt_out;
1934 #define INSERT_FILT(name, arg) do { \
1935 AVFilterContext *filt_ctx; \
1937 ret = avfilter_graph_create_filter(&filt_ctx, \
1938 avfilter_get_by_name(name), \
1939 "ffplay_" name, arg, NULL, graph); \
1943 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
1947 last_filter = filt_ctx; \
1956 if (!displaymatrix) {
1958 is->video_st->codecpar->nb_coded_side_data,
1965 if (
fabs(theta - 90) < 1.0) {
1966 INSERT_FILT(
"transpose", displaymatrix[3] > 0 ?
"cclock_flip" :
"clock");
1967 }
else if (
fabs(theta - 180) < 1.0) {
1968 if (displaymatrix[0] < 0)
1970 if (displaymatrix[4] < 0)
1972 }
else if (
fabs(theta - 270) < 1.0) {
1973 INSERT_FILT(
"transpose", displaymatrix[3] < 0 ?
"clock_flip" :
"cclock");
1974 }
else if (
fabs(theta) > 1.0) {
1975 char rotate_buf[64];
1976 snprintf(rotate_buf,
sizeof(rotate_buf),
"%f*PI/180", theta);
1979 if (displaymatrix && displaymatrix[4] < 0)
1987 is->in_video_filter = filt_src;
1988 is->out_video_filter = filt_out;
2000 char aresample_swr_opts[512] =
"";
2003 char asrc_args[256];
2015 if (strlen(aresample_swr_opts))
2016 aresample_swr_opts[strlen(aresample_swr_opts)-1] =
'\0';
2017 av_opt_set(
is->agraph,
"aresample_swr_opts", aresample_swr_opts, 0);
2022 "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:channel_layout=%s",
2024 1,
is->audio_filter_src.freq, bp.str);
2028 asrc_args,
NULL,
is->agraph);
2044 if (force_output_format) {
2060 is->in_audio_filter = filt_asrc;
2061 is->out_audio_filter = filt_asink;
2076 int last_serial = -1;
2094 frame->format,
frame->ch_layout.nb_channels) ||
2096 is->audio_filter_src.freq !=
frame->sample_rate ||
2097 is->auddec.pkt_serial != last_serial;
2100 char buf1[1024], buf2[1024];
2104 "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",
2105 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,
2108 is->audio_filter_src.fmt =
frame->format;
2112 is->audio_filter_src.freq =
frame->sample_rate;
2113 last_serial =
is->auddec.pkt_serial;
2130 af->
serial =
is->auddec.pkt_serial;
2136 if (
is->audioq.serial !=
is->auddec.pkt_serial)
2140 is->auddec.finished =
is->auddec.pkt_serial;
2175 int last_serial = -1;
2176 int last_vfilter_idx = 0;
2188 if ( last_w !=
frame->width
2189 || last_h !=
frame->height
2190 || last_format !=
frame->format
2191 || last_serial !=
is->viddec.pkt_serial
2192 || last_vfilter_idx !=
is->vfilter_idx) {
2194 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
2209 event.user.data1 =
is;
2210 SDL_PushEvent(&event);
2213 filt_in =
is->in_video_filter;
2214 filt_out =
is->out_video_filter;
2215 last_w =
frame->width;
2216 last_h =
frame->height;
2217 last_format =
frame->format;
2218 last_serial =
is->viddec.pkt_serial;
2219 last_vfilter_idx =
is->vfilter_idx;
2235 is->viddec.finished =
is->viddec.pkt_serial;
2244 is->frame_last_filter_delay = 0;
2250 if (
is->videoq.serial !=
is->viddec.pkt_serial)
2279 if (got_subtitle && sp->
sub.
format == 0) {
2283 sp->
serial =
is->subdec.pkt_serial;
2284 sp->
width =
is->subdec.avctx->width;
2285 sp->
height =
is->subdec.avctx->height;
2290 }
else if (got_subtitle) {
2307 memcpy(
is->sample_array +
is->sample_array_index,
samples,
len *
sizeof(
short));
2309 is->sample_array_index +=
len;
2311 is->sample_array_index = 0;
2320 int wanted_nb_samples = nb_samples;
2324 double diff, avg_diff;
2325 int min_nb_samples, max_nb_samples;
2330 is->audio_diff_cum =
diff +
is->audio_diff_avg_coef *
is->audio_diff_cum;
2333 is->audio_diff_avg_count++;
2336 avg_diff =
is->audio_diff_cum * (1.0 -
is->audio_diff_avg_coef);
2338 if (
fabs(avg_diff) >=
is->audio_diff_threshold) {
2339 wanted_nb_samples = nb_samples + (int)(
diff *
is->audio_src.freq);
2342 wanted_nb_samples =
av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
2345 diff, avg_diff, wanted_nb_samples - nb_samples,
2346 is->audio_clock,
is->audio_diff_threshold);
2351 is->audio_diff_avg_count = 0;
2352 is->audio_diff_cum = 0;
2356 return wanted_nb_samples;
2368 int data_size, resampled_data_size;
2370 int wanted_nb_samples;
2387 }
while (af->
serial !=
is->audioq.serial);
2402 &
is->audio_tgt.ch_layout,
is->audio_tgt.fmt,
is->audio_tgt.freq,
2407 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2421 uint8_t **
out = &
is->audio_buf1;
2437 if (!
is->audio_buf1)
2444 if (len2 == out_count) {
2449 is->audio_buf =
is->audio_buf1;
2453 resampled_data_size = data_size;
2456 audio_clock0 =
is->audio_clock;
2461 is->audio_clock =
NAN;
2462 is->audio_clock_serial = af->
serial;
2465 static double last_clock;
2466 printf(
"audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
2467 is->audio_clock - last_clock,
2468 is->audio_clock, audio_clock0);
2469 last_clock =
is->audio_clock;
2472 return resampled_data_size;
2479 int audio_size, len1;
2484 if (
is->audio_buf_index >=
is->audio_buf_size) {
2486 if (audio_size < 0) {
2491 if (
is->show_mode != SHOW_MODE_VIDEO)
2493 is->audio_buf_size = audio_size;
2495 is->audio_buf_index = 0;
2497 len1 =
is->audio_buf_size -
is->audio_buf_index;
2500 if (!
is->muted &&
is->audio_buf &&
is->audio_volume == SDL_MIX_MAXVOLUME)
2501 memcpy(stream, (uint8_t *)
is->audio_buf +
is->audio_buf_index, len1);
2503 memset(stream, 0, len1);
2504 if (!
is->muted &&
is->audio_buf)
2505 SDL_MixAudioFormat(stream, (uint8_t *)
is->audio_buf +
is->audio_buf_index, AUDIO_S16SYS, len1,
is->audio_volume);
2509 is->audio_buf_index += len1;
2511 is->audio_write_buf_size =
is->audio_buf_size -
is->audio_buf_index;
2513 if (!
isnan(
is->audio_clock)) {
2521 SDL_AudioSpec wanted_spec, spec;
2523 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2524 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
2525 int next_sample_rate_idx =
FF_ARRAY_ELEMS(next_sample_rates) - 1;
2526 int wanted_nb_channels = wanted_channel_layout->
nb_channels;
2528 env = SDL_getenv(
"SDL_AUDIO_CHANNELS");
2530 wanted_nb_channels = atoi(env);
2538 wanted_nb_channels = wanted_channel_layout->
nb_channels;
2539 wanted_spec.channels = wanted_nb_channels;
2540 wanted_spec.freq = wanted_sample_rate;
2541 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2545 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
2546 next_sample_rate_idx--;
2547 wanted_spec.format = AUDIO_S16SYS;
2548 wanted_spec.silence = 0;
2551 wanted_spec.userdata = opaque;
2552 while (!(
audio_dev = SDL_OpenAudioDevice(
NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
2554 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
2555 wanted_spec.channels = next_nb_channels[
FFMIN(7, wanted_spec.channels)];
2556 if (!wanted_spec.channels) {
2557 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
2558 wanted_spec.channels = wanted_nb_channels;
2559 if (!wanted_spec.freq) {
2561 "No more combinations to try, audio open failed\n");
2567 if (spec.format != AUDIO_S16SYS) {
2569 "SDL advised audio format %d is not supported!\n", spec.format);
2572 if (spec.channels != wanted_spec.channels) {
2577 "SDL advised channel count %d is not supported!\n", spec.channels);
2583 audio_hw_params->
freq = spec.freq;
2632 const char *forced_codec_name =
NULL;
2637 int stream_lowres =
lowres;
2639 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2658 if (forced_codec_name)
2662 "No codec could be found with name '%s'\n", forced_codec_name);
2675 avctx->
lowres = stream_lowres;
2719 sink =
is->out_audio_filter;
2729 is->audio_hw_buf_size =
ret;
2730 is->audio_src =
is->audio_tgt;
2731 is->audio_buf_size = 0;
2732 is->audio_buf_index = 0;
2736 is->audio_diff_avg_count = 0;
2739 is->audio_diff_threshold = (
double)(
is->audio_hw_buf_size) /
is->audio_tgt.bytes_per_sec;
2741 is->audio_stream = stream_index;
2742 is->audio_st = ic->
streams[stream_index];
2747 is->auddec.start_pts =
is->audio_st->start_time;
2748 is->auddec.start_pts_tb =
is->audio_st->time_base;
2755 is->video_stream = stream_index;
2756 is->video_st = ic->
streams[stream_index];
2762 is->queue_attachments_req = 1;
2765 is->subtitle_stream = stream_index;
2766 is->subtitle_st = ic->
streams[stream_index];
2790 return is->abort_request;
2794 return stream_id < 0 ||
2802 if( !strcmp(
s->iformat->name,
"rtp")
2803 || !strcmp(
s->iformat->name,
"rtsp")
2804 || !strcmp(
s->iformat->name,
"sdp")
2808 if(
s->pb && ( !strncmp(
s->url,
"rtp:", 4)
2809 || !strncmp(
s->url,
"udp:", 4)
2825 int pkt_in_play_range = 0;
2827 SDL_mutex *wait_mutex = SDL_CreateMutex();
2828 int scan_all_pmts_set = 0;
2837 memset(st_index, -1,
sizeof(st_index));
2856 scan_all_pmts_set = 1;
2864 if (scan_all_pmts_set)
2883 "Error setting up avformat_find_stream_info() options\n");
2890 for (
i = 0;
i < orig_nb_streams;
i++)
2896 "%s: could not find codec parameters\n",
is->filename);
2946 st_index[
i] = INT_MAX;
2974 if (codecpar->
width)
2987 if (
is->show_mode == SHOW_MODE_NONE)
2988 is->show_mode =
ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
2994 if (
is->video_stream < 0 &&
is->audio_stream < 0) {
3001 if (infinite_buffer < 0 && is->realtime)
3005 if (
is->abort_request)
3007 if (
is->paused !=
is->last_paused) {
3008 is->last_paused =
is->paused;
3014 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
3026 int64_t seek_min =
is->seek_rel > 0 ? seek_target -
is->seek_rel + 2: INT64_MIN;
3027 int64_t seek_max =
is->seek_rel < 0 ? seek_target -
is->seek_rel - 2: INT64_MAX;
3034 "%s: error while seeking\n",
is->ic->url);
3036 if (
is->audio_stream >= 0)
3038 if (
is->subtitle_stream >= 0)
3040 if (
is->video_stream >= 0)
3049 is->queue_attachments_req = 1;
3054 if (
is->queue_attachments_req) {
3061 is->queue_attachments_req = 0;
3071 SDL_LockMutex(wait_mutex);
3072 SDL_CondWaitTimeout(
is->continue_read_thread, wait_mutex, 10);
3073 SDL_UnlockMutex(wait_mutex);
3089 if (
is->video_stream >= 0)
3091 if (
is->audio_stream >= 0)
3093 if (
is->subtitle_stream >= 0)
3103 SDL_LockMutex(wait_mutex);
3104 SDL_CondWaitTimeout(
is->continue_read_thread, wait_mutex, 10);
3105 SDL_UnlockMutex(wait_mutex);
3114 (pkt_ts - (stream_start_time !=
AV_NOPTS_VALUE ? stream_start_time : 0)) *
3140 event.user.data1 =
is;
3141 SDL_PushEvent(&event);
3143 SDL_DestroyMutex(wait_mutex);
3155 is->last_video_stream =
is->video_stream = -1;
3156 is->last_audio_stream =
is->audio_stream = -1;
3157 is->last_subtitle_stream =
is->subtitle_stream = -1;
3178 if (!(
is->continue_read_thread = SDL_CreateCond())) {
3186 is->audio_clock_serial = -1;
3197 if (!
is->read_tid) {
3209 int start_index, stream_index;
3216 start_index =
is->last_video_stream;
3217 old_index =
is->video_stream;
3219 start_index =
is->last_audio_stream;
3220 old_index =
is->audio_stream;
3222 start_index =
is->last_subtitle_stream;
3223 old_index =
is->subtitle_stream;
3225 stream_index = start_index;
3231 for (start_index = 0; start_index <
nb_streams; start_index++)
3236 stream_index = start_index;
3246 is->last_subtitle_stream = -1;
3249 if (start_index == -1)
3253 if (stream_index == start_index)
3255 st =
is->ic->streams[p ? p->
stream_index[stream_index] : stream_index];
3273 if (p && stream_index != -1)
3293 int next =
is->show_mode;
3295 next = (next + 1) % SHOW_MODE_NB;
3296 }
while (next !=
is->show_mode && (next == SHOW_MODE_VIDEO && !
is->video_st || next != SHOW_MODE_VIDEO && !
is->audio_st));
3297 if (
is->show_mode != next) {
3298 is->force_refresh = 1;
3299 is->show_mode = next;
3304 double remaining_time = 0.0;
3306 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
3311 if (remaining_time > 0.0)
3314 if (
is->show_mode != SHOW_MODE_NONE && (!
is->paused ||
is->force_refresh))
3325 if (!
is->ic->nb_chapters)
3329 for (
i = 0;
i <
is->ic->nb_chapters;
i++) {
3339 if (
i >=
is->ic->nb_chapters)
3351 double incr,
pos, frac;
3356 switch (event.type) {
3358 if (
exit_on_keydown || event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q) {
3363 if (!cur_stream->
width)
3365 switch (event.key.keysym.sym) {
3377 case SDLK_KP_MULTIPLY:
3381 case SDLK_KP_DIVIDE:
3465 case SDL_MOUSEBUTTONDOWN:
3470 if (event.button.button == SDL_BUTTON_LEFT) {
3471 static int64_t last_mouse_left_click = 0;
3475 last_mouse_left_click = 0;
3480 case SDL_MOUSEMOTION:
3486 if (event.type == SDL_MOUSEBUTTONDOWN) {
3487 if (event.button.button != SDL_BUTTON_RIGHT)
3491 if (!(event.motion.state & SDL_BUTTON_RMASK))
3501 int tns, thh, tmm, tss;
3504 tmm = (tns % 3600) / 60;
3506 frac = x / cur_stream->
width;
3509 mm = (
ns % 3600) / 60;
3512 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3513 hh, mm,
ss, thh, tmm, tss);
3520 case SDL_WINDOWEVENT:
3521 switch (event.window.event) {
3522 case SDL_WINDOWEVENT_SIZE_CHANGED:
3531 case SDL_WINDOWEVENT_EXPOSED:
3579 if (!strcmp(
arg,
"audio"))
3581 else if (!strcmp(
arg,
"video"))
3583 else if (!strcmp(
arg,
"ext"))
3595 !strcmp(
arg,
"waves") ? SHOW_MODE_WAVES :
3596 !strcmp(
arg,
"rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE;
3612 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3616 if (!strcmp(filename,
"-"))
3627 const char *spec = strchr(opt,
':');
3631 "No media specifier was specified in '%s' in option '%s'\n",
3643 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
3700 "read and decode the streams to fill missing information with heuristics" },
3725 printf(
"\nWhile playing:\n"
3727 "f toggle full screen\n"
3730 "9, 0 decrease and increase volume respectively\n"
3731 "/, * decrease and increase volume respectively\n"
3732 "a cycle audio channel in the current program\n"
3733 "v cycle video channel\n"
3734 "t cycle subtitle channel in the current program\n"
3736 "w cycle video filters or show modes\n"
3737 "s activate frame-step mode\n"
3738 "left/right seek backward/forward 10 seconds or to custom interval if -seek_interval is set\n"
3739 "down/up seek backward/forward 1 minute\n"
3740 "page down/page up seek backward/forward 10 minutes\n"
3741 "right mouse click seek to percentage in file corresponding to fraction of width\n"
3742 "left double-click toggle full screen\n"
3776 "Use -h to get full help or, even better, run 'man %s'\n",
program_name);
3783 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3785 flags &= ~SDL_INIT_AUDIO;
3789 if (!SDL_getenv(
"SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
3790 SDL_setenv(
"SDL_AUDIO_ALSA_SET_BUFFER_SIZE",
"1", 1);
3793 flags &= ~SDL_INIT_VIDEO;
3794 if (SDL_Init (
flags)) {
3800 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3801 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3804 int flags = SDL_WINDOW_HIDDEN;
3806 #if SDL_VERSION_ATLEAST(2,0,5)
3807 flags |= SDL_WINDOW_ALWAYS_ON_TOP;
3809 av_log(
NULL,
AV_LOG_WARNING,
"Your SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
3812 flags |= SDL_WINDOW_BORDERLESS;
3814 flags |= SDL_WINDOW_RESIZABLE;
3816 #ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
3817 SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,
"0");
3826 #if SDL_VERSION_ATLEAST(2, 0, 6)
3827 flags |= SDL_WINDOW_VULKAN;
3835 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
"linear");
3858 renderer = SDL_CreateRenderer(
window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);