1 // Copyright (c) 2017-2019 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20
21 #include "umc_video_data.h"
22 #include "vm_debug.h"
23 #include "mfx_utils.h"
24
25 namespace UMC
26 {
27
28 // Number of planes in format description table.
29 // Number of planes in image can be greater. In this case additional
30 // planes should be supported by the user with functions SetPlanePointer,
31 // SetPlanePitch.
32 enum
33 {
34 MAX_PLANE_NUMBER = 4
35 };
36
37 // Color format description structure
38 struct ColorFormatInfo
39 {
40 ColorFormat m_cFormat;
41 int32_t m_iPlanes; // Number of planes
42 int32_t m_iMinBitDepth; // Minimum bitdepth
43 int32_t m_iMinAlign; // Minimal required alignment in bytes
44 struct {
45 int32_t m_iWidthDiv; // Horizontal downsampling factor
46 int32_t m_iHeightDiv; // Vertical downsampling factor
47 int32_t m_iChannels; // Number of merged channels in the plane
48 int32_t m_iAlignMult; // Alignment value multiplier
49 } m_PlaneFormatInfo[MAX_PLANE_NUMBER];
50 };
51
52 // Color format description table
53 static
54 const
55 ColorFormatInfo FormatInfo[] =
56 {
57 {YV12, 3, 8, 1, {{1, 1, 1, 2}, {2, 2, 1, 1}, {2, 2, 1, 1}}},
58 {NV12, 2, 8, 2, {{1, 1, 1, 1}, {1, 2, 1, 1}, }},
59 {YUY2, 1, 8, 2, {{2, 1, 4, 1}, }},
60 {UYVY, 1, 8, 2, {{2, 1, 4, 1}, }},
61 {YUV411, 3, 8, 1, {{1, 1, 1, 1}, {4, 1, 1, 1}, {4, 1, 1, 1}}},
62 {YUV420, 3, 8, 1, {{1, 1, 1, 1}, {2, 2, 1, 1}, {2, 2, 1, 1}}},
63 {YUV422, 3, 8, 1, {{1, 1, 1, 1}, {2, 1, 1, 1}, {2, 1, 1, 1}}},
64 {YUV444, 3, 8, 1, {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}},
65 {YUV_VC1, 3, 8, 1, {{1, 1, 1, 1}, {2, 2, 1, 1}, {2, 2, 1, 1}}},
66 {Y411, 1, 8, 2, {{4, 1, 6, 1}}},
67 {Y41P, 1, 8, 2, {{8, 1, 12, 1}}},
68 {RGB32, 1, 8, 1, {{1, 1, 4, 1}}},
69 {RGB24, 1, 8, 4, {{1, 1, 3, 1}}},
70 {RGB565, 1, 16, 2, {{1, 1, 1, 1}}},
71 {RGB555, 1, 16, 2, {{1, 1, 1, 1}}},
72 {RGB444, 1, 16, 2, {{1, 1, 1, 1}}},
73 {GRAY, 1, 8, 1, {{1, 1, 1, 1}}},
74 {GRAYA, 2, 8, 1, {{1, 1, 1, 1}, {1, 1, 1, 1}}},
75 {YUV420A, 4, 8, 1, {{1, 1, 1, 1}, {2, 2, 1, 1}, {2, 2, 1, 1}, {1, 1, 1, 1}}},
76 {YUV422A, 4, 8, 1, {{1, 1, 1, 1}, {2, 1, 1, 1}, {2, 1, 1, 1}, {1, 1, 1, 1}}},
77 {YUV444A, 4, 8, 1, {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}},
78 {YVU9, 3, 8, 1, {{1, 1, 1, 1}, {4, 4, 1, 1}, {4, 4, 1, 1}}}
79 };
80
81 // Number of entries in the FormatInfo table
82 static
83 const
84 int32_t iNumberOfFormats = sizeof(FormatInfo) / sizeof(FormatInfo[0]);
85
86 // returns pointer to color format description table for cFormat
87 // or NULL if cFormat is not described (unknown color format).
88 static
89 const
GetColorFormatInfo(ColorFormat cFormat)90 ColorFormatInfo *GetColorFormatInfo(ColorFormat cFormat)
91 {
92 const ColorFormatInfo *pReturn = NULL;
93 int32_t i;
94
95 // find required format
96 for (i = 0; i < iNumberOfFormats; i += 1)
97 {
98 if (FormatInfo[i].m_cFormat == cFormat)
99 {
100 pReturn = FormatInfo + i;
101 break;
102 }
103 }
104
105 return pReturn;
106 } // ColorFormatInfo *GetColorFormatInfo(ColorFormat cFormat)
107
108 // Initialization to undefined image type
VideoData(void)109 VideoData::VideoData(void)
110 {
111 m_iAlignment = 1;
112 m_pPlaneData = NULL;
113 m_iPlanes = 0;
114 m_ippSize.width = 0;
115 m_ippSize.height = 0;
116 m_ColorFormat = NONE;
117 m_picStructure = PS_FRAME;
118
119 // set square pixel
120 m_iHorzAspect =
121 m_iVertAspect = 1;
122
123 m_pbAllocated = NULL;
124
125 } // VideoData::VideoData(void)
126
~VideoData(void)127 VideoData::~VideoData(void)
128 {
129 Close();
130
131 } // VideoData::~VideoData(void)
132
133 // Release all possessed memory
Close(void)134 Status VideoData::Close(void)
135 {
136 if (m_pPlaneData)
137 delete [] m_pPlaneData;
138
139 m_pPlaneData = NULL;
140 m_iPlanes = 0;
141
142 return ReleaseImage();
143
144 } // Status VideoData::Close(void)
145
146 // Release image memory if it was owned
ReleaseImage(void)147 Status VideoData::ReleaseImage(void)
148 {
149 int32_t i;
150 for (i = 0; i < m_iPlanes; i++)
151 m_pPlaneData[i].m_pPlane = NULL;
152
153 if (m_pbAllocated)
154 delete [] m_pbAllocated;
155
156 m_pbAllocated = NULL;
157
158 return MediaData::Close();
159
160 } // Status VideoData::ReleaseImage(void)
161
162 // Initializes image dimensions and bitdepth.
163 // Has to be followed by SetColorFormat call.
164 // Planes' information is initialized to invalid values
Init(int32_t iWidth,int32_t iHeight,int32_t iPlanes,int32_t iBitDepth)165 Status VideoData::Init(int32_t iWidth,
166 int32_t iHeight,
167 int32_t iPlanes,
168 int32_t iBitDepth)
169 {
170 int32_t i;
171
172 // check error(s)
173 if ((0 >= iWidth) ||
174 (0 >= iHeight) ||
175 (0 >= iPlanes) ||
176 (8 > iBitDepth))
177 return UMC_ERR_INVALID_STREAM;
178
179 // release object before initialization
180 Close();
181
182 // allocate plane info
183 m_pPlaneData = new PlaneInfo[iPlanes];
184
185 // fill plane info
186 for (i = 0; i < iPlanes; i++)
187 {
188 m_pPlaneData[i].m_iSamples = 1;
189 m_pPlaneData[i].m_iSampleSize = (iBitDepth+7)>>3;
190 m_pPlaneData[i].m_iBitDepth = iBitDepth;
191 m_pPlaneData[i].m_pPlane = NULL;
192 m_pPlaneData[i].m_nMemSize = 0;
193 // we can't set pitch without align value
194 m_pPlaneData[i].m_nPitch = 0;
195 m_pPlaneData[i].m_nOffset = 0;
196 // can't assign dimension to unknown planes
197 m_pPlaneData[i].m_ippSize.width = 0;
198 m_pPlaneData[i].m_ippSize.height = 0;
199 }
200
201 m_iPlanes = iPlanes;
202 m_ippSize.width = iWidth;
203 m_ippSize.height = iHeight;
204
205 return UMC_OK;
206
207 } // Status VideoData::Init(int32_t iWidth,
208
209 // Completely sets image information, without allocation or linking to
210 // image memory.
Init(int32_t iWidth,int32_t iHeight,ColorFormat cFormat,int32_t iBitDepth)211 Status VideoData::Init(int32_t iWidth,
212 int32_t iHeight,
213 ColorFormat cFormat,
214 int32_t iBitDepth)
215 {
216 Status umcRes;
217 const ColorFormatInfo* pFormat;
218
219 pFormat = GetColorFormatInfo(cFormat);
220 if(NULL == pFormat)
221 return UMC_ERR_INVALID_STREAM;
222
223 // allocate planes
224 if(iBitDepth == 0)
225 iBitDepth = pFormat->m_iMinBitDepth;
226 umcRes = Init(iWidth, iHeight, pFormat->m_iPlanes, iBitDepth);
227 if (UMC_OK != umcRes)
228 return umcRes;
229
230 // set color format and
231 // correct width & height for planes
232 umcRes = SetColorFormat(cFormat);
233 if (UMC_OK != umcRes)
234 return umcRes;
235
236 return UMC_OK;
237
238 } // Status VideoData::Init(int32_t iWidth,
239
240 // Sets or change Color format information for image, only when it has
241 // specified size, number of planes and bitdepth. Number of planes in cFormat must
242 // be not greater than specified in image.
SetColorFormat(ColorFormat cFormat)243 Status VideoData::SetColorFormat(ColorFormat cFormat)
244 {
245 int32_t i;
246 const ColorFormatInfo *pFormat;
247
248 // check error(s)
249 pFormat = GetColorFormatInfo(cFormat);
250 if (NULL == pFormat)
251 return UMC_ERR_INVALID_STREAM;
252 if (m_iPlanes < pFormat->m_iPlanes)
253 return UMC_ERR_INVALID_STREAM;
254
255 m_ColorFormat = cFormat;
256
257 m_pPlaneData[0].m_nOffset = 0;
258
259 // set correct width & height to planes
260 for (i = 0; i < m_iPlanes; i += 1)
261 {
262 int32_t align, bpp;
263 if(i>0) {
264 m_pPlaneData[i].m_nOffset =
265 m_pPlaneData[i-1].m_nOffset + m_pPlaneData[i-1].m_nMemSize;
266 }
267 if (i < pFormat->m_iPlanes)
268 {
269 m_pPlaneData[i].m_iWidthDiv = pFormat->m_PlaneFormatInfo[i].m_iWidthDiv;
270 m_pPlaneData[i].m_iHeightDiv = pFormat->m_PlaneFormatInfo[i].m_iHeightDiv;
271 m_pPlaneData[i].m_iSamples = pFormat->m_PlaneFormatInfo[i].m_iChannels;
272 } else {
273 m_pPlaneData[i].m_iWidthDiv = 1;
274 m_pPlaneData[i].m_iHeightDiv = 1;
275 m_pPlaneData[i].m_iSamples = 1;
276 }
277 if (m_pPlaneData[i].m_iWidthDiv != 1) {
278 int sz = m_pPlaneData[i].m_iWidthDiv;
279 m_pPlaneData[i].m_ippSize.width = (m_ippSize.width + sz - 1) / sz;
280 } else {
281 m_pPlaneData[i].m_ippSize.width = m_ippSize.width;
282 }
283 if (m_pPlaneData[i].m_iHeightDiv != 1) {
284 int sz = m_pPlaneData[i].m_iHeightDiv;
285 m_pPlaneData[i].m_ippSize.height = (m_ippSize.height + sz - 1) / sz;
286 } else {
287 m_pPlaneData[i].m_ippSize.height = m_ippSize.height;
288 }
289 bpp = m_pPlaneData[i].m_iSampleSize * m_pPlaneData[i].m_iSamples;
290 align = std::max(m_iAlignment, bpp);
291 if (i < pFormat->m_iPlanes) {
292 // sometimes dimension of image may be not aligned to native size
293 align = std::max(align, pFormat->m_iMinAlign);
294 align *= pFormat->m_PlaneFormatInfo[i].m_iAlignMult;
295 }
296 m_pPlaneData[i].m_nPitch =
297 mfx::align2_value(m_pPlaneData[i].m_ippSize.width * bpp, align);
298 m_pPlaneData[i].m_nMemSize = m_pPlaneData[i].m_nPitch * m_pPlaneData[i].m_ippSize.height;
299 }
300 // special case, can't be completely covered by format table
301 //if(cFormat == YV12) { // V than U
302 // size_t tmp = m_pPlaneData[1].m_nOffset;
303 // m_pPlaneData[1].m_nOffset = m_pPlaneData[2].m_nOffset;
304 // m_pPlaneData[2].m_nOffset = tmp;
305 //}
306
307 // for complexer cases, such as IMC2 or IMC4, need more manual changes here
308
309 return UMC_OK;
310
311 } // Status VideoData::SetColorFormat(ColorFormat cFormat)
312
313
314 // Set common Alignment
SetAlignment(int32_t iAlignment)315 Status VideoData::SetAlignment(int32_t iAlignment)
316 {
317 // check alignment
318 int32_t i;
319 if(iAlignment <= 0)
320 return UMC_ERR_INVALID_STREAM;
321 for (i = 1; i < (1 << 16); i <<= 1) {
322 if (i & iAlignment) {
323 m_iAlignment = i;
324 break; // stop at last nonzero bit
325 }
326 }
327
328 if (i != iAlignment)
329 return UMC_WRN_INVALID_STREAM;
330
331 return UMC_OK;
332 }
333
334 // Allocates memory according to existing information in VideoData and given alignment
335 // If image memory was already allocated it is released.
336 // return UMC_OK on success, UMC_ERR_INVALID_STREAM if image is improperly described
Alloc(size_t)337 Status VideoData::Alloc(size_t /* requiredSize */)
338 {
339 size_t nSize;
340
341 // Release previous buffer
342 ReleaseImage();
343
344 // get size of buffer to allocate
345 nSize = GetMappingSize();
346 if (0 == nSize)
347 return UMC_ERR_INVALID_STREAM;
348
349 // allocate buffer
350 m_pbAllocated = new uint8_t[nSize + m_iAlignment - 1];
351
352 // set pointer to image
353 return SetBufferPointer(m_pbAllocated, nSize);
354
355 } // Status VideoData::Alloc()
356
357 // Links to provided image memory
358 // Image must be described before
SetBufferPointer(uint8_t * pbBuffer,size_t nSize)359 Status VideoData::SetBufferPointer(uint8_t *pbBuffer, size_t nSize)
360 {
361 int32_t i;
362 size_t mapsize;
363 uint8_t *ptr = align_pointer<uint8_t *>(pbBuffer, m_iAlignment);
364
365 // check error(s)
366 if (NULL == m_pPlaneData) {
367 SetDataSize(0);
368 return UMC_ERR_FAILED;
369 }
370
371 mapsize = GetMappingSize();
372 if (nSize < mapsize) {
373 SetDataSize(0);
374 return UMC_ERR_NOT_ENOUGH_BUFFER;
375 }
376
377 // set new plane pointers
378 if (m_pPlaneData)
379 {
380 uint8_t *tmp = ptr;
381 for(i=0; i<m_iPlanes; i++) {
382 m_pPlaneData[i].m_pPlane = tmp;
383 tmp += m_pPlaneData[i].m_nMemSize;
384 }
385 }
386
387 // call parent class methods
388 MediaData::SetBufferPointer(pbBuffer, nSize);
389 // set valid data size
390 SetDataSize(mapsize + (ptr - pbBuffer));
391 MoveDataPointer((int32_t)(ptr - pbBuffer));
392
393 return UMC_OK;
394
395 } // Status VideoData::SetBufferPointer(uint8_t *pbBuffer, size_t nSize)
396
397 // Returns required image memory size according to alignment and current image description
GetMappingSize() const398 size_t VideoData::GetMappingSize() const
399 {
400 int32_t i;
401 size_t size = 0;
402
403 UMC_CHECK(m_pPlaneData, 0);
404
405 for (i = 0; i < m_iPlanes; i++) {
406 size += m_pPlaneData[i].m_nMemSize;
407 }
408
409 return size;
410
411 } // size_t VideoData::GetMappingSize(int32_t iAlignment)
412
413 // Set pointer for specified plane. Should be used for additional planes,
414 // or when image layout is different.
SetPlanePointer(void * pDest,int32_t iPlaneNumber)415 Status VideoData::SetPlanePointer(void *pDest, int32_t iPlaneNumber)
416 {
417 // check error(s)
418 if ((m_iPlanes <= iPlaneNumber) ||
419 (0 > iPlaneNumber) ||
420 (NULL == m_pPlaneData))
421 return UMC_ERR_FAILED;
422
423 m_pPlaneData[iPlaneNumber].m_pPlane = (uint8_t *) pDest;
424
425 return UMC_OK;
426
427 } // Status VideoData::SetPlanePointer(void *pDest, int32_t iPlaneNumber)
428
SetImageSize(int32_t width,int32_t height)429 Status VideoData::SetImageSize(int32_t width, int32_t height)
430 {
431 // check error(s)
432 if (NULL == m_pPlaneData)
433 return UMC_ERR_FAILED;
434
435 m_ippSize.width = width;
436 m_ippSize.height = height;
437
438 return UMC_OK;
439 }
440
441 // Set pitch for specified plane. Should be used for additional planes,
442 // or when image layout is different.
SetPlanePitch(size_t nPitch,int32_t iPlaneNumber)443 Status VideoData::SetPlanePitch(size_t nPitch, int32_t iPlaneNumber)
444 {
445 // check error(s)
446 if ((m_iPlanes <= iPlaneNumber) ||
447 (0 > iPlaneNumber) ||
448 (NULL == m_pPlaneData))
449 return UMC_ERR_FAILED;
450
451 m_pPlaneData[iPlaneNumber].m_nPitch = nPitch;
452 m_pPlaneData[iPlaneNumber].m_nMemSize = nPitch * m_pPlaneData[iPlaneNumber].m_ippSize.height;
453
454 return UMC_OK;
455
456 } // Status VideoData::SetPlanePitch(size_t nPitch, int32_t iPlaneNumber)
457
458 // Set bitdepth for specified plane, usually additional or when bitdepth differs
459 // for main planes
SetPlaneBitDepth(int32_t iBitDepth,int32_t iPlaneNumber)460 Status VideoData::SetPlaneBitDepth(int32_t iBitDepth, int32_t iPlaneNumber)
461 {
462 // check error(s)
463 if ((m_iPlanes <= iPlaneNumber) ||
464 (0 > iPlaneNumber) ||
465 (NULL == m_pPlaneData))
466 return UMC_ERR_FAILED;
467
468 m_pPlaneData[iPlaneNumber].m_iBitDepth = iBitDepth;
469 if(m_pPlaneData[iPlaneNumber].m_iSampleSize*8 < iBitDepth)
470 m_pPlaneData[iPlaneNumber].m_iSampleSize = (iBitDepth+7)>>3;
471
472 return UMC_OK;
473
474 } // Status VideoData::SetPlaneBitDepth(int32_t iBitDepth, int32_t iPlaneNumber)
475
476 // Set sample size for specified plane, usually additional or when bitdepth differs
477 // for main planes
SetPlaneSampleSize(int32_t iSampleSize,int32_t iPlaneNumber)478 Status VideoData::SetPlaneSampleSize(int32_t iSampleSize, int32_t iPlaneNumber)
479 {
480 // check error(s)
481 if ((m_iPlanes <= iPlaneNumber) ||
482 (0 > iPlaneNumber) ||
483 (NULL == m_pPlaneData))
484 return UMC_ERR_FAILED;
485
486 m_pPlaneData[iPlaneNumber].m_iSampleSize = iSampleSize;
487 if(iSampleSize*8 < m_pPlaneData[iPlaneNumber].m_iBitDepth)
488 m_pPlaneData[iPlaneNumber].m_iBitDepth = iSampleSize*8;
489
490 return UMC_OK;
491
492 } // Status VideoData::SetPlaneSampleSize(int32_t iSampleSize, int32_t iPlaneNumber)
493
494 // Links plane pointers to surface using provided pitch.
495 // All pitches and plane info are updated according to current
496 // color format.
497 // Supposes no gaps between planes.
SetSurface(void * ptr,size_t nPitch)498 Status VideoData::SetSurface(void* ptr, size_t nPitch)
499 {
500 // check error(s)
501 UMC_CHECK(ptr, UMC_ERR_NULL_PTR);
502 UMC_CHECK(m_pPlaneData, UMC_ERR_NOT_INITIALIZED);
503
504 if(nPitch == 0) // use current
505 nPitch = m_pPlaneData[0].m_nPitch;
506
507 m_pPlaneData[0].m_nOffset = 0;
508 size_t size = 0;
509
510 for (int i = 0; i < m_iPlanes; i++) {
511 m_pPlaneData[i].m_nPitch = nPitch;
512 if (i > 0) {
513 m_pPlaneData[i].m_nPitch *= m_pPlaneData[i].m_iSamples*m_pPlaneData[0].m_iWidthDiv;
514 m_pPlaneData[i].m_nPitch /= m_pPlaneData[i].m_iWidthDiv*m_pPlaneData[0].m_iSamples;
515 m_pPlaneData[i].m_nOffset = m_pPlaneData[i - 1].m_nOffset + m_pPlaneData[i - 1].m_nMemSize;
516 }
517 m_pPlaneData[i].m_pPlane = (uint8_t*)ptr + m_pPlaneData[i].m_nOffset;
518 m_pPlaneData[i].m_nMemSize = m_pPlaneData[i].m_nPitch * m_pPlaneData[i].m_ippSize.height;
519 size += m_pPlaneData[i].m_nMemSize;
520 }
521
522 MediaData::SetBufferPointer((uint8_t*)ptr, size);
523
524 return MediaData::SetDataSize(size);
525 }
526
527 #define PITCH_PREC 8
528
529 // Calculate pitch from mapping size
GetPitchFromMappingSize(size_t mappingSize) const530 size_t VideoData::GetPitchFromMappingSize(size_t mappingSize) const
531 {
532 size_t size = 0;
533 int i;
534
535 // check error(s)
536 UMC_CHECK(m_pPlaneData, 0);
537
538 // calculate mapping size for pitch equal to (1 << PITCH_PREC)
539 size = m_pPlaneData[0].m_ippSize.height << PITCH_PREC;
540 for (i = 1; i < m_iPlanes; i++) {
541 size_t plane_size = m_pPlaneData[i].m_ippSize.height << PITCH_PREC;
542 plane_size *= m_pPlaneData[i].m_iSamples*m_pPlaneData[0].m_iWidthDiv;
543 plane_size /= m_pPlaneData[i].m_iWidthDiv*m_pPlaneData[0].m_iSamples;
544 size += plane_size;
545 }
546
547 UMC_CHECK(size, 0);
548
549 // calulate real pitch
550 return ((mappingSize << PITCH_PREC)/size);
551 }
552
ConvertPictureStructure(PictureStructure newPicStructure)553 Status VideoData::ConvertPictureStructure(PictureStructure newPicStructure)
554 {
555 PictureStructure curr = (PictureStructure)(m_picStructure & PS_FRAME);
556 int k;
557
558 vm_debug_trace2(VM_DEBUG_VERBOSE, VM_STRING("VideoData::ConvertPictureStructure %d->%d\n"), curr, newPicStructure);
559
560 if (curr == PS_FRAME && newPicStructure == PS_TOP_FIELD) {
561 m_ippSize.height >>= 1;
562 for (k = 0; k < m_iPlanes; k++) {
563 m_pPlaneData[k].m_ippSize.height >>= 1;
564 m_pPlaneData[k].m_nPitch <<= 1;
565 }
566 curr = PS_TOP_FIELD;
567 }
568
569 if (curr == PS_TOP_FIELD && newPicStructure == PS_BOTTOM_FIELD) {
570 for (k = 0; k < m_iPlanes; k++) {
571 m_pPlaneData[k].m_pPlane += (m_pPlaneData[k].m_nPitch >> 1);
572 }
573 curr = PS_BOTTOM_FIELD;
574 }
575
576 if (curr == PS_BOTTOM_FIELD && (newPicStructure == PS_TOP_FIELD || newPicStructure == PS_FRAME)) {
577 for (k = 0; k < m_iPlanes; k++) {
578 m_pPlaneData[k].m_pPlane -= (m_pPlaneData[k].m_nPitch >> 1);
579 }
580 curr = PS_TOP_FIELD;
581 }
582
583 if (curr == PS_TOP_FIELD && newPicStructure == PS_FRAME) {
584 m_ippSize.height <<= 1;
585 for (k = 0; k < m_iPlanes; k++) {
586 m_pPlaneData[k].m_ippSize.height <<= 1;
587 m_pPlaneData[k].m_nPitch >>= 1;
588 }
589 curr = PS_FRAME;
590 }
591
592 return SetPictureStructure(curr /*| (m_picStructure &~ PS_FRAME)*/);
593 }
594
595 // fills PlaneInfo structure
GetPlaneInfo(PlaneInfo * pInfo,int32_t iPlaneNumber)596 Status VideoData::GetPlaneInfo(PlaneInfo* pInfo, int32_t iPlaneNumber)
597 {
598 // check error(s)
599 if (NULL == pInfo)
600 return UMC_ERR_NULL_PTR;
601 if ((m_iPlanes <= iPlaneNumber) ||
602 (0 > iPlaneNumber) ||
603 (NULL == m_pPlaneData))
604 return UMC_ERR_FAILED;
605
606 *pInfo = m_pPlaneData[iPlaneNumber];
607 return UMC_OK;
608
609 } // Status VideoData::GetPlaneInfo(PlaneInfo* pInfo, int32_t iPlaneNumber)
610
611 // converts display aspect ratio to pixel AR
612 // or vise versa with exchanged width and height
DARtoPAR(int32_t width,int32_t height,int32_t dar_h,int32_t dar_v,int32_t * par_h,int32_t * par_v)613 Status DARtoPAR(int32_t width, int32_t height, int32_t dar_h, int32_t dar_v,
614 int32_t *par_h, int32_t *par_v)
615 {
616 // (width*par_h) / (height*par_v) == dar_h/dar_v =>
617 // par_h / par_v == dar_h * height / (dar_v * width)
618 int32_t simple_tab[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59};
619 int32_t denom;
620 size_t i;
621
622 // suppose no overflow of 32s
623 int32_t h = dar_h * height;
624 int32_t v = dar_v * width;
625 // remove common multipliers
626 while( ((h|v)&1) == 0 ) {
627 h>>=1;
628 v>>=1;
629 }
630
631 for(i=0;i<sizeof(simple_tab)/sizeof(simple_tab[0]);i++) {
632 denom = simple_tab[i];
633 while(h%denom==0 && v%denom==0) {
634 v /= denom;
635 h /= denom;
636 }
637 if(v<=denom || h<=denom)
638 break;
639 }
640 *par_h = h;
641 *par_v = v;
642 // can don't reach minimum, no problem
643 if(i<sizeof(simple_tab)/sizeof(simple_tab[0]))
644 return UMC_WRN_INVALID_STREAM;
645 return UMC_OK;
646 }
647
648 // Crop
Crop(UMC::sRECT CropArea)649 Status VideoData::Crop(UMC::sRECT CropArea)
650 {
651 int left = CropArea.left;
652 int top = CropArea.top;
653 int right = CropArea.right;
654 int bottom = CropArea.bottom;
655 if (!right) right = m_ippSize.width;
656 if (!bottom) bottom = m_ippSize.height;
657 int w = right - left;
658 int h = bottom - top;
659 int k;
660
661 UMC_CHECK(w > 0, UMC_ERR_INVALID_PARAMS);
662 UMC_CHECK(h > 0, UMC_ERR_INVALID_PARAMS);
663 UMC_CHECK(left >= 0, UMC_ERR_INVALID_PARAMS);
664 UMC_CHECK(top >= 0, UMC_ERR_INVALID_PARAMS);
665 UMC_CHECK(right <= m_ippSize.width, UMC_ERR_INVALID_PARAMS);
666 UMC_CHECK(bottom <= m_ippSize.height, UMC_ERR_INVALID_PARAMS);
667
668 for (k = 0; k < m_iPlanes; k++) {
669 int wDiv = (m_pPlaneData[k].m_ippSize.width) ? m_ippSize.width/m_pPlaneData[k].m_ippSize.width : 1;
670 int hDiv = (m_pPlaneData[k].m_ippSize.height) ? m_ippSize.height/m_pPlaneData[k].m_ippSize.height : 1;
671 m_pPlaneData[k].m_pPlane += (top / hDiv) * m_pPlaneData[k].m_nPitch +
672 (left / wDiv) * m_pPlaneData[k].m_iSamples * m_pPlaneData[k].m_iSampleSize;
673 m_pPlaneData[k].m_ippSize.width = w / wDiv;
674 m_pPlaneData[k].m_ippSize.height = h / hDiv;
675 }
676 m_ippSize.width = w;
677 m_ippSize.height = h;
678
679 return UMC_OK;
680 }
681
operator =(const VideoData & par)682 VideoData & VideoData::operator = (const VideoData &par)
683 {
684 // check assignment for self
685 if (this == &par)
686 {
687 return *this;
688 }
689
690 PlaneInfo *PlaneData = m_pPlaneData;
691 if(m_iPlanes < par.m_iPlanes)
692 {
693 Close();
694 PlaneData = new PlaneInfo[par.m_iPlanes];
695 } else {
696 ReleaseImage();
697 }
698
699 MediaData::operator=(par);
700
701 std::copy(par.m_pPlaneData, par.m_pPlaneData + par.m_iPlanes, PlaneData);
702
703 m_iPlanes = par.m_iPlanes;
704 m_ippSize = par.m_ippSize;
705 m_ColorFormat = par.m_ColorFormat;
706 m_picStructure = par.m_picStructure;
707 m_iHorzAspect = par.m_iHorzAspect;
708 m_iVertAspect = par.m_iVertAspect;
709 m_iAlignment = par.m_iAlignment;
710
711 m_pPlaneData = PlaneData;
712
713 m_pbAllocated = NULL;
714
715 return *this;
716 }
717
718 } // end namespace UMC
719