Cosmetics
[rawv.git] / view.cpp
blobc21b09c691771b8f6fd2bc60104370a0deeb016d
1 /* view submodule for rawv
2 * Copyright (C) 2010,2011,2012 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);
38 * FIXME pixfmt & w,h hardcoded, but better to adapt to incoming stream in
39 * ->v_query_framebuf()
41 overlay = SDL_CreateYUVOverlay(width, height, SDL_YUY2_OVERLAY, display);
42 if (!overlay)
43 die("SDL_CreateYUVOverlay: %s", SDL_GetError());
45 this->upscale = upscale;
49 View::~View()
51 SDL_FreeYUVOverlay(overlay);
52 SDL_QuitSubSystem(SDL_INIT_VIDEO); // XXX needed at all?
56 /* non-forgiving helper for SDL_LockYUVOverlay();
58 * NOTE SDL_UnlockYUVOverlay returns void, so no need to check.
60 static void SDLU_XLockYUVOverlay(SDL_Overlay *overlay)
62 int err;
64 err = SDL_LockYUVOverlay(overlay);
65 if (err)
66 die("view: SDL_LockYUVOverlay() failed");
70 bool View::v_query_framebuf(Frame *f)
72 switch (f->pixfmt_4cc) {
73 case MKTAG32('Y','U','Y','V'):
74 case MKTAG32('Y','U','Y','2'):
75 /* FIXME YUYV only because of hardcoded SDL_YUY2_OVERLAY */
76 break;
78 default:
79 return false;
82 /* FIXME hardcoded, but can be relaxed */
83 if ((f->width > overlay->w) || (f->height > overlay->h))
84 return false;
86 /* otherwise ok - we can provide framebuf for queried frame-metric */
87 SDLU_XLockYUVOverlay(overlay);
89 f->start = overlay->pixels[0];
90 f->bytesperline = overlay->pitches[0];
91 f->length = overlay->pitches[0] * overlay->h;
93 return true;
97 /* upon receiving new frame display it */
98 void View::v_on_frame(const Frame *f)
100 #if 0
101 double tstamp = buf->timestamp.tv_sec + 1E-6*buf->timestamp.tv_usec;
103 fprintf(stderr, "buf[%i] timestamp: %.7lf sequence: %u\n", buf->index, tstamp, buf->sequence);
104 #endif
106 SDL_Rect rsrc, rdst;
107 int w, h;
108 int i, j, istart;
109 int bt;
112 w = min(f->width, overlay->w);
113 h = min(f->height, overlay->h);
115 /* no need to copy pixels if we provided this framebuf */
116 if (f->start == overlay->pixels[0])
117 goto display;
120 bt = f->interlace_tb_swapped;
121 if (bt)
122 /* bt=+1 -> h=2k
123 * bt=-1 -> h=2k-1
125 h = (h & ~1U) - int((1-bt)/2);
127 /* for bt=-1, we have to start from 1, for bt=0,+1 - from 0'th line */
128 istart = 0;
129 if (bt==-1) {
130 istart = 1;
131 bt = -bt; /* account for i 0->1 move */
135 SDLU_XLockYUVOverlay(overlay);
137 switch (f->pixfmt_4cc) {
138 case MKTAG32('Y','U','Y','V'):
139 case MKTAG32('Y','U','Y','2'):
141 if (
142 overlay->pitches[0] == f->bytesperline &&
143 overlay->w == f->width && w == f->width &&
144 overlay->h == f->height && h == f->height &&
148 /* special case for w=w, h=h, fmt=fmt, stride=stride, lines=01234... -- one large memcpy */
149 memcpy(overlay->pixels[0], f->start, h*w * /*pixsize_yuy2*/ 2);
151 else {
152 for (i=istart; i<h; ++i) {
153 memcpy(overlay->pixels[0] + (i+bt)*overlay->pitches[0],
154 f->start + i*f->bytesperline,
155 w * /*pixsize_yuy2*/ 2);
157 bt = -bt;
161 break;
163 case MKTAG32('U','Y','V','Y'):
165 /* TODO optimize me through mmx */
166 for (i=istart; i<h; ++i) {
167 __u8 *dst = overlay->pixels[0] + (i+bt)*overlay->pitches[0];
168 __u8 *src = f->start + i*f->bytesperline;
170 for (j=0; j<w/2; j++) {
171 /* YUYV <- UYVY */
172 dst[0] = src[1];
173 dst[1] = src[0];
174 dst[2] = src[3];
175 dst[3] = src[2];
177 dst += 4;
178 src += 4;
181 bt = -bt;
184 break;
186 case MKTAG32('Y','8','0','0'):
187 case MKTAG32('Y','8',' ',' '):
188 case MKTAG32('G','R','E','Y'):
190 for (i=istart; i<h; ++i) {
191 __u8 *dst = overlay->pixels[0] + (i+bt)*overlay->pitches[0];
192 __u8 *src = f->start + i*f->bytesperline;
194 for (j=0; j<w; ++j) {
195 dst[0] = src[0];
196 dst[1] = 0x80; /* 0-level for Cb/Cr */
198 dst += 2;
199 src += 1;
202 bt = -bt;
205 break;
207 default:
208 die("view: W: unsupported pixfmt 0x%08x", f->pixfmt_4cc);
212 display:
213 SDL_UnlockYUVOverlay(overlay);
215 /* blit overlay to its associated surface */
216 rsrc.x = 0;
217 rsrc.y = 0;
218 rsrc.w = w;
219 rsrc.h = h;
221 rdst.x = 0;
222 rdst.y = 0;
224 if (!upscale) {
225 rdst.w = w;
226 rdst.h = h;
228 else {
229 double ratio_w = (double)overlay->w / (w ? w : 1);
230 double ratio_h = (double)overlay->h / (h ? h : 1);
232 /* keep aspect ratio */
233 double ratio = min(ratio_w, ratio_h);
235 rdst.w = w * ratio;
236 rdst.h = h * ratio;
238 /* center picture */
239 rdst.x = w * (ratio_w - ratio) / 2;
240 rdst.y = h * (ratio_h - ratio) / 2;
243 SDLU_DisplayYUVOverlay(overlay, &rsrc, &rdst);
247 } // rawv::