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.
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);
32 die("SDL_SetVideoMode: %s", SDL_GetError());
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
);
43 die("SDL_CreateYUVOverlay: %s", SDL_GetError());
45 this->upscale
= upscale
;
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
)
64 err
= SDL_LockYUVOverlay(overlay
);
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 */
82 /* FIXME hardcoded, but can be relaxed */
83 if ((f
->width
> overlay
->w
) || (f
->height
> overlay
->h
))
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
;
97 /* upon receiving new frame display it */
98 void View::v_on_frame(const Frame
*f
)
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
);
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])
120 bt
= f
->interlace_tb_swapped
;
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 */
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'):
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);
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);
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
++) {
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
) {
196 dst
[1] = 0x80; /* 0-level for Cb/Cr */
208 die("view: W: unsupported pixfmt 0x%08x", f
->pixfmt_4cc
);
213 SDL_UnlockYUVOverlay(overlay
);
215 /* blit overlay to its associated surface */
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
);
239 rdst
.x
= w
* (ratio_w
- ratio
) / 2;
240 rdst
.y
= h
* (ratio_h
- ratio
) / 2;
243 SDLU_DisplayYUVOverlay(overlay
, &rsrc
, &rdst
);