diff mbox

[FFmpeg-devel] ffplay: convert ffplay to use SDL2

Message ID 1473706695-77571-1-git-send-email-josh@itanimul.li
State Superseded
Headers show

Commit Message

Josh Dekker Sept. 12, 2016, 6:58 p.m. UTC
From: Marton Balint <cus@passwd.hu>

Depends on the other SDL patches.

Signed-off-by: Josh de Kock <josh@itanimul.li>
---
 configure |   6 +-
 ffplay.c  | 594 ++++++++++++++++++++++++++------------------------------------
 2 files changed, 249 insertions(+), 351 deletions(-)

Comments

James Almer Sept. 13, 2016, 4:45 p.m. UTC | #1
On 9/12/2016 3:58 PM, Josh de Kock wrote:
> From: Marton Balint <cus@passwd.hu>
> 
> Depends on the other SDL patches.
> 
> Signed-off-by: Josh de Kock <josh@itanimul.li>
> ---
>  configure |   6 +-
>  ffplay.c  | 594 ++++++++++++++++++++++++++------------------------------------
>  2 files changed, 249 insertions(+), 351 deletions(-)

Tested on Windows (compiled with mingw-w64) and works fine.
Michael Niedermayer Sept. 14, 2016, 9:12 a.m. UTC | #2
On Tue, Sep 13, 2016 at 01:45:12PM -0300, James Almer wrote:
> On 9/12/2016 3:58 PM, Josh de Kock wrote:
> > From: Marton Balint <cus@passwd.hu>
> > 
> > Depends on the other SDL patches.
> > 
> > Signed-off-by: Josh de Kock <josh@itanimul.li>
> > ---
> >  configure |   6 +-
> >  ffplay.c  | 594 ++++++++++++++++++++++++++------------------------------------
> >  2 files changed, 249 insertions(+), 351 deletions(-)
> 
> Tested on Windows (compiled with mingw-w64) and works fine.

patchwork uses "^Tested-by:" to detect patches having been tested
should the regexp be changed/extended ?

[...]
Josh Dekker Sept. 14, 2016, 12:53 p.m. UTC | #3
On Wed, Sep 14, 2016, at 10:12 AM, Michael Niedermayer wrote:
> On Tue, Sep 13, 2016 at 01:45:12PM -0300, James Almer wrote:
> > 
> > Tested on Windows (compiled with mingw-w64) and works fine.
> 
> patchwork uses "^Tested-by:" to detect patches having been tested
> should the regexp be changed/extended ?

I think it may be useful to extend it to define OSes and environments
as well. Maybe something like:

Tested-by: James Almer <jamrial@gmail.com> (Windows, mingw-w64)

Obviously this would require people to use this format but I don't see
how else you'd do it.

--
Josh
Carl Eugen Hoyos Sept. 14, 2016, 3:34 p.m. UTC | #4
2016-09-12 20:58 GMT+02:00 Josh de Kock <josh@itanimul.li>:
> From: Marton Balint <cus@passwd.hu>
>
> Depends on the other SDL patches.

This works fine on my antique desktop system (where an
extra repository provides sdl2 2.0.3) but not on my laptop
that I did not consider eol so far, it only has 2.0.0.

If a supported Linux distribution does not ship a sufficiently
recent sdl2, I am not sure if this is such a good idea.
Does the patch offer new functionality?

Carl Eugen
Josh Dekker Sept. 14, 2016, 3:54 p.m. UTC | #5
On 14/09/2016 16:34, Carl Eugen Hoyos wrote:
> [...]
> If a supported Linux distribution does not ship a sufficiently
> recent sdl2, I am not sure if this is such a good idea.
> Does the patch offer new functionality?
It doesn't add any extra functionality, but SDL1 has been unmaintained 
for more than 4 years. We discussed this in IRC and thought that ffmpeg 
was a big enough library, and it switching to SDL2 may help distros to 
consider supporting SDL2, also taking into account the length of time 
SDL1 has been unmaintained. Another option is just to compile SDL2 from 
source.

--
Josh
Michael Niedermayer Sept. 14, 2016, 3:59 p.m. UTC | #6
On Wed, Sep 14, 2016 at 05:34:05PM +0200, Carl Eugen Hoyos wrote:
> 2016-09-12 20:58 GMT+02:00 Josh de Kock <josh@itanimul.li>:
> > From: Marton Balint <cus@passwd.hu>
> >
> > Depends on the other SDL patches.
> 
> This works fine on my antique desktop system (where an
> extra repository provides sdl2 2.0.3) but not on my laptop
> that I did not consider eol so far, it only has 2.0.0.

did it get autodetected and failed ? (it should not i think)
was it forced enabled and then failed ? (maybe it should print an
error if the sdl2 version is not recent enough)

[...]
Carl Eugen Hoyos Sept. 14, 2016, 4 p.m. UTC | #7
2016-09-14 17:54 GMT+02:00 Josh de Kock <josh@itanimul.li>:
> We discussed this in IRC and thought that ffmpeg was a
> big enough library, and it switching to SDL2 may help
> distros to consider supporting SDL2

If this really were the only reason, I sincerely hope we
wouldn't even consider this patch.

My question remains: What about Debian, Ubunut and
Fedora? Do they still have supported versions without
sdl2 2.0.1?

Carl Eugen
Carl Eugen Hoyos Sept. 14, 2016, 4:04 p.m. UTC | #8
2016-09-14 17:59 GMT+02:00 Michael Niedermayer <michael@niedermayer.cc>:
> On Wed, Sep 14, 2016 at 05:34:05PM +0200, Carl Eugen Hoyos wrote:
>> 2016-09-12 20:58 GMT+02:00 Josh de Kock <josh@itanimul.li>:
>> > From: Marton Balint <cus@passwd.hu>
>> >
>> > Depends on the other SDL patches.
>>
>> This works fine on my antique desktop system (where an
>> extra repository provides sdl2 2.0.3) but not on my laptop
>> that I did not consider eol so far, it only has 2.0.0.
>
> did it get autodetected and failed ? (it should not i think)
> was it forced enabled and then failed ? (maybe it should
> print an error if the sdl2 version is not recent enough)

What I meant is:
On a system that I did not consider old before testing
this patch ffplay suddenly stops working making
FFmpeg development much harder.

So my question is: Did I just miss how old this system of
mine is or will we maybe stop supporting easy FFmpeg
development on supported major Linux distributions if
the patch gets applied?

Carl Eugen
James Almer Sept. 14, 2016, 4:05 p.m. UTC | #9
On 9/14/2016 12:34 PM, Carl Eugen Hoyos wrote:
> 2016-09-12 20:58 GMT+02:00 Josh de Kock <josh@itanimul.li>:
>> From: Marton Balint <cus@passwd.hu>
>>
>> Depends on the other SDL patches.
> 
> This works fine on my antique desktop system (where an
> extra repository provides sdl2 2.0.3) but not on my laptop
> that I did not consider eol so far, it only has 2.0.0.
> 
> If a supported Linux distribution does not ship a sufficiently
> recent sdl2, I am not sure if this is such a good idea.
> Does the patch offer new functionality?

