1 /* ***** BEGIN LICENSE BLOCK *****
5 * Copyright (c) 2008 BBC Research
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * ***** END LICENSE BLOCK ***** */
27 #include "videoData.h"
39 VideoData::VideoData()
41 //make a bogus 1x1 4:4:4 8 bit image
48 void VideoData::resize(int w
, int h
, DataFmt f
)
50 if (w
!= Ywidth
|| h
!= Yheight
|| f
!= diskFormat
) {
56 /* Some type conversions don't need to reallocate but
57 * do change the render format, so there is diskformat
58 * space avaliable but only renderformat used. */
62 void VideoData::allocate(int w
, int h
, DataFmt f
)
70 case V8P4
: //8 bit 444 planar
73 YdataSize
= Ywidth
* Yheight
;
74 UdataSize
= YdataSize
;
75 VdataSize
= YdataSize
;
78 case V16P4
: //16 bit 444 planar
81 YdataSize
= Ywidth
* Yheight
* 2;
82 UdataSize
= YdataSize
;
83 VdataSize
= YdataSize
;
86 case V8P2
: //8 bit 422 planar
89 YdataSize
= Ywidth
* Yheight
;
90 UdataSize
= YdataSize
/ 2;
91 VdataSize
= YdataSize
/ 2;
94 case V16P2
: //16 bit 422 planar
97 YdataSize
= Ywidth
* Yheight
* 2;
98 UdataSize
= YdataSize
/ 2;
99 VdataSize
= YdataSize
/ 2;
102 case V16P0
: //16 bit 420
104 Cheight
= Yheight
/ 2;
105 YdataSize
= Ywidth
* Yheight
* 2;
106 UdataSize
= YdataSize
/ 4;
107 VdataSize
= YdataSize
/ 4;
110 case V8P0
: //8 bit 420, YUV
111 case YV12
: //8 bit 420, YVU
113 Cheight
= Yheight
/ 2;
114 YdataSize
= Ywidth
* Yheight
;
115 UdataSize
= YdataSize
/ 4;
116 VdataSize
= YdataSize
/ 4;
122 YdataSize
= Ywidth
* Yheight
* 2;
130 YdataSize
= Ywidth
* Yheight
* 4;
136 //3 10 bit components packed into 4 bytes
139 YdataSize
= (Ywidth
* Yheight
* 2 * 4) / 3;
149 //total size of the frame
150 dataSize
= YdataSize
+ UdataSize
+ VdataSize
;
152 //get some nicely page aligned memory
153 data
= (unsigned char *)valloc(dataSize
);
156 glMinMaxFilter
= GL_LINEAR
; //linear interpolation
159 renderFormat
= diskFormat
;
161 switch (diskFormat
) {
169 glYTextureWidth
= Ywidth
;
170 glInternalFormat
= GL_LUMINANCE
;
171 glFormat
= GL_LUMINANCE
;
172 glType
= GL_UNSIGNED_BYTE
;
174 Udata
= Ydata
+ YdataSize
;
175 Vdata
= Udata
+ UdataSize
;
181 glYTextureWidth
= Ywidth
;
182 glInternalFormat
= GL_LUMINANCE
;
183 glFormat
= GL_LUMINANCE
;
184 glType
= GL_UNSIGNED_BYTE
;
185 //U&V components are exchanged
186 Vdata
= Ydata
+ (Ywidth
* Yheight
);
187 Udata
= Vdata
+ ((Ywidth
* Yheight
) / 4);
192 glYTextureWidth
= Ywidth
/ 2; //2 Y samples per RGBA quad
193 glInternalFormat
= GL_RGBA
;
195 glType
= GL_UNSIGNED_BYTE
;
198 case V210
: //gets converted to UYVY
199 glYTextureWidth
= Ywidth
/ 2; //2 Y samples per RGBA quad
200 glInternalFormat
= GL_RGBA
;
202 glType
= GL_UNSIGNED_BYTE
;
206 glYTextureWidth
= Ywidth
/ 2; //2 Y samples per RGBA quad
207 glInternalFormat
= GL_RGBA
;
209 glType
= GL_UNSIGNED_SHORT
;
218 VideoData::~VideoData()
227 typedef unsigned int uint_t
;
228 typedef unsigned char uint8_t;
230 //read the first 10 bit sample from the least significant bits of the 4 bytes pointed to by 'data'
231 inline uint_t
readv210sample_pos2of3(uint8_t* data
)
233 const uint_t lsb
= (data
[2] & 0xf0) >> 4;
234 const uint_t msb
= (data
[3] & 0x3f) << 4;
238 //read the second 10 bit sample from the middle bits of the 4 bytes pointed to by 'data'
239 inline uint_t
readv210sample_pos1of3(uint8_t* data
)
241 const uint_t lsb
= (data
[1] & 0xfc) >> 2;
242 const uint_t msb
= (data
[2] & 0x0f) << 6;
246 //read the third 10 bit sample from the more significant bits of the 4 bytes pointed to by 'data'
247 inline uint_t
readv210sample_pos0of3(uint8_t* data
)
249 const uint_t lsb
= (data
[0] & 0xff);
250 const uint_t msb
= (data
[1] & 0x03) << 8;
254 void unpackv210line(uint8_t* dst
, uint8_t* src
, uint_t luma_width
)
256 /* number of blocks completely filled with active samples (6 per block) */
257 const uint_t num_firstpass_samples
= 2*(luma_width
/6)*6;
259 for (x
=0; x
< num_firstpass_samples
; src
+= 16) {
260 dst
[x
++] = readv210sample_pos0of3(src
+ 0) >> 2; /* Cb */
261 dst
[x
++] = readv210sample_pos1of3(src
+ 0) >> 2; /* Y' */
262 dst
[x
++] = readv210sample_pos2of3(src
+ 0) >> 2; /* Cr */
263 dst
[x
++] = readv210sample_pos0of3(src
+ 4) >> 2; /* Y' */
265 dst
[x
++] = readv210sample_pos1of3(src
+ 4) >> 2;
266 dst
[x
++] = readv210sample_pos2of3(src
+ 4) >> 2;
267 dst
[x
++] = readv210sample_pos0of3(src
+ 8) >> 2;
268 dst
[x
++] = readv210sample_pos1of3(src
+ 8) >> 2;
270 dst
[x
++] = readv210sample_pos2of3(src
+ 8) >> 2;
271 dst
[x
++] = readv210sample_pos0of3(src
+ 12) >> 2;
272 dst
[x
++] = readv210sample_pos1of3(src
+ 12) >> 2;
273 dst
[x
++] = readv210sample_pos2of3(src
+ 12) >> 2;
275 /* mop up last subblock (4 or 2 active samples) */
277 if (x
< 2*luma_width
) {
278 dst
[x
++] = readv210sample_pos0of3(src
+ 0) >> 2; /* Cb */
279 dst
[x
++] = readv210sample_pos1of3(src
+ 0) >> 2; /* Y' */
280 dst
[x
++] = readv210sample_pos2of3(src
+ 0) >> 2; /* Cr */
281 dst
[x
++] = readv210sample_pos0of3(src
+ 4) >> 2; /* Y' */
284 if (x
< 2*luma_width
) {
285 dst
[x
++] = readv210sample_pos1of3(src
+ 4) >> 2;
286 dst
[x
++] = readv210sample_pos2of3(src
+ 4) >> 2;
287 dst
[x
++] = readv210sample_pos0of3(src
+ 8) >> 2;
288 dst
[x
++] = readv210sample_pos1of3(src
+ 8) >> 2;
292 //utility function to convert V210 data into something easier to display
293 //it is too difficult to do this in the openGL shader
294 void VideoData::convertV210()
296 /* pad to a multiple of 48 luma samples */
297 /* nb, 48 luma samples becomes 128 bytes */
298 const uint_t padded_w
= ((Ywidth
+ 47)/48) * 48; //number of luma samples, padded
299 const uint_t padded_line_length
= (2*padded_w
*4) / 3; //number of bytes on each line in the file, including padding data
301 uint8_t *dst
= (uint8_t*) data
; /* destination for 8bit uyvy, may = src */
302 uint8_t *src
= (uint8_t*) data
; /* source of v210 data */
304 for (int y
=0; y
<Yheight
; y
++) {
305 unpackv210line(dst
, src
, Ywidth
);
306 src
+= padded_line_length
;
310 //change the description of the data to match UYVY
311 //note that the dataSize stays the same
313 glYTextureWidth
= Ywidth
/ 2; //2 Y samples per RGBA quad
314 YdataSize
= Ywidth
* Yheight
* 2;
319 void VideoData::convertPlanar16()
321 uint8_t *src
=(uint8_t *)Ydata
;
322 uint8_t *dst
=(uint8_t *)Ydata
;
323 const uint8_t *end
=(uint8_t *)(Ydata
+dataSize
);
325 //convert the 16 bit source to 8 bit destination, in place
326 //just throw away the LSBs
333 YdataSize
= Ywidth
* Yheight
;
335 //tell the renderer that this is now 8 bit data
336 switch (renderFormat
) {
339 UdataSize
= YdataSize
/4;
340 VdataSize
= YdataSize
/4;
345 UdataSize
= YdataSize
/2;
346 VdataSize
= YdataSize
/2;
351 UdataSize
= YdataSize
;
352 VdataSize
= YdataSize
;
360 //update pointers to the start of each plane
361 Udata
= Ydata
+ YdataSize
;
362 Vdata
= Udata
+ UdataSize
;