27 #include "config_components.h"
58 #include <SDL_thread.h>
66 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
68 #define EXTERNAL_CLOCK_MIN_FRAMES 2
69 #define EXTERNAL_CLOCK_MAX_FRAMES 10
72 #define SDL_AUDIO_MIN_BUFFER_SIZE 512
74 #define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30
77 #define SDL_VOLUME_STEP (0.75)
80 #define AV_SYNC_THRESHOLD_MIN 0.04
82 #define AV_SYNC_THRESHOLD_MAX 0.1
84 #define AV_SYNC_FRAMEDUP_THRESHOLD 0.1
86 #define AV_NOSYNC_THRESHOLD 10.0
89 #define SAMPLE_CORRECTION_PERCENT_MAX 10
92 #define EXTERNAL_CLOCK_SPEED_MIN 0.900
93 #define EXTERNAL_CLOCK_SPEED_MAX 1.010
94 #define EXTERNAL_CLOCK_SPEED_STEP 0.001
97 #define AUDIO_DIFF_AVG_NB 20
100 #define REFRESH_RATE 0.01
104 #define SAMPLE_ARRAY_SIZE (8 * 65536)
106 #define CURSOR_HIDE_DELAY 1000000
108 #define USE_ONEPASS_SUBTITLE_RENDER 1
126 #define VIDEO_PICTURE_QUEUE_SIZE 3
127 #define SUBPICTURE_QUEUE_SIZE 16
128 #define SAMPLE_QUEUE_SIZE 9
129 #define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
358 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
406 if (channel_count1 == 1 && channel_count2 == 1)
409 return channel_count1 != channel_count2 || fmt1 != fmt2;
431 SDL_CondSignal(q->
cond);
447 SDL_LockMutex(q->
mutex);
449 SDL_UnlockMutex(q->
mutex);
470 q->
mutex = SDL_CreateMutex();
475 q->
cond = SDL_CreateCond();
488 SDL_LockMutex(q->
mutex);
495 SDL_UnlockMutex(q->
mutex);
502 SDL_DestroyMutex(q->
mutex);
503 SDL_DestroyCond(q->
cond);
508 SDL_LockMutex(q->
mutex);
512 SDL_CondSignal(q->
cond);
514 SDL_UnlockMutex(q->
mutex);
519 SDL_LockMutex(q->
mutex);
522 SDL_UnlockMutex(q->
mutex);
531 SDL_LockMutex(q->
mutex);
556 SDL_UnlockMutex(q->
mutex);
567 d->empty_queue_cond = empty_queue_cond;
577 if (
d->queue->serial ==
d->pkt_serial) {
579 if (
d->queue->abort_request)
582 switch (
d->avctx->codec_type) {
609 d->finished =
d->pkt_serial;
619 if (
d->queue->nb_packets == 0)
620 SDL_CondSignal(
d->empty_queue_cond);
621 if (
d->packet_pending) {
622 d->packet_pending = 0;
624 int old_serial =
d->pkt_serial;
627 if (old_serial !=
d->pkt_serial) {
630 d->next_pts =
d->start_pts;
631 d->next_pts_tb =
d->start_pts_tb;
634 if (
d->queue->serial ==
d->pkt_serial)
645 if (got_frame && !
d->pkt->data) {
646 d->packet_pending = 1;
652 if (
d->pkt->buf && !
d->pkt->opaque_ref) {
656 if (!
d->pkt->opaque_ref)
663 av_log(
d->avctx,
AV_LOG_ERROR,
"Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
664 d->packet_pending = 1;
687 if (!(
f->mutex = SDL_CreateMutex())) {
691 if (!(
f->cond = SDL_CreateCond())) {
697 f->keep_last = !!keep_last;
698 for (
i = 0;
i <
f->max_size;
i++)
707 for (
i = 0;
i <
f->max_size;
i++) {
712 SDL_DestroyMutex(
f->mutex);
713 SDL_DestroyCond(
f->cond);
718 SDL_LockMutex(
f->mutex);
719 SDL_CondSignal(
f->cond);
720 SDL_UnlockMutex(
f->mutex);
725 return &
f->queue[(
f->rindex +
f->rindex_shown) %
f->max_size];
730 return &
f->queue[(
f->rindex +
f->rindex_shown + 1) %
f->max_size];
735 return &
f->queue[
f->rindex];
741 SDL_LockMutex(
f->mutex);
742 while (
f->size >=
f->max_size &&
743 !
f->pktq->abort_request) {
744 SDL_CondWait(
f->cond,
f->mutex);
746 SDL_UnlockMutex(
f->mutex);
748 if (
f->pktq->abort_request)
751 return &
f->queue[
f->windex];
757 SDL_LockMutex(
f->mutex);
758 while (
f->size -
f->rindex_shown <= 0 &&
759 !
f->pktq->abort_request) {
760 SDL_CondWait(
f->cond,
f->mutex);
762 SDL_UnlockMutex(
f->mutex);
764 if (
f->pktq->abort_request)
767 return &
f->queue[(
f->rindex +
f->rindex_shown) %
f->max_size];
772 if (++
f->windex ==
f->max_size)
774 SDL_LockMutex(
f->mutex);
776 SDL_CondSignal(
f->cond);
777 SDL_UnlockMutex(
f->mutex);
782 if (
f->keep_last && !
f->rindex_shown) {
787 if (++
f->rindex ==
f->max_size)
789 SDL_LockMutex(
f->mutex);
791 SDL_CondSignal(
f->cond);
792 SDL_UnlockMutex(
f->mutex);
798 return f->size -
f->rindex_shown;
805 if (
f->rindex_shown &&
fp->serial ==
f->pktq->serial)
815 SDL_WaitThread(
d->decoder_tid,
NULL);
816 d->decoder_tid =
NULL;
831 static int realloc_texture(SDL_Texture **texture, Uint32 new_format,
int new_width,
int new_height, SDL_BlendMode blendmode,
int init_texture)
835 if (!*texture || SDL_QueryTexture(*texture, &
format, &access, &
w, &
h) < 0 || new_width !=
w || new_height !=
h || new_format !=
format) {
839 SDL_DestroyTexture(*texture);
840 if (!(*texture = SDL_CreateTexture(
renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
842 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
845 if (SDL_LockTexture(*texture,
NULL, &pixels, &pitch) < 0)
847 memset(pixels, 0, pitch * new_height);
848 SDL_UnlockTexture(*texture);
850 av_log(
NULL,
AV_LOG_VERBOSE,
"Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
856 int scr_xleft,
int scr_ytop,
int scr_width,
int scr_height,
857 int pic_width,
int pic_height,
AVRational pic_sar)
870 if (
width > scr_width) {
874 x = (scr_width -
width) / 2;
875 y = (scr_height -
height) / 2;
876 rect->
x = scr_xleft + x;
877 rect->
y = scr_ytop + y;
885 *sdl_blendmode = SDL_BLENDMODE_NONE;
886 *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN;
891 *sdl_blendmode = SDL_BLENDMODE_BLEND;
904 SDL_BlendMode sdl_blendmode;
906 if (
realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt,
frame->width,
frame->height, sdl_blendmode, 0) < 0)
908 switch (sdl_pix_fmt) {
909 case SDL_PIXELFORMAT_IYUV:
910 if (
frame->linesize[0] > 0 &&
frame->linesize[1] > 0 &&
frame->linesize[2] > 0) {
914 }
else if (
frame->linesize[0] < 0 &&
frame->linesize[1] < 0 &&
frame->linesize[2] < 0) {
924 if (
frame->linesize[0] < 0) {
936 #if SDL_VERSION_ATLEAST(2,0,8)
937 SDL_YUV_CONVERSION_MODE
mode = SDL_YUV_CONVERSION_AUTOMATIC;
940 mode = SDL_YUV_CONVERSION_JPEG;
942 mode = SDL_YUV_CONVERSION_BT709;
944 mode = SDL_YUV_CONVERSION_BT601;
946 SDL_SetYUVConversionMode(
mode);
957 if (
is->subtitle_st) {
961 if (vp->
pts >=
sp->pts + ((
float)
sp->sub.start_display_time / 1000)) {
966 if (!
sp->width || !
sp->height) {
970 if (
realloc_texture(&
is->sub_texture, SDL_PIXELFORMAT_ARGB8888,
sp->width,
sp->height, SDL_BLENDMODE_BLEND, 1) < 0)
973 for (
i = 0;
i <
sp->sub.num_rects;
i++) {
978 sub_rect->
w =
av_clip(sub_rect->
w, 0,
sp->width - sub_rect->
x);
979 sub_rect->
h =
av_clip(sub_rect->
h, 0,
sp->height - sub_rect->
y);
985 if (!
is->sub_convert_ctx) {
989 if (!SDL_LockTexture(
is->sub_texture, (SDL_Rect *)sub_rect, (
void **)pixels, pitch)) {
990 sws_scale(
is->sub_convert_ctx, (
const uint8_t *
const *)sub_rect->data, sub_rect->linesize,
991 0, sub_rect->h, pixels, pitch);
992 SDL_UnlockTexture(
is->sub_texture);
1017 #if USE_ONEPASS_SUBTITLE_RENDER
1023 for (
i = 0;
i <
sp->sub.num_rects;
i++) {
1024 SDL_Rect *sub_rect = (SDL_Rect*)
sp->sub.rects[
i];
1025 SDL_Rect target = {.x =
rect.
x + sub_rect->x * xratio,
1026 .y =
rect.
y + sub_rect->y * yratio,
1027 .w = sub_rect->w * xratio,
1028 .h = sub_rect->h * yratio};
1029 SDL_RenderCopy(
renderer,
is->sub_texture, sub_rect, &target);
1037 return a < 0 ?
a%
b +
b :
a%
b;
1042 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1045 int rdft_bits, nb_freq;
1047 for (rdft_bits = 1; (1 << rdft_bits) < 2 *
s->height; rdft_bits++)
1049 nb_freq = 1 << (rdft_bits - 1);
1052 channels =
s->audio_tgt.ch_layout.nb_channels;
1055 int data_used=
s->show_mode == SHOW_MODE_WAVES ?
s->width : (2*nb_freq);
1057 delay =
s->audio_write_buf_size;
1064 delay -= (time_diff *
s->audio_tgt.freq) / 1000000;
1067 delay += 2 * data_used;
1068 if (delay < data_used)
1072 if (
s->show_mode == SHOW_MODE_WAVES) {
1076 int a =
s->sample_array[idx];
1081 if (
h < score && (
b ^
c) < 0) {
1088 s->last_i_start = i_start;
1090 i_start =
s->last_i_start;
1093 if (
s->show_mode == SHOW_MODE_WAVES) {
1094 SDL_SetRenderDrawColor(
renderer, 255, 255, 255, 255);
1097 h =
s->height / nb_display_channels;
1100 for (ch = 0; ch < nb_display_channels; ch++) {
1102 y1 =
s->ytop + ch *
h + (
h / 2);
1103 for (x = 0; x <
s->width; x++) {
1104 y = (
s->sample_array[
i] * h2) >> 15;
1118 SDL_SetRenderDrawColor(
renderer, 0, 0, 255, 255);
1120 for (ch = 1; ch < nb_display_channels; ch++) {
1121 y =
s->ytop + ch *
h;
1126 if (
realloc_texture(&
s->vis_texture, SDL_PIXELFORMAT_ARGB8888,
s->width,
s->height, SDL_BLENDMODE_NONE, 1) < 0)
1129 if (
s->xpos >=
s->width)
1131 nb_display_channels=
FFMIN(nb_display_channels, 2);
1132 if (rdft_bits !=
s->rdft_bits) {
1133 const float rdft_scale = 1.0;
1137 s->rdft_bits = rdft_bits;
1141 0, 1 << rdft_bits, &rdft_scale, 0);
1143 if (err < 0 || !s->rdft_data) {
1145 s->show_mode = SHOW_MODE_WAVES;
1149 SDL_Rect
rect = {.
x =
s->xpos, .y = 0, .w = 1, .h =
s->height};
1152 for (ch = 0; ch < nb_display_channels; ch++) {
1153 data_in[ch] =
s->real_data + 2 * nb_freq * ch;
1154 data[ch] =
s->rdft_data + nb_freq * ch;
1156 for (x = 0; x < 2 * nb_freq; x++) {
1157 double w = (x-nb_freq) * (1.0 / nb_freq);
1158 data_in[ch][x] =
s->sample_array[
i] * (1.0 -
w *
w);
1163 s->rdft_fn(
s->rdft,
data[ch], data_in[ch],
sizeof(
float));
1164 data[ch][0].im =
data[ch][nb_freq].re;
1165 data[ch][nb_freq].re = 0;
1169 if (!SDL_LockTexture(
s->vis_texture, &
rect, (
void **)&pixels, &pitch)) {
1171 pixels += pitch *
s->height;
1172 for (y = 0; y <
s->height; y++) {
1173 double w = 1 / sqrt(nb_freq);
1174 int a = sqrt(
w * sqrt(
data[0][y].re *
data[0][y].re +
data[0][y].im *
data[0][y].im));
1175 int b = (nb_display_channels == 2 ) ? sqrt(
w *
hypot(
data[1][y].re,
data[1][y].im))
1180 *pixels = (
a << 16) + (
b << 8) + ((
a+
b) >> 1);
1182 SDL_UnlockTexture(
s->vis_texture);
1196 if (stream_index < 0 || stream_index >= ic->
nb_streams)
1207 is->audio_buf1_size = 0;
1234 is->audio_stream = -1;
1238 is->video_stream = -1;
1242 is->subtitle_stream = -1;
1252 is->abort_request = 1;
1253 SDL_WaitThread(
is->read_tid,
NULL);
1256 if (
is->audio_stream >= 0)
1258 if (
is->video_stream >= 0)
1260 if (
is->subtitle_stream >= 0)
1273 SDL_DestroyCond(
is->continue_read_thread);
1276 if (
is->vis_texture)
1277 SDL_DestroyTexture(
is->vis_texture);
1278 if (
is->vid_texture)
1279 SDL_DestroyTexture(
is->vid_texture);
1280 if (
is->sub_texture)
1281 SDL_DestroyTexture(
is->sub_texture);
1293 SDL_DestroyWindow(
window);
1314 if (max_width == INT_MAX && max_height == INT_MAX)
1335 SDL_SetWindowFullscreen(
window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1350 SDL_SetRenderDrawColor(
renderer, 0, 0, 0, 255);
1352 if (
is->audio_st &&
is->show_mode != SHOW_MODE_VIDEO)
1354 else if (
is->video_st)
1361 if (*
c->queue_serial !=
c->serial)
1367 return c->pts_drift + time - (time -
c->last_updated) * (1.0 -
c->speed);
1374 c->last_updated = time;
1375 c->pts_drift =
c->pts - time;
1395 c->queue_serial = queue_serial;
1450 double speed =
is->extclk.speed;
1459 if (!
is->seek_req) {
1466 SDL_CondSignal(
is->continue_read_thread);
1475 if (
is->read_pause_return !=
AVERROR(ENOSYS)) {
1476 is->vidclk.paused = 0;
1481 is->paused =
is->audclk.paused =
is->vidclk.paused =
is->extclk.paused = !
is->paused;
1492 is->muted = !
is->muted;
1497 double volume_level =
is->audio_volume ? (20 *
log(
is->audio_volume / (
double)SDL_MIX_MAXVOLUME) /
log(10)) : -1000.0;
1498 int new_volume =
lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign *
step) / 20.0));
1499 is->audio_volume =
av_clip(
is->audio_volume == new_volume ? (
is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
1512 double sync_threshold,
diff = 0;
1525 if (
diff <= -sync_threshold)
1528 delay = delay +
diff;
1529 else if (
diff >= sync_threshold)
1543 if (
isnan(
duration) || duration <= 0 || duration >
is->max_frame_duration)
1572 if (
is->force_refresh ||
is->last_vis_time +
rdftspeed < time) {
1574 is->last_vis_time = time;
1576 *remaining_time =
FFMIN(*remaining_time,
is->last_vis_time +
rdftspeed - time);
1584 double last_duration,
duration, delay;
1591 if (vp->
serial !=
is->videoq.serial) {
1607 if (time < is->frame_timer + delay) {
1608 *remaining_time =
FFMIN(
is->frame_timer + delay - time, *remaining_time);
1612 is->frame_timer += delay;
1614 is->frame_timer = time;
1616 SDL_LockMutex(
is->pictq.mutex);
1619 SDL_UnlockMutex(
is->pictq.mutex);
1625 is->frame_drops_late++;
1631 if (
is->subtitle_st) {
1640 if (
sp->serial !=
is->subtitleq.serial
1641 || (
is->vidclk.pts > (
sp->pts + ((
float)
sp->sub.end_display_time / 1000)))
1646 for (
i = 0;
i <
sp->sub.num_rects;
i++) {
1651 if (!SDL_LockTexture(
is->sub_texture, (SDL_Rect *)sub_rect, (
void **)&pixels, &pitch)) {
1652 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
1653 memset(pixels, 0, sub_rect->w << 2);
1654 SDL_UnlockTexture(
is->sub_texture);
1666 is->force_refresh = 1;
1668 if (
is->step && !
is->paused)
1673 if (!
display_disable &&
is->force_refresh &&
is->show_mode == SHOW_MODE_VIDEO &&
is->pictq.rindex_shown)
1676 is->force_refresh = 0;
1679 static int64_t last_time;
1681 int aqsize, vqsize, sqsize;
1685 if (!last_time || (cur_time - last_time) >= 30000) {
1690 aqsize =
is->audioq.size;
1692 vqsize =
is->videoq.size;
1693 if (
is->subtitle_st)
1694 sqsize =
is->subtitleq.size;
1696 if (
is->audio_st &&
is->video_st)
1698 else if (
is->video_st)
1700 else if (
is->audio_st)
1705 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64
"/%"PRId64
" \r",
1707 (
is->audio_st &&
is->video_st) ?
"A-V" : (
is->video_st ?
"M-V" : (
is->audio_st ?
"M-A" :
" ")),
1709 is->frame_drops_early +
is->frame_drops_late,
1713 is->video_st ?
is->viddec.avctx->pts_correction_num_faulty_dts : 0,
1714 is->video_st ?
is->viddec.avctx->pts_correction_num_faulty_pts : 0);
1717 fprintf(stderr,
"%s", buf.str);
1724 last_time = cur_time;
1733 #if defined(DEBUG_SYNC)
1734 printf(
"frame_type=%c pts=%0.3f\n",
1779 diff -
is->frame_last_filter_delay < 0 &&
1780 is->viddec.pkt_serial ==
is->vidclk.serial &&
1781 is->videoq.nb_packets) {
1782 is->frame_drops_early++;
1809 outputs->filter_ctx = source_ctx;
1814 inputs->filter_ctx = sink_ctx;
1839 char sws_flags_str[512] =
"";
1840 char buffersrc_args[256];
1846 int nb_pix_fmts = 0;
1860 if (!strcmp(e->
key,
"sws_flags")) {
1861 av_strlcatf(sws_flags_str,
sizeof(sws_flags_str),
"%s=%s:",
"flags", e->
value);
1865 if (strlen(sws_flags_str))
1866 sws_flags_str[strlen(sws_flags_str)-1] =
'\0';
1870 snprintf(buffersrc_args,
sizeof(buffersrc_args),
1871 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
1873 is->video_st->time_base.num,
is->video_st->time_base.den,
1876 av_strlcatf(buffersrc_args,
sizeof(buffersrc_args),
":frame_rate=%d/%d", fr.
num, fr.
den);
1880 "ffplay_buffer", buffersrc_args,
NULL,
1886 "ffplay_buffersink",
NULL,
NULL, graph);
1893 last_filter = filt_out;
1897 #define INSERT_FILT(name, arg) do { \
1898 AVFilterContext *filt_ctx; \
1900 ret = avfilter_graph_create_filter(&filt_ctx, \
1901 avfilter_get_by_name(name), \
1902 "ffplay_" name, arg, NULL, graph); \
1906 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
1910 last_filter = filt_ctx; \
1923 if (
fabs(theta - 90) < 1.0) {
1925 }
else if (
fabs(theta - 180) < 1.0) {
1928 }
else if (
fabs(theta - 270) < 1.0) {
1930 }
else if (
fabs(theta) > 1.0) {
1931 char rotate_buf[64];
1932 snprintf(rotate_buf,
sizeof(rotate_buf),
"%f*PI/180", theta);
1940 is->in_video_filter = filt_src;
1941 is->out_video_filter = filt_out;
1952 char aresample_swr_opts[512] =
"";
1955 char asrc_args[256];
1967 if (strlen(aresample_swr_opts))
1968 aresample_swr_opts[strlen(aresample_swr_opts)-1] =
'\0';
1969 av_opt_set(
is->agraph,
"aresample_swr_opts", aresample_swr_opts, 0);
1974 "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:channel_layout=%s",
1976 1,
is->audio_filter_src.freq, bp.str);
1980 asrc_args,
NULL,
is->agraph);
1996 if (force_output_format) {
2010 is->in_audio_filter = filt_asrc;
2011 is->out_audio_filter = filt_asink;
2026 int last_serial = -1;
2044 frame->format,
frame->ch_layout.nb_channels) ||
2046 is->audio_filter_src.freq !=
frame->sample_rate ||
2047 is->auddec.pkt_serial != last_serial;
2050 char buf1[1024], buf2[1024];
2054 "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",
2055 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,
2058 is->audio_filter_src.fmt =
frame->format;
2062 is->audio_filter_src.freq =
frame->sample_rate;
2063 last_serial =
is->auddec.pkt_serial;
2080 af->
serial =
is->auddec.pkt_serial;
2086 if (
is->audioq.serial !=
is->auddec.pkt_serial)
2090 is->auddec.finished =
is->auddec.pkt_serial;
2102 d->decoder_tid = SDL_CreateThread(
fn, thread_name,
arg);
2103 if (!
d->decoder_tid) {
2125 int last_serial = -1;
2126 int last_vfilter_idx = 0;
2138 if ( last_w !=
frame->width
2139 || last_h !=
frame->height
2140 || last_format !=
frame->format
2141 || last_serial !=
is->viddec.pkt_serial
2142 || last_vfilter_idx !=
is->vfilter_idx) {
2144 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
2159 event.user.data1 =
is;
2160 SDL_PushEvent(&event);
2163 filt_in =
is->in_video_filter;
2164 filt_out =
is->out_video_filter;
2165 last_w =
frame->width;
2166 last_h =
frame->height;
2167 last_format =
frame->format;
2168 last_serial =
is->viddec.pkt_serial;
2169 last_vfilter_idx =
is->vfilter_idx;
2185 is->viddec.finished =
is->viddec.pkt_serial;
2194 is->frame_last_filter_delay = 0;
2200 if (
is->videoq.serial !=
is->viddec.pkt_serial)
2229 if (got_subtitle &&
sp->sub.format == 0) {
2233 sp->serial =
is->subdec.pkt_serial;
2234 sp->width =
is->subdec.avctx->width;
2235 sp->height =
is->subdec.avctx->height;
2240 }
else if (got_subtitle) {
2257 memcpy(
is->sample_array +
is->sample_array_index,
samples,
len *
sizeof(
short));
2259 is->sample_array_index +=
len;
2261 is->sample_array_index = 0;
2270 int wanted_nb_samples = nb_samples;
2274 double diff, avg_diff;
2275 int min_nb_samples, max_nb_samples;
2280 is->audio_diff_cum =
diff +
is->audio_diff_avg_coef *
is->audio_diff_cum;
2283 is->audio_diff_avg_count++;
2286 avg_diff =
is->audio_diff_cum * (1.0 -
is->audio_diff_avg_coef);
2288 if (
fabs(avg_diff) >=
is->audio_diff_threshold) {
2289 wanted_nb_samples = nb_samples + (
int)(
diff *
is->audio_src.freq);
2292 wanted_nb_samples =
av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
2295 diff, avg_diff, wanted_nb_samples - nb_samples,
2296 is->audio_clock,
is->audio_diff_threshold);
2301 is->audio_diff_avg_count = 0;
2302 is->audio_diff_cum = 0;
2306 return wanted_nb_samples;
2318 int data_size, resampled_data_size;
2320 int wanted_nb_samples;
2337 }
while (af->
serial !=
is->audioq.serial);
2351 &
is->audio_tgt.ch_layout,
is->audio_tgt.fmt,
is->audio_tgt.freq,
2356 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2370 uint8_t **
out = &
is->audio_buf1;
2371 int out_count = (int64_t)wanted_nb_samples *
is->audio_tgt.freq / af->
frame->
sample_rate + 256;
2386 if (!
is->audio_buf1)
2393 if (len2 == out_count) {
2398 is->audio_buf =
is->audio_buf1;
2402 resampled_data_size = data_size;
2405 audio_clock0 =
is->audio_clock;
2410 is->audio_clock =
NAN;
2411 is->audio_clock_serial = af->
serial;
2414 static double last_clock;
2415 printf(
"audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
2416 is->audio_clock - last_clock,
2417 is->audio_clock, audio_clock0);
2418 last_clock =
is->audio_clock;
2421 return resampled_data_size;
2428 int audio_size, len1;
2433 if (
is->audio_buf_index >=
is->audio_buf_size) {
2435 if (audio_size < 0) {
2440 if (
is->show_mode != SHOW_MODE_VIDEO)
2442 is->audio_buf_size = audio_size;
2444 is->audio_buf_index = 0;
2446 len1 =
is->audio_buf_size -
is->audio_buf_index;
2449 if (!
is->muted &&
is->audio_buf &&
is->audio_volume == SDL_MIX_MAXVOLUME)
2450 memcpy(stream, (uint8_t *)
is->audio_buf +
is->audio_buf_index, len1);
2452 memset(stream, 0, len1);
2453 if (!
is->muted &&
is->audio_buf)
2454 SDL_MixAudioFormat(stream, (uint8_t *)
is->audio_buf +
is->audio_buf_index, AUDIO_S16SYS, len1,
is->audio_volume);
2458 is->audio_buf_index += len1;
2460 is->audio_write_buf_size =
is->audio_buf_size -
is->audio_buf_index;
2462 if (!
isnan(
is->audio_clock)) {
2470 SDL_AudioSpec wanted_spec, spec;
2472 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2473 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
2474 int next_sample_rate_idx =
FF_ARRAY_ELEMS(next_sample_rates) - 1;
2475 int wanted_nb_channels = wanted_channel_layout->
nb_channels;
2477 env = SDL_getenv(
"SDL_AUDIO_CHANNELS");
2479 wanted_nb_channels = atoi(env);
2487 wanted_nb_channels = wanted_channel_layout->
nb_channels;
2488 wanted_spec.channels = wanted_nb_channels;
2489 wanted_spec.freq = wanted_sample_rate;
2490 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2494 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
2495 next_sample_rate_idx--;
2496 wanted_spec.format = AUDIO_S16SYS;
2497 wanted_spec.silence = 0;
2500 wanted_spec.userdata = opaque;
2501 while (!(
audio_dev = SDL_OpenAudioDevice(
NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
2503 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
2504 wanted_spec.channels = next_nb_channels[
FFMIN(7, wanted_spec.channels)];
2505 if (!wanted_spec.channels) {
2506 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
2507 wanted_spec.channels = wanted_nb_channels;
2508 if (!wanted_spec.freq) {
2510 "No more combinations to try, audio open failed\n");
2516 if (spec.format != AUDIO_S16SYS) {
2518 "SDL advised audio format %d is not supported!\n", spec.format);
2521 if (spec.channels != wanted_spec.channels) {
2526 "SDL advised channel count %d is not supported!\n", spec.channels);
2532 audio_hw_params->
freq = spec.freq;
2550 const char *forced_codec_name =
NULL;
2556 int stream_lowres =
lowres;
2558 if (stream_index < 0 || stream_index >= ic->
nb_streams)
2577 if (forced_codec_name)
2581 "No codec could be found with name '%s'\n", forced_codec_name);
2594 avctx->
lowres = stream_lowres;
2634 sink =
is->out_audio_filter;
2644 is->audio_hw_buf_size =
ret;
2645 is->audio_src =
is->audio_tgt;
2646 is->audio_buf_size = 0;
2647 is->audio_buf_index = 0;
2651 is->audio_diff_avg_count = 0;
2654 is->audio_diff_threshold = (
double)(
is->audio_hw_buf_size) /
is->audio_tgt.bytes_per_sec;
2656 is->audio_stream = stream_index;
2657 is->audio_st = ic->
streams[stream_index];
2662 is->auddec.start_pts =
is->audio_st->start_time;
2663 is->auddec.start_pts_tb =
is->audio_st->time_base;
2670 is->video_stream = stream_index;
2671 is->video_st = ic->
streams[stream_index];
2677 is->queue_attachments_req = 1;
2680 is->subtitle_stream = stream_index;
2681 is->subtitle_st = ic->
streams[stream_index];
2705 return is->abort_request;
2709 return stream_id < 0 ||
2717 if( !strcmp(
s->iformat->name,
"rtp")
2718 || !strcmp(
s->iformat->name,
"rtsp")
2719 || !strcmp(
s->iformat->name,
"sdp")
2723 if(
s->pb && ( !strncmp(
s->url,
"rtp:", 4)
2724 || !strncmp(
s->url,
"udp:", 4)
2739 int64_t stream_start_time;
2740 int pkt_in_play_range = 0;
2742 SDL_mutex *wait_mutex = SDL_CreateMutex();
2743 int scan_all_pmts_set = 0;
2752 memset(st_index, -1,
sizeof(st_index));
2771 scan_all_pmts_set = 1;
2779 if (scan_all_pmts_set)
2801 "Error setting up avformat_find_stream_info() options\n");
2808 for (
i = 0;
i < orig_nb_streams;
i++)
2814 "%s: could not find codec parameters\n",
is->filename);
2864 st_index[
i] = INT_MAX;
2892 if (codecpar->
width)
2905 if (
is->show_mode == SHOW_MODE_NONE)
2906 is->show_mode =
ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
2912 if (
is->video_stream < 0 &&
is->audio_stream < 0) {
2919 if (infinite_buffer < 0 && is->realtime)
2923 if (
is->abort_request)
2925 if (
is->paused !=
is->last_paused) {
2926 is->last_paused =
is->paused;
2932 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
2943 int64_t seek_target =
is->seek_pos;
2944 int64_t seek_min =
is->seek_rel > 0 ? seek_target -
is->seek_rel + 2: INT64_MIN;
2945 int64_t seek_max =
is->seek_rel < 0 ? seek_target -
is->seek_rel - 2: INT64_MAX;
2952 "%s: error while seeking\n",
is->ic->url);
2954 if (
is->audio_stream >= 0)
2956 if (
is->subtitle_stream >= 0)
2958 if (
is->video_stream >= 0)
2967 is->queue_attachments_req = 1;
2972 if (
is->queue_attachments_req) {
2979 is->queue_attachments_req = 0;
2989 SDL_LockMutex(wait_mutex);
2990 SDL_CondWaitTimeout(
is->continue_read_thread, wait_mutex, 10);
2991 SDL_UnlockMutex(wait_mutex);
3007 if (
is->video_stream >= 0)
3009 if (
is->audio_stream >= 0)
3011 if (
is->subtitle_stream >= 0)
3021 SDL_LockMutex(wait_mutex);
3022 SDL_CondWaitTimeout(
is->continue_read_thread, wait_mutex, 10);
3023 SDL_UnlockMutex(wait_mutex);
3032 (pkt_ts - (stream_start_time !=
AV_NOPTS_VALUE ? stream_start_time : 0)) *
3058 event.user.data1 =
is;
3059 SDL_PushEvent(&event);
3061 SDL_DestroyMutex(wait_mutex);
3073 is->last_video_stream =
is->video_stream = -1;
3074 is->last_audio_stream =
is->audio_stream = -1;
3075 is->last_subtitle_stream =
is->subtitle_stream = -1;
3096 if (!(
is->continue_read_thread = SDL_CreateCond())) {
3104 is->audio_clock_serial = -1;
3115 if (!
is->read_tid) {
3127 int start_index, stream_index;
3134 start_index =
is->last_video_stream;
3135 old_index =
is->video_stream;
3137 start_index =
is->last_audio_stream;
3138 old_index =
is->audio_stream;
3140 start_index =
is->last_subtitle_stream;
3141 old_index =
is->subtitle_stream;
3143 stream_index = start_index;
3149 for (start_index = 0; start_index <
nb_streams; start_index++)
3154 stream_index = start_index;
3164 is->last_subtitle_stream = -1;
3167 if (start_index == -1)
3171 if (stream_index == start_index)
3173 st =
is->ic->streams[p ? p->
stream_index[stream_index] : stream_index];
3191 if (p && stream_index != -1)
3211 int next =
is->show_mode;
3213 next = (next + 1) % SHOW_MODE_NB;
3214 }
while (next !=
is->show_mode && (next == SHOW_MODE_VIDEO && !
is->video_st || next != SHOW_MODE_VIDEO && !
is->audio_st));
3215 if (
is->show_mode != next) {
3216 is->force_refresh = 1;
3217 is->show_mode = next;
3222 double remaining_time = 0.0;
3224 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
3229 if (remaining_time > 0.0)
3230 av_usleep((int64_t)(remaining_time * 1000000.0));
3232 if (
is->show_mode != SHOW_MODE_NONE && (!
is->paused ||
is->force_refresh))
3243 if (!
is->ic->nb_chapters)
3247 for (
i = 0;
i <
is->ic->nb_chapters;
i++) {
3257 if (
i >=
is->ic->nb_chapters)
3269 double incr,
pos, frac;
3274 switch (event.type) {
3276 if (
exit_on_keydown || event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q) {
3281 if (!cur_stream->
width)
3283 switch (event.key.keysym.sym) {
3295 case SDLK_KP_MULTIPLY:
3299 case SDLK_KP_DIVIDE:
3383 case SDL_MOUSEBUTTONDOWN:
3388 if (event.button.button == SDL_BUTTON_LEFT) {
3389 static int64_t last_mouse_left_click = 0;
3393 last_mouse_left_click = 0;
3398 case SDL_MOUSEMOTION:
3404 if (event.type == SDL_MOUSEBUTTONDOWN) {
3405 if (event.button.button != SDL_BUTTON_RIGHT)
3409 if (!(event.motion.state & SDL_BUTTON_RMASK))
3419 int tns, thh, tmm, tss;
3422 tmm = (tns % 3600) / 60;
3424 frac = x / cur_stream->
width;
3427 mm = (
ns % 3600) / 60;
3430 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3431 hh, mm,
ss, thh, tmm, tss);
3438 case SDL_WINDOWEVENT:
3439 switch (event.window.event) {
3440 case SDL_WINDOWEVENT_SIZE_CHANGED:
3447 case SDL_WINDOWEVENT_EXPOSED:
3495 if (!strcmp(
arg,
"audio"))
3497 else if (!strcmp(
arg,
"video"))
3499 else if (!strcmp(
arg,
"ext"))
3511 !strcmp(
arg,
"waves") ? SHOW_MODE_WAVES :
3512 !strcmp(
arg,
"rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE;
3528 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3532 if (!strcmp(filename,
"-"))
3541 const char *spec = strchr(opt,
':');
3544 "No media specifier was specified in '%s' in option '%s'\n",
3555 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
3565 {
"x",
HAS_ARG, { .func_arg =
opt_width },
"force displayed width",
"width" },
3566 {
"y",
HAS_ARG, { .func_arg =
opt_height },
"force displayed height",
"height" },
3588 {
"sync",
HAS_ARG |
OPT_EXPERT, { .func_arg =
opt_sync },
"set audio-video sync. type (type=audio/video/ext)",
"type" },
3601 {
"showmode",
HAS_ARG, { .func_arg =
opt_show_mode},
"select show mode (0 = video, 1 = waves, 2 = RDFT)",
"mode" },
3602 {
"i",
OPT_BOOL, { &
dummy},
"read specified file",
"input_file"},
3603 {
"codec",
HAS_ARG, { .func_arg =
opt_codec},
"force decoder",
"decoder_name" },
3609 "read and decode the streams to fill missing information with heuristics" },
3631 printf(
"\nWhile playing:\n"
3633 "f toggle full screen\n"
3636 "9, 0 decrease and increase volume respectively\n"
3637 "/, * decrease and increase volume respectively\n"
3638 "a cycle audio channel in the current program\n"
3639 "v cycle video channel\n"
3640 "t cycle subtitle channel in the current program\n"
3642 "w cycle video filters or show modes\n"
3643 "s activate frame-step mode\n"
3644 "left/right seek backward/forward 10 seconds or to custom interval if -seek_interval is set\n"
3645 "down/up seek backward/forward 1 minute\n"
3646 "page down/page up seek backward/forward 10 minutes\n"
3647 "right mouse click seek to percentage in file corresponding to fraction of width\n"
3648 "left double-click toggle full screen\n"
3682 "Use -h to get full help or, even better, run 'man %s'\n",
program_name);
3689 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3691 flags &= ~SDL_INIT_AUDIO;
3695 if (!SDL_getenv(
"SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
3696 SDL_setenv(
"SDL_AUDIO_ALSA_SET_BUFFER_SIZE",
"1", 1);
3699 flags &= ~SDL_INIT_VIDEO;
3700 if (SDL_Init (
flags)) {
3706 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3707 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3710 int flags = SDL_WINDOW_HIDDEN;
3712 #if SDL_VERSION_ATLEAST(2,0,5)
3713 flags |= SDL_WINDOW_ALWAYS_ON_TOP;
3715 av_log(
NULL,
AV_LOG_WARNING,
"Your SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
3718 flags |= SDL_WINDOW_BORDERLESS;
3720 flags |= SDL_WINDOW_RESIZABLE;
3722 #ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
3723 SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,
"0");
3726 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
"linear");
3728 renderer = SDL_CreateRenderer(
window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);