https://ffmpeg.org/pipermail/ffmpeg-devel/2016-January/186299.html
Has a good summary of the advantages of SDL2.

> 
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Ronald S. Bultje Sept. 14, 2016, 4:10 p.m. UTC | #10
Hi,

On Wed, Sep 14, 2016 at 12:04 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
wrote:

> 2016-09-14 17:59 GMT+02:00 Michael Niedermayer <michael@niedermayer.cc>:
> > On Wed, Sep 14, 2016 at 05:34:05PM +0200, Carl Eugen Hoyos wrote:
> >> 2016-09-12 20:58 GMT+02:00 Josh de Kock <josh@itanimul.li>:
> >> > From: Marton Balint <cus@passwd.hu>
> >> >
> >> > Depends on the other SDL patches.
> >>
> >> This works fine on my antique desktop system (where an
> >> extra repository provides sdl2 2.0.3) but not on my laptop
> >> that I did not consider eol so far, it only has 2.0.0.
> >
> > did it get autodetected and failed ? (it should not i think)
> > was it forced enabled and then failed ? (maybe it should
> > print an error if the sdl2 version is not recent enough)
>
> What I meant is:
> On a system that I did not consider old before testing
> this patch ffplay suddenly stops working making
> FFmpeg development much harder.


Is ffplay really that critical in testing ffmpeg?

Ronald
Clément Bœsch Sept. 14, 2016, 4:12 p.m. UTC | #11
On Wed, Sep 14, 2016 at 05:34:05PM +0200, Carl Eugen Hoyos wrote:
> 2016-09-12 20:58 GMT+02:00 Josh de Kock <josh@itanimul.li>:
> > From: Marton Balint <cus@passwd.hu>
> >
> > Depends on the other SDL patches.
> 
> This works fine on my antique desktop system (where an
> extra repository provides sdl2 2.0.3) but not on my laptop
> that I did not consider eol so far, it only has 2.0.0.
> 

According to semantic versioning (not sure if SDL follows it) 2.0.3 a bug
fix release for 2.0.x. So 2.0.0 is probably officially broken and the
maintainer might be doing a very poor job at maintaining his packages.
James Almer Sept. 14, 2016, 4:15 p.m. UTC | #12
On 9/14/2016 1:00 PM, Carl Eugen Hoyos wrote:
> 2016-09-14 17:54 GMT+02:00 Josh de Kock <josh@itanimul.li>:
>> We discussed this in IRC and thought that ffmpeg was a
>> big enough library, and it switching to SDL2 may help
>> distros to consider supporting SDL2
> 
> If this really were the only reason, I sincerely hope we
> wouldn't even consider this patch.
> 
> My question remains: What about Debian, Ubunut and
> Fedora? Do they still have supported versions without
> sdl2 2.0.1?

Ubuntu has 2.0.2 as the oldest. Debian 7 (old-stable) seems
to be at 2.0.0, but support for that release will be dropped
in about six months, and it may nonetheless get updated with
a point release before that.
No idea about Fedora.

What kind of error did you get with 2.0.0 that a point release
seemingly fixes it? Configure failed to detect it, or ffplay
just misbehaves?
You could try to work with Josh on this and see if it can be
solved.

> 
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Carl Eugen Hoyos Sept. 14, 2016, 4:18 p.m. UTC | #13
2016-09-14 18:15 GMT+02:00 James Almer <jamrial@gmail.com>:

> Configure failed to detect it

configure requires 2.0.1

Carl Eugen (who wonders how Ronald tests...)
Hendrik Leppkes Sept. 14, 2016, 4:23 p.m. UTC | #14
Am 14.09.2016 18:00 schrieb "Carl Eugen Hoyos" <ceffmpeg@gmail.com>:
>
> 2016-09-14 17:54 GMT+02:00 Josh de Kock <josh@itanimul.li>:
> > We discussed this in IRC and thought that ffmpeg was a
> > big enough library, and it switching to SDL2 may help
> > distros to consider supporting SDL2
>
> If this really were the only reason, I sincerely hope we
> wouldn't even consider this patch.
>
> My question remains: What about Debian, Ubunut and
> Fedora? Do they still have supported versions without
> sdl2 2.0.1?
>

Ubuntu and debian have 2.0.2 or newer in their oldest supported versions
(ie. Debian stable and Ubuntu 14.04 LTS)

Not sure where to check for fedora right now.
James Almer Sept. 14, 2016, 4:31 p.m. UTC | #15
On 9/14/2016 1:12 PM, Clément Bœsch wrote:
> On Wed, Sep 14, 2016 at 05:34:05PM +0200, Carl Eugen Hoyos wrote:
>> 2016-09-12 20:58 GMT+02:00 Josh de Kock <josh@itanimul.li>:
>>> From: Marton Balint <cus@passwd.hu>
>>>
>>> Depends on the other SDL patches.
>>
>> This works fine on my antique desktop system (where an
>> extra repository provides sdl2 2.0.3) but not on my laptop
>> that I did not consider eol so far, it only has 2.0.0.
>>
> 
> According to semantic versioning (not sure if SDL follows it) 2.0.3 a bug
> fix release for 2.0.x. So 2.0.0 is probably officially broken and the
> maintainer might be doing a very poor job at maintaining his packages.

Debian Stable has 2.0.2, Debian Testing has 2.0.4.

It's Debian Old-Stable that apparently has 2.0.0, and may or may not
get it updated before it's EOLed early next year. But then again, you
shouldn't be using Old-Stable for a desktop environment.
Marton Balint Sept. 14, 2016, 5:54 p.m. UTC | #16
On Wed, 14 Sep 2016, Carl Eugen Hoyos wrote:

> 2016-09-14 18:15 GMT+02:00 James Almer <jamrial@gmail.com>:
>
>> Configure failed to detect it
>
> configure requires 2.0.1

YUV texture updates require 2.0.1 as far as I remember.

Regards,
Marton
Ronald S. Bultje Sept. 14, 2016, 6:03 p.m. UTC | #17
Hi,

On Wed, Sep 14, 2016 at 12:18 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
wrote:

> 2016-09-14 18:15 GMT+02:00 James Almer <jamrial@gmail.com>:
>
> > Configure failed to detect it
>
> configure requires 2.0.1
>
> Carl Eugen (who wonders how Ronald tests...)


ffmpeg (the tool), of course! :)

