This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_sysyuv.cc
322 lines (280 loc) · 9.59 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2006 Sam Lantinga
4
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) any later version.
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
20
21
Sam Lantinga
slouken@libsdl.org
*/
22
#include "SDL_config.h"
23
24
25
26
27
/* This is the BeOS version of SDL YUV video overlays */
#include "SDL_video.h"
#include "SDL_sysyuv.h"
28
#include "../SDL_yuvfuncs.h"
29
30
31
extern "C"
{
32
33
/* The functions used to manipulate software video overlays */
34
35
36
37
38
39
40
static struct private_yuvhwfuncs be_yuvfuncs = {
BE_LockYUVOverlay,
BE_UnlockYUVOverlay,
BE_DisplayYUVOverlay,
BE_FreeYUVOverlay
};
41
BBitmap *BE_GetOverlayBitmap(BRect bounds, color_space cs)
42
43
{
BBitmap *bbitmap;
44
45
bbitmap = new BBitmap(bounds, B_BITMAP_WILL_OVERLAY, cs);
if (!bbitmap || bbitmap->InitCheck() != B_OK) {
46
47
48
49
delete bbitmap;
return 0;
}
overlay_restrictions r;
50
51
52
bbitmap->GetOverlayRestrictions(&r);
uint32 width = bounds.IntegerWidth() + 1;
uint32 height = bounds.IntegerHeight() + 1;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
uint32 width_padding = 0;
uint32 height_padding = 0;
if ((r.source.horizontal_alignment != 0) ||
(r.source.vertical_alignment != 0)) {
delete bbitmap;
return 0;
}
if (r.source.width_alignment != 0) {
uint32 aligned_width = r.source.width_alignment + 1;
if (width % aligned_width > 0) {
width_padding = aligned_width - width % aligned_width;
}
}
if (r.source.height_alignment != 0) {
uint32 aligned_height = r.source.height_alignment + 1;
if (height % aligned_height > 0) {
69
70
71
fprintf(stderr, "GetOverlayBitmap failed height alignment\n");
fprintf(stderr, "- height = %lu, aligned_height = %lu\n",
height, aligned_height);
72
73
74
75
76
77
78
delete bbitmap;
return 0;
}
}
if ((r.source.min_width > width) ||
(r.source.min_height > height) ||
(r.source.max_width < width) || (r.source.max_height < height)) {
79
fprintf(stderr, "GetOverlayBitmap failed bounds tests\n");
80
81
82
83
84
delete bbitmap;
return 0;
}
if ((width_padding != 0) || (height_padding != 0)) {
delete bbitmap;
85
86
87
88
89
90
bounds.Set(bounds.left, bounds.top,
bounds.right + width_padding,
bounds.bottom + height_padding);
bbitmap = new BBitmap(bounds, B_BITMAP_WILL_OVERLAY, cs);
if (!bbitmap || bbitmap->InitCheck() != B_OK) {
fprintf(stderr, "GetOverlayBitmap failed late\n");
91
92
93
94
95
96
delete bbitmap;
return 0;
}
}
return bbitmap;
}
97
98
99
// See <GraphicsDefs.h> [btw: Cb=U, Cr=V]
// See also http://www.fourcc.org/indexyuv.htm
100
enum color_space convert_color_space(Uint32 format)
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
{
switch (format) {
case SDL_YV12_OVERLAY:
return B_YUV9;
case SDL_IYUV_OVERLAY:
return B_YUV12;
case SDL_YUY2_OVERLAY:
return B_YCbCr422;
case SDL_UYVY_OVERLAY:
return B_YUV422;
case SDL_YVYU_OVERLAY: // not supported on beos?
return B_NO_COLOR_SPACE;
default:
return B_NO_COLOR_SPACE;
}
}
117
118
// See SDL_video.h
119
int count_planes(Uint32 format)
120
{
121
122
123
124
125
126
127
128
129
130
131
switch (format) {
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
return 3;
case SDL_YUY2_OVERLAY:
case SDL_UYVY_OVERLAY:
case SDL_YVYU_OVERLAY:
return 1;
default:
return 0;
}
132
133
}
134
135
SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height,
Uint32 format, SDL_Surface * display)
136
137
138
139
140
141
142
{
SDL_Overlay *overlay;
struct private_yuvhwdata *hwdata;
BBitmap *bbitmap;
int planes;
BRect bounds;
color_space cs;
143
144
/* find the appropriate BeOS colorspace descriptor */
145
cs = convert_color_space(format);
146
147
148
if (cs == B_NO_COLOR_SPACE) {
return NULL;
}
149
150
/* count planes */
151
planes = count_planes(format);
152
153
154
155
156
157
158
if (planes == 0) {
return NULL;
}
/* TODO: figure out planar modes, if anyone cares */
if (planes == 3) {
return NULL;
}
159
160
/* Create the overlay structure */
161
overlay = (SDL_Overlay *) SDL_calloc(1, sizeof(SDL_Overlay));
162
163
if (overlay == NULL) {
164
SDL_OutOfMemory();
165
166
167
168
169
170
171
172
173
174
175
176
177
178
return NULL;
}
/* Fill in the basic members */
overlay->format = format;
overlay->w = width;
overlay->h = height;
overlay->hwdata = NULL;
/* Set up the YUV surface function structure */
overlay->hwfuncs = &be_yuvfuncs;
/* Create the pixel data and lookup tables */
hwdata =
179
180
181
(struct private_yuvhwdata *) SDL_calloc(1,
sizeof(struct
private_yuvhwdata));
182
183
if (hwdata == NULL) {
184
185
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
return NULL;
}
overlay->hwdata = hwdata;
overlay->hwdata->display = display;
overlay->hwdata->bview = NULL;
overlay->hwdata->bbitmap = NULL;
overlay->hwdata->locked = 0;
/* Create the BBitmap framebuffer */
bounds.top = 0;
bounds.left = 0;
bounds.right = width - 1;
bounds.bottom = height - 1;
BView *bview =
202
new BView(bounds, "overlay", B_FOLLOW_NONE, B_WILL_DRAW);
203
if (!bview) {
204
205
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
206
207
208
209
return NULL;
}
overlay->hwdata->bview = bview;
overlay->hwdata->first_display = true;
210
bview->Hide();
211
212
bbitmap = BE_GetOverlayBitmap(bounds, cs);
213
214
if (!bbitmap) {
overlay->hwdata->bbitmap = NULL;
215
SDL_FreeYUVOverlay(overlay);
216
217
218
219
220
221
return NULL;
}
overlay->hwdata->bbitmap = bbitmap;
overlay->planes = planes;
overlay->pitches =
222
(Uint16 *) SDL_calloc(overlay->planes, sizeof(Uint16));
223
overlay->pixels =
224
(Uint8 **) SDL_calloc(overlay->planes, sizeof(Uint8 *));
225
if (!overlay->pitches || !overlay->pixels) {
226
227
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
228
229
return (NULL);
}
230
231
232
overlay->pitches[0] = bbitmap->BytesPerRow();
overlay->pixels[0] = (Uint8 *) bbitmap->Bits();
233
234
overlay->hw_overlay = 1;
235
236
if (SDL_Win->LockWithTimeout(1000000) != B_OK) {
SDL_FreeYUVOverlay(overlay);
237
238
return (NULL);
}
239
240
BView *view = SDL_Win->View();
view->AddChild(bview);
241
rgb_color key;
242
243
244
245
246
247
248
bview->SetViewOverlay(bbitmap, bounds, bview->Bounds(), &key,
B_FOLLOW_ALL,
B_OVERLAY_FILTER_HORIZONTAL |
B_OVERLAY_FILTER_VERTICAL);
bview->SetViewColor(key);
bview->Flush();
SDL_Win->Unlock();
249
250
251
252
current_overlay = overlay;
return overlay;
253
}
254
255
int BE_LockYUVOverlay(_THIS, SDL_Overlay * overlay)
256
{
257
258
259
260
261
if (overlay == NULL) {
return 0;
}
overlay->hwdata->locked = 1;
262
263
264
return 0;
}
265
void BE_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay)
266
{
267
268
269
if (overlay == NULL) {
return;
}
270
271
272
overlay->hwdata->locked = 0;
}
273
274
275
int BE_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
SDL_Rect * dst)
276
{
277
if ((overlay == NULL) || (overlay->hwdata == NULL)
278
|| (overlay->hwdata->bview == NULL) || (SDL_Win->View() == NULL)) {
279
280
return -1;
}
281
if (SDL_Win->LockWithTimeout(50000) != B_OK) {
282
283
284
return 0;
}
BView *bview = overlay->hwdata->bview;
285
if (SDL_Win->IsFullScreen()) {
286
int left, top;
287
288
SDL_Win->GetXYOffset(left, top);
bview->MoveTo(left + dst->x, top + dst->y);
289
} else {
290
bview->MoveTo(dst->x, dst->y);
291
}
292
293
bview->ResizeTo(dst->w, dst->h);
bview->Flush();
294
if (overlay->hwdata->first_display) {
295
bview->Show();
296
297
overlay->hwdata->first_display = false;
}
298
SDL_Win->Unlock();
299
300
301
302
return 0;
}
303
void BE_FreeYUVOverlay(_THIS, SDL_Overlay * overlay)
304
{
305
306
307
308
309
310
311
if (overlay == NULL) {
return;
}
if (overlay->hwdata == NULL) {
return;
}
312
313
current_overlay = NULL;
314
315
316
delete overlay->hwdata->bbitmap;
317
SDL_free(overlay->hwdata);
318
}
319
320
}; // extern "C"
321
322
/* vi: set ts=4 sw=4 expandtab: */