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