Ronald
Michael Niedermayer Sept. 14, 2016, 6:51 p.m. UTC | #18
On Wed, Sep 14, 2016 at 06:00:00PM +0200, Carl Eugen Hoyos wrote:
> 2016-09-14 17:54 GMT+02:00 Josh de Kock <josh@itanimul.li>:
> > We discussed this in IRC and thought that ffmpeg was a
> > big enough library, and it switching to SDL2 may help
> > distros to consider supporting SDL2
> 
> If this really were the only reason, I sincerely hope we
> wouldn't even consider this patch.
> 
> My question remains: What about Debian, Ubunut and
> Fedora? Do they still have supported versions without
> sdl2 2.0.1?

ubuntu 12.04 LTS has SDL 1.2, no 2.0
its supported till 2017-04-26

should we keep old ffplay as a ffplay-sdl1 until then ?

[...]
James Almer Sept. 14, 2016, 7:07 p.m. UTC | #19
On 9/14/2016 3:51 PM, Michael Niedermayer wrote:
> On Wed, Sep 14, 2016 at 06:00:00PM +0200, Carl Eugen Hoyos wrote:
>> 2016-09-14 17:54 GMT+02:00 Josh de Kock <josh@itanimul.li>:
>>> We discussed this in IRC and thought that ffmpeg was a
>>> big enough library, and it switching to SDL2 may help
>>> distros to consider supporting SDL2
>>
>> If this really were the only reason, I sincerely hope we
>> wouldn't even consider this patch.
>>
>> My question remains: What about Debian, Ubunut and
>> Fedora? Do they still have supported versions without
>> sdl2 2.0.1?
> 
> ubuntu 12.04 LTS has SDL 1.2, no 2.0

Not even in the backports repository? Afaik that's how Debian
7 ships SDL 2.0.0.

> its supported till 2017-04-26

That is also more or less the date when Debian 7 will be EOLed,
so it's a good time to fully drop SDL1 support.

> 
> should we keep old ffplay as a ffplay-sdl1 until then ?

I'm fine with that if others are (Especially Marton and Josh,
since they develop/maintain ffplay). It's a good compromise.

But much like ffserver it should similarly be marked as
deprecated and essentially unmaintained somewhere.
Michael Niedermayer Sept. 14, 2016, 7:21 p.m. UTC | #20
On Wed, Sep 14, 2016 at 04:07:50PM -0300, James Almer wrote:
> On 9/14/2016 3:51 PM, Michael Niedermayer wrote:
> > On Wed, Sep 14, 2016 at 06:00:00PM +0200, Carl Eugen Hoyos wrote:
> >> 2016-09-14 17:54 GMT+02:00 Josh de Kock <josh@itanimul.li>:
> >>> We discussed this in IRC and thought that ffmpeg was a
> >>> big enough library, and it switching to SDL2 may help
> >>> distros to consider supporting SDL2
> >>
> >> If this really were the only reason, I sincerely hope we
> >> wouldn't even consider this patch.
> >>
> >> My question remains: What about Debian, Ubunut and
> >> Fedora? Do they still have supported versions without
> >> sdl2 2.0.1?
> > 
> > ubuntu 12.04 LTS has SDL 1.2, no 2.0
> 
> Not even in the backports repository? Afaik that's how Debian
> 7 ships SDL 2.0.0.

no
https://launchpad.net/ubuntu/precise/+source/libsdl2
also my 12.04 LTS box doesnt seem to have a sdl2 unless i did
something dumb


> 
> > its supported till 2017-04-26
> 
> That is also more or less the date when Debian 7 will be EOLed,
> so it's a good time to fully drop SDL1 support.
> 
> > 
> > should we keep old ffplay as a ffplay-sdl1 until then ?
> 
> I'm fine with that if others are (Especially Marton and Josh,
> since they develop/maintain ffplay). It's a good compromise.

Id be happy too as i actually use ffplay on that old 12.04 box
didnt realize previously that it doesnt have sdl2
i could upgrade the OS but i intended to actually replace by new hw
just intel failing to inovate and produce faster CPUs since years
delays it ...


> 
> But much like ffserver it should similarly be marked as
> deprecated and essentially unmaintained somewhere.

yes

[...]
Josh Dekker Sept. 14, 2016, 7:31 p.m. UTC | #21
On 14/09/2016 20:07, James Almer wrote:
> [...]
> I'm fine with that if others are (Especially Marton and Josh,
> since they develop/maintain ffplay). It's a good compromise.
>
> But much like ffserver it should similarly be marked as
> deprecated and essentially unmaintained somewhere.

I'm fine with this, I can help backport ffplay stuff to the SDL1 variant 
as well.

I will resubmit the set like this:
- SDL2 device added
- ffplay renamed
- ffplay (sdl2) added

I will not submit the deprecation patches again until SDL1 is fully 
deprecated throughout ffmpeg.

Please tell me if you have other suggestions.

--
Josh
diff mbox

Patch

diff --git a/configure b/configure
index 6ef2410..c24784d 100755
--- a/configure
+++ b/configure
@@ -3138,8 +3138,8 @@  ffmpeg_deps="avcodec avfilter avformat swresample"
 ffmpeg_select="aformat_filter anull_filter atrim_filter format_filter
                null_filter
                setpts_filter trim_filter"
-ffplay_deps="avcodec avformat swscale swresample sdl"
-ffplay_libs='$sdl_libs'
+ffplay_deps="avcodec avformat swscale swresample sdl2"
+ffplay_libs='$sdl2_libs'
 ffplay_select="rdft crop_filter transpose_filter hflip_filter vflip_filter rotate_filter"
 ffprobe_deps="avcodec avformat"
 ffserver_deps="avformat fork sarestart"
@@ -6665,7 +6665,7 @@  HOSTLD_O=$HOSTLD_O
 TARGET_EXEC=$target_exec $target_exec_args
 TARGET_PATH=$target_path
 TARGET_SAMPLES=${target_samples:-\$(SAMPLES)}
-CFLAGS-ffplay=$sdl_cflags
+CFLAGS-ffplay=$sdl2_cflags
 ZLIB=$($ldflags_filter -lz)
 LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD
 EXTRALIBS=$extralibs
diff --git a/ffplay.c b/ffplay.c
index adbe9cb..e64909a 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -105,6 +105,8 @@  const int program_birth_year = 2003;
 
 #define CURSOR_HIDE_DELAY 1000000
 
