Migrates the FFplay media player to the new SDL version using the
official tutorial at https://wiki.libsdl.org/SDL3/README-migration.

Signed-off-by: Marcin Serwin <[email protected]>
---
This is just first iteration but I wanted to make sure if you're interested in
doing the migration and gather some early feedback. With this path I am able to
play some basic video and audio files on my Linux system but I haven't tested it
with other platforms.

 configure                 |  26 +---
 fftools/ffplay.c          | 283 ++++++++++++++++++--------------------
 fftools/ffplay_renderer.c |  12 +-
 fftools/ffplay_renderer.h |   2 +-
 4 files changed, 150 insertions(+), 173 deletions(-)

diff --git a/configure b/configure
index 301a3e5e3e..e3927fe4ab 100755
--- a/configure
+++ b/configure
@@ -338,7 +338,7 @@ External library support:
   --disable-sndio          disable sndio support [autodetect]
   --disable-schannel       disable SChannel SSP, needed for TLS support on
                            Windows if openssl and gnutls are not used 
[autodetect]
-  --disable-sdl2           disable sdl2 [autodetect]
+  --disable-sdl3           disable sdl3 [autodetect]
   --disable-securetransport disable Secure Transport, needed for TLS support
                            on OSX if openssl and gnutls are not used 
[autodetect]
   --enable-vapoursynth     enable VapourSynth demuxer [no]
@@ -1904,7 +1904,7 @@ EXTERNAL_AUTODETECT_LIBRARY_LIST="
     mediafoundation
     metal
     schannel
-    sdl2
+    sdl3
     securetransport
     sndio
     xlib
@@ -4217,7 +4217,7 @@ ffmpeg_select="aformat_filter anull_filter atrim_filter 
crop_filter
                format_filter hflip_filter null_filter rotate_filter
                transpose_filter trim_filter vflip_filter"
 ffmpeg_suggest="ole32 psapi shell32"
-ffplay_deps="avcodec avformat avfilter swscale swresample sdl2"
+ffplay_deps="avcodec avformat avfilter swscale swresample sdl3"
 ffplay_select="crop_filter transpose_filter hflip_filter vflip_filter 
rotate_filter"
 ffplay_suggest="shell32 libplacebo vulkan"
 ffprobe_deps="avcodec avformat"
@@ -4562,7 +4562,7 @@ for opt do
             do_random ${action#--} $optval
         ;;
         --enable-sdl)
