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