+#define USE_ONEPASS_SUBTITLE_RENDER 1
+
 static unsigned sws_flags = SWS_BICUBIC;
 
 typedef struct MyAVPacketList {
@@ -152,17 +154,17 @@  typedef struct Clock {
 typedef struct Frame {
     AVFrame *frame;
     AVSubtitle sub;
-    AVSubtitleRect **subrects;  /* rescaled subtitle rectangles in yuva */
     int serial;
     double pts;           /* presentation timestamp for the frame */
     double duration;      /* estimated duration of the frame */
     int64_t pos;          /* byte position of the frame in the input file */
-    SDL_Overlay *bmp;
+    SDL_Texture *bmp;
     int allocated;
-    int reallocate;
     int width;
     int height;
+    int format;
     AVRational sar;
+    int uploaded;
 } Frame;
 
 typedef struct FrameQueue {
@@ -272,6 +274,8 @@  typedef struct VideoState {
     FFTSample *rdft_data;
     int xpos;
     double last_vis_time;
+    SDL_Texture *vis_texture;
+    SDL_Texture *sub_texture;
 
     int subtitle_stream;
     AVStream *subtitle_st;
@@ -284,11 +288,8 @@  typedef struct VideoState {
     AVStream *video_st;
     PacketQueue videoq;
     double max_frame_duration;      // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
-#if !CONFIG_AVFILTER
     struct SwsContext *img_convert_ctx;
-#endif
     struct SwsContext *sub_convert_ctx;
-    SDL_Rect last_display_rect;
     int eof;
 
     char *filename;
@@ -313,8 +314,6 @@  typedef struct VideoState {
 static AVInputFormat *file_iformat;
 static const char *input_filename;
 static const char *window_title;
-static int fs_screen_width;
-static int fs_screen_height;
 static int default_width  = 640;
 static int default_height = 480;
 static int screen_width  = 0;
@@ -362,7 +361,8 @@  static AVPacket flush_pkt;
 #define FF_ALLOC_EVENT   (SDL_USEREVENT)
 #define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
 
-static SDL_Surface *screen;
+static SDL_Window *window;
+static SDL_Renderer *renderer;
 
 #if CONFIG_AVFILTER
 static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
@@ -650,12 +650,6 @@  static void decoder_destroy(Decoder *d) {
 
 static void frame_queue_unref_item(Frame *vp)
 {
-    int i;
-    for (i = 0; i < vp->sub.num_rects; i++) {
-        av_freep(&vp->subrects[i]->data[0]);
-        av_freep(&vp->subrects[i]);
-    }
-    av_freep(&vp->subrects);
     av_frame_unref(vp->frame);
     avsubtitle_free(&vp->sub);
 }
@@ -798,113 +792,47 @@  static void decoder_abort(Decoder *d, FrameQueue *fq)
     packet_queue_flush(d->queue);
 }
 
-static inline void fill_rectangle(SDL_Surface *screen,
-                                  int x, int y, int w, int h, int color, int update)
+static inline void fill_rectangle(int x, int y, int w, int h)
 {
     SDL_Rect rect;
     rect.x = x;
     rect.y = y;
     rect.w = w;
     rect.h = h;
-    SDL_FillRect(screen, &rect, color);
-    if (update && w > 0 && h > 0)
-        SDL_UpdateRect(screen, x, y, w, h);
-}
-
-/* draw only the border of a rectangle */
-static void fill_border(int xleft, int ytop, int width, int height, int x, int y, int w, int h, int color, int update)
-{
-    int w1, w2, h1, h2;
-
-    /* fill the background */
-    w1 = x;
-    if (w1 < 0)
-        w1 = 0;
-    w2 = width - (x + w);
-    if (w2 < 0)
-        w2 = 0;
-    h1 = y;
-    if (h1 < 0)
-        h1 = 0;
-    h2 = height - (y + h);
-    if (h2 < 0)
-        h2 = 0;
-    fill_rectangle(screen,
-                   xleft, ytop,
-                   w1, height,
-                   color, update);
-    fill_rectangle(screen,
-                   xleft + width - w2, ytop,
-                   w2, height,
-                   color, update);
-    fill_rectangle(screen,
-                   xleft + w1, ytop,
-                   width - w1 - w2, h1,
-                   color, update);
-    fill_rectangle(screen,
-                   xleft + w1, ytop + height - h2,
-                   width - w1 - w2, h2,
-                   color, update);
-}
-
-#define ALPHA_BLEND(a, oldp, newp, s)\
-((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
-
-
-
-#define BPP 1
-
-static void blend_subrect(uint8_t **data, int *linesize, const AVSubtitleRect *rect, int imgw, int imgh)
-{
-    int x, y, Y, U, V, A;
-    uint8_t *lum, *cb, *cr;
-    int dstx, dsty, dstw, dsth;
-    const AVSubtitleRect *src = rect;
-
-    dstw = av_clip(rect->w, 0, imgw);
-    dsth = av_clip(rect->h, 0, imgh);
-    dstx = av_clip(rect->x, 0, imgw - dstw);
-    dsty = av_clip(rect->y, 0, imgh - dsth);
-    lum = data[0] + dstx + dsty * linesize[0];
-    cb  = data[1] + dstx/2 + (dsty >> 1) * linesize[1];
-    cr  = data[2] + dstx/2 + (dsty >> 1) * linesize[2];
-
-    for (y = 0; y<dsth; y++) {
-        for (x = 0; x<dstw; x++) {
-            Y = src->data[0][x + y*src->linesize[0]];
-            A = src->data[3][x + y*src->linesize[3]];
-            lum[0] = ALPHA_BLEND(A, lum[0], Y, 0);
-            lum++;
-        }
-        lum += linesize[0] - dstw;
-    }
-
-    for (y = 0; y<dsth/2; y++) {
-        for (x = 0; x<dstw/2; x++) {
-            U = src->data[1][x + y*src->linesize[1]];
-            V = src->data[2][x + y*src->linesize[2]];
-            A = src->data[3][2*x     +  2*y   *src->linesize[3]]
-              + src->data[3][2*x + 1 +  2*y   *src->linesize[3]]
-              + src->data[3][2*x + 1 + (2*y+1)*src->linesize[3]]
-              + src->data[3][2*x     + (2*y+1)*src->linesize[3]];
-            cb[0] = ALPHA_BLEND(A>>2, cb[0], U, 0);
-            cr[0] = ALPHA_BLEND(A>>2, cr[0], V, 0);
-            cb++;
-            cr++;
-        }
-        cb += linesize[1] - dstw/2;
-        cr += linesize[2] - dstw/2;
-    }
+    if (w && h)
+        SDL_RenderFillRect(renderer, &rect);
 }
 
 static void free_picture(Frame *vp)
 {
      if (vp->bmp) {
-         SDL_FreeYUVOverlay(vp->bmp);
+         SDL_DestroyTexture(vp->bmp);
          vp->bmp = NULL;
      }
 }
 
+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 (SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
+        void *pixels;
+        int pitch;
+        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)
+            return -1;
+        if (init_texture) {
+            if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0)
+                return -1;
+            memset(pixels, 0, pitch * new_height);
+            SDL_UnlockTexture(*texture);
+        }
+    }
+    return 0;
+}
+
 static void calculate_display_rect(SDL_Rect *rect,
                                    int scr_xleft, int scr_ytop, int scr_width, int scr_height,
                                    int pic_width, int pic_height, AVRational pic_sar)
@@ -936,12 +864,44 @@  static void calculate_display_rect(SDL_Rect *rect,
     rect->h = FFMAX(height, 1);
 }
 
+static int upload_texture(SDL_Texture *tex, AVFrame *frame, struct SwsContext **img_convert_ctx) {
+    int ret = 0;
+    switch (frame->format) {
+        case AV_PIX_FMT_YUV420P:
+            ret = SDL_UpdateYUVTexture(tex, NULL, frame->data[0], frame->linesize[0],
+                                                  frame->data[1], frame->linesize[1],
+                                                  frame->data[2], frame->linesize[2]);
+            break;
+        case AV_PIX_FMT_BGRA:
+            ret = SDL_UpdateTexture(tex, NULL, frame->data[0], frame->linesize[0]);
+            break;
+        default:
+            /* This should only happen if we are not using avfilter... */
+            *img_convert_ctx = sws_getCachedContext(*img_convert_ctx,
+                frame->width, frame->height, frame->format, frame->width, frame->height,
+                AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);
+            if (*img_convert_ctx != NULL) {
+                uint8_t *pixels;
+                int pitch;
+                if (!SDL_LockTexture(tex, NULL, (void **)&pixels, &pitch)) {
+                    sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize,
+                              0, frame->height, &pixels, &pitch);
+                    SDL_UnlockTexture(tex);
+                }
+            } else {
+                av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
+                ret = -1;
+            }
+            break;
+    }
+    return ret;
+}
+
 static void video_image_display(VideoState *is)
 {
     Frame *vp;
-    Frame *sp;
+    Frame *sp = NULL;
     SDL_Rect rect;
-    int i;
 
     vp = frame_queue_peek_last(&is->pictq);
     if (vp->bmp) {
@@ -950,36 +910,71 @@  static void video_image_display(VideoState *is)
                 sp = frame_queue_peek(&is->subpq);
 
                 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
-                    uint8_t *data[4];
-                    int linesize[4];
-
-                    SDL_LockYUVOverlay (vp->bmp);
-
-                    data[0] = vp->bmp->pixels[0];
-                    data[1] = vp->bmp->pixels[2];
-                    data[2] = vp->bmp->pixels[1];
-
-                    linesize[0] = vp->bmp->pitches[0];
-                    linesize[1] = vp->bmp->pitches[2];
-                    linesize[2] = vp->bmp->pitches[1];
-
-                    for (i = 0; i < sp->sub.num_rects; i++)
-                        blend_subrect(data, linesize, sp->subrects[i],
-                                      vp->bmp->w, vp->bmp->h);
-
-                    SDL_UnlockYUVOverlay (vp->bmp);
-                }
+                    if (!sp->uploaded) {
+                        uint8_t *pixels;
+                        int pitch;
+                        int i;
+                        if (!sp->width || !sp->height) {
+                            sp->width = vp->width;
+                            sp->height = vp->height;
+                        }
+                        if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888, sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0)
+                            return;
+
+                        for (i = 0; i < sp->sub.num_rects; i++) {
+                            AVSubtitleRect *sub_rect = sp->sub.rects[i];
+
+                            sub_rect->x = av_clip(sub_rect->x, 0, sp->width );
+                            sub_rect->y = av_clip(sub_rect->y, 0, sp->height);
+                            sub_rect->w = av_clip(sub_rect->w, 0, sp->width  - sub_rect->x);
+                            sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y);
+
+                            is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
+                                sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8,
+                                sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA,
+                                0, NULL, NULL, NULL);
+                            if (!is->sub_convert_ctx) {
+                                av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
+                                return;
+                            }
+                            if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) {
+                                sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize,
+                                          0, sub_rect->h, &pixels, &pitch);
+                                SDL_UnlockTexture(is->sub_texture);
+                            }
+                        }
+                        sp->uploaded = 1;
+                    }
+                } else
+                    sp = NULL;
             }
         }
 
         calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
 