-            enable sdl2
+            enable sdl3
         ;;
         --enable-lto*)
             lto=-f${opt#--enable-}
@@ -7404,20 +7404,8 @@ if enabled gcrypt; then
     fi
 fi

-if enabled sdl2; then
-    SDL2_CONFIG="${cross_prefix}sdl2-config"
-    test_pkg_config sdl2 "sdl2 >= 2.0.1 sdl2 < 3.0.0" SDL_events.h 
SDL_PollEvent
-    if disabled sdl2 && "${SDL2_CONFIG}" --version > /dev/null 2>&1; then
-        sdl2_cflags=$("${SDL2_CONFIG}" --cflags)
-        sdl2_extralibs=$("${SDL2_CONFIG}" --libs)
-        test_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | 
SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x020001" $sdl2_cflags &&
-        test_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | 
SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x030000" $sdl2_cflags &&
-        check_func_headers SDL_events.h SDL_PollEvent $sdl2_extralibs 
$sdl2_cflags &&
-            enable sdl2
-    fi
-    if test $target_os = "mingw32"; then
-        sdl2_extralibs=$(filter_out '-mwindows' $sdl2_extralibs)
-    fi
+if enabled sdl3; then
+    test_pkg_config sdl3 "sdl3 >= 3.2.0 sdl3 < 4.0.0" SDL3/SDL_events.h 
SDL_PollEvent
 fi

 if enabled decklink; then
@@ -8467,7 +8455,7 @@ HOSTLD_O=$HOSTLD_O
 TARGET_EXEC=$target_exec $target_exec_args
 TARGET_PATH=$target_path
 TARGET_SAMPLES=${target_samples:-\$(SAMPLES)}
-CFLAGS-ffplay=${sdl2_cflags}
+CFLAGS-ffplay=${sdl3_cflags}
 CFLAGS_HEADERS=$CFLAGS_HEADERS
 LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD
 EXTRALIBS=$extralibs
diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index dcd20e70bc..52d842083c 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -51,8 +51,9 @@
 #include "libavfilter/buffersink.h"
 #include "libavfilter/buffersrc.h"

-#include <SDL.h>
-#include <SDL_thread.h>
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
+#include <SDL3/SDL_thread.h>

 #include "cmdutils.h"
 #include "ffplay_renderer.h"
@@ -117,8 +118,8 @@ typedef struct PacketQueue {
     int64_t duration;
     int abort_request;
     int serial;
-    SDL_mutex *mutex;
-    SDL_cond *cond;
+    SDL_Mutex *mutex;
+    SDL_Condition *cond;
 } PacketQueue;

 #define VIDEO_PICTURE_QUEUE_SIZE 3
@@ -172,8 +173,8 @@ typedef struct FrameQueue {
     int max_size;
     int keep_last;
     int rindex_shown;
-    SDL_mutex *mutex;
-    SDL_cond *cond;
+    SDL_Mutex *mutex;
+    SDL_Condition *cond;
     PacketQueue *pktq;
 } FrameQueue;

@@ -190,7 +191,7 @@ typedef struct Decoder {
     int pkt_serial;
     int finished;
     int packet_pending;
-    SDL_cond *empty_queue_cond;
+    SDL_Condition *empty_queue_cond;
     int64_t start_pts;
     AVRational start_pts_tb;
     int64_t next_pts;
@@ -245,7 +246,7 @@ typedef struct VideoState {
     unsigned int audio_buf1_size;
     int audio_buf_index; /* in bytes */
     int audio_write_buf_size;
-    int audio_volume;
+    float audio_volume;
     int muted;
     struct AudioParams audio_src;
     struct AudioParams audio_filter_src;
@@ -283,7 +284,8 @@ typedef struct VideoState {
     PacketQueue videoq;
     double max_frame_duration;      // maximum duration of a frame - above 
this, we consider the jump a timestamp discontinuity
     struct SwsContext *sub_convert_ctx;
-    int eof;
+    bool shown;
+    bool eof;

     char *filename;
     int width, height, xleft, ytop;
@@ -298,7 +300,7 @@ typedef struct VideoState {

     int last_video_stream, last_audio_stream, last_subtitle_stream;

-    SDL_cond *continue_read_thread;
+    SDL_Condition *continue_read_thread;
 } VideoState;

 /* options specified by the user */
@@ -356,12 +358,12 @@ static const char *hwaccel = NULL;
 static int is_full_screen;
 static int64_t audio_callback_time;

-#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
+#define FF_QUIT_EVENT    (SDL_EVENT_USER + 2)

 static SDL_Window *window;
 static SDL_Renderer *renderer;
-static SDL_RendererInfo renderer_info = {0};
-static SDL_AudioDeviceID audio_dev;
+static const SDL_PixelFormat *renderer_texture_formats;
+static SDL_AudioStream *audio_stream;

 static VkRenderer *vk_renderer;

@@ -370,15 +372,15 @@ static const struct TextureFormatEntry {
     int texture_fmt;
 } sdl_texture_format_map[] = {
     { AV_PIX_FMT_RGB8,           SDL_PIXELFORMAT_RGB332 },
-    { AV_PIX_FMT_RGB444,         SDL_PIXELFORMAT_RGB444 },
-    { AV_PIX_FMT_RGB555,         SDL_PIXELFORMAT_RGB555 },
-    { AV_PIX_FMT_BGR555,         SDL_PIXELFORMAT_BGR555 },
+    { AV_PIX_FMT_RGB444,         SDL_PIXELFORMAT_XRGB4444 },
+    { AV_PIX_FMT_RGB555,         SDL_PIXELFORMAT_XRGB1555 },
+    { AV_PIX_FMT_BGR555,         SDL_PIXELFORMAT_XBGR1555 },
     { AV_PIX_FMT_RGB565,         SDL_PIXELFORMAT_RGB565 },
     { AV_PIX_FMT_BGR565,         SDL_PIXELFORMAT_BGR565 },
     { AV_PIX_FMT_RGB24,          SDL_PIXELFORMAT_RGB24 },
     { AV_PIX_FMT_BGR24,          SDL_PIXELFORMAT_BGR24 },
-    { AV_PIX_FMT_0RGB32,         SDL_PIXELFORMAT_RGB888 },
-    { AV_PIX_FMT_0BGR32,         SDL_PIXELFORMAT_BGR888 },
+    { AV_PIX_FMT_0RGB32,         SDL_PIXELFORMAT_XRGB8888 },
+    { AV_PIX_FMT_0BGR32,         SDL_PIXELFORMAT_XBGR8888 },
     { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
     { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
     { AV_PIX_FMT_RGB32,          SDL_PIXELFORMAT_ARGB8888 },
@@ -433,7 +435,7 @@ static int packet_queue_put_private(PacketQueue *q, 
AVPacket *pkt)
     q->size += pkt1.pkt->size + sizeof(pkt1);
     q->duration += pkt1.pkt->duration;
     /* XXX: should duplicate packet data in DV case */
-    SDL_CondSignal(q->cond);
+    SDL_SignalCondition(q->cond);
     return 0;
 }

@@ -477,7 +479,7 @@ static int packet_queue_init(PacketQueue *q)
         av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
         return AVERROR(ENOMEM);
     }
-    q->cond = SDL_CreateCond();
+    q->cond = SDL_CreateCondition();
     if (!q->cond) {
         av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
         return AVERROR(ENOMEM);
@@ -505,7 +507,7 @@ static void packet_queue_destroy(PacketQueue *q)
     packet_queue_flush(q);
     av_fifo_freep2(&q->pkt_list);
     SDL_DestroyMutex(q->mutex);
-    SDL_DestroyCond(q->cond);
+    SDL_DestroyCondition(q->cond);
 }

 static void packet_queue_abort(PacketQueue *q)
@@ -514,7 +516,7 @@ static void packet_queue_abort(PacketQueue *q)

     q->abort_request = 1;

-    SDL_CondSignal(q->cond);
+    SDL_SignalCondition(q->cond);

     SDL_UnlockMutex(q->mutex);
 }
@@ -555,14 +557,14 @@ static int packet_queue_get(PacketQueue *q, AVPacket 
*pkt, int block, int *seria
             ret = 0;
             break;
         } else {
-            SDL_CondWait(q->cond, q->mutex);
+            SDL_WaitCondition(q->cond, q->mutex);
         }
     }
     SDL_UnlockMutex(q->mutex);
     return ret;
 }

-static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, 
SDL_cond *empty_queue_cond) {
+static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, 
SDL_Condition *empty_queue_cond) {
     memset(d, 0, sizeof(Decoder));
     d->pkt = av_packet_alloc();
     if (!d->pkt)
@@ -622,7 +624,7 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, 
AVSubtitle *sub) {

         do {
             if (d->queue->nb_packets == 0)
-                SDL_CondSignal(d->empty_queue_cond);
+                SDL_SignalCondition(d->empty_queue_cond);
             if (d->packet_pending) {
                 d->packet_pending = 0;
             } else {
@@ -693,7 +695,7 @@ static int frame_queue_init(FrameQueue *f, PacketQueue 
*pktq, int max_size, int
         av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
         return AVERROR(ENOMEM);
     }
-    if (!(f->cond = SDL_CreateCond())) {
+    if (!(f->cond = SDL_CreateCondition())) {
         av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
         return AVERROR(ENOMEM);
     }
@@ -715,13 +717,13 @@ static void frame_queue_destroy(FrameQueue *f)
         av_frame_free(&vp->frame);
     }
     SDL_DestroyMutex(f->mutex);
-    SDL_DestroyCond(f->cond);
+    SDL_DestroyCondition(f->cond);
 }

 static void frame_queue_signal(FrameQueue *f)
 {
     SDL_LockMutex(f->mutex);
-    SDL_CondSignal(f->cond);
+    SDL_SignalCondition(f->cond);
     SDL_UnlockMutex(f->mutex);
 }

@@ -746,7 +748,7 @@ static Frame *frame_queue_peek_writable(FrameQueue *f)
     SDL_LockMutex(f->mutex);
     while (f->size >= f->max_size &&
            !f->pktq->abort_request) {
-        SDL_CondWait(f->cond, f->mutex);
+        SDL_WaitCondition(f->cond, f->mutex);
     }
     SDL_UnlockMutex(f->mutex);

@@ -762,7 +764,7 @@ static Frame *frame_queue_peek_readable(FrameQueue *f)
     SDL_LockMutex(f->mutex);
     while (f->size - f->rindex_shown <= 0 &&
            !f->pktq->abort_request) {
-        SDL_CondWait(f->cond, f->mutex);
+        SDL_WaitCondition(f->cond, f->mutex);
     }
     SDL_UnlockMutex(f->mutex);

@@ -778,7 +780,7 @@ static void frame_queue_push(FrameQueue *f)
         f->windex = 0;
     SDL_LockMutex(f->mutex);
     f->size++;
-    SDL_CondSignal(f->cond);
+    SDL_SignalCondition(f->cond);
     SDL_UnlockMutex(f->mutex);
 }

@@ -793,7 +795,7 @@ static void frame_queue_next(FrameQueue *f)
         f->rindex = 0;
     SDL_LockMutex(f->mutex);
     f->size--;
-    SDL_CondSignal(f->cond);
+    SDL_SignalCondition(f->cond);
     SDL_UnlockMutex(f->mutex);
 }

@@ -824,7 +826,7 @@ static void decoder_abort(Decoder *d, FrameQueue *fq)

 static inline void fill_rectangle(int x, int y, int w, int h)
 {
-    SDL_Rect rect;
+    SDL_FRect rect;
     rect.x = x;
     rect.y = y;
     rect.w = w;
@@ -835,19 +837,21 @@ static inline void fill_rectangle(int x, int y, int w, 
int h)

 static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int 
new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
 {
-    Uint32 format;
-    int access, w, h;
-    if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 
|| new_width != w || new_height != h || new_format != format) {
+    SDL_PropertiesID props = SDL_GetTextureProperties(*texture);
+    if (!*texture || !props ||
+        SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0) != 
new_width ||
+        SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0) != 
new_height ||
+        SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_FORMAT_NUMBER, 0) != 
new_format) {
         void *pixels;
         int pitch;
         if (*texture)
             SDL_DestroyTexture(*texture);
         if (!(*texture = SDL_CreateTexture(renderer, new_format, 
SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
             return -1;
-        if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
+        if (!SDL_SetTextureBlendMode(*texture, blendmode))
             return -1;
         if (init_texture) {
-            if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0)
+            if (!SDL_LockTexture(*texture, NULL, &pixels, &pitch))
                 return -1;
             memset(pixels, 0, pitch * new_height);
             SDL_UnlockTexture(*texture);
@@ -857,7 +861,7 @@ static int realloc_texture(SDL_Texture **texture, Uint32 
new_format, int new_wid
     return 0;
 }

-static void calculate_display_rect(SDL_Rect *rect,
+static void calculate_display_rect(SDL_FRect *rect,
                                    int scr_xleft, int scr_ytop, int scr_width, 
int scr_height,
                                    int pic_width, int pic_height, AVRational 
pic_sar)
 {
@@ -949,25 +953,14 @@ static enum AVAlphaMode sdl_supported_alpha_modes[] = {

 static void set_sdl_yuv_conversion_mode(AVFrame *frame)
 {
-#if SDL_VERSION_ATLEAST(2,0,8)
-    SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC;
-    if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == 
AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) {
-        if (frame->color_range == AVCOL_RANGE_JPEG)
-            mode = SDL_YUV_CONVERSION_JPEG;
-        else if (frame->colorspace == AVCOL_SPC_BT709)
-            mode = SDL_YUV_CONVERSION_BT709;
-        else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace 
== AVCOL_SPC_SMPTE170M)
-            mode = SDL_YUV_CONVERSION_BT601;
-    }
-    SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */
-#endif
+  /* TODO */
 }

 static void video_image_display(VideoState *is)
 {
     Frame *vp;
     Frame *sp = NULL;
-    SDL_Rect rect;
+    SDL_FRect rect;

     vp = frame_queue_peek_last(&is->pictq);
     if (vk_renderer) {
@@ -1032,11 +1025,11 @@ static void video_image_display(VideoState *is)
         vp->flip_v = vp->frame->linesize[0] < 0;
     }

-    SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, 
vp->flip_v ? SDL_FLIP_VERTICAL : 0);
+    SDL_RenderTextureRotated(renderer, is->vid_texture, NULL, &rect, 0, NULL, 
vp->flip_v ? SDL_FLIP_VERTICAL : 0);
     set_sdl_yuv_conversion_mode(NULL);
     if (sp) {
 #if USE_ONEPASS_SUBTITLE_RENDER
-        SDL_RenderCopy(renderer, is->sub_texture, NULL, &rect);
+        SDL_RenderTexture(renderer, is->sub_texture, NULL, &rect);
 #else
         int i;
         double xratio = (double)rect.w / (double)sp->width;
@@ -1047,7 +1040,7 @@ static void video_image_display(VideoState *is)
                                .y = rect.y + sub_rect->y * yratio,
                                .w = sub_rect->w * xratio,
                                .h = sub_rect->h * yratio};
-            SDL_RenderCopy(renderer, is->sub_texture, sub_rect, &target);
+            SDL_RenderTexture(renderer, is->sub_texture, sub_rect, &target);
         }
 #endif
     }
@@ -1202,7 +1195,7 @@ static void video_audio_display(VideoState *s)
                 }
                 SDL_UnlockTexture(s->vis_texture);
             }
-            SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL);
+            SDL_RenderTexture(renderer, s->vis_texture, NULL, NULL);
         }
         if (!s->paused)
             s->xpos++;
