1 #ifndef __LIBRETRO_SDK_VIDEOBUFFER_H__
2 #define __LIBRETRO_SDK_VIDEOBUFFER_H__
3 
4 #include <retro_common_api.h>
5 
6 #include <boolean.h>
7 #include <stdint.h>
8 
9 #ifdef RARCH_INTERNAL
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13 #endif
14 
15 #ifdef HAVE_SSA
16 #include <ass/ass.h>
17 #endif
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 #include <libavutil/frame.h>
24 #include <libswscale/swscale.h>
25 
26 #ifdef __cplusplus
27 }
28 #endif
29 
30 #include <retro_miscellaneous.h>
31 
32 RETRO_BEGIN_DECLS
33 
34 #ifndef PIX_FMT_RGB32
35 #define PIX_FMT_RGB32 AV_PIX_FMT_RGB32
36 #endif
37 
38 /**
39  * video_decoder_context
40  *
41  * Context object for the sws worker threads.
42  *
43  */
44 struct video_decoder_context
45 {
46    int64_t pts;
47    struct SwsContext *sws;
48    AVFrame *source;
49 #if LIBAVUTIL_VERSION_MAJOR > 55
50    AVFrame *hw_source;
51 #endif
52    AVFrame *target;
53 #ifdef HAVE_SSA
54    ASS_Track *ass_track_active;
55 #endif
56    uint8_t *frame_buf;
57    int index;
58 };
59 typedef struct video_decoder_context video_decoder_context_t;
60 
61 /**
62  * video_buffer
63  *
64  * The video buffer is a ring buffer, that can be used as a
65  * buffer for many workers while keeping the order.
66  *
67  * It is thread safe in a sensem that it is designed to work
68  * with one work coordinator, that allocates work slots for
69  * workers threads to work on and later collect the work
70  * product in the same order, as the slots were allocated.
71  *
72  */
73 struct video_buffer;
74 typedef struct video_buffer video_buffer_t;
75 
76 /**
77  * video_buffer_create:
78  * @capacity      : Size of the buffer.
79  * @frame_size    : Size of the target frame.
80  * @width         : Width of the target frame.
81  * @height        : Height of the target frame.
82  *
83  * Create a video buffer.
84  *
85  * Returns: A video buffer.
86  */
87 video_buffer_t *video_buffer_create(size_t capacity, int frame_size, int width, int height);
88 
89 /**
90  * video_buffer_destroy:
91  * @video_buffer      : video buffer.
92  *
93  * Destroys a video buffer.
94  *
95  * Does also free the buffer allocated with video_buffer_create().
96  * User has to shut down any external worker threads that may have
97  * a reference to this video buffer.
98  *
99  **/
100 void video_buffer_destroy(video_buffer_t *video_buffer);
101 
102 /**
103  * video_buffer_clear:
104  * @video_buffer      : video buffer.
105  *
106  * Clears a video buffer.
107  *
108  **/
109 void video_buffer_clear(video_buffer_t *video_buffer);
110 
111 /**
112  * video_buffer_get_open_slot:
113  * @video_buffer     : video buffer.
114  * @context          : sws context.
115  *
116  * Returns the next open context inside the ring buffer
117  * and it's index. The status of the slot will be marked as
118  * 'in progress' until slot is marked as finished with
119  * video_buffer_finish_slot();
120  *
121  **/
122 void video_buffer_get_open_slot(video_buffer_t *video_buffer, video_decoder_context_t **context);
123 
124 /**
125  * video_buffer_return_open_slot:
126  * @video_buffer     : video buffer.
127  * @context          : sws context.
128  *
129  * Marks the given sws context that is "in progress" as "open" again.
130  *
131  **/
132 void video_buffer_return_open_slot(video_buffer_t *video_buffer, video_decoder_context_t *context);
133 
134 /**
135  * video_buffer_open_slot:
136  * @video_buffer     : video buffer.
137  * @context          : sws context.
138  *
139  * Sets the status of the given context from "finished" to "open".
140  * The slot is then available for producers to claim again with video_buffer_get_open_slot().
141  **/
142 void video_buffer_open_slot(video_buffer_t *video_buffer, video_decoder_context_t *context);
143 
144 /**
145  * video_buffer_get_finished_slot:
146  * @video_buffer     : video buffer.
147  * @context          : sws context.
148  *
149  * Returns a reference for the next context inside
150  * the ring buffer. User needs to use video_buffer_open_slot()
151  * to open the slot in the ringbuffer for the next
152  * work assignment. User is free to re-allocate or
153  * re-use the context.
154  */
155 void video_buffer_get_finished_slot(video_buffer_t *video_buffer, video_decoder_context_t **context);
156 
157 /**
158  * video_buffer_finish_slot:
159  * @video_buffer     : video buffer.
160  * @context          : sws context.
161  *
162  * Sets the status of the given context from "in progress" to "finished".
163  * This is normally done by a producer. User can then retrieve the finished work
164  * context by calling video_buffer_get_finished_slot().
165  */
166 void video_buffer_finish_slot(video_buffer_t *video_buffer, video_decoder_context_t *context);
167 
168 /**
169  * video_buffer_wait_for_open_slot:
170  * @video_buffer      : video buffer.
171  *
172  * Blocks until open slot is available.
173  *
174  * Returns true if the buffer has a open slot available.
175  */
176 bool video_buffer_wait_for_open_slot(video_buffer_t *video_buffer);
177 
178 /**
179  * video_buffer_wait_for_finished_slot:
180  * @video_buffer      : video buffer.
181  *
182  * Blocks until finished slot is available.
183  *
184  * Returns true if the buffers next slot is finished and a
185  * context available.
186  */
187 bool video_buffer_wait_for_finished_slot(video_buffer_t *video_buffer);
188 
189 /**
190  * bool video_buffer_has_open_slot(video_buffer_t *video_buffer)
191 :
192  * @video_buffer      : video buffer.
193  *
194  * Returns true if the buffer has a open slot available.
195  */
196 bool video_buffer_has_open_slot(video_buffer_t *video_buffer);
197 
198 /**
199  * video_buffer_has_finished_slot:
200  * @video_buffer      : video buffer.
201  *
202  * Returns true if the buffers next slot is finished and a
203  * context available.
204  */
205 bool video_buffer_has_finished_slot(video_buffer_t *video_buffer);
206 
207 RETRO_END_DECLS
208 
209 #endif
210