-        SDL_DisplayYUVOverlay(vp->bmp, &rect);
+        if (!vp->uploaded) {
+            if (upload_texture(vp->bmp, vp->frame, &is->img_convert_ctx) < 0)
+                return;
+            vp->uploaded = 1;
+        }
 
-        if (rect.x != is->last_display_rect.x || rect.y != is->last_display_rect.y || rect.w != is->last_display_rect.w || rect.h != is->last_display_rect.h || is->force_refresh) {
-            int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
-            fill_border(is->xleft, is->ytop, is->width, is->height, rect.x, rect.y, rect.w, rect.h, bgcolor, 1);
-            is->last_display_rect = rect;
+        SDL_RenderCopy(renderer, vp->bmp, NULL, &rect);
+        if (sp) {
+#if USE_ONEPASS_SUBTITLE_RENDER
+            SDL_RenderCopy(renderer, is->sub_texture, NULL, &rect);
+#else
+            int i;
+            double xratio = (double)rect.w / (double)sp->width;
+            double yratio = (double)rect.h / (double)sp->height;
+            for (i = 0; i < sp->sub.num_rects; i++) {
+                SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i];
+                SDL_Rect target = {.x = rect.x + sub_rect->x * xratio,
+                                   .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);
+            }
+#endif
         }
     }
 }
@@ -992,7 +987,7 @@  static inline int compute_mod(int a, int b)
 static void video_audio_display(VideoState *s)
 {
     int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
-    int ch, channels, h, h2, bgcolor, fgcolor;
+    int ch, channels, h, h2;
     int64_t time_diff;
     int rdft_bits, nb_freq;
 
@@ -1042,13 +1037,8 @@  static void video_audio_display(VideoState *s)
         i_start = s->last_i_start;
     }
 
-    bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
     if (s->show_mode == SHOW_MODE_WAVES) {
-        fill_rectangle(screen,
-                       s->xleft, s->ytop, s->width, s->height,
-                       bgcolor, 0);
-
-        fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
+        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
 
         /* total height for one channel */
         h = s->height / nb_display_channels;
@@ -1065,25 +1055,23 @@  static void video_audio_display(VideoState *s)
                 } else {
                     ys = y1;
                 }
-                fill_rectangle(screen,
-                               s->xleft + x, ys, 1, y,
-                               fgcolor, 0);
+                fill_rectangle(s->xleft + x, ys, 1, y);
                 i += channels;
                 if (i >= SAMPLE_ARRAY_SIZE)
                     i -= SAMPLE_ARRAY_SIZE;
             }
         }
 
-        fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
+        SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
 
         for (ch = 1; ch < nb_display_channels; ch++) {
             y = s->ytop + ch * h;
-            fill_rectangle(screen,
-                           s->xleft, y, s->width, 1,
-                           fgcolor, 0);
+            fill_rectangle(s->xleft, y, s->width, 1);
         }