@@ -1221,7 +1214,7 @@ static void stream_component_close(VideoState *is, int 
stream_index)
     switch (codecpar->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
         decoder_abort(&is->auddec, &is->sampq);
-        SDL_CloseAudioDevice(audio_dev);
+        SDL_DestroyAudioStream(audio_stream);
         decoder_destroy(&is->auddec);
         swr_free(&is->swr_ctx);
         av_freep(&is->audio_buf1);
@@ -1291,7 +1284,7 @@ static void stream_close(VideoState *is)
     frame_queue_destroy(&is->pictq);
     frame_queue_destroy(&is->sampq);
     frame_queue_destroy(&is->subpq);
-    SDL_DestroyCond(is->continue_read_thread);
+    SDL_DestroyCondition(is->continue_read_thread);
     sws_freeContext(is->sub_convert_ctx);
     av_free(is->filename);
     if (is->vis_texture)
@@ -1337,7 +1330,7 @@ static void sigterm_handler(int sig)

 static void set_default_window_size(int width, int height, AVRational sar)
 {
-    SDL_Rect rect;
+    SDL_FRect rect;
     int max_width  = screen_width  ? screen_width  : INT_MAX;
     int max_height = screen_height ? screen_height : INT_MAX;
     if (max_width == INT_MAX && max_height == INT_MAX)
@@ -1361,11 +1354,12 @@ static int video_open(VideoState *is)
     SDL_SetWindowSize(window, w, h);
     SDL_SetWindowPosition(window, screen_left, screen_top);
     if (is_full_screen)
-        SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
+        SDL_SetWindowFullscreen(window, true);
     SDL_ShowWindow(window);

     is->width  = w;
     is->height = h;
+    is->shown = true;

     return 0;
 }
@@ -1373,7 +1367,7 @@ static int video_open(VideoState *is)
 /* display the current picture, if any */
 static void video_display(VideoState *is)
 {
-    if (!is->width)
+    if (!is->shown)
         video_open(is);

     SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
@@ -1492,7 +1486,7 @@ static void stream_seek(VideoState *is, int64_t pos, 
int64_t rel, int by_bytes)
         if (by_bytes)
             is->seek_flags |= AVSEEK_FLAG_BYTE;
         is->seek_req = 1;
-        SDL_CondSignal(is->continue_read_thread);
+        SDL_SignalCondition(is->continue_read_thread);
     }
 }

