[mmap] partial revert of 8cef8db4 to disable using mmap file reader
[videoplayer.git] / videoData.cpp
blobf6f4470d86a459c06464ea5b4903b5bc0d1e5154
1 /* ***** BEGIN LICENSE BLOCK *****
3 * The MIT License
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
23 * THE SOFTWARE.
25 * ***** END LICENSE BLOCK ***** */
27 #include "videoData.h"
29 #include <stdlib.h>
30 #include <QtGlobal>
32 #include <QtGlobal>
34 #ifdef Q_OS_WIN32
35 #include <malloc.h>
36 #define valloc malloc
37 #endif
39 VideoData::VideoData()
41 //make a bogus 1x1 4:4:4 8 bit image
42 allocate(1, 1, V8P4);
43 data[0] = 16;
44 data[1] = 128;
45 data[2] = 128;
48 void VideoData::resize(int w, int h, DataFmt f)
50 if (w != Ywidth || h != Yheight || f != diskFormat) {
51 if (data)
52 free(data);
53 allocate(w, h, f);
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. */
59 renderFormat = f;
62 void VideoData::allocate(int w, int h, DataFmt f)
64 Ywidth = w;
65 Yheight = h;
66 diskFormat = f;
68 switch (diskFormat) {
70 case V8P4: //8 bit 444 planar
71 Cwidth = Ywidth;
72 Cheight = Yheight;
73 YdataSize = Ywidth * Yheight;
74 UdataSize = YdataSize;
75 VdataSize = YdataSize;
76 break;
78 case V16P4: //16 bit 444 planar
79 Cwidth = Ywidth;
80 Cheight = Yheight;
81 YdataSize = Ywidth * Yheight * 2;
82 UdataSize = YdataSize;
83 VdataSize = YdataSize;
84 break;
86 case V8P2: //8 bit 422 planar
87 Cwidth = Ywidth / 2;
88 Cheight = Yheight;
89 YdataSize = Ywidth * Yheight;
90 UdataSize = YdataSize / 2;
91 VdataSize = YdataSize / 2;
92 break;
94 case V16P2: //16 bit 422 planar
95 Cwidth = Ywidth / 2;
96 Cheight = Yheight;
97 YdataSize = Ywidth * Yheight * 2;
98 UdataSize = YdataSize / 2;
99 VdataSize = YdataSize / 2;
100 break;
102 case V16P0: //16 bit 420
103 Cwidth = Ywidth / 2;
104 Cheight = Yheight / 2;
105 YdataSize = Ywidth * Yheight * 2;
106 UdataSize = YdataSize / 4;
107 VdataSize = YdataSize / 4;
108 break;
110 case V8P0: //8 bit 420, YUV
111 case YV12: //8 bit 420, YVU
112 Cwidth = Ywidth / 2;
113 Cheight = Yheight / 2;
114 YdataSize = Ywidth * Yheight;
115 UdataSize = YdataSize / 4;
116 VdataSize = YdataSize / 4;
117 break;
119 case UYVY:
120 Cwidth = Ywidth / 2;
121 Cheight = Yheight;
122 YdataSize = Ywidth * Yheight * 2;
123 UdataSize = 0;
124 VdataSize = 0;
125 break;
127 case V216:
128 Cwidth = Ywidth / 2;
129 Cheight = Yheight;
130 YdataSize = Ywidth * Yheight * 4;
131 UdataSize = 0;
132 VdataSize = 0;
133 break;
135 case V210:
136 //3 10 bit components packed into 4 bytes
137 Cwidth = Ywidth / 2;
138 Cheight = Yheight;
139 YdataSize = (Ywidth * Yheight * 2 * 4) / 3;
140 UdataSize = 0;
141 VdataSize = 0;
142 break;
144 default:
145 //oh-no!
146 break;
149 //total size of the frame
150 dataSize = YdataSize + UdataSize + VdataSize;
152 //get some nicely page aligned memory
153 data = (unsigned char *)valloc(dataSize);
154 Ydata = data;
155 isPlanar = false;
156 glMinMaxFilter = GL_LINEAR; //linear interpolation
157 Udata = Ydata;
158 Vdata = Ydata;
159 renderFormat = diskFormat;
161 switch (diskFormat) {
162 //planar formats YUV
163 case V16P4:
164 case V16P2:
165 case V16P0:
166 case V8P4:
167 case V8P2:
168 case V8P0:
169 glYTextureWidth = Ywidth;
170 glInternalFormat = GL_LUMINANCE;
171 glFormat = GL_LUMINANCE;
172 glType = GL_UNSIGNED_BYTE;
173 isPlanar = true;
174 Udata = Ydata + YdataSize;
175 Vdata = Udata + UdataSize;
176 break;
178 //planar format, YVU
179 case YV12:
180 isPlanar = true;
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);
188 break;
190 case UYVY:
191 //muxed 8 bit format
192 glYTextureWidth = Ywidth / 2; //2 Y samples per RGBA quad
193 glInternalFormat = GL_RGBA;
194 glFormat = GL_RGBA;
195 glType = GL_UNSIGNED_BYTE;
196 break;
198 case V210: //gets converted to UYVY
199 glYTextureWidth = Ywidth / 2; //2 Y samples per RGBA quad
200 glInternalFormat = GL_RGBA;
201 glFormat = GL_RGBA;
202 glType = GL_UNSIGNED_BYTE;
203 break;
205 case V216:
206 glYTextureWidth = Ywidth / 2; //2 Y samples per RGBA quad
207 glInternalFormat = GL_RGBA;
208 glFormat = GL_RGBA;
209 glType = GL_UNSIGNED_SHORT;
210 break;
212 default:
213 //oh-no!
214 break;
218 VideoData::~VideoData()
220 if (data) {
221 free(data);
222 data = NULL;
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;
235 return msb | lsb;
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;
243 return msb | lsb;
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;
251 return msb | lsb;
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;
258 uint_t x;
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;
307 dst += Ywidth*2;
310 //change the description of the data to match UYVY
311 //note that the dataSize stays the same
312 renderFormat = UYVY;
313 glYTextureWidth = Ywidth / 2; //2 Y samples per RGBA quad
314 YdataSize = Ywidth * Yheight * 2;
315 UdataSize = 0;
316 VdataSize = 0;
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
327 while (src < end) {
328 *dst++ = *src;
329 src+=2;
332 //new data size
333 YdataSize = Ywidth * Yheight;
335 //tell the renderer that this is now 8 bit data
336 switch (renderFormat) {
337 case V16P0:
338 renderFormat = V8P0;
339 UdataSize = YdataSize/4;
340 VdataSize = YdataSize/4;
341 break;
343 case V16P2:
344 renderFormat = V8P2;
345 UdataSize = YdataSize/2;
346 VdataSize = YdataSize/2;
347 break;
349 case V16P4:
350 renderFormat = V8P4;
351 UdataSize = YdataSize;
352 VdataSize = YdataSize;
353 break;
355 default:
356 //doh!
357 break;
360 //update pointers to the start of each plane
361 Udata = Ydata + YdataSize;
362 Vdata = Udata + UdataSize;