-        SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
     } else {
+        if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
+            return;
+
         nb_display_channels= FFMIN(nb_display_channels, 2);
         if (rdft_bits != s->rdft_bits) {
             av_rdft_end(s->rdft);
@@ -1097,6 +1085,9 @@  static void video_audio_display(VideoState *s)
             s->show_mode = SHOW_MODE_WAVES;
         } else {
             FFTSample *data[2];
+            SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height};
+            uint32_t *pixels;
+            int pitch;
             for (ch = 0; ch < nb_display_channels; ch++) {
                 data[ch] = s->rdft_data + 2 * nb_freq * ch;
                 i = i_start + ch;
@@ -1111,21 +1102,23 @@  static void video_audio_display(VideoState *s)
             }
             /* Least efficient way to do this, we should of course
              * directly access it but it is more than fast enough. */
-            for (y = 0; y < s->height; y++) {
-                double w = 1 / sqrt(nb_freq);
-                int a = sqrt(w * hypot(data[0][2 * y + 0], data[0][2 * y + 1]));
-                int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1]))
-                                                    : a;
-                a = FFMIN(a, 255);
-                b = FFMIN(b, 255);
-                fgcolor = SDL_MapRGB(screen->format, a, b, (a + b) / 2);
-
-                fill_rectangle(screen,
-                            s->xpos, s->height-y, 1, 1,
-                            fgcolor, 0);
+            if (!SDL_LockTexture(s->vis_texture, &rect, (void **)&pixels, &pitch)) {
+                pitch >>= 2;
+                pixels += pitch * s->height;
+                for (y = 0; y < s->height; y++) {
+                    double w = 1 / sqrt(nb_freq);
+                    int a = sqrt(w * sqrt(data[0][2 * y + 0] * data[0][2 * y + 0] + data[0][2 * y + 1] * data[0][2 * y + 1]));
+                    int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1]))
+                                                        : a;
+                    a = FFMIN(a, 255);
+                    b = FFMIN(b, 255);
+                    pixels -= pitch;
+                    *pixels = (a << 16) + (b << 8) + ((a+b) >> 1);
+                }
+                SDL_UnlockTexture(s->vis_texture);
             }
+            SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL);
         }
-        SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
         if (!s->paused)
             s->xpos++;
         if (s->xpos >= s->width)
@@ -1215,11 +1208,13 @@  static void stream_close(VideoState *is)
     frame_queue_destory(&is->sampq);
     frame_queue_destory(&is->subpq);
     SDL_DestroyCond(is->continue_read_thread);
-#if !CONFIG_AVFILTER
     sws_freeContext(is->img_convert_ctx);
-#endif
     sws_freeContext(is->sub_convert_ctx);
     av_free(is->filename);
+    if (is->vis_texture)
+        SDL_DestroyTexture(is->vis_texture);
+    if (is->sub_texture)
+        SDL_DestroyTexture(is->sub_texture);
     av_free(is);
 }
 
@@ -1228,6 +1223,10 @@  static void do_exit(VideoState *is)
     if (is) {
         stream_close(is);
     }
+    if (renderer)
+        SDL_DestroyRenderer(renderer);
+    if (window)
+        SDL_DestroyWindow(window);
     av_lockmgr_register(NULL);
     uninit_opts();
 #if CONFIG_AVFILTER
@@ -1254,42 +1253,48 @@  static void set_default_window_size(int width, int height, AVRational sar)
     default_height = rect.h;
 }
 
-static int video_open(VideoState *is, int force_set_video_mode, Frame *vp)
+static int video_open(VideoState *is, Frame *vp)
 {
-    int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
     int w,h;
 
-    if (is_full_screen) flags |= SDL_FULLSCREEN;
-    else                flags |= SDL_RESIZABLE;
-
     if (vp && vp->width)
         set_default_window_size(vp->width, vp->height, vp->sar);
 
-    if (is_full_screen && fs_screen_width) {
-        w = fs_screen_width;
-        h = fs_screen_height;
-    } else if (!is_full_screen && screen_width) {
+    if (screen_width) {
         w = screen_width;
         h = screen_height;
     } else {
         w = default_width;
         h = default_height;
     }
-    w = FFMIN(16383, w);
-    if (screen && is->width == screen->w && screen->w == w
-       && is->height== screen->h && screen->h == h && !force_set_video_mode)
-        return 0;
-    screen = SDL_SetVideoMode(w, h, 0, flags);
-    if (!screen) {
+
+    if (!window) {
+        int flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
+        if (!window_title)
+            window_title = input_filename;
+        if (is_full_screen)
+            flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+        window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, flags);
+        SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+        if (window) {
+            SDL_RendererInfo info;
+            renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+            if (renderer) {
+                if (!SDL_GetRendererInfo(renderer, &info))
+                    av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", info.name);
+            }
+        }
+    } else {
+        SDL_SetWindowSize(window, w, h);
+    }
+
+    if (!window || !renderer) {
         av_log(NULL, AV_LOG_FATAL, "SDL: could not set video mode - exiting\n");
         do_exit(is);
     }
-    if (!window_title)
-        window_title = input_filename;
-    SDL_WM_SetCaption(window_title, window_title);
 
-    is->width  = screen->w;
-    is->height = screen->h;
+    is->width  = w;
+    is->height = h;
 
     return 0;
 }
@@ -1297,12 +1302,16 @@  static int video_open(VideoState *is, int force_set_video_mode, Frame *vp)
 /* display the current picture, if any */
 static void video_display(VideoState *is)
 {
-    if (!screen)
-        video_open(is, 0, NULL);
+    if (!window)
+        video_open(is, NULL);
+
+    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
+    SDL_RenderClear(renderer);
     if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO)
         video_audio_display(is);
     else if (is->video_st)
         video_image_display(is);
+    SDL_RenderPresent(renderer);
 }
 
 static double get_clock(Clock *c)
