view: Check return value of SDL_LockYUVOverlay()
[rawv.git] / view.cpp
blobb93370348dca8c9515fedd00181c237f10972d37
1 /* view submodule for rawv
2 * Copyright (C) 2010,2011 Kirill Smelkov <kirr@navytux.spb.ru>
3 * Copyright (C) 2011 Marine Bridge and Navigation Systems (http://mns.spb.ru/)
5 * This library is free software: you can Use, Study, Modify and Redistribute
6 * it under the terms of the GNU Lesser General Public License version 2.1, or
7 * any later version. This library is distributed WITHOUT ANY WARRANTY. See
8 * COPYING.LIB file for full License terms.
9 */
11 #include "rawv.h"
13 #include <stdio.h>
14 #include <SDL.h>
15 #include "sdlu.h"
17 using std::min;
19 namespace rawv {
21 /******** View ********/
23 View::View(int width, int height, bool upscale, const char *title)
25 fprintf(stderr, "Viewing w: %i h: %i upscale: %i\n", width, height, upscale);
27 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
28 die("SDL_INIT_VIDEO: %s", SDL_GetError());
30 display = SDL_SetVideoMode(width, height, /*bpp=*/0, /*flags=*/0UL);
31 if (!display)
32 die("SDL_SetVideoMode: %s", SDL_GetError());
34 if (title)
35 SDL_WM_SetCaption(title, NULL);
37 overlay = SDL_CreateYUVOverlay(width, height, SDL_YUY2_OVERLAY, display);
38 if (!overlay)
39 die("SDL_CreateYUVOverlay: %s", SDL_GetError());
41 this->upscale = upscale;
45 View::~View()
47 SDL_FreeYUVOverlay(overlay);
48 SDL_QuitSubSystem(SDL_INIT_VIDEO); // XXX needed at all?
52 /* non-forgiving helper for SDL_LockYUVOverlay();
54 * NOTE SDL_UnlockYUVOverlay returns void, so no need to check.
56 static void SDLU_XLockYUVOverlay(SDL_Overlay *overlay)
58 int err;
60 err = SDL_LockYUVOverlay(overlay);
61 if (err)
62 die("view: SDL_LockYUVOverlay() failed");
66 void View::display_frame(const Frame *f)
68 #if 0
69 double tstamp = buf->timestamp.tv_sec + 1E-6*buf->timestamp.tv_usec;
71 fprintf(stderr, "buf[%i] timestamp: %.7lf sequence: %u\n", buf->index, tstamp, buf->sequence);
72 #endif
74 SDL_Rect rsrc, rdst;
75 int w, h;
76 int i, j, istart;
77 int bt;
80 w = min(f->width, overlay->w);
81 h = min(f->height, overlay->h);
83 bt = f->interlace_tb_swapped;
84 if (bt)
85 /* bt=+1 -> h=2k
86 * bt=-1 -> h=2k-1
88 h = (h & ~1U) - int((1-bt)/2);
90 /* for bt=-1, we have to start from 1, for bt=0,+1 - from 0'th line */
91 istart = 0;
92 if (bt==-1) {
93 istart = 1;
94 bt = -bt; /* account for i 0->1 move */
98 SDLU_XLockYUVOverlay(overlay);
100 switch (f->pixfmt_4cc) {
101 case MKTAG32('Y','U','Y','V'):
102 case MKTAG32('Y','U','Y','2'):
104 if (
105 overlay->pitches[0] == f->bytesperline &&
106 overlay->w == f->width && w == f->width &&
107 overlay->h == f->height && h == f->height &&
111 /* special case for w=w, h=h, fmt=fmt, stride=stride, lines=01234... -- one large memcpy */
112 memcpy(overlay->pixels[0], f->start, h*w * /*pixsize_yuy2*/ 2);
114 else {
115 for (i=istart; i<h; ++i) {
116 memcpy(overlay->pixels[0] + (i+bt)*overlay->pitches[0],
117 f->start + i*f->bytesperline,
118 w * /*pixsize_yuy2*/ 2);
120 bt = -bt;
124 break;
126 case MKTAG32('U','Y','V','Y'):
128 /* TODO optimize me through mmx */
129 for (i=istart; i<h; ++i) {
130 __u8 *dst = overlay->pixels[0] + (i+bt)*overlay->pitches[0];
131 __u8 *src = f->start + i*f->bytesperline;
133 for (j=0; j<w/2; j++) {
134 /* YUYV <- UYVY */
135 dst[0] = src[1];
136 dst[1] = src[0];
137 dst[2] = src[3];
138 dst[3] = src[2];
140 dst += 4;
141 src += 4;
144 bt = -bt;
147 break;
149 case MKTAG32('Y','8','0','0'):
150 case MKTAG32('Y','8',' ',' '):
151 case MKTAG32('G','R','E','Y'):
153 for (i=istart; i<h; ++i) {
154 __u8 *dst = overlay->pixels[0] + (i+bt)*overlay->pitches[0];
155 __u8 *src = f->start + i*f->bytesperline;
157 for (j=0; j<w; ++j) {
158 dst[0] = src[0];
159 dst[1] = 0x80; /* 0-level for Cb/Cr */
161 dst += 2;
162 src += 1;
165 bt = -bt;
168 break;
170 default:
171 die("view: W: unsupported pixfmt 0x%08x", f->pixfmt_4cc);
176 SDL_UnlockYUVOverlay(overlay);
178 /* blit overlay to its associated surface */
179 rsrc.x = 0;
180 rsrc.y = 0;
181 rsrc.w = w;
182 rsrc.h = h;
184 rdst.x = 0;
185 rdst.y = 0;
187 if (!upscale) {
188 rdst.w = w;
189 rdst.h = h;
191 else {
192 double ratio_w = (double)overlay->w / (w ? w : 1);
193 double ratio_h = (double)overlay->h / (h ? h : 1);
195 /* keep aspect ratio */
196 double ratio = min(ratio_w, ratio_h);
198 rdst.w = w * ratio;
199 rdst.h = h * ratio;
201 /* center picture */
202 rdst.x = w * (ratio_w - ratio) / 2;
203 rdst.y = h * (ratio_h - ratio) / 2;
206 SDLU_DisplayYUVOverlay(overlay, &rsrc, &rdst);
210 void View::__display_frame(const Frame *f, void *self)
212 ((View *)self)->display_frame(f);
216 } // rawv::