• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2020, VideoLAN and dav1d authors
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *    list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions and the following disclaimer in the documentation
13  *    and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "dp_renderer.h"
28 
29 #include <assert.h>
30 
31 /**
32  * Renderer context for SDL
33  */
34 typedef struct renderer_priv_ctx
35 {
36     // SDL window
37     SDL_Window *win;
38     // SDL renderer
39     SDL_Renderer *renderer;
40     // Lock protecting access to the texture
41     SDL_mutex *lock;
42     // Texture to render
43     SDL_Texture *tex;
44 } Dav1dPlayRendererPrivateContext;
45 
sdl_renderer_create(void)46 static void *sdl_renderer_create(void)
47 {
48     SDL_Window *win = dp_create_sdl_window(0);
49     if (win == NULL)
50         return NULL;
51 
52     // Alloc
53     Dav1dPlayRendererPrivateContext *rd_priv_ctx = malloc(sizeof(Dav1dPlayRendererPrivateContext));
54     if (rd_priv_ctx == NULL) {
55         return NULL;
56     }
57     rd_priv_ctx->win = win;
58 
59     // Create renderer
60     rd_priv_ctx->renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
61     // Set scale quality
62     SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
63 
64     // Create Mutex
65     rd_priv_ctx->lock = SDL_CreateMutex();
66     if (rd_priv_ctx->lock == NULL) {
67         fprintf(stderr, "SDL_CreateMutex failed: %s\n", SDL_GetError());
68         free(rd_priv_ctx);
69         return NULL;
70     }
71 
72     rd_priv_ctx->tex = NULL;
73 
74     return rd_priv_ctx;
75 }
76 
sdl_renderer_destroy(void * cookie)77 static void sdl_renderer_destroy(void *cookie)
78 {
79     Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
80     assert(rd_priv_ctx != NULL);
81 
82     SDL_DestroyRenderer(rd_priv_ctx->renderer);
83     SDL_DestroyMutex(rd_priv_ctx->lock);
84     free(rd_priv_ctx);
85 }
86 
sdl_render(void * cookie,const Dav1dPlaySettings * settings)87 static void sdl_render(void *cookie, const Dav1dPlaySettings *settings)
88 {
89     Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
90     assert(rd_priv_ctx != NULL);
91 
92     SDL_LockMutex(rd_priv_ctx->lock);
93 
94     if (rd_priv_ctx->tex == NULL) {
95         SDL_UnlockMutex(rd_priv_ctx->lock);
96         return;
97     }
98 
99     // Display the frame
100     SDL_RenderClear(rd_priv_ctx->renderer);
101     SDL_RenderCopy(rd_priv_ctx->renderer, rd_priv_ctx->tex, NULL, NULL);
102     SDL_RenderPresent(rd_priv_ctx->renderer);
103 
104     SDL_UnlockMutex(rd_priv_ctx->lock);
105 }
106 
sdl_update_texture(void * cookie,Dav1dPicture * dav1d_pic,const Dav1dPlaySettings * settings)107 static int sdl_update_texture(void *cookie, Dav1dPicture *dav1d_pic,
108                               const Dav1dPlaySettings *settings)
109 {
110     Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
111     assert(rd_priv_ctx != NULL);
112 
113     SDL_LockMutex(rd_priv_ctx->lock);
114 
115     if (dav1d_pic == NULL) {
116         rd_priv_ctx->tex = NULL;
117         SDL_UnlockMutex(rd_priv_ctx->lock);
118         return 0;
119     }
120 
121     int width = dav1d_pic->p.w;
122     int height = dav1d_pic->p.h;
123     int tex_w = width;
124     int tex_h = height;
125 
126     enum Dav1dPixelLayout dav1d_layout = dav1d_pic->p.layout;
127 
128     if (DAV1D_PIXEL_LAYOUT_I420 != dav1d_layout || dav1d_pic->p.bpc != 8) {
129         fprintf(stderr, "Unsupported pixel format, only 8bit 420 supported so far.\n");
130         exit(50);
131     }
132 
133     SDL_Texture *texture = rd_priv_ctx->tex;
134     if (texture != NULL) {
135         SDL_QueryTexture(texture, NULL, NULL, &tex_w, &tex_h);
136         if (tex_w != width || tex_h != height) {
137             SDL_DestroyTexture(texture);
138             texture = NULL;
139         }
140     }
141 
142     if (texture == NULL) {
143         texture = SDL_CreateTexture(rd_priv_ctx->renderer, SDL_PIXELFORMAT_IYUV,
144             SDL_TEXTUREACCESS_STREAMING, width, height);
145     }
146 
147     SDL_UpdateYUVTexture(texture, NULL,
148         dav1d_pic->data[0], (int)dav1d_pic->stride[0], // Y
149         dav1d_pic->data[1], (int)dav1d_pic->stride[1], // U
150         dav1d_pic->data[2], (int)dav1d_pic->stride[1]  // V
151         );
152 
153     rd_priv_ctx->tex = texture;
154     SDL_UnlockMutex(rd_priv_ctx->lock);
155     return 0;
156 }
157 
158 const Dav1dPlayRenderInfo rdr_sdl = {
159     .name = "sdl",
160     .create_renderer = sdl_renderer_create,
161     .destroy_renderer = sdl_renderer_destroy,
162     .render = sdl_render,
163     .update_frame = sdl_update_texture
164 };
165