@@ -1587,6 +1596,20 @@  retry:
                                 || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
                                 || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
                         {
+                            if (sp->uploaded) {
+                                int i;
+                                for (i = 0; i < sp->sub.num_rects; i++) {
+                                    AVSubtitleRect *sub_rect = sp->sub.rects[i];
+                                    uint8_t *pixels;
+                                    int pitch, j;
+
+                                    if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) {
+                                        for (j = 0; j < sub_rect->h; j++, pixels += pitch)
+                                            memset(pixels, 0, sub_rect->w << 2);
+                                        SDL_UnlockTexture(is->sub_texture);
+                                    }
+                                }
+                            }
                             frame_queue_next(&is->subpq);
                         } else {
                             break;
@@ -1652,19 +1675,18 @@  display:
 static void alloc_picture(VideoState *is)
 {
     Frame *vp;
-    int64_t bufferdiff;
+    int sdl_format;
 
     vp = &is->pictq.queue[is->pictq.windex];
 
-    free_picture(vp);
+    video_open(is, vp);
 
-    video_open(is, 0, vp);
+    if (vp->format == AV_PIX_FMT_YUV420P)
+        sdl_format = SDL_PIXELFORMAT_YV12;
+    else
+        sdl_format = SDL_PIXELFORMAT_ARGB8888;
 
-    vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
-                                   SDL_YV12_OVERLAY,
-                                   screen);
-    bufferdiff = vp->bmp ? FFMAX(vp->bmp->pixels[0], vp->bmp->pixels[1]) - FFMIN(vp->bmp->pixels[0], vp->bmp->pixels[1]) : 0;
-    if (!vp->bmp || vp->bmp->pitches[0] < vp->width || bufferdiff < (int64_t)vp->height * vp->bmp->pitches[0]) {
+    if (realloc_texture(&vp->bmp, sdl_format, vp->width, vp->height, SDL_BLENDMODE_NONE, 0) < 0) {
         /* SDL allocates a buffer smaller than requested if the video
          * overlay hardware is unable to support the requested size. */
         av_log(NULL, AV_LOG_FATAL,
@@ -1680,24 +1702,6 @@  static void alloc_picture(VideoState *is)
     SDL_UnlockMutex(is->pictq.mutex);
 }
 
-static void duplicate_right_border_pixels(SDL_Overlay *bmp) {
-    int i, width, height;
-    Uint8 *p, *maxp;
-    for (i = 0; i < 3; i++) {
-        width  = bmp->w;
-        height = bmp->h;
-        if (i > 0) {
-            width  >>= 1;
-            height >>= 1;
-        }
-        if (bmp->pitches[i] > width) {
-            maxp = bmp->pixels[i] + bmp->pitches[i] * height - 1;
-            for (p = bmp->pixels[i] + width - 1; p < maxp; p += bmp->pitches[i])
-                *(p+1) = *p;
-        }
-    }
-}
-
 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
 {
     Frame *vp;
@@ -1711,17 +1715,19 @@  static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double
         return -1;
 
     vp->sar = src_frame->sample_aspect_ratio;
+    vp->uploaded = 0;
 
     /* alloc or resize hardware picture buffer */
-    if (!vp->bmp || vp->reallocate || !vp->allocated ||
+    if (!vp->bmp || !vp->allocated ||
         vp->width  != src_frame->width ||
-        vp->height != src_frame->height) {
+        vp->height != src_frame->height ||
+        vp->format != src_frame->format) {
         SDL_Event event;
 
-        vp->allocated  = 0;
-        vp->reallocate = 0;
+        vp->allocated = 0;
         vp->width = src_frame->width;
         vp->height = src_frame->height;
+        vp->format = src_frame->format;
 
         /* the allocation must be done in the main thread to avoid
            locking problems. */
@@ -1735,7 +1741,7 @@  static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double
             SDL_CondWait(is->pictq.cond, is->pictq.mutex);
         }
         /* if the queue is aborted, we have to pop the pending ALLOC event or wait for the allocation to complete */
-        if (is->videoq.abort_request && SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENTMASK(FF_ALLOC_EVENT)) != 1) {
+        if (is->videoq.abort_request && SDL_PeepEvents(&event, 1, SDL_GETEVENT, FF_ALLOC_EVENT, FF_ALLOC_EVENT) != 1) {
             while (!vp->allocated && !is->abort_request) {
                 SDL_CondWait(is->pictq.cond, is->pictq.mutex);
             }
@@ -1748,58 +1754,12 @@  static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double
 
     /* if the frame is not skipped, then display it */
     if (vp->bmp) {
-        uint8_t *data[4];
-        int linesize[4];
-
-        /* get a pointer on the bitmap */
-        SDL_LockYUVOverlay (vp->bmp);
-
-        data[0] = vp->bmp->pixels[0];
-        data[1] = vp->bmp->pixels[2];
-        data[2] = vp->bmp->pixels[1];
-
-        linesize[0] = vp->bmp->pitches[0];
-        linesize[1] = vp->bmp->pitches[2];
-        linesize[2] = vp->bmp->pitches[1];
-
-#if CONFIG_AVFILTER
-        // FIXME use direct rendering
-        av_image_copy(data, linesize, (const uint8_t **)src_frame->data, src_frame->linesize,
-                        src_frame->format, vp->width, vp->height);
-#else
-        {
-            AVDictionaryEntry *e = av_dict_get(sws_dict, "sws_flags", NULL, 0);
-            if (e) {
-                const AVClass *class = sws_get_class();
-                const AVOption    *o = av_opt_find(&class, "sws_flags", NULL, 0,
-                                                   AV_OPT_SEARCH_FAKE_OBJ);
-                int ret = av_opt_eval_flags(&class, o, e->value, &sws_flags);
-                if (ret < 0)
-                    exit(1);
-            }
-        }
-
-        is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
-            vp->width, vp->height, src_frame->format, vp->width, vp->height,
-            AV_PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
-        if (!is->img_convert_ctx) {
-            av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
-            exit(1);
-        }
-        sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
-                  0, vp->height, data, linesize);
-#endif
-        /* workaround SDL PITCH_WORKAROUND */
-        duplicate_right_border_pixels(vp->bmp);
-        /* update the bitmap content */
-        SDL_UnlockYUVOverlay(vp->bmp);
-
         vp->pts = pts;
         vp->duration = duration;
         vp->pos = pos;
         vp->serial = serial;
 
-        /* now we can update the picture count */
+        av_frame_move_ref(vp->frame, src_frame);
         frame_queue_push(&is->pictq);
     }
     return 0;
@@ -1887,7 +1847,7 @@  fail:
 
 static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
 {
-    static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };
+    static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE };
     char sws_flags_str[512] = "";
     char buffersrc_args[256];
     int ret;
@@ -1950,10 +1910,6 @@  static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
     last_filter = filt_ctx;                                                  \
 } while (0)
 
-    /* SDL YUV code is not handling odd width/height for some driver
-     * combinations, therefore we crop the picture to an even width/height. */
-    INSERT_FILT("crop", "floor(in_w/2)*2:floor(in_h/2)*2");
-
     if (autorotate) {
         double theta  = get_rotation(is->video_st);
 
@@ -2148,7 +2104,7 @@  static int audio_thread(void *arg)
 static int decoder_start(Decoder *d, int (*fn)(void *), void *arg)
 {
     packet_queue_start(d->queue);
-    d->decoder_tid = SDL_CreateThread(fn, arg);
+    d->decoder_tid = SDL_CreateThread(fn, "decoder", arg);
     if (!d->decoder_tid) {
         av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError());
         return AVERROR(ENOMEM);
@@ -2268,10 +2224,10 @@  static int video_thread(void *arg)
 static int subtitle_thread(void *arg)
 {
     VideoState *is = arg;
+    AVCodecParameters *codecpar = is->subtitle_st->codecpar;
     Frame *sp;
     int got_subtitle;
     double pts;
-    int i;
 
     for (;;) {
         if (!(sp = frame_queue_peek_writable(&is->subpq)))
@@ -2287,42 +2243,9 @@  static int subtitle_thread(void *arg)
                 pts = sp->sub.pts / (double)AV_TIME_BASE;
             sp->pts = pts;
             sp->serial = is->subdec.pkt_serial;
-            if (!(sp->subrects = av_mallocz_array(sp->sub.num_rects, sizeof(AVSubtitleRect*)))) {
-                av_log(NULL, AV_LOG_FATAL, "Cannot allocate subrects\n");
-                exit(1);
-            }
-
-            for (i = 0; i < sp->sub.num_rects; i++)
-            {
-                int in_w = sp->sub.rects[i]->w;
-                int in_h = sp->sub.rects[i]->h;
-                int subw = is->subdec.avctx->width  ? is->subdec.avctx->width  : is->viddec_width;
-                int subh = is->subdec.avctx->height ? is->subdec.avctx->height : is->viddec_height;
-                int out_w = is->viddec_width  ? in_w * is->viddec_width  / subw : in_w;
-                int out_h = is->viddec_height ? in_h * is->viddec_height / subh : in_h;
-
-                if (!(sp->subrects[i] = av_mallocz(sizeof(AVSubtitleRect))) ||
-                    av_image_alloc(sp->subrects[i]->data, sp->subrects[i]->linesize, out_w, out_h, AV_PIX_FMT_YUVA420P, 16) < 0) {
-                    av_log(NULL, AV_LOG_FATAL, "Cannot allocate subtitle data\n");
-                    exit(1);
-                }
-
-                is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
-                    in_w, in_h, AV_PIX_FMT_PAL8, out_w, out_h,
-                    AV_PIX_FMT_YUVA420P, sws_flags, NULL, NULL, NULL);
-                if (!is->sub_convert_ctx) {
-                    av_log(NULL, AV_LOG_FATAL, "Cannot initialize the sub conversion context\n");
-                    exit(1);
-                }
-                sws_scale(is->sub_convert_ctx,
-                          (void*)sp->sub.rects[i]->data, sp->sub.rects[i]->linesize,
-                          0, in_h, sp->subrects[i]->data, sp->subrects[i]->linesize);
-
-                sp->subrects[i]->w = out_w;
-                sp->subrects[i]->h = out_h;
-                sp->subrects[i]->x = sp->sub.rects[i]->x * out_w / in_w;
-                sp->subrects[i]->y = sp->sub.rects[i]->y * out_h / in_h;
-            }
+            sp->width = codecpar->width;
+            sp->height = codecpar->height;
+            sp->uploaded = 0;
 
             /* now we can update the picture count */
             frame_queue_push(&is->subpq);
@@ -3185,7 +3108,7 @@  static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
     is->audio_volume = SDL_MIX_MAXVOLUME;
     is->muted = 0;
     is->av_sync_type = av_sync_type;
-    is->read_tid     = SDL_CreateThread(read_thread, is);
+    is->read_tid     = SDL_CreateThread(read_thread, "read_thread", is);
     if (!is->read_tid) {
         av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError());
 fail:
@@ -3276,27 +3199,17 @@  static void stream_cycle_channel(VideoState *is, int codec_type)
 
 static void toggle_full_screen(VideoState *is)
 {
-#if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
-    /* OS X needs to reallocate the SDL overlays */
-    int i;
-    for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++)
-        is->pictq.queue[i].reallocate = 1;
-#endif
     is_full_screen = !is_full_screen;
-    video_open(is, 1, NULL);
+    SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
 }
 
 static void toggle_audio_display(VideoState *is)
 {
-    int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
     int next = is->show_mode;
     do {
         next = (next + 1) % SHOW_MODE_NB;
     } while (next != is->show_mode && (next == SHOW_MODE_VIDEO && !is->video_st || next != SHOW_MODE_VIDEO && !is->audio_st));
     if (is->show_mode != next) {
-        fill_rectangle(screen,
-                    is->xleft, is->ytop, is->width, is->height,
-                    bgcolor, 1);
         is->force_refresh = 1;
         is->show_mode = next;
     }
@@ -3305,7 +3218,7 @@  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_ALLEVENTS)) {
+    while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
         if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) {
             SDL_ShowCursor(0);
             cursor_hidden = 1;
@@ -3469,9 +3382,6 @@  static void event_loop(VideoState *cur_stream)
                 break;
             }
             break;
-        case SDL_VIDEOEXPOSE:
-            cur_stream->force_refresh = 1;
-            break;
         case SDL_MOUSEBUTTONDOWN:
             if (exit_on_mousedown) {
                 do_exit(cur_stream);
@@ -3527,16 +3437,18 @@  static void event_loop(VideoState *cur_stream)
                     stream_seek(cur_stream, ts, 0, 0);
                 }
             break;
-        case SDL_VIDEORESIZE:
-                screen = SDL_SetVideoMode(FFMIN(16383, event.resize.w), event.resize.h, 0,
-                                          SDL_HWSURFACE|(is_full_screen?SDL_FULLSCREEN:SDL_RESIZABLE)|SDL_ASYNCBLIT|SDL_HWACCEL);
-                if (!screen) {
-                    av_log(NULL, AV_LOG_FATAL, "Failed to set video mode\n");
-                    do_exit(cur_stream);
-                }
-                screen_width  = cur_stream->width  = screen->w;
-                screen_height = cur_stream->height = screen->h;
-                cur_stream->force_refresh = 1;
+        case SDL_WINDOWEVENT:
+            switch (event.window.event) {
+                case SDL_WINDOWEVENT_RESIZED:
+                    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;
+                    }
+                case SDL_WINDOWEVENT_EXPOSED:
+                    cur_stream->force_refresh = 1;
+            }
             break;
         case SDL_QUIT:
         case FF_QUIT_EVENT:
@@ -3773,8 +3685,6 @@  int main(int argc, char **argv)
 {
     int flags;
     VideoState *is;
-    char dummy_videodriver[] = "SDL_VIDEODRIVER=dummy";
-    char alsa_bufsize[] = "SDL_AUDIO_ALSA_SET_BUFFER_SIZE=1";
 
     init_dynload();
 
@@ -3818,31 +3728,19 @@  int main(int argc, char **argv)
         /* 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_putenv(alsa_bufsize);
+            SDL_setenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE","1", 1);
     }
     if (display_disable)
-        SDL_putenv(dummy_videodriver); /* For the event queue, we always need a video driver. */
-#if !defined(_WIN32) && !defined(__APPLE__)
-    flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
-#endif
+        flags &= ~SDL_INIT_VIDEO;
     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);
     }
 
-    if (!display_disable) {
-        const SDL_VideoInfo *vi = SDL_GetVideoInfo();
-        fs_screen_width = vi->current_w;
-        fs_screen_height = vi->current_h;
-    }
-
-    SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
     SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
     SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
 
-    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-
     if (av_lockmgr_register(lockmgr)) {
         av_log(NULL, AV_LOG_FATAL, "Could not initialize lock manager!\n");
         do_exit(NULL);