@@ -1523,9 +1517,9 @@ static void toggle_mute(VideoState *is)

 static void update_volume(VideoState *is, int sign, double step)
 {
-    double volume_level = is->audio_volume ? (20 * log(is->audio_volume / 
(double)SDL_MIX_MAXVOLUME) / log(10)) : -1000.0;
-    int new_volume = lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign 
* step) / 20.0));
-    is->audio_volume = av_clip(is->audio_volume == new_volume ? 
(is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
+    float volume_level = is->audio_volume ? (20 * log(is->audio_volume - 10)) 
: -1000.0;
+    float new_volume = pow(10.0, (volume_level + sign * step) / 20.0);
+    is->audio_volume = SDL_max(0.0, SDL_min(new_volume, 1.0));
 }

 static void step_to_next_frame(VideoState *is)
@@ -1876,9 +1870,9 @@ static int configure_video_filters(AVFilterGraph *graph, 
VideoState *is, const c
     if (!par)
         return AVERROR(ENOMEM);

-    for (i = 0; i < renderer_info.num_texture_formats; i++) {
+    for (i = 0; renderer_texture_formats[i] != SDL_PIXELFORMAT_UNKNOWN; i++) {
         for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map); j++) {
-            if (renderer_info.texture_formats[i] == 
sdl_texture_format_map[j].texture_fmt) {
+            if (renderer_texture_formats[i] == 
sdl_texture_format_map[j].texture_fmt) {
                 pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format;
                 break;
             }
@@ -2513,12 +2507,13 @@ static void sdl_audio_callback(void *opaque, Uint8 
*stream, int len)
         len1 = is->audio_buf_size - is->audio_buf_index;
         if (len1 > len)
             len1 = len;
-        if (!is->muted && is->audio_buf && is->audio_volume == 
SDL_MIX_MAXVOLUME)
+        if (!is->muted && is->audio_buf && is->audio_volume == 1.0)
             memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, 
len1);
         else {
             memset(stream, 0, len1);
             if (!is->muted && is->audio_buf)
-                SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + 
is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume);
+                SDL_MixAudio(stream, (uint8_t *)is->audio_buf + 
is->audio_buf_index,
+                                   SDL_AUDIO_S16, len1, is->audio_volume);
         }
         len -= len1;
         stream += len1;
@@ -2532,9 +2527,22 @@ static void sdl_audio_callback(void *opaque, Uint8 
*stream, int len)
     }
 }

+static void SDLCALL sdl3_audio_callback(void *userdata, SDL_AudioStream 
*stream, int additional_amount, int total_amount)
+{
+    if (additional_amount > 0) {
+        Uint8 *data = SDL_stack_alloc(Uint8, additional_amount);
+        if (data) {
+            /* TODO: inline and refactor */
+            sdl_audio_callback(userdata, data, additional_amount);
+            SDL_PutAudioStreamData(stream, data, additional_amount);
+            SDL_stack_free(data);
+        }
+    }
+}
+
 static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layout, 
int wanted_sample_rate, struct AudioParams *audio_hw_params)
 {
-    SDL_AudioSpec wanted_spec, spec;
+    SDL_AudioSpec wanted_spec;
     const char *env;
     static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
     static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
@@ -2560,12 +2568,8 @@ static int audio_open(void *opaque, AVChannelLayout 
*wanted_channel_layout, int
     }
     while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= 
wanted_spec.freq)
         next_sample_rate_idx--;
-    wanted_spec.format = AUDIO_S16SYS;
-    wanted_spec.silence = 0;
-    wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << 
av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
-    wanted_spec.callback = sdl_audio_callback;
-    wanted_spec.userdata = opaque;
-    while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, 
SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
+    wanted_spec.format = SDL_AUDIO_S16;
+    while (!(audio_stream = 
SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &wanted_spec, 
sdl3_audio_callback, opaque))) {
         av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): 
%s\n",
                wanted_spec.channels, wanted_spec.freq, SDL_GetError());
         wanted_spec.channels = next_nb_channels[FFMIN(7, 
wanted_spec.channels)];
@@ -2580,23 +2584,9 @@ static int audio_open(void *opaque, AVChannelLayout 
*wanted_channel_layout, int
         }
         av_channel_layout_default(wanted_channel_layout, wanted_spec.channels);
     }
-    if (spec.format != AUDIO_S16SYS) {
-        av_log(NULL, AV_LOG_ERROR,
-               "SDL advised audio format %d is not supported!\n", spec.format);
-        return -1;
-    }
-    if (spec.channels != wanted_spec.channels) {
-        av_channel_layout_uninit(wanted_channel_layout);
-        av_channel_layout_default(wanted_channel_layout, spec.channels);
-        if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
-            av_log(NULL, AV_LOG_ERROR,
-                   "SDL advised channel count %d is not supported!\n", 
spec.channels);
-            return -1;
-        }
-    }

     audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
-    audio_hw_params->freq = spec.freq;
+    audio_hw_params->freq = wanted_spec.freq;
     if (av_channel_layout_copy(&audio_hw_params->ch_layout, 
wanted_channel_layout) < 0)
         return -1;
     audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, 
audio_hw_params->ch_layout.nb_channels, 1, audio_hw_params->fmt, 1);
@@ -2605,7 +2595,7 @@ static int audio_open(void *opaque, AVChannelLayout 
*wanted_channel_layout, int
         av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
         return -1;
     }
-    return spec.size;
+    return 0; /* TODO: is zero here ok? */
 }

 static int create_hwaccel(AVBufferRef **device_ctx)
@@ -2770,7 +2760,7 @@ static int stream_component_open(VideoState *is, int 
stream_index)
         }
         if ((ret = decoder_start(&is->auddec, audio_thread, "audio_decoder", 
is)) < 0)
             goto out;
-        SDL_PauseAudioDevice(audio_dev, 0);
+        SDL_ResumeAudioStreamDevice(audio_stream);
         break;
     case AVMEDIA_TYPE_VIDEO:
         is->video_stream = stream_index;
@@ -2846,7 +2836,7 @@ static int read_thread(void *arg)
     char metadata_description[96];
     int pkt_in_play_range = 0;
     const AVDictionaryEntry *t;
-    SDL_mutex *wait_mutex = SDL_CreateMutex();
+    SDL_Mutex *wait_mutex = SDL_CreateMutex();
     int scan_all_pmts_set = 0;
     int64_t pkt_ts;

@@ -3096,7 +3086,7 @@ static int read_thread(void *arg)
                 stream_has_enough_packets(is->subtitle_st, 
is->subtitle_stream, &is->subtitleq)))) {
             /* wait 10 ms */
             SDL_LockMutex(wait_mutex);
-            SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
+            SDL_WaitConditionTimeout(is->continue_read_thread, wait_mutex, 10);
             SDL_UnlockMutex(wait_mutex);
             continue;
         }
@@ -3128,7 +3118,7 @@ static int read_thread(void *arg)
                     break;
             }
             SDL_LockMutex(wait_mutex);
-            SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
+            SDL_WaitConditionTimeout(is->continue_read_thread, wait_mutex, 10);
             SDL_UnlockMutex(wait_mutex);
             continue;
         } else {
@@ -3215,7 +3205,7 @@ static VideoState *stream_open(const char *filename,
         packet_queue_init(&is->subtitleq) < 0)
         goto fail;

-    if (!(is->continue_read_thread = SDL_CreateCond())) {
+    if (!(is->continue_read_thread = SDL_CreateCondition())) {
         av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
         goto fail;
     }
@@ -3229,8 +3219,7 @@ static VideoState *stream_open(const char *filename,
     if (startup_volume > 100)
         av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", 
startup_volume);
     startup_volume = av_clip(startup_volume, 0, 100);
-    startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, 
SDL_MIX_MAXVOLUME);
-    is->audio_volume = startup_volume;
+    is->audio_volume = startup_volume / 100.0;
     is->muted = 0;
     is->av_sync_type = av_sync_type;
     is->read_tid     = SDL_CreateThread(read_thread, "read_thread", is);
@@ -3325,7 +3314,7 @@ static void stream_cycle_channel(VideoState *is, int 
codec_type)
 static void toggle_full_screen(VideoState *is)
 {
     is_full_screen = !is_full_screen;
-    SDL_SetWindowFullscreen(window, is_full_screen ? 
SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
+    SDL_SetWindowFullscreen(window, is_full_screen);
 }

 static void toggle_audio_display(VideoState *is)
@@ -3343,9 +3332,9 @@ static void toggle_audio_display(VideoState *is)
 static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
     double remaining_time = 0.0;
     SDL_PumpEvents();
-    while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, 
SDL_LASTEVENT)) {
+    while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, 
SDL_EVENT_LAST)) {
         if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > 
CURSOR_HIDE_DELAY) {
-            SDL_ShowCursor(0);
+            SDL_HideCursor();
             cursor_hidden = 1;
         }
         if (remaining_time > 0.0)
@@ -3394,24 +3383,24 @@ static void event_loop(VideoState *cur_stream)
         double x;
         refresh_loop_wait_event(cur_stream, &event);
         switch (event.type) {
-        case SDL_KEYDOWN:
-            if (exit_on_keydown || event.key.keysym.sym == SDLK_ESCAPE || 
event.key.keysym.sym == SDLK_q) {
+        case SDL_EVENT_KEY_DOWN:
+            if (exit_on_keydown || event.key.key == SDLK_ESCAPE || 
event.key.key == SDLK_Q) {
                 do_exit(cur_stream);
                 break;
             }
             // If we don't yet have a window, skip all key events, because 
read_thread might still be initializing...
             if (!cur_stream->width)
                 continue;
-            switch (event.key.keysym.sym) {
-            case SDLK_f:
+            switch (event.key.key) {
+            case SDLK_F:
                 toggle_full_screen(cur_stream);
                 cur_stream->force_refresh = 1;
                 break;
-            case SDLK_p:
+            case SDLK_P:
             case SDLK_SPACE:
                 toggle_pause(cur_stream);
                 break;
-            case SDLK_m:
+            case SDLK_M:
                 toggle_mute(cur_stream);
                 break;
             case SDLK_KP_MULTIPLY:
@@ -3422,24 +3411,24 @@ static void event_loop(VideoState *cur_stream)
             case SDLK_9:
                 update_volume(cur_stream, -1, SDL_VOLUME_STEP);
                 break;
-            case SDLK_s: // S: Step to next frame
+            case SDLK_S: // S: Step to next frame
                 step_to_next_frame(cur_stream);
                 break;
-            case SDLK_a:
+            case SDLK_A:
                 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
                 break;
-            case SDLK_v:
+            case SDLK_V:
                 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
                 break;
-            case SDLK_c:
+            case SDLK_C:
                 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
                 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
                 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
                 break;
-            case SDLK_t:
+            case SDLK_T:
                 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
                 break;
-            case SDLK_w:
+            case SDLK_W:
                 if (cur_stream->show_mode == SHOW_MODE_VIDEO && 
cur_stream->vfilter_idx < nb_vfilters - 1) {
                     if (++cur_stream->vfilter_idx >= nb_vfilters)
                         cur_stream->vfilter_idx = 0;
@@ -3502,7 +3491,7 @@ static void event_loop(VideoState *cur_stream)
                 break;
             }
             break;
-        case SDL_MOUSEBUTTONDOWN:
+        case SDL_EVENT_MOUSE_BUTTON_DOWN:
             if (exit_on_mousedown) {
                 do_exit(cur_stream);
                 break;
@@ -3517,13 +3506,13 @@ static void event_loop(VideoState *cur_stream)
                     last_mouse_left_click = av_gettime_relative();
                 }
             }
-        case SDL_MOUSEMOTION:
+        case SDL_EVENT_MOUSE_MOTION:
             if (cursor_hidden) {
-                SDL_ShowCursor(1);
+                SDL_ShowCursor();
                 cursor_hidden = 0;
             }
             cursor_last_shown = av_gettime_relative();
-            if (event.type == SDL_MOUSEBUTTONDOWN) {
+            if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
                 if (event.button.button != SDL_BUTTON_RIGHT)
                     break;
                 x = event.button.x;
@@ -3557,22 +3546,19 @@ static void event_loop(VideoState *cur_stream)
                     stream_seek(cur_stream, ts, 0, 0);
                 }
             break;
-        case SDL_WINDOWEVENT:
-            switch (event.window.event) {
-                case SDL_WINDOWEVENT_SIZE_CHANGED:
-                    screen_width  = cur_stream->width  = event.window.data1;
-                    screen_height = cur_stream->height = event.window.data2;
-                    if (cur_stream->vis_texture) {
-                        SDL_DestroyTexture(cur_stream->vis_texture);
-                        cur_stream->vis_texture = NULL;
-                    }
-                    if (vk_renderer)
-                        vk_renderer_resize(vk_renderer, screen_width, 
screen_height);
-                case SDL_WINDOWEVENT_EXPOSED:
-                    cur_stream->force_refresh = 1;
+        case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
+            screen_width  = cur_stream->width  = event.window.data1;
+            screen_height = cur_stream->height = event.window.data2;
+            if (cur_stream->vis_texture) {
+                SDL_DestroyTexture(cur_stream->vis_texture);
+                cur_stream->vis_texture = NULL;
             }
+            if (vk_renderer)
+                vk_renderer_resize(vk_renderer, screen_width, screen_height);
+        case SDL_EVENT_WINDOW_EXPOSED:
+            cur_stream->force_refresh = 1;
             break;
-        case SDL_QUIT:
+        case SDL_EVENT_QUIT:
         case FF_QUIT_EVENT:
             do_exit(cur_stream);
             break;
@@ -3820,25 +3806,24 @@ int main(int argc, char **argv)
     if (display_disable) {
         video_disable = 1;
     }
-    flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
+    flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO;
     if (audio_disable)
         flags &= ~SDL_INIT_AUDIO;
     else {
         /* Try to work around an occasional ALSA buffer underflow issue when 
the
          * period size is NPOT due to ALSA resampling by forcing the buffer 
size. */
         if (!SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
-            SDL_setenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE","1", 1);
+            SDL_setenv_unsafe("SDL_AUDIO_ALSA_SET_BUFFER_SIZE","1", 1);
     }
     if (display_disable)
         flags &= ~SDL_INIT_VIDEO;
-    if (SDL_Init (flags)) {
+    if (!SDL_Init (flags)) {
         av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", 
SDL_GetError());
         av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
         exit(1);
     }

-    SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
-    SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
+    SDL_SetEventEnabled(SDL_EVENT_USER, false);

     if (!display_disable) {
         int flags = SDL_WINDOW_HIDDEN;
@@ -3871,8 +3856,7 @@ int main(int argc, char **argv)
                 enable_vulkan = 0;
             }
         }
-        window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, 
SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
-        SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+        window = SDL_CreateWindow(program_name, default_width, default_height, 
flags);
         if (!window) {
             av_log(NULL, AV_LOG_FATAL, "Failed to create window: %s", 
SDL_GetError());
             do_exit(NULL);
@@ -3895,19 +3879,24 @@ int main(int argc, char **argv)
                 do_exit(NULL);
             }
         } else {
-            renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED 
| SDL_RENDERER_PRESENTVSYNC);
+            SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");
+            renderer = SDL_CreateRenderer(window, NULL);
             if (!renderer) {
-                av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware 
accelerated renderer: %s\n", SDL_GetError());
-                renderer = SDL_CreateRenderer(window, -1, 0);
+                av_log(NULL, AV_LOG_FATAL, "Failed to create renderer: %s", 
SDL_GetError());
+                do_exit(NULL);
             }
-            if (renderer) {
-                if (!SDL_GetRendererInfo(renderer, &renderer_info))
-                    av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", 
renderer_info.name);
+            if (!strcmp(SDL_GetRendererName(renderer), SDL_SOFTWARE_RENDERER)) 
{
+                av_log(NULL, AV_LOG_WARNING, "Created renderer is not hardware 
accelerated\n");
             }
-            if (!renderer || !renderer_info.num_texture_formats) {
-                av_log(NULL, AV_LOG_FATAL, "Failed to create window or 
renderer: %s", SDL_GetError());
+            SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
+            renderer_texture_formats = SDL_GetPointerProperty(props, 
SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER, NULL);
+            if (!renderer_texture_formats ||
+                *renderer_texture_formats == SDL_PIXELFORMAT_UNKNOWN) {
+                av_log(NULL, AV_LOG_FATAL, "Created renderer supports no 
texture formats");
                 do_exit(NULL);
             }
+
+            av_log(NULL, AV_LOG_VERBOSE, "Initialized %s 
renderer.\n",SDL_GetRendererName(renderer));
         }
     }

diff --git a/fftools/ffplay_renderer.c b/fftools/ffplay_renderer.c
index 1321452ad8..83f8849e44 100644
--- a/fftools/ffplay_renderer.c
+++ b/fftools/ffplay_renderer.c
@@ -220,7 +220,7 @@ static int create_vk_by_hwcontext(VkRenderer *renderer,

     // There is no way to pass SDL GetInstanceProcAddr to hwdevice.
     // Check the result and return error if they don't match.
-    if (hwctx->get_proc_addr != SDL_Vulkan_GetVkGetInstanceProcAddr()) {
+    if (hwctx->get_proc_addr != (PFN_vkGetInstanceProcAddr) 
SDL_Vulkan_GetVkGetInstanceProcAddr()) {
         av_log(renderer, AV_LOG_ERROR,
                "hwdevice and SDL use different get_proc_addr. "
                "Try -vulkan_params create_by_placebo=1\n");
@@ -347,7 +347,7 @@ static int create_vk_by_placebo(VkRenderer *renderer,
     const char **dev_exts;
     int num_dev_exts;

-    ctx->get_proc_addr = SDL_Vulkan_GetVkGetInstanceProcAddr();
+    ctx->get_proc_addr = (PFN_vkGetInstanceProcAddr) 
SDL_Vulkan_GetVkGetInstanceProcAddr();

     ctx->placebo_instance = pl_vk_inst_create(ctx->vk_log, pl_vk_inst_params(
             .get_proc_addr = ctx->get_proc_addr,
@@ -459,7 +459,7 @@ static int create(VkRenderer *renderer, SDL_Window *window, 
AVDictionary *opt)

     ctx->vk_log = pl_log_create(PL_API_VER, &vk_log_params);

-    if (!SDL_Vulkan_GetInstanceExtensions(window, &num_ext, NULL)) {
+    if (!SDL_Vulkan_GetInstanceExtensions(&num_ext, NULL)) {
         av_log(NULL, AV_LOG_FATAL, "Failed to get vulkan extensions: %s\n",
                SDL_GetError());
         return AVERROR_EXTERNAL;
@@ -471,7 +471,7 @@ static int create(VkRenderer *renderer, SDL_Window *window, 
AVDictionary *opt)
         goto out;
     }

-    SDL_Vulkan_GetInstanceExtensions(window, &num_ext, ext);
+    SDL_Vulkan_GetInstanceExtensions(&num_ext, ext);

     entry = av_dict_get(opt, "create_by_placebo", NULL, 0);
     if (entry && strtol(entry->value, NULL, 10))
@@ -481,7 +481,7 @@ static int create(VkRenderer *renderer, SDL_Window *window, 
AVDictionary *opt)
     if (ret < 0)
         goto out;

-    if (!SDL_Vulkan_CreateSurface(window, ctx->inst, &ctx->vk_surface)) {
+    if (!SDL_Vulkan_CreateSurface(window, ctx->inst, NULL, &ctx->vk_surface)) {
         ret = AVERROR_EXTERNAL;
         goto out;
     }
@@ -496,7 +496,7 @@ static int create(VkRenderer *renderer, SDL_Window *window, 
AVDictionary *opt)
         goto out;
     }

-    SDL_Vulkan_GetDrawableSize(window, &w, &h);
+    SDL_GetWindowSizeInPixels(window, &w, &h);
     pl_swapchain_resize(ctx->swapchain, &w, &h);

     ctx->renderer = pl_renderer_create(ctx->vk_log, ctx->placebo_vulkan->gpu);
diff --git a/fftools/ffplay_renderer.h b/fftools/ffplay_renderer.h
index dd8e9c06e7..f026f42692 100644
--- a/fftools/ffplay_renderer.h
+++ b/fftools/ffplay_renderer.h
@@ -19,7 +19,7 @@
 #ifndef FFTOOLS_FFPLAY_RENDERER_H
 #define FFTOOLS_FFPLAY_RENDERER_H

-#include <SDL.h>
+#include <SDL3/SDL.h>

 #include "libavutil/frame.h"

--
2.51.2
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to