1 /******************************************************************************\
2 Copyright (c) 2005-2020, Intel Corporation
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 
7 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 
9 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 
11 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12 
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14 
15 This sample was distributed or derived from the Intel's Media Samples package.
16 The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
17 or https://software.intel.com/en-us/media-client-solutions-support.
18 \**********************************************************************************/
19 
20 #include "mfx_samples_config.h"
21 
22 #include <math.h>
23 #include <iostream>
24 #include <algorithm>
25 #include <map>
26 
27 #include "vm/strings_defs.h"
28 #include "time_statistics.h"
29 #include "sample_defs.h"
30 #include "sample_utils.h"
31 #include "mfxcommon.h"
32 #include "mfxjpeg.h"
33 #include "mfxvp8.h"
34 
35 
36 msdk_tick CTimer::frequency = 0;
37 msdk_tick CTimeStatisticsReal::frequency = 0;
38 
CopyBitstream2(mfxBitstream * dest,mfxBitstream * src)39 mfxStatus CopyBitstream2(mfxBitstream *dest, mfxBitstream *src)
40 {
41     if (!dest || !src)
42         return MFX_ERR_NULL_PTR;
43 
44     if (!dest->DataLength)
45     {
46         dest->DataOffset = 0;
47     }
48     else
49     {
50         memmove(dest->Data, dest->Data + dest->DataOffset, dest->DataLength);
51         dest->DataOffset = 0;
52     }
53 
54     if (src->DataLength > dest->MaxLength - dest->DataLength - dest->DataOffset)
55         return MFX_ERR_NOT_ENOUGH_BUFFER;
56 
57     MSDK_MEMCPY_BITSTREAM(*dest, dest->DataOffset, src->Data, src->DataLength);
58     dest->DataLength = src->DataLength;
59 
60     dest->DataFlag = src->DataFlag;
61 
62     //common Extended buffer will be for src and dest bit streams
63     dest->EncryptedData = src->EncryptedData;
64 
65     return MFX_ERR_NONE;
66 }
67 
GetFrameLength(mfxU16 width,mfxU16 height,mfxU32 ColorFormat,mfxU32 & length)68 mfxStatus GetFrameLength(mfxU16 width, mfxU16 height, mfxU32 ColorFormat, mfxU32 &length)
69 {
70     switch (ColorFormat)
71     {
72     case MFX_FOURCC_NV12:
73     case MFX_FOURCC_I420:
74         length = 3 * width * height / 2;
75         break;
76     case MFX_FOURCC_YUY2:
77         length = 2 * width * height;
78         break;
79     case MFX_FOURCC_RGB4:
80         length = 4 * width * height;
81         break;
82     case MFX_FOURCC_P010:
83         length = 3 * width * height;
84         break;
85     default:
86         return MFX_ERR_UNSUPPORTED;
87     }
88 
89     return MFX_ERR_NONE;
90 }
91 
CSmplYUVReader()92 CSmplYUVReader::CSmplYUVReader()
93 {
94     m_bInited = false;
95     m_ColorFormat = MFX_FOURCC_YV12;
96     shouldShift10BitsHigh = false;
97 }
98 
Init(std::list<msdk_string> inputs,mfxU32 ColorFormat,bool enableShifting)99 mfxStatus CSmplYUVReader::Init(std::list<msdk_string> inputs, mfxU32 ColorFormat, bool enableShifting)
100 {
101     Close();
102 
103     if( MFX_FOURCC_NV12 != ColorFormat &&
104         MFX_FOURCC_YV12 != ColorFormat &&
105         MFX_FOURCC_I420 != ColorFormat &&
106         MFX_FOURCC_YUY2 != ColorFormat &&
107         MFX_FOURCC_UYVY != ColorFormat &&
108         MFX_FOURCC_RGB4 != ColorFormat &&
109         MFX_FOURCC_BGR4 != ColorFormat &&
110         MFX_FOURCC_P010 != ColorFormat &&
111         MFX_FOURCC_P210 != ColorFormat &&
112         MFX_FOURCC_AYUV != ColorFormat &&
113         MFX_FOURCC_A2RGB10 != ColorFormat
114 #if (MFX_VERSION >= 1027)
115         && MFX_FOURCC_Y210 != ColorFormat
116         && MFX_FOURCC_Y410 != ColorFormat
117 #endif
118 #if (MFX_VERSION >= 1031)
119         && MFX_FOURCC_P016 != ColorFormat
120         && MFX_FOURCC_Y216 != ColorFormat
121 #endif
122         )
123     {
124         return MFX_ERR_UNSUPPORTED;
125     }
126 
127     if (   MFX_FOURCC_P010 == ColorFormat
128         || MFX_FOURCC_P210 == ColorFormat
129 #if (MFX_VERSION >= 1027)
130         || MFX_FOURCC_Y210 == ColorFormat
131 #endif
132 #if (MFX_VERSION >= 1031)
133         || MFX_FOURCC_P016 == ColorFormat
134         || MFX_FOURCC_Y216 == ColorFormat
135 #endif
136     )
137     {
138         shouldShift10BitsHigh = enableShifting;
139     }
140 
141     if (!inputs.size())
142     {
143         return MFX_ERR_UNSUPPORTED;
144     }
145 
146     for (ls_iterator it = inputs.begin(); it != inputs.end(); it++)
147     {
148         FILE *f = 0;
149         MSDK_FOPEN(f, (*it).c_str(), MSDK_STRING("rb"));
150         MSDK_CHECK_POINTER(f, MFX_ERR_NULL_PTR);
151 
152         m_files.push_back(f);
153     }
154 
155     m_ColorFormat = ColorFormat;
156 
157     m_bInited = true;
158 
159     return MFX_ERR_NONE;
160 }
161 
~CSmplYUVReader()162 CSmplYUVReader::~CSmplYUVReader()
163 {
164     Close();
165 }
166 
Close()167 void CSmplYUVReader::Close()
168 {
169     for (mfxU32 i = 0; i < m_files.size(); i++)
170     {
171         fclose(m_files[i]);
172     }
173     m_files.clear();
174     m_bInited = false;
175 }
176 
Reset()177 void CSmplYUVReader::Reset()
178 {
179     for (mfxU32 i = 0; i < m_files.size(); i++)
180     {
181         fseek(m_files[i], 0, SEEK_SET);
182     }
183 }
184 
SkipNframesFromBeginning(mfxU16 w,mfxU16 h,mfxU32 viewId,mfxU32 nframes)185 mfxStatus CSmplYUVReader::SkipNframesFromBeginning(mfxU16 w, mfxU16 h, mfxU32 viewId, mfxU32 nframes)
186 {
187     // change file position for read from beginning to "frameLength * nframes".
188     mfxU32 frameLength;
189 
190     if (MFX_ERR_NONE != GetFrameLength(w, h, m_ColorFormat, frameLength))
191     {
192         msdk_printf(MSDK_STRING("Input color format %s is unsupported in qpfile mode\n"), ColorFormatToStr(m_ColorFormat));
193         return MFX_ERR_UNSUPPORTED;
194     }
195 
196     if (0 != fseek(m_files[viewId], frameLength * nframes, SEEK_SET))
197         return MFX_ERR_MORE_DATA;
198 
199     return MFX_ERR_NONE;
200 }
201 
LoadNextFrame(mfxFrameSurface1 * pSurface)202 mfxStatus CSmplYUVReader::LoadNextFrame(mfxFrameSurface1* pSurface)
203 {
204     // check if reader is initialized
205     MSDK_CHECK_ERROR(m_bInited, false, MFX_ERR_NOT_INITIALIZED);
206     MSDK_CHECK_POINTER(pSurface, MFX_ERR_NULL_PTR);
207 
208     mfxU32 nBytesRead;
209     mfxU16 w, h, i, pitch;
210     mfxU8 *ptr, *ptr2;
211     mfxFrameInfo& pInfo = pSurface->Info;
212     mfxFrameData& pData = pSurface->Data;
213 
214     mfxU32 shiftSizeLuma   = 16 - pInfo.BitDepthLuma;
215     mfxU32 shiftSizeChroma = 16 - pInfo.BitDepthChroma;
216 
217     mfxU32 vid = pInfo.FrameId.ViewId;
218 
219     if (vid > m_files.size())
220     {
221         return MFX_ERR_UNSUPPORTED;
222     }
223 
224     if (pInfo.CropH > 0 && pInfo.CropW > 0)
225     {
226         w = pInfo.CropW;
227         h = pInfo.CropH;
228     }
229     else
230     {
231         w = pInfo.Width;
232         h = pInfo.Height;
233     }
234 
235     mfxU32 nBytesPerPixel = (pInfo.FourCC == MFX_FOURCC_P010 || pInfo.FourCC == MFX_FOURCC_P210
236 #if (MFX_VERSION >= 1031)
237         || pInfo.FourCC == MFX_FOURCC_P016
238 #endif
239     ) ? 2 : 1;
240 
241     if (   MFX_FOURCC_YUY2 == pInfo.FourCC
242         || MFX_FOURCC_UYVY == pInfo.FourCC
243         || MFX_FOURCC_RGB4 == pInfo.FourCC
244         || MFX_FOURCC_BGR4 == pInfo.FourCC
245         || MFX_FOURCC_AYUV == pInfo.FourCC
246         || MFX_FOURCC_A2RGB10 == pInfo.FourCC
247 #if (MFX_VERSION >= 1027)
248         || MFX_FOURCC_Y210 == pInfo.FourCC
249         || MFX_FOURCC_Y410 == pInfo.FourCC
250 #endif
251 #if (MFX_VERSION >= 1031)
252         || MFX_FOURCC_Y216 == pInfo.FourCC
253 #endif
254     )
255     {
256         //Packed format: Luminance and chrominance are on the same plane
257         switch (m_ColorFormat)
258         {
259         case MFX_FOURCC_A2RGB10:
260         case MFX_FOURCC_RGB4:
261         case MFX_FOURCC_BGR4:
262             pitch = pData.Pitch;
263             ptr = std::min({pData.R, pData.G, pData.B});
264             ptr = ptr + pInfo.CropX*4 + pInfo.CropY * pData.Pitch;
265 
266             for(i = 0; i < h; i++)
267             {
268                 nBytesRead = (mfxU32)fread(ptr + i * pitch, 1, 4*w, m_files[vid]);
269 
270                 if ((mfxU32)4*w != nBytesRead)
271                 {
272                     return MFX_ERR_MORE_DATA;
273                 }
274             }
275             break;
276         case MFX_FOURCC_YUY2:
277         case MFX_FOURCC_UYVY:
278             pitch = pData.Pitch;
279             ptr = m_ColorFormat == MFX_FOURCC_YUY2?
280                   pData.Y + pInfo.CropX*2 + pInfo.CropY * pData.Pitch
281                 : pData.U + pInfo.CropX   + pInfo.CropY * pData.Pitch;
282 
283             for(i = 0; i < h; i++)
284             {
285                 nBytesRead = (mfxU32)fread(ptr + i * pitch, 2, w, m_files[vid]);
286 
287                 if ((mfxU32)w != nBytesRead)
288                 {
289                     return MFX_ERR_MORE_DATA;
290                 }
291             }
292             break;
293         case MFX_FOURCC_AYUV:
294             pitch = pData.Pitch;
295             ptr = pData.V + pInfo.CropX*4 + pInfo.CropY * pData.Pitch;
296 
297             for (i = 0; i < h; i++)
298             {
299                 nBytesRead = (mfxU32)fread(ptr + i * pitch, 4, w, m_files[vid]);
300 
301                 if ((mfxU32)w != nBytesRead)
302                 {
303                     return MFX_ERR_MORE_DATA;
304                 }
305             }
306             break;
307 
308 #if (MFX_VERSION >= 1027)
309         case MFX_FOURCC_Y210:
310         case MFX_FOURCC_Y410:
311 #if (MFX_VERSION >= 1031)
312         case MFX_FOURCC_Y216:
313 #endif
314             pitch = pData.Pitch;
315             ptr = ((pInfo.FourCC == MFX_FOURCC_Y210
316 #if (MFX_VERSION >= 1031)
317             || pInfo.FourCC == MFX_FOURCC_Y216
318 #endif
319             )  ? pData.Y : (mfxU8*)pData.Y410) + pInfo.CropX*4 + pInfo.CropY * pData.Pitch;
320 
321             for (i = 0; i < h; i++)
322             {
323                 nBytesRead = (mfxU32)fread(ptr + i * pitch, 1, 4 * w, m_files[vid]);
324 
325                 if ((mfxU32)4 * w != nBytesRead)
326                 {
327                     return MFX_ERR_MORE_DATA;
328                 }
329 
330                 if ((MFX_FOURCC_Y210 == pInfo.FourCC
331 #if (MFX_VERSION >= 1031)
332                     || MFX_FOURCC_Y216 == pInfo.FourCC
333 #endif
334                 ) && shouldShift10BitsHigh)
335                 {
336                     mfxU16* shortPtr = (mfxU16*)(ptr + i * pitch);
337                     for (int idx = 0; idx < w*2; idx++)
338                     {
339                         shortPtr[idx] <<= shiftSizeLuma;
340                     }
341                 }
342 
343             }
344             break;
345 #endif
346         default:
347             return MFX_ERR_UNSUPPORTED;
348         }
349     }
350     else if (MFX_FOURCC_NV12 == pInfo.FourCC
351             || MFX_FOURCC_YV12 == pInfo.FourCC
352             || MFX_FOURCC_P010 == pInfo.FourCC
353             || MFX_FOURCC_P210 == pInfo.FourCC
354 #if (MFX_VERSION >= 1031)
355             || MFX_FOURCC_P016 == pInfo.FourCC
356 #endif
357     )
358     {
359         pitch = pData.Pitch;
360         ptr = pData.Y + pInfo.CropX + pInfo.CropY * pData.Pitch;
361 
362         // read luminance plane
363         for(i = 0; i < h; i++)
364         {
365             nBytesRead = (mfxU32)fread(ptr + i * pitch, nBytesPerPixel, w, m_files[vid]);
366 
367             if (w != nBytesRead)
368             {
369                 return MFX_ERR_MORE_DATA;
370             }
371 
372             // Shifting data if required
373             if((MFX_FOURCC_P010 == pInfo.FourCC
374              || MFX_FOURCC_P210 == pInfo.FourCC
375 #if (MFX_VERSION >= 1031)
376              || MFX_FOURCC_P016 == pInfo.FourCC
377 #endif
378             ) && shouldShift10BitsHigh)
379             {
380                 mfxU16* shortPtr = (mfxU16*)(ptr + i * pitch);
381                 for(int idx = 0; idx < w; idx++)
382                 {
383                     shortPtr[idx]<<=shiftSizeLuma;
384                 }
385             }
386         }
387 
388         // read chroma planes
389         switch (m_ColorFormat) // color format of data in the input file
390         {
391         case MFX_FOURCC_I420:
392         case MFX_FOURCC_YV12:
393             switch (pInfo.FourCC)
394             {
395             case MFX_FOURCC_NV12:
396 
397                 mfxU8 buf[2048]; // maximum supported chroma width for nv12
398                 mfxU32 j, dstOffset[2];
399                 w /= 2;
400                 h /= 2;
401                 ptr = pData.UV + pInfo.CropX + (pInfo.CropY / 2) * pitch;
402                 if (w > 2048)
403                 {
404                     return MFX_ERR_UNSUPPORTED;
405                 }
406 
407                 if (m_ColorFormat == MFX_FOURCC_I420) {
408                     dstOffset[0] = 0;
409                     dstOffset[1] = 1;
410                 } else {
411                     dstOffset[0] = 1;
412                     dstOffset[1] = 0;
413                 }
414 
415                 // load first chroma plane: U (input == I420) or V (input == YV12)
416                 for (i = 0; i < h; i++)
417                 {
418                     nBytesRead = (mfxU32)fread(buf, 1, w, m_files[vid]);
419                     if (w != nBytesRead)
420                     {
421                         return MFX_ERR_MORE_DATA;
422                     }
423                     for (j = 0; j < w; j++)
424                     {
425                         ptr[i * pitch + j * 2 + dstOffset[0]] = buf[j];
426                     }
427                 }
428 
429                 // load second chroma plane: V (input == I420) or U (input == YV12)
430                 for (i = 0; i < h; i++)
431                 {
432 
433                     nBytesRead = (mfxU32)fread(buf, 1, w, m_files[vid]);
434 
435                     if (w != nBytesRead)
436                     {
437                         return MFX_ERR_MORE_DATA;
438                     }
439                     for (j = 0; j < w; j++)
440                     {
441                         ptr[i * pitch + j * 2 + dstOffset[1]] = buf[j];
442                     }
443                 }
444 
445                 break;
446             case MFX_FOURCC_YV12:
447                 w /= 2;
448                 h /= 2;
449                 pitch /= 2;
450 
451                 if (m_ColorFormat == MFX_FOURCC_I420) {
452                     ptr  = pData.U + (pInfo.CropX / 2) + (pInfo.CropY / 2) * pitch;
453                     ptr2 = pData.V + (pInfo.CropX / 2) + (pInfo.CropY / 2) * pitch;
454                 } else {
455                     ptr  = pData.V + (pInfo.CropX / 2) + (pInfo.CropY / 2) * pitch;
456                     ptr2 = pData.U + (pInfo.CropX / 2) + (pInfo.CropY / 2) * pitch;
457                 }
458 
459                 for(i = 0; i < h; i++)
460                 {
461 
462                     nBytesRead = (mfxU32)fread(ptr + i * pitch, 1, w, m_files[vid]);
463 
464                     if (w != nBytesRead)
465                     {
466                         return MFX_ERR_MORE_DATA;
467                     }
468                 }
469                 for(i = 0; i < h; i++)
470                 {
471                     nBytesRead = (mfxU32)fread(ptr2 + i * pitch, 1, w, m_files[vid]);
472 
473                     if (w != nBytesRead)
474                     {
475                         return MFX_ERR_MORE_DATA;
476                     }
477                 }
478                 break;
479             default:
480                 return MFX_ERR_UNSUPPORTED;
481             }
482             break;
483         case MFX_FOURCC_NV12:
484         case MFX_FOURCC_P010:
485         case MFX_FOURCC_P210:
486 #if (MFX_VERSION >= 1031)
487         case MFX_FOURCC_P016:
488 #endif
489             if (MFX_FOURCC_P210 != pInfo.FourCC)
490             {
491                 h /= 2;
492             }
493             ptr  = pData.UV + pInfo.CropX + (pInfo.CropY / 2) * pitch;
494             for(i = 0; i < h; i++)
495             {
496                 nBytesRead = (mfxU32)fread(ptr + i * pitch, nBytesPerPixel, w, m_files[vid]);
497 
498                 if (w != nBytesRead)
499                 {
500                     return MFX_ERR_MORE_DATA;
501                 }
502 
503                 // Shifting data if required
504             if((MFX_FOURCC_P010 == pInfo.FourCC
505              || MFX_FOURCC_P210 == pInfo.FourCC
506 #if (MFX_VERSION >= 1031)
507              || MFX_FOURCC_P016 == pInfo.FourCC
508 #endif
509              ) && shouldShift10BitsHigh)
510                 {
511                     mfxU16* shortPtr = (mfxU16*)(ptr + i * pitch);
512                     for(int idx = 0; idx < w; idx++)
513                     {
514                         shortPtr[idx]<<=shiftSizeChroma;
515                     }
516                 }
517             }
518 
519             break;
520         default:
521             return MFX_ERR_UNSUPPORTED;
522         }
523     }
524     else
525     {
526         return MFX_ERR_UNSUPPORTED;
527     }
528 
529     return MFX_ERR_NONE;
530 }
531 
CSmplBitstreamWriter()532 CSmplBitstreamWriter::CSmplBitstreamWriter()
533 {
534     m_fSource = NULL;
535     m_bInited = false;
536     m_nProcessedFramesNum = 0;
537 }
538 
~CSmplBitstreamWriter()539 CSmplBitstreamWriter::~CSmplBitstreamWriter()
540 {
541     Close();
542 }
543 
Close()544 void CSmplBitstreamWriter::Close()
545 {
546     if (m_fSource)
547     {
548         fclose(m_fSource);
549         m_fSource = NULL;
550     }
551 
552     m_bInited = false;
553 }
554 
Init(const msdk_char * strFileName)555 mfxStatus CSmplBitstreamWriter::Init(const msdk_char *strFileName)
556 {
557     MSDK_CHECK_POINTER(strFileName, MFX_ERR_NULL_PTR);
558     if (!msdk_strlen(strFileName))
559         return MFX_ERR_NONE;
560 
561     Close();
562 
563     //init file to write encoded data
564     MSDK_FOPEN(m_fSource, strFileName, MSDK_STRING("wb+"));
565     MSDK_CHECK_POINTER(m_fSource, MFX_ERR_NULL_PTR);
566 
567     m_sFile = msdk_string(strFileName);
568     //set init state to true in case of success
569     m_bInited = true;
570     return MFX_ERR_NONE;
571 }
572 
Reset()573 mfxStatus CSmplBitstreamWriter::Reset()
574 {
575     return Init(m_sFile.c_str());
576 }
577 
WriteNextFrame(mfxBitstream * pMfxBitstream,bool isPrint)578 mfxStatus CSmplBitstreamWriter::WriteNextFrame(mfxBitstream *pMfxBitstream, bool isPrint)
579 {
580     // check if writer is initialized
581     MSDK_CHECK_ERROR(m_bInited, false, MFX_ERR_NOT_INITIALIZED);
582     MSDK_CHECK_POINTER(pMfxBitstream, MFX_ERR_NULL_PTR);
583 
584     mfxU32 nBytesWritten = 0;
585 
586     nBytesWritten = (mfxU32)fwrite(pMfxBitstream->Data + pMfxBitstream->DataOffset, 1, pMfxBitstream->DataLength, m_fSource);
587     MSDK_CHECK_NOT_EQUAL(nBytesWritten, pMfxBitstream->DataLength, MFX_ERR_UNDEFINED_BEHAVIOR);
588 
589     // mark that we don't need bit stream data any more
590     pMfxBitstream->DataLength = 0;
591 
592     m_nProcessedFramesNum++;
593 
594     // print encoding progress to console every certain number of frames (not to affect performance too much)
595     if (isPrint && (1 == m_nProcessedFramesNum  || (0 == (m_nProcessedFramesNum % 100))))
596     {
597         msdk_printf(MSDK_STRING("Frame number: %u\r"), m_nProcessedFramesNum);
598     }
599 
600     return MFX_ERR_NONE;
601 }
602 
603 
CSmplBitstreamDuplicateWriter()604 CSmplBitstreamDuplicateWriter::CSmplBitstreamDuplicateWriter()
605     : CSmplBitstreamWriter()
606 {
607     m_fSourceDuplicate = NULL;
608     m_bJoined = false;
609 }
610 
InitDuplicate(const msdk_char * strFileName)611 mfxStatus CSmplBitstreamDuplicateWriter::InitDuplicate(const msdk_char *strFileName)
612 {
613     MSDK_CHECK_POINTER(strFileName, MFX_ERR_NULL_PTR);
614     MSDK_CHECK_ERROR(msdk_strlen(strFileName), 0, MFX_ERR_NOT_INITIALIZED);
615 
616     if (m_fSourceDuplicate)
617     {
618         fclose(m_fSourceDuplicate);
619         m_fSourceDuplicate = NULL;
620     }
621     MSDK_FOPEN(m_fSourceDuplicate, strFileName, MSDK_STRING("wb+"));
622     MSDK_CHECK_POINTER(m_fSourceDuplicate, MFX_ERR_NULL_PTR);
623 
624     m_bJoined = false; // mark we own the file handle
625 
626     return MFX_ERR_NONE;
627 }
628 
JoinDuplicate(CSmplBitstreamDuplicateWriter * pJoinee)629 mfxStatus CSmplBitstreamDuplicateWriter::JoinDuplicate(CSmplBitstreamDuplicateWriter *pJoinee)
630 {
631     MSDK_CHECK_POINTER(pJoinee, MFX_ERR_NULL_PTR);
632     MSDK_CHECK_ERROR(pJoinee->m_fSourceDuplicate, NULL, MFX_ERR_NOT_INITIALIZED);
633 
634     m_fSourceDuplicate = pJoinee->m_fSourceDuplicate;
635     m_bJoined = true; // mark we do not own the file handle
636 
637     return MFX_ERR_NONE;
638 }
639 
WriteNextFrame(mfxBitstream * pMfxBitstream,bool isPrint)640 mfxStatus CSmplBitstreamDuplicateWriter::WriteNextFrame(mfxBitstream *pMfxBitstream, bool isPrint)
641 {
642     MSDK_CHECK_ERROR(m_fSourceDuplicate, NULL, MFX_ERR_NOT_INITIALIZED);
643     MSDK_CHECK_POINTER(pMfxBitstream, MFX_ERR_NULL_PTR);
644 
645     mfxU32 nBytesWritten = (mfxU32)fwrite(pMfxBitstream->Data + pMfxBitstream->DataOffset, 1, pMfxBitstream->DataLength, m_fSourceDuplicate);
646     MSDK_CHECK_NOT_EQUAL(nBytesWritten, pMfxBitstream->DataLength, MFX_ERR_UNDEFINED_BEHAVIOR);
647 
648     CSmplBitstreamWriter::WriteNextFrame(pMfxBitstream, isPrint);
649 
650     return MFX_ERR_NONE;
651 }
652 
Close()653 void CSmplBitstreamDuplicateWriter::Close()
654 {
655     if (m_fSourceDuplicate && !m_bJoined)
656     {
657         fclose(m_fSourceDuplicate);
658     }
659 
660     m_fSourceDuplicate = NULL;
661     m_bJoined = false;
662 
663     CSmplBitstreamWriter::Close();
664 }
665 
CSmplBitstreamReader()666 CSmplBitstreamReader::CSmplBitstreamReader()
667 {
668     m_fSource = NULL;
669     m_bInited = false;
670 }
671 
~CSmplBitstreamReader()672 CSmplBitstreamReader::~CSmplBitstreamReader()
673 {
674     Close();
675 }
676 
Close()677 void CSmplBitstreamReader::Close()
678 {
679     if (m_fSource)
680     {
681         fclose(m_fSource);
682         m_fSource = NULL;
683     }
684 
685     m_bInited = false;
686 }
687 
Reset()688 void CSmplBitstreamReader::Reset()
689 {
690     if (!m_bInited)
691         return;
692 
693     fseek(m_fSource, 0, SEEK_SET);
694 }
695 
Init(const msdk_char * strFileName)696 mfxStatus CSmplBitstreamReader::Init(const msdk_char *strFileName)
697 {
698     MSDK_CHECK_POINTER(strFileName, MFX_ERR_NULL_PTR);
699     if (!msdk_strlen(strFileName))
700         return MFX_ERR_NONE;
701 
702     Close();
703 
704     //open file to read input stream
705     MSDK_FOPEN(m_fSource, strFileName, MSDK_STRING("rb"));
706     MSDK_CHECK_POINTER(m_fSource, MFX_ERR_NULL_PTR);
707 
708     m_bInited = true;
709     return MFX_ERR_NONE;
710 }
711 
712 #define CHECK_SET_EOS(pBitstream)                  \
713     if (feof(m_fSource))                           \
714     {                                              \
715         pBitstream->DataFlag |= MFX_BITSTREAM_EOS; \
716     }
717 
ReadNextFrame(mfxBitstream * pBS)718 mfxStatus CSmplBitstreamReader::ReadNextFrame(mfxBitstream *pBS)
719 {
720     if (!m_bInited)
721         return MFX_ERR_NOT_INITIALIZED;
722 
723     MSDK_CHECK_POINTER(pBS, MFX_ERR_NULL_PTR);
724 
725     // Not enough memory to read new chunk of data
726     if (pBS->MaxLength == pBS->DataLength)
727         return MFX_ERR_NOT_ENOUGH_BUFFER;
728 
729     memmove(pBS->Data, pBS->Data + pBS->DataOffset, pBS->DataLength);
730     pBS->DataOffset = 0;
731     mfxU32 nBytesRead = (mfxU32)fread(pBS->Data + pBS->DataLength, 1, pBS->MaxLength - pBS->DataLength, m_fSource);
732 
733     CHECK_SET_EOS(pBS);
734 
735     if (0 == nBytesRead)
736     {
737         return MFX_ERR_MORE_DATA;
738     }
739 
740     pBS->DataLength += nBytesRead;
741 
742     return MFX_ERR_NONE;
743 }
744 
745 
FindMarker(mfxBitstream * pBS,mfxU32 startOffset,CJPEGFrameReader::JPEGMarker marker)746 mfxU32 CJPEGFrameReader::FindMarker(mfxBitstream *pBS,mfxU32 startOffset,CJPEGFrameReader::JPEGMarker marker)
747 {
748     for (mfxU32 i = startOffset; i + sizeof(mfxU16) <= pBS->DataLength; i++)
749     {
750         if ( *(mfxU16*)(pBS->Data + i)==(mfxU16)marker)
751         {
752             return i;
753         }
754     }
755     return 0xFFFFFFFF;
756 }
757 
ReadNextFrame(mfxBitstream * pBS)758 mfxStatus CJPEGFrameReader::ReadNextFrame(mfxBitstream *pBS)
759 {
760     mfxStatus sts = MFX_ERR_NONE;
761     mfxU32 offsetSOI=0xFFFFFFFF;
762 
763     pBS->DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
764 
765     while ((offsetSOI = FindMarker(pBS,pBS->DataOffset,CJPEGFrameReader::SOI))==0xFFFFFFFF && sts == MFX_ERR_NONE)
766     {
767         sts = CSmplBitstreamReader::ReadNextFrame(pBS);
768     }
769 
770     //--- Finding EOI of frame, to make sure that it is complete
771     while (FindMarker(pBS,offsetSOI,CJPEGFrameReader::EOI)==0xFFFFFFFF && sts == MFX_ERR_NONE)
772     {
773         sts = CSmplBitstreamReader::ReadNextFrame(pBS);
774     }
775 
776     return sts;
777 }
778 
CIVFFrameReader()779 CIVFFrameReader::CIVFFrameReader()
780 {
781     MSDK_ZERO_MEMORY(m_hdr);
782 }
783 
784 #define READ_BYTES(pBuf, size)\
785 {\
786     mfxU32 nBytesRead = (mfxU32)fread(pBuf, 1, size, m_fSource);\
787     if (nBytesRead !=size)\
788         return MFX_ERR_MORE_DATA;\
789 }\
790 
ReadHeader()791 mfxStatus CIVFFrameReader::ReadHeader()
792 {
793     // read and skip IVF header
794     READ_BYTES(&m_hdr.dkif, sizeof(m_hdr.dkif));
795     READ_BYTES(&m_hdr.version, sizeof(m_hdr.version));
796     READ_BYTES(&m_hdr.header_len, sizeof(m_hdr.header_len));
797     READ_BYTES(&m_hdr.codec_FourCC, sizeof(m_hdr.codec_FourCC));
798     READ_BYTES(&m_hdr.width, sizeof(m_hdr.width));
799     READ_BYTES(&m_hdr.height, sizeof(m_hdr.height));
800     READ_BYTES(&m_hdr.frame_rate, sizeof(m_hdr.frame_rate));
801     READ_BYTES(&m_hdr.time_scale, sizeof(m_hdr.time_scale));
802     READ_BYTES(&m_hdr.num_frames, sizeof(m_hdr.num_frames));
803     READ_BYTES(&m_hdr.unused, sizeof(m_hdr.unused));
804     MSDK_CHECK_NOT_EQUAL(fseek(m_fSource, m_hdr.header_len, SEEK_SET), 0, MFX_ERR_UNSUPPORTED);
805     return MFX_ERR_NONE;
806 }
807 
Reset()808 void CIVFFrameReader::Reset()
809 {
810     CSmplBitstreamReader::Reset();
811     std::ignore = ReadHeader();
812 }
813 
Init(const msdk_char * strFileName)814 mfxStatus CIVFFrameReader::Init(const msdk_char *strFileName)
815 {
816     mfxStatus sts = CSmplBitstreamReader::Init(strFileName);
817     MSDK_CHECK_STATUS(sts, "CSmplBitstreamReader::Init failed");
818 
819     sts = ReadHeader();
820     MSDK_CHECK_STATUS(sts, "CIVFFrameReader::ReadHeader failed");
821 
822     // check header
823     MSDK_CHECK_NOT_EQUAL(MFX_MAKEFOURCC('D','K','I','F'), m_hdr.dkif, MFX_ERR_UNSUPPORTED);
824     if ((m_hdr.codec_FourCC != MFX_MAKEFOURCC('V','P','8','0')) &&
825         (m_hdr.codec_FourCC != MFX_MAKEFOURCC('V','P','9','0')) &&
826         (m_hdr.codec_FourCC != MFX_MAKEFOURCC('A','V','0','1')))
827     {
828         return MFX_ERR_UNSUPPORTED;
829     }
830 
831     return MFX_ERR_NONE;
832 }
833 
834 // reads a complete frame into given bitstream
ReadNextFrame(mfxBitstream * pBS)835 mfxStatus CIVFFrameReader::ReadNextFrame(mfxBitstream *pBS)
836 {
837     MSDK_CHECK_POINTER(pBS, MFX_ERR_NULL_PTR);
838 
839     memmove(pBS->Data, pBS->Data + pBS->DataOffset, pBS->DataLength);
840     pBS->DataOffset = 0;
841     pBS->DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
842 
843     /*bytes pos-(pos+3)                       size of frame in bytes (not including the 12-byte header)
844       bytes (pos+4)-(pos+11)                  64-bit presentation timestamp
845       bytes (pos+12)-(pos+12+nBytesInFrame)   frame data
846     */
847 
848     mfxU32 nBytesInFrame = 0;
849     mfxU64 nTimeStamp = 0;
850 
851     // read frame size
852     READ_BYTES(&nBytesInFrame, sizeof(nBytesInFrame));
853     CHECK_SET_EOS(pBS);
854 
855     // read time stamp
856     READ_BYTES(&nTimeStamp, sizeof(nTimeStamp));
857     CHECK_SET_EOS(pBS);
858 
859     //check if bitstream has enough space to hold the frame
860     if (nBytesInFrame > pBS->MaxLength - pBS->DataLength - pBS->DataOffset)
861         return MFX_ERR_NOT_ENOUGH_BUFFER;
862 
863     // read frame data
864     READ_BYTES(pBS->Data + pBS->DataOffset + pBS->DataLength, nBytesInFrame);
865     CHECK_SET_EOS(pBS);
866     pBS->DataLength += nBytesInFrame;
867 
868     // it is application's responsibility to make sure the bitstream contains a single complete frame and nothing else
869     // application has to provide input pBS with pBS->DataLength = 0
870 
871     return MFX_ERR_NONE;
872 }
873 
874 
CSmplYUVWriter()875 CSmplYUVWriter::CSmplYUVWriter()
876 {
877     m_bInited = false;
878     m_bIsMultiView = false;
879     m_fDest = NULL;
880     m_fDestMVC = NULL;
881     m_numCreatedFiles = 0;
882     m_nViews = 0;
883 };
884 
Init(const msdk_char * strFileName,const mfxU32 numViews)885 mfxStatus CSmplYUVWriter::Init(const msdk_char *strFileName, const mfxU32 numViews)
886 {
887     MSDK_CHECK_POINTER(strFileName, MFX_ERR_NULL_PTR);
888     MSDK_CHECK_ERROR(msdk_strlen(strFileName), 0, MFX_ERR_NOT_INITIALIZED);
889 
890     m_sFile = msdk_string(strFileName);
891     m_nViews = numViews;
892 
893     Close();
894 
895     //open file to write decoded data
896 
897     if (!m_bIsMultiView)
898     {
899         MSDK_FOPEN(m_fDest, m_sFile.c_str(), MSDK_STRING("wb"));
900         MSDK_CHECK_POINTER(m_fDest, MFX_ERR_NULL_PTR);
901         ++m_numCreatedFiles;
902     }
903     else
904     {
905         mfxU32 i;
906 
907         MSDK_CHECK_ERROR(numViews, 0, MFX_ERR_NOT_INITIALIZED);
908 
909         m_fDestMVC = new FILE*[numViews];
910         for (i = 0; i < numViews; ++i)
911         {
912             MSDK_FOPEN(m_fDestMVC[i], FormMVCFileName(m_sFile.c_str(), i).c_str(), MSDK_STRING("wb"));
913             MSDK_CHECK_POINTER(m_fDestMVC[i], MFX_ERR_NULL_PTR);
914             ++m_numCreatedFiles;
915         }
916     }
917 
918     m_bInited = true;
919 
920     return MFX_ERR_NONE;
921 }
922 
Reset()923 mfxStatus CSmplYUVWriter::Reset()
924 {
925     if (!m_bInited)
926         return MFX_ERR_NONE;
927 
928     return Init(m_sFile.c_str(), m_nViews);
929 }
930 
~CSmplYUVWriter()931 CSmplYUVWriter::~CSmplYUVWriter()
932 {
933     Close();
934 }
935 
Close()936 void CSmplYUVWriter::Close()
937 {
938     if (m_fDest)
939     {
940         fclose(m_fDest);
941         m_fDest = NULL;
942     }
943 
944     if (m_fDestMVC)
945     {
946         mfxU32 i = 0;
947         for (i = 0; i < m_numCreatedFiles; ++i)
948         {
949             if  (m_fDestMVC[i] != NULL)
950             {
951                 fclose(m_fDestMVC[i]);
952                 m_fDestMVC[i] = NULL;
953             }
954         }
955         delete [] m_fDestMVC;
956         m_fDestMVC = NULL;
957     }
958 
959     m_numCreatedFiles = 0;
960     m_bInited = false;
961 }
962 
GetChromaSize(const mfxFrameInfo & pInfo,mfxU32 & ChromaW,mfxU32 & ChromaH)963 mfxStatus GetChromaSize(const mfxFrameInfo & pInfo, mfxU32 & ChromaW, mfxU32 & ChromaH)
964 {
965     switch (pInfo.FourCC)
966     {
967     case MFX_FOURCC_YV12:
968     {
969         ChromaW = (pInfo.CropW + 1) / 2;
970         ChromaH = (pInfo.CropH + 1) / 2;
971         break;
972     }
973     case MFX_FOURCC_NV12:
974     {
975         ChromaW = (pInfo.CropW % 2) ? (pInfo.CropW + 1) : pInfo.CropW;
976         ChromaH = (pInfo.CropH + 1) / 2;
977         break;
978     }
979     case MFX_FOURCC_P010:
980     case MFX_FOURCC_P016:
981     {
982         ChromaW = (pInfo.CropW % 2) ? (pInfo.CropW + 1) : pInfo.CropW;
983         ChromaH = (mfxU32)(pInfo.CropH + 1) / 2;
984         break;
985     }
986 
987     case MFX_FOURCC_P210:
988     case MFX_FOURCC_Y210:
989     case MFX_FOURCC_Y216:
990     {
991         ChromaW = (pInfo.CropW % 2) ? (pInfo.CropW + 1) : pInfo.CropW;
992         ChromaH = pInfo.CropH;
993         break;
994     }
995 
996     case MFX_FOURCC_RGB4:
997     case MFX_FOURCC_AYUV:
998     case MFX_FOURCC_YUY2:
999     case MFX_FOURCC_NV16:
1000     case MFX_FOURCC_A2RGB10:
1001     case MFX_FOURCC_Y410:
1002     case MFX_FOURCC_Y416:
1003     {
1004         if (pInfo.CropH > 0 && pInfo.CropW > 0)
1005         {
1006             ChromaW = pInfo.FourCC == MFX_FOURCC_YUY2 ? (pInfo.CropW + 1) / 2 : pInfo.CropW;
1007             ChromaH = pInfo.CropH;
1008         }
1009         else
1010         {
1011             ChromaW = pInfo.FourCC == MFX_FOURCC_YUY2 ? (pInfo.Width + 1) / 2 : pInfo.Width;
1012             ChromaH = pInfo.Height;
1013         }
1014         break;
1015     }
1016 
1017     default:
1018         return MFX_ERR_UNSUPPORTED;
1019     }
1020 
1021     return MFX_ERR_NONE;
1022 }
1023 
WriteNextFrame(mfxFrameSurface1 * pSurface)1024 mfxStatus CSmplYUVWriter::WriteNextFrame(mfxFrameSurface1 *pSurface)
1025 {
1026     MSDK_CHECK_ERROR(m_bInited, false, MFX_ERR_NOT_INITIALIZED);
1027     MSDK_CHECK_POINTER(pSurface, MFX_ERR_NULL_PTR);
1028 
1029     mfxFrameInfo &pInfo = pSurface->Info;
1030     mfxFrameData &pData = pSurface->Data;
1031 
1032     mfxU32 i;
1033     mfxU32 vid = pInfo.FrameId.ViewId;
1034 
1035     mfxU32 shiftSizeLuma   = 16 - pInfo.BitDepthLuma;
1036     mfxU32 shiftSizeChroma = 16 - pInfo.BitDepthChroma;
1037     // Temporary buffer to convert MS to no-MS format
1038     std::vector<mfxU16> tmp;
1039 
1040     if (!m_bIsMultiView)
1041     {
1042         MSDK_CHECK_POINTER(m_fDest, MFX_ERR_NULL_PTR);
1043     }
1044     else
1045     {
1046         MSDK_CHECK_POINTER(m_fDestMVC, MFX_ERR_NULL_PTR);
1047         MSDK_CHECK_POINTER(m_fDestMVC[vid], MFX_ERR_NULL_PTR);
1048     }
1049 
1050     FILE* dstFile = m_bIsMultiView ? m_fDestMVC[vid] : m_fDest;
1051 
1052     mfxU32 ChromaW, ChromaH;
1053     if (MFX_ERR_NONE != GetChromaSize(pInfo, ChromaW, ChromaH))
1054         return MFX_ERR_UNSUPPORTED;
1055 
1056     switch (pInfo.FourCC)
1057     {
1058     case MFX_FOURCC_YV12:
1059     case MFX_FOURCC_NV12:
1060     case MFX_FOURCC_NV16:
1061         for (i = 0; i < pInfo.CropH; i++)
1062         {
1063             MSDK_CHECK_NOT_EQUAL(
1064                 fwrite(pData.Y + (pInfo.CropY * pData.Pitch + pInfo.CropX) + i * pData.Pitch, 1, pInfo.CropW, dstFile),
1065                 pInfo.CropW, MFX_ERR_UNDEFINED_BEHAVIOR);
1066         }
1067         break;
1068 #if (MFX_VERSION >= 1027)
1069     case MFX_FOURCC_Y210:
1070 #if (MFX_VERSION >= 1031)
1071     case MFX_FOURCC_Y216: // Luma and chroma will be filled below
1072 #endif
1073     {
1074         for (i = 0; i < pInfo.CropH; i++)
1075         {
1076             mfxU8* pBuffer = ((mfxU8*)pData.Y) + (pInfo.CropY * pData.Pitch + pInfo.CropX * 4) + i * pData.Pitch;
1077             if (pInfo.Shift)
1078             {
1079                 // Bits will be shifted to the lower position
1080                 tmp.resize(pInfo.CropW * 2);
1081 
1082                 for (int idx = 0; idx < pInfo.CropW*2; idx++)
1083                 {
1084                     tmp[idx] = ((mfxU16*)pBuffer)[idx] >> shiftSizeLuma;
1085                 }
1086 
1087                 MSDK_CHECK_NOT_EQUAL(
1088                     fwrite(((const mfxU8*)tmp.data()), 4, pInfo.CropW, dstFile),
1089                     pInfo.CropW, MFX_ERR_UNDEFINED_BEHAVIOR);
1090             }
1091             else
1092             {
1093                 MSDK_CHECK_NOT_EQUAL(
1094                     fwrite(pBuffer, 4, pInfo.CropW, dstFile),
1095                     pInfo.CropW, MFX_ERR_UNDEFINED_BEHAVIOR);
1096             }
1097         }
1098         return MFX_ERR_NONE;
1099     }
1100     break;
1101 #endif
1102 #if (MFX_VERSION >= 1027)
1103     case MFX_FOURCC_Y410: // Luma and chroma will be filled below
1104     {
1105         mfxU8* pBuffer = (mfxU8*)pData.Y410;
1106         for (i = 0; i < pInfo.CropH; i++)
1107         {
1108             MSDK_CHECK_NOT_EQUAL(
1109                 fwrite(pBuffer + (pInfo.CropY * pData.Pitch + pInfo.CropX * 4) + i * pData.Pitch, 4, pInfo.CropW, dstFile),
1110                 pInfo.CropW, MFX_ERR_UNDEFINED_BEHAVIOR);
1111         }
1112         return MFX_ERR_NONE;
1113     }
1114     break;
1115 #endif
1116 #if (MFX_VERSION >= 1031)
1117     case MFX_FOURCC_Y416:  // Luma and chroma will be filled below
1118     {
1119         for (i = 0; i < pInfo.CropH; i++)
1120         {
1121             mfxU8* pBuffer = ((mfxU8*)pData.U) + (pInfo.CropY * pData.Pitch + pInfo.CropX * 8) + i * pData.Pitch;
1122             if (pInfo.Shift)
1123             {
1124                 tmp.resize(pInfo.CropW * 4);
1125 
1126                 for (int idx = 0; idx < pInfo.CropW*4; idx++)
1127                 {
1128                     tmp[idx] = ((mfxU16*)pBuffer)[idx] >> shiftSizeLuma;
1129                 }
1130 
1131                 MSDK_CHECK_NOT_EQUAL(
1132                     fwrite(((const mfxU8*)tmp.data()), 8, pInfo.CropW, dstFile),
1133                     pInfo.CropW, MFX_ERR_UNDEFINED_BEHAVIOR);
1134             }
1135             else
1136             {
1137                 MSDK_CHECK_NOT_EQUAL(
1138                     fwrite(pBuffer, 8, pInfo.CropW, dstFile),
1139                     pInfo.CropW, MFX_ERR_UNDEFINED_BEHAVIOR);
1140             }
1141         }
1142         return MFX_ERR_NONE;
1143     }
1144     break;
1145 #endif
1146     case MFX_FOURCC_P010:
1147 #if (MFX_VERSION >= 1031)
1148     case MFX_FOURCC_P016:
1149 #endif
1150     case MFX_FOURCC_P210:
1151     {
1152         for (i = 0; i < pInfo.CropH; i++)
1153         {
1154             mfxU16* shortPtr = (mfxU16*)(pData.Y + (pInfo.CropY * pData.Pitch + pInfo.CropX) + i * pData.Pitch);
1155             if (pInfo.Shift)
1156             {
1157                 // Convert MS-P*1* to P*1* and write
1158                 // Bits will be shifted to the lower position
1159                 tmp.resize(pData.Pitch);
1160 
1161                 for (int idx = 0; idx < pInfo.CropW; idx++)
1162                 {
1163                     tmp[idx] = shortPtr[idx] >> shiftSizeLuma;
1164                 }
1165 
1166                 MSDK_CHECK_NOT_EQUAL(
1167                     fwrite(&tmp[0], 1, (mfxU32)pInfo.CropW * 2, dstFile),
1168                     (mfxU32)pInfo.CropW * 2, MFX_ERR_UNDEFINED_BEHAVIOR);
1169 
1170             }
1171             else
1172             {
1173                 MSDK_CHECK_NOT_EQUAL(
1174                     fwrite(shortPtr, 1, (mfxU32)pInfo.CropW * 2, dstFile),
1175                     (mfxU32)pInfo.CropW * 2, MFX_ERR_UNDEFINED_BEHAVIOR);
1176             }
1177         }
1178 
1179         break;
1180     }
1181     case MFX_FOURCC_RGB4:
1182     case MFX_FOURCC_AYUV:
1183     case MFX_FOURCC_A2RGB10:
1184     case MFX_FOURCC_YUY2:
1185         // Implementation for these formats is in the next switch below
1186         break;
1187 
1188     default:
1189         return MFX_ERR_UNSUPPORTED;
1190     }
1191     switch (pInfo.FourCC)
1192     {
1193     case MFX_FOURCC_YV12:
1194     {
1195         for (i = 0; i < ChromaH; i++)
1196         {
1197             MSDK_CHECK_NOT_EQUAL(
1198                 fwrite(pData.V + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX / 2) + i * pData.Pitch, 1, ChromaW, dstFile),
1199                 ChromaW, MFX_ERR_UNDEFINED_BEHAVIOR);
1200         }
1201         for (i = 0; i < ChromaH; i++)
1202         {
1203             MSDK_CHECK_NOT_EQUAL(
1204                 fwrite(pData.U + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX / 2) + i * pData.Pitch / 2, 1, ChromaW, dstFile),
1205                 ChromaW, MFX_ERR_UNDEFINED_BEHAVIOR);
1206         }
1207         break;
1208     }
1209     case MFX_FOURCC_NV12:
1210     {
1211         for (i = 0; i < ChromaH; i++)
1212         {
1213             MSDK_CHECK_NOT_EQUAL(
1214                 fwrite(pData.UV + (pInfo.CropY * pData.Pitch + pInfo.CropX) + i * pData.Pitch, 1, ChromaW, dstFile),
1215                 ChromaW, MFX_ERR_UNDEFINED_BEHAVIOR);
1216         }
1217         break;
1218     }
1219     case MFX_FOURCC_NV16:
1220     {
1221         for (i = 0; i < ChromaH; i++)
1222         {
1223             MSDK_CHECK_NOT_EQUAL(
1224                 fwrite(pData.UV + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX) + i * pData.Pitch, 1, ChromaW, dstFile),
1225                 ChromaW, MFX_ERR_UNDEFINED_BEHAVIOR);
1226         }
1227         break;
1228     }
1229     case MFX_FOURCC_P010:
1230 #if (MFX_VERSION >= 1031)
1231     case MFX_FOURCC_P016:
1232 #endif
1233     case MFX_FOURCC_P210:
1234     {
1235         for (i = 0; i < ChromaH; i++)
1236         {
1237             mfxU16* shortPtr = (mfxU16*)(pData.UV + (pInfo.CropY * pData.Pitch + pInfo.CropX*2) + i * pData.Pitch);
1238             if (pInfo.Shift)
1239             {
1240                 // Convert MS-P*1* to P*1* and write
1241                 // Bits will be shifted to the lower position
1242                 tmp.resize(pData.Pitch);
1243 
1244                 for (mfxU32 idx = 0; idx < ChromaW; idx++)
1245                 {
1246                     tmp[idx] = shortPtr[idx] >> shiftSizeChroma;
1247                 }
1248 
1249                 MSDK_CHECK_NOT_EQUAL(
1250                     fwrite(&tmp[0], 1, ChromaW * 2, dstFile),
1251                     (mfxU32)ChromaW * 2, MFX_ERR_UNDEFINED_BEHAVIOR);
1252 
1253             }
1254             else
1255             {
1256                 MSDK_CHECK_NOT_EQUAL(
1257                     fwrite(shortPtr, 1, ChromaW * 2, dstFile),
1258                     ChromaW * 2, MFX_ERR_UNDEFINED_BEHAVIOR);
1259             }
1260         }
1261         break;
1262     }
1263 
1264     case MFX_FOURCC_RGB4:
1265     case MFX_FOURCC_AYUV:
1266     case MFX_FOURCC_YUY2:
1267     case MFX_FOURCC_A2RGB10:
1268     {
1269         mfxU8* ptr;
1270 
1271         ptr = std::min({pData.R, pData.G, pData.B});
1272         ptr = ptr + pInfo.CropX + pInfo.CropY * pData.Pitch;
1273 
1274         for (i = 0; i < ChromaH; i++)
1275         {
1276             MSDK_CHECK_NOT_EQUAL(fwrite(ptr + i * pData.Pitch, 1, 4 * ChromaW, dstFile), 4 * ChromaW, MFX_ERR_UNDEFINED_BEHAVIOR);
1277         }
1278         fflush(dstFile);
1279         break;
1280     }
1281 
1282     default:
1283         return MFX_ERR_UNSUPPORTED;
1284     }
1285 
1286     return MFX_ERR_NONE;
1287 }
1288 
WriteNextFrameI420(mfxFrameSurface1 * pSurface)1289 mfxStatus CSmplYUVWriter::WriteNextFrameI420(mfxFrameSurface1 *pSurface)
1290 {
1291     MSDK_CHECK_ERROR(m_bInited, false,   MFX_ERR_NOT_INITIALIZED);
1292     MSDK_CHECK_POINTER(pSurface,         MFX_ERR_NULL_PTR);
1293 
1294     mfxFrameInfo &pInfo = pSurface->Info;
1295     mfxFrameData &pData = pSurface->Data;
1296 
1297     mfxU32 i, j;
1298     mfxU32 vid = pInfo.FrameId.ViewId;
1299 
1300     if (!m_bIsMultiView)
1301     {
1302         MSDK_CHECK_POINTER(m_fDest, MFX_ERR_NULL_PTR);
1303     }
1304     else
1305     {
1306         MSDK_CHECK_POINTER(m_fDestMVC, MFX_ERR_NULL_PTR);
1307         MSDK_CHECK_POINTER(m_fDestMVC[vid], MFX_ERR_NULL_PTR);
1308     }
1309 
1310     mfxU32 ChromaW, ChromaH;
1311     if (MFX_ERR_NONE != GetChromaSize(pInfo, ChromaW, ChromaH))
1312         return MFX_ERR_UNSUPPORTED;
1313 
1314     // Write Y
1315     switch (pInfo.FourCC)
1316     {
1317         case MFX_FOURCC_YV12:
1318         case MFX_FOURCC_NV12:
1319         {
1320             for (i = 0; i < pInfo.CropH; i++)
1321             {
1322                 if (!m_bIsMultiView)
1323                 {
1324                     MSDK_CHECK_NOT_EQUAL(
1325                         fwrite(pData.Y + (pInfo.CropY * pData.Pitch + pInfo.CropX)+ i * pData.Pitch, 1, pInfo.CropW, m_fDest),
1326                         pInfo.CropW, MFX_ERR_UNDEFINED_BEHAVIOR);
1327                 }
1328                 else
1329                 {
1330                     MSDK_CHECK_NOT_EQUAL(
1331                         fwrite(pData.Y + (pInfo.CropY * pData.Pitch + pInfo.CropX)+ i * pData.Pitch, 1, pInfo.CropW, m_fDestMVC[vid]),
1332                         pInfo.CropW, MFX_ERR_UNDEFINED_BEHAVIOR);
1333                 }
1334             }
1335             break;
1336         }
1337         default:
1338         {
1339             msdk_printf(MSDK_STRING("ERROR: I420 output is accessible only for NV12 and YV12.\n"));
1340             return MFX_ERR_UNSUPPORTED;
1341         }
1342     }
1343 
1344     // Write U and V
1345     switch (pInfo.FourCC)
1346     {
1347         case MFX_FOURCC_YV12:
1348         {
1349             for (i = 0; i < ChromaH; i++)
1350             {
1351                 if (!m_bIsMultiView)
1352                 {
1353                     MSDK_CHECK_NOT_EQUAL(
1354                         fwrite(pData.U + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX / 2)+ i * pData.Pitch / 2, 1, ChromaW, m_fDest),
1355                         (mfxU32)pInfo.CropW/2, MFX_ERR_UNDEFINED_BEHAVIOR);
1356                 }
1357                 else
1358                 {
1359                     MSDK_CHECK_NOT_EQUAL(
1360                         fwrite(pData.U + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX / 2)+ i * pData.Pitch / 2, 1, ChromaW, m_fDestMVC[vid]),
1361                         (mfxU32)pInfo.CropW/2, MFX_ERR_UNDEFINED_BEHAVIOR);
1362                 }
1363             }
1364             for (i = 0; i < ChromaH; i++)
1365             {
1366                 if (!m_bIsMultiView)
1367                 {
1368                     MSDK_CHECK_NOT_EQUAL(
1369                         fwrite(pData.V + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX / 2)+ i * pData.Pitch / 2, 1, ChromaW, m_fDest),
1370                         (mfxU32)pInfo.CropW/2, MFX_ERR_UNDEFINED_BEHAVIOR);
1371                 }
1372                 else
1373                 {
1374                     MSDK_CHECK_NOT_EQUAL(
1375                         fwrite(pData.V + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX / 2)+ i * pData.Pitch / 2, 1, ChromaW, m_fDestMVC[vid]),
1376                         (mfxU32)pInfo.CropW/2, MFX_ERR_UNDEFINED_BEHAVIOR);
1377                 }
1378             }
1379             break;
1380         }
1381         case MFX_FOURCC_NV12:
1382         {
1383             for (i = 0; i < ChromaH; i++)
1384             {
1385                 for (j = 0; j < ChromaW; j += 2)
1386                 {
1387                     if (!m_bIsMultiView)
1388                     {
1389                         MSDK_CHECK_NOT_EQUAL(
1390                             fwrite(pData.UV + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX) + i * pData.Pitch + j, 1, 1, m_fDest),
1391                             1, MFX_ERR_UNDEFINED_BEHAVIOR);
1392                     }
1393                     else
1394                     {
1395                         MSDK_CHECK_NOT_EQUAL(
1396                             fwrite(pData.UV + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX) + i * pData.Pitch + j, 1, 1, m_fDestMVC[vid]),
1397                             1, MFX_ERR_UNDEFINED_BEHAVIOR);
1398                     }
1399                 }
1400             }
1401             for (i = 0; i < ChromaH; i++)
1402             {
1403                 for (j = 1; j < ChromaW; j += 2)
1404                 {
1405                     if (!m_bIsMultiView)
1406                     {
1407                         MSDK_CHECK_NOT_EQUAL(
1408                             fwrite(pData.UV + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX)+ i * pData.Pitch + j, 1, 1, m_fDest),
1409                             1, MFX_ERR_UNDEFINED_BEHAVIOR);
1410                     }
1411                     else
1412                     {
1413                         MSDK_CHECK_NOT_EQUAL(
1414                             fwrite(pData.UV + (pInfo.CropY * pData.Pitch / 2 + pInfo.CropX)+ i * pData.Pitch + j, 1, 1, m_fDestMVC[vid]),
1415                             1, MFX_ERR_UNDEFINED_BEHAVIOR);
1416                     }
1417                 }
1418             }
1419             break;
1420         }
1421         default:
1422         {
1423             msdk_printf(MSDK_STRING("ERROR: I420 output is accessible only for NV12 and YV12.\n"));
1424             return MFX_ERR_UNSUPPORTED;
1425         }
1426     }
1427 
1428     return MFX_ERR_NONE;
1429 }
1430 
ResetState()1431 void QPFile::Reader::ResetState()
1432 {
1433     ResetState(READER_ERR_NOT_INITIALIZED);
1434 }
1435 
ResetState(ReaderStatus set_sts)1436 void QPFile::Reader::ResetState(ReaderStatus set_sts)
1437 {
1438     m_CurFrameNum = std::numeric_limits<mfxU32>::max();
1439     m_nFrames     = std::numeric_limits<mfxU32>::max();
1440     m_ReaderSts   = set_sts;
1441     m_FrameVals.clear();
1442 }
1443 
Read(const msdk_string & strFileName,mfxU32 codecid)1444 mfxStatus QPFile::Reader::Read(const msdk_string& strFileName, mfxU32 codecid)
1445 {
1446     m_ReaderSts   = READER_ERR_NONE;
1447     m_CurFrameNum = 0;
1448 
1449     if (codecid != MFX_CODEC_AVC && codecid != MFX_CODEC_HEVC)
1450     {
1451         ResetState(READER_ERR_CODEC_UNSUPPORTED);
1452         return MFX_ERR_NOT_INITIALIZED;
1453     }
1454 
1455     std::ifstream ifs(strFileName, msdk_fstream::in);
1456     if (!ifs.is_open())
1457     {
1458         ResetState(READER_ERR_FILE_NOT_OPEN);
1459         return MFX_ERR_NOT_INITIALIZED;
1460     }
1461 
1462     FrameInfo   frameInfo{};
1463     std::string line;
1464     std::getline(ifs, line);
1465     m_nFrames = std::stoi(line); // number of frames at first line
1466 
1467     m_FrameVals.reserve(m_nFrames);
1468 
1469     while (QPFile::get_line(ifs, line))
1470     {
1471         frameInfo.displayOrder = QPFile::ReadDisplayOrder(line);
1472         frameInfo.QP = QPFile::ReadQP(line);
1473         frameInfo.frameType = QPFile::ReadFrameType(line);
1474         if ( frameInfo.displayOrder > m_nFrames ||
1475                 frameInfo.QP > 51 ||
1476                 frameInfo.frameType == MFX_FRAMETYPE_UNKNOWN )
1477         {
1478             ResetState(READER_ERR_INCORRECT_FILE);
1479             return MFX_ERR_NOT_INITIALIZED;
1480         }
1481         m_FrameVals.push_back(frameInfo);
1482     }
1483     if (m_FrameVals.size() < m_nFrames)
1484     {
1485         ResetState(READER_ERR_INCORRECT_FILE);
1486         return MFX_ERR_NOT_INITIALIZED;
1487     }
1488 
1489     return MFX_ERR_NONE;
1490 }
1491 
GetErrorMessage() const1492 std::string QPFile::Reader::GetErrorMessage() const   { return ReaderStatusToString(m_ReaderSts); }
GetCurrentEncodedOrder() const1493 mfxU32 QPFile::Reader::GetCurrentEncodedOrder() const { return m_CurFrameNum; }
GetCurrentDisplayOrder() const1494 mfxU32 QPFile::Reader::GetCurrentDisplayOrder() const { return m_FrameVals.at(m_CurFrameNum).displayOrder; }
GetCurrentQP() const1495 mfxU16 QPFile::Reader::GetCurrentQP() const           { return m_FrameVals.at(m_CurFrameNum).QP; }
GetCurrentFrameType() const1496 mfxU16 QPFile::Reader::GetCurrentFrameType() const    { return m_FrameVals.at(m_CurFrameNum).frameType; }
GetFramesNum() const1497 mfxU32 QPFile::Reader::GetFramesNum() const           { return m_nFrames; }
NextFrame()1498 void   QPFile::Reader::NextFrame()                    { ++m_CurFrameNum; }
1499 
1500 
ResetState(ReaderStatus set_sts)1501 void TCBRCTestFile::Reader::ResetState(ReaderStatus set_sts)
1502 {
1503     m_CurFrameNum = std::numeric_limits<mfxU32>::max();
1504     m_ReaderSts = set_sts;
1505     m_FrameVals.clear();
1506 }
1507 
Read(const msdk_string & strFileName,mfxU32 codecid)1508 mfxStatus TCBRCTestFile::Reader::Read(const msdk_string& strFileName, mfxU32 codecid)
1509 {
1510     m_ReaderSts = READER_ERR_NONE;
1511     m_CurFrameNum = 0;
1512 
1513     if (codecid != MFX_CODEC_AVC && codecid != MFX_CODEC_HEVC)
1514     {
1515         ResetState(READER_ERR_CODEC_UNSUPPORTED);
1516         return MFX_ERR_NOT_INITIALIZED;
1517     }
1518 
1519     std::ifstream ifs(strFileName, msdk_fstream::in);
1520     if (!ifs.is_open())
1521     {
1522         ResetState(READER_ERR_FILE_NOT_OPEN);
1523         return MFX_ERR_NOT_INITIALIZED;
1524     }
1525 
1526     FrameInfo   frameInfo{};
1527     std::string line;
1528 
1529 
1530     mfxU32 n = 0;
1531     while (TCBRCTestFile::get_line(ifs, line))
1532     {
1533         frameInfo.displayOrder = TCBRCTestFile::ReadDisplayOrder(line);
1534         frameInfo.targetFrameSize = TCBRCTestFile::ReadTargetFrameSize(line);
1535         if (frameInfo.displayOrder==0)
1536             frameInfo.displayOrder  = n;
1537         m_FrameVals.push_back(frameInfo);
1538         n++;
1539     }
1540     return MFX_ERR_NONE;
1541 }
GetErrorMessage() const1542 std::string TCBRCTestFile::Reader::GetErrorMessage() const { return ReaderStatusToString(m_ReaderSts); }
GetTargetFrameSize(mfxU32 displayOrder) const1543 mfxU32 TCBRCTestFile::Reader::GetTargetFrameSize(mfxU32 displayOrder) const
1544 {
1545     mfxU32 num = (mfxU32)m_FrameVals.size();
1546     if (num == 0) return 0;
1547     for (mfxU32 i = 0; i < num - 1; i++)
1548     {
1549         if (m_FrameVals.at(i + 1).displayOrder > displayOrder)
1550             return m_FrameVals.at(i).targetFrameSize;
1551 
1552     }
1553     return m_FrameVals.at(num - 1).targetFrameSize;
1554 }
1555 
ConvertFrameRate(mfxF64 dFrameRate,mfxU32 * pnFrameRateExtN,mfxU32 * pnFrameRateExtD)1556 mfxStatus ConvertFrameRate(mfxF64 dFrameRate, mfxU32* pnFrameRateExtN, mfxU32* pnFrameRateExtD)
1557 {
1558     MSDK_CHECK_POINTER(pnFrameRateExtN, MFX_ERR_NULL_PTR);
1559     MSDK_CHECK_POINTER(pnFrameRateExtD, MFX_ERR_NULL_PTR);
1560 
1561     mfxU32 fr;
1562 
1563     fr = (mfxU32)(dFrameRate + .5);
1564 
1565     if (fabs(fr - dFrameRate) < 0.0001)
1566     {
1567         *pnFrameRateExtN = fr;
1568         *pnFrameRateExtD = 1;
1569         return MFX_ERR_NONE;
1570     }
1571 
1572     fr = (mfxU32)(dFrameRate * 1.001 + .5);
1573 
1574     if (fabs(fr * 1000 - dFrameRate * 1001) < 10)
1575     {
1576         *pnFrameRateExtN = fr * 1000;
1577         *pnFrameRateExtD = 1001;
1578         return MFX_ERR_NONE;
1579     }
1580 
1581     *pnFrameRateExtN = (mfxU32)(dFrameRate * 10000 + .5);
1582     *pnFrameRateExtD = 10000;
1583 
1584     return MFX_ERR_NONE;
1585 }
1586 
CalculateFrameRate(mfxU32 nFrameRateExtN,mfxU32 nFrameRateExtD)1587 mfxF64 CalculateFrameRate(mfxU32 nFrameRateExtN, mfxU32 nFrameRateExtD)
1588 {
1589     if (nFrameRateExtN && nFrameRateExtD)
1590         return (mfxF64)nFrameRateExtN / nFrameRateExtD;
1591     else
1592         return 0;
1593 }
1594 
FreeSurfacePool(mfxFrameSurface1 * pSurfacesPool,mfxU16 nPoolSize)1595 void FreeSurfacePool(mfxFrameSurface1* pSurfacesPool, mfxU16 nPoolSize)
1596 {
1597     if (pSurfacesPool)
1598     {
1599         for (mfxU16 i = 0; i < nPoolSize; i++)
1600         {
1601             pSurfacesPool[i].Data.Locked = 0;
1602         }
1603     }
1604 }
1605 
GetFreeSurface(mfxFrameSurface1 * pSurfacesPool,mfxU16 nPoolSize)1606 mfxU16 GetFreeSurface(mfxFrameSurface1* pSurfacesPool, mfxU16 nPoolSize)
1607 {
1608     mfxU32 SleepInterval = 10; // milliseconds
1609 
1610     mfxU16 idx = MSDK_INVALID_SURF_IDX;
1611 
1612     CTimer t;
1613     t.Start();
1614     //wait if there's no free surface
1615     do
1616     {
1617         idx = GetFreeSurfaceIndex(pSurfacesPool, nPoolSize);
1618 
1619         if (MSDK_INVALID_SURF_IDX != idx)
1620         {
1621             break;
1622         }
1623         else
1624         {
1625             MSDK_SLEEP(SleepInterval);
1626         }
1627     } while ( t.GetTime() < MSDK_SURFACE_WAIT_INTERVAL / 1000 );
1628 
1629     if(idx==MSDK_INVALID_SURF_IDX)
1630     {
1631         msdk_printf(MSDK_STRING("ERROR: No free surfaces in pool (during long period)\n"));
1632     }
1633 
1634     return idx;
1635 }
1636 
CodecIdToStr(mfxU32 nFourCC)1637 std::basic_string<msdk_char> CodecIdToStr(mfxU32 nFourCC)
1638 {
1639     std::basic_string<msdk_char> fcc;
1640     for (size_t i = 0; i < 4; i++)
1641     {
1642         fcc.push_back((msdk_char)*(i + (char*)&nFourCC));
1643     }
1644     return fcc;
1645 }
1646 
PartiallyLinearFNC()1647 PartiallyLinearFNC::PartiallyLinearFNC()
1648 : m_pX()
1649 , m_pY()
1650 , m_nPoints()
1651 , m_nAllocated()
1652 {
1653 }
1654 
~PartiallyLinearFNC()1655 PartiallyLinearFNC::~PartiallyLinearFNC()
1656 {
1657     delete []m_pX;
1658     m_pX = NULL;
1659     delete []m_pY;
1660     m_pY = NULL;
1661 }
1662 
AddPair(mfxF64 x,mfxF64 y)1663 void PartiallyLinearFNC::AddPair(mfxF64 x, mfxF64 y)
1664 {
1665     //duplicates searching
1666     for (mfxU32 i = 0; i < m_nPoints; i++)
1667     {
1668         if (m_pX[i] == x)
1669             return;
1670     }
1671     if (m_nPoints == m_nAllocated)
1672     {
1673         m_nAllocated += 20;
1674         mfxF64 * pnew;
1675         pnew = new mfxF64[m_nAllocated];
1676         //memcpy_s(pnew, sizeof(mfxF64)*m_nAllocated, m_pX, sizeof(mfxF64) * m_nPoints);
1677         MSDK_MEMCPY_BUF(pnew,0,sizeof(mfxF64)*m_nAllocated, m_pX,sizeof(mfxF64) * m_nPoints);
1678         delete [] m_pX;
1679         m_pX = pnew;
1680 
1681         pnew = new mfxF64[m_nAllocated];
1682         //memcpy_s(pnew, sizeof(mfxF64)*m_nAllocated, m_pY, sizeof(mfxF64) * m_nPoints);
1683         MSDK_MEMCPY_BUF(pnew,0,sizeof(mfxF64)*m_nAllocated, m_pY,sizeof(mfxF64) * m_nPoints);
1684         delete [] m_pY;
1685         m_pY = pnew;
1686     }
1687     m_pX[m_nPoints] = x;
1688     m_pY[m_nPoints] = y;
1689 
1690     m_nPoints ++;
1691 }
1692 
at(mfxF64 x)1693 mfxF64 PartiallyLinearFNC::at(mfxF64 x)
1694 {
1695     if (m_nPoints < 2)
1696     {
1697         return 0;
1698     }
1699     bool bwasmin = false;
1700     bool bwasmax = false;
1701 
1702     mfxU32 maxx = 0;
1703     mfxU32 minx = 0;
1704     mfxU32 i;
1705 
1706     for (i=0; i < m_nPoints; i++)
1707     {
1708         if (m_pX[i] <= x && (!bwasmin || m_pX[i] > m_pX[maxx]))
1709         {
1710             maxx = i;
1711             bwasmin = true;
1712         }
1713         if (m_pX[i] > x && (!bwasmax || m_pX[i] < m_pX[minx]))
1714         {
1715             minx = i;
1716             bwasmax = true;
1717         }
1718     }
1719 
1720     //point on the left
1721     if (!bwasmin)
1722     {
1723         for (i=0; i < m_nPoints; i++)
1724         {
1725             if (m_pX[i] > m_pX[minx] && (!bwasmin || m_pX[i] < m_pX[minx]))
1726             {
1727                 maxx = i;
1728                 bwasmin = true;
1729             }
1730         }
1731     }
1732     //point on the right
1733     if (!bwasmax)
1734     {
1735         for (i=0; i < m_nPoints; i++)
1736         {
1737             if (m_pX[i] < m_pX[maxx] && (!bwasmax || m_pX[i] > m_pX[minx]))
1738             {
1739                 minx = i;
1740                 bwasmax = true;
1741             }
1742         }
1743     }
1744 
1745     //linear interpolation
1746     return (x - m_pX[minx])*(m_pY[maxx] - m_pY[minx]) / (m_pX[maxx] - m_pX[minx]) + m_pY[minx];
1747 }
1748 
CalculateDefaultBitrate(mfxU32 nCodecId,mfxU32 nTargetUsage,mfxU32 nWidth,mfxU32 nHeight,mfxF64 dFrameRate)1749 mfxU16 CalculateDefaultBitrate(mfxU32 nCodecId, mfxU32 nTargetUsage, mfxU32 nWidth, mfxU32 nHeight, mfxF64 dFrameRate)
1750 {
1751     PartiallyLinearFNC fnc;
1752     mfxF64 bitrate = 0;
1753 
1754     switch (nCodecId)
1755     {
1756     case MFX_CODEC_HEVC :
1757     {
1758         fnc.AddPair(0, 0);
1759         fnc.AddPair(25344, 225/1.3);
1760         fnc.AddPair(101376, 1000/1.3);
1761         fnc.AddPair(414720, 4000/1.3);
1762         fnc.AddPair(2058240, 5000/1.3);
1763         break;
1764     }
1765     case MFX_CODEC_AVC :
1766         {
1767             fnc.AddPair(0, 0);
1768             fnc.AddPair(25344, 225);
1769             fnc.AddPair(101376, 1000);
1770             fnc.AddPair(414720, 4000);
1771             fnc.AddPair(2058240, 5000);
1772             break;
1773         }
1774     case MFX_CODEC_MPEG2:
1775         {
1776             fnc.AddPair(0, 0);
1777             fnc.AddPair(414720, 12000);
1778             break;
1779         }
1780     default:
1781         {
1782             fnc.AddPair(0, 0);
1783             fnc.AddPair(414720, 12000);
1784             break;
1785         }
1786     }
1787 
1788     mfxF64 at = nWidth * nHeight * dFrameRate / 30.0;
1789 
1790     if (!at)
1791         return 0;
1792 
1793     switch (nTargetUsage)
1794     {
1795     case MFX_TARGETUSAGE_BEST_QUALITY :
1796         {
1797             bitrate = (&fnc)->at(at);
1798             break;
1799         }
1800     case MFX_TARGETUSAGE_BEST_SPEED :
1801         {
1802             bitrate = (&fnc)->at(at) * 0.5;
1803             break;
1804         }
1805     case MFX_TARGETUSAGE_BALANCED :
1806     default:
1807         {
1808             bitrate = (&fnc)->at(at) * 0.75;
1809             break;
1810         }
1811     }
1812 
1813     return (mfxU16)bitrate;
1814 }
1815 
StrToTargetUsage(msdk_string strInput)1816 mfxU16 StrToTargetUsage(msdk_string strInput)
1817 {
1818     std::map<msdk_string, mfxU16> tu;
1819     tu[MSDK_STRING("quality")] =  (mfxU16)MFX_TARGETUSAGE_1;
1820     tu[MSDK_STRING("veryslow")] = (mfxU16)MFX_TARGETUSAGE_1;
1821     tu[MSDK_STRING("slower")] =   (mfxU16)MFX_TARGETUSAGE_2;
1822     tu[MSDK_STRING("slow")] =     (mfxU16)MFX_TARGETUSAGE_3;
1823     tu[MSDK_STRING("medium")] =   (mfxU16)MFX_TARGETUSAGE_4;
1824     tu[MSDK_STRING("balanced")] = (mfxU16)MFX_TARGETUSAGE_4;
1825     tu[MSDK_STRING("fast")] =     (mfxU16)MFX_TARGETUSAGE_5;
1826     tu[MSDK_STRING("faster")] =   (mfxU16)MFX_TARGETUSAGE_6;
1827     tu[MSDK_STRING("veryfast")] = (mfxU16)MFX_TARGETUSAGE_7;
1828     tu[MSDK_STRING("speed")] =    (mfxU16)MFX_TARGETUSAGE_7;
1829     tu[MSDK_STRING("1")] =        (mfxU16)MFX_TARGETUSAGE_1;
1830     tu[MSDK_STRING("2")] =        (mfxU16)MFX_TARGETUSAGE_2;
1831     tu[MSDK_STRING("3")] =        (mfxU16)MFX_TARGETUSAGE_3;
1832     tu[MSDK_STRING("4")] =        (mfxU16)MFX_TARGETUSAGE_4;
1833     tu[MSDK_STRING("5")] =        (mfxU16)MFX_TARGETUSAGE_5;
1834     tu[MSDK_STRING("6")] =        (mfxU16)MFX_TARGETUSAGE_6;
1835     tu[MSDK_STRING("7")] =        (mfxU16)MFX_TARGETUSAGE_7;
1836 
1837     if (tu.find(strInput) == tu.end())
1838         return 0;
1839     else
1840         return tu[strInput];
1841 }
1842 
TargetUsageToStr(mfxU16 tu)1843 const msdk_char* TargetUsageToStr(mfxU16 tu)
1844 {
1845     switch(tu)
1846     {
1847     case MFX_TARGETUSAGE_BALANCED:
1848         return MSDK_STRING("balanced");
1849     case MFX_TARGETUSAGE_BEST_QUALITY:
1850         return MSDK_STRING("quality");
1851     case MFX_TARGETUSAGE_BEST_SPEED:
1852         return MSDK_STRING("speed");
1853     case MFX_TARGETUSAGE_UNKNOWN:
1854         return MSDK_STRING("unknown");
1855     default:
1856         return MSDK_STRING("unsupported");
1857     }
1858 }
1859 
ColorFormatToStr(mfxU32 format)1860 const msdk_char* ColorFormatToStr(mfxU32 format)
1861 {
1862     switch(format)
1863     {
1864     case MFX_FOURCC_NV12:
1865         return MSDK_STRING("NV12");
1866     case MFX_FOURCC_YV12:
1867         return MSDK_STRING("YV12");
1868     case MFX_FOURCC_I420:
1869         return MSDK_STRING("YUV420");
1870     case MFX_FOURCC_RGB4:
1871         return MSDK_STRING("RGB4");
1872     case MFX_FOURCC_YUY2:
1873         return MSDK_STRING("YUY2");
1874     case MFX_FOURCC_UYVY:
1875        return MSDK_STRING("UYVY");
1876     case MFX_FOURCC_P010:
1877        return MSDK_STRING("P010");
1878     case MFX_FOURCC_P210:
1879         return MSDK_STRING("P210");
1880 #if (MFX_VERSION >= 1027)
1881     case MFX_FOURCC_Y210:
1882         return MSDK_STRING("Y210");
1883     case MFX_FOURCC_Y410:
1884         return MSDK_STRING("Y410");
1885 #endif
1886 #if (MFX_VERSION >= 1031)
1887     case MFX_FOURCC_P016:
1888         return MSDK_STRING("P016");
1889     case MFX_FOURCC_Y216:
1890         return MSDK_STRING("Y216");
1891 #endif
1892     default:
1893         return MSDK_STRING("unsupported");
1894     }
1895 }
1896 
GCD(mfxU32 a,mfxU32 b)1897 mfxU32 GCD(mfxU32 a, mfxU32 b)
1898 {
1899     if (0 == a)
1900         return b;
1901     else if (0 == b)
1902         return a;
1903 
1904     mfxU32 a1, b1;
1905 
1906     if (a >= b)
1907     {
1908         a1 = a;
1909         b1 = b;
1910     }
1911     else
1912     {
1913         a1 = b;
1914         b1 = a;
1915     }
1916 
1917     // a1 >= b1;
1918     mfxU32 r = a1 % b1;
1919 
1920     while (0 != r)
1921     {
1922         a1 = b1;
1923         b1 = r;
1924         r = a1 % b1;
1925     }
1926 
1927     return b1;
1928 }
1929 
1930 
1931 
FormMVCFileName(const msdk_char * strFileNamePattern,const mfxU32 numView)1932 std::basic_string<msdk_char> FormMVCFileName(const msdk_char *strFileNamePattern, const mfxU32 numView)
1933 {
1934     if (NULL == strFileNamePattern)
1935         return MSDK_STRING("");
1936 
1937     std::basic_string<msdk_char> fileName, mvcFileName, fileExt;
1938     fileName = strFileNamePattern;
1939 
1940     msdk_char postfixBuffer[4];
1941     msdk_itoa_decimal(numView, postfixBuffer);
1942     mvcFileName = fileName;
1943     mvcFileName.append(MSDK_STRING("_"));
1944     mvcFileName.append(postfixBuffer);
1945     mvcFileName.append(MSDK_STRING(".yuv"));
1946 
1947     return mvcFileName;
1948 }
1949 
1950 // function for getting a pointer to a specific external buffer from the array
GetExtBuffer(mfxExtBuffer ** ebuffers,mfxU32 nbuffers,mfxU32 BufferId)1951 mfxExtBuffer* GetExtBuffer(mfxExtBuffer** ebuffers, mfxU32 nbuffers, mfxU32 BufferId)
1952 {
1953     if (!ebuffers) return 0;
1954     for(mfxU32 i=0; i<nbuffers; i++) {
1955         if (!ebuffers[i]) continue;
1956         if (ebuffers[i]->BufferId == BufferId) {
1957             return ebuffers[i];
1958         }
1959     }
1960     return 0;
1961 }
1962 
MJPEG_AVI_ParsePicStruct(mfxBitstream * bitstream)1963 mfxStatus MJPEG_AVI_ParsePicStruct(mfxBitstream *bitstream)
1964 {
1965     // check input for consistency
1966     MSDK_CHECK_POINTER(bitstream->Data, MFX_ERR_MORE_DATA);
1967     if (bitstream->DataLength <= 0)
1968         return MFX_ERR_MORE_DATA;
1969 
1970     // define JPEG markers
1971     const mfxU8 APP0_marker [] = { 0xFF, 0xE0 };
1972     const mfxU8 SOI_marker  [] = { 0xFF, 0xD8 };
1973     const mfxU8 AVI1        [] = { 'A', 'V', 'I', '1' };
1974 
1975     // size of length field in header
1976     const mfxU8 len_size  = 2;
1977     // size of picstruct field in header
1978     const mfxU8 picstruct_size = 1;
1979 
1980     mfxU32 length = bitstream->DataLength;
1981     const mfxU8 *ptr = reinterpret_cast<const mfxU8*>(bitstream->Data);
1982 
1983     //search for SOI marker
1984     while ((length >= sizeof(SOI_marker)) && memcmp(ptr, SOI_marker, sizeof(SOI_marker)))
1985     {
1986         skip(ptr, length, (mfxU32)1);
1987     }
1988 
1989     // skip SOI
1990     if (!skip(ptr, length, (mfxU32)sizeof(SOI_marker)) || length < sizeof(APP0_marker))
1991         return MFX_ERR_MORE_DATA;
1992 
1993     // if there is no APP0 marker return
1994     if (memcmp(ptr, APP0_marker, sizeof(APP0_marker)))
1995     {
1996         bitstream->PicStruct = MFX_PICSTRUCT_UNKNOWN;
1997         return MFX_ERR_NONE;
1998     }
1999 
2000     // skip APP0 & length value
2001     if (!skip(ptr, length, (mfxU32)sizeof(APP0_marker) + len_size) || length < sizeof(AVI1))
2002         return MFX_ERR_MORE_DATA;
2003 
2004     if (memcmp(ptr, AVI1, sizeof(AVI1)))
2005     {
2006         bitstream->PicStruct = MFX_PICSTRUCT_UNKNOWN;
2007         return MFX_ERR_NONE;
2008     }
2009 
2010     // skip 'AVI1'
2011     if (!skip(ptr, length, (mfxU32)sizeof(AVI1)) || length < picstruct_size)
2012         return MFX_ERR_MORE_DATA;
2013 
2014     // get PicStruct
2015     switch (*ptr)
2016     {
2017         case 0:
2018             bitstream->PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
2019             break;
2020         case 1:
2021             bitstream->PicStruct = MFX_PICSTRUCT_FIELD_TFF;
2022             break;
2023         case 2:
2024             bitstream->PicStruct = MFX_PICSTRUCT_FIELD_BFF;
2025             break;
2026         default:
2027             bitstream->PicStruct = MFX_PICSTRUCT_UNKNOWN;
2028     }
2029 
2030     return MFX_ERR_NONE;
2031 }
2032 
getMinimalRequiredVersion(const APIChangeFeatures & features)2033 mfxVersion getMinimalRequiredVersion(const APIChangeFeatures &features)
2034 {
2035     mfxVersion version = {{1, 1}};
2036 
2037     if (features.MVCDecode || features.MVCEncode || features.LowLatency || features.JpegDecode)
2038     {
2039         version.Minor = 3;
2040     }
2041 
2042     if (features.ViewOutput)
2043     {
2044         version.Minor = 4;
2045     }
2046 
2047     if (features.JpegEncode || features.IntraRefresh)
2048     {
2049         version.Minor = 6;
2050     }
2051 
2052     if (features.LookAheadBRC)
2053     {
2054         version.Minor = 7;
2055     }
2056 
2057     if (features.AudioDecode) {
2058         version.Minor = 8;
2059     }
2060 
2061     if (features.SupportCodecPluginAPI) {
2062         version.Minor = 8;
2063     }
2064 
2065     return version;
2066 }
2067 
CheckVersion(mfxVersion * version,msdkAPIFeature feature)2068 bool CheckVersion(mfxVersion* version, msdkAPIFeature feature)
2069 {
2070     if (!version) {
2071         return false;
2072     }
2073 
2074     mfxU32 ver = MakeVersion(version->Major, version->Minor);
2075 
2076     switch (feature) {
2077     case MSDK_FEATURE_NONE:
2078         return true;
2079     case MSDK_FEATURE_MVC:
2080         if (ver >= 1003) {
2081             return true;
2082         }
2083         break;
2084     case MSDK_FEATURE_JPEG_DECODE:
2085         if (ver >= 1003) {
2086             return true;
2087         }
2088         break;
2089    case MSDK_FEATURE_LOW_LATENCY:
2090         if (ver >= 1003) {
2091             return true;
2092         }
2093         break;
2094     case MSDK_FEATURE_MVC_VIEWOUTPUT:
2095         if (ver >= 1004) {
2096             return true;
2097         }
2098         break;
2099     case MSDK_FEATURE_JPEG_ENCODE:
2100         if (ver >= 1006) {
2101             return true;
2102         }
2103         break;
2104     case MSDK_FEATURE_LOOK_AHEAD:
2105         if (ver >= 1007) {
2106             return true;
2107         }
2108         break;
2109     case MSDK_FEATURE_PLUGIN_API:
2110         if (ver >= 1008) {
2111             return true;
2112         }
2113         break;
2114     default:
2115         return false;
2116     }
2117     return false;
2118 }
2119 
ConfigureAspectRatioConversion(mfxInfoVPP * pVppInfo)2120 void ConfigureAspectRatioConversion(mfxInfoVPP* pVppInfo)
2121 {
2122     if (!pVppInfo) return;
2123 
2124     if (pVppInfo->In.AspectRatioW &&
2125         pVppInfo->In.AspectRatioH &&
2126         pVppInfo->In.CropW &&
2127         pVppInfo->In.CropH &&
2128         pVppInfo->Out.AspectRatioW &&
2129         pVppInfo->Out.AspectRatioH &&
2130         pVppInfo->Out.CropW &&
2131         pVppInfo->Out.CropH)
2132     {
2133         mfxF64 dFrameAR         = ((mfxF64)pVppInfo->In.AspectRatioW * pVppInfo->In.CropW) /
2134                                    (mfxF64)pVppInfo->In.AspectRatioH /
2135                                    (mfxF64)pVppInfo->In.CropH;
2136 
2137         mfxF64 dPixelAR         = pVppInfo->Out.AspectRatioW / (mfxF64)pVppInfo->Out.AspectRatioH;
2138 
2139         mfxU16 dProportionalH   = (mfxU16)(pVppInfo->Out.CropW * dPixelAR / dFrameAR + 1) & -2; //round to closest odd (values are always positive)
2140 
2141         if (dProportionalH < pVppInfo->Out.CropH)
2142         {
2143             pVppInfo->Out.CropY = (mfxU16)((pVppInfo->Out.CropH - dProportionalH) / 2. + 1) & -2;
2144             pVppInfo->Out.CropH = pVppInfo->Out.CropH - 2 * pVppInfo->Out.CropY;
2145         }
2146         else if (dProportionalH > pVppInfo->Out.CropH)
2147         {
2148             mfxU16 dProportionalW = (mfxU16)(pVppInfo->Out.CropH * dFrameAR / dPixelAR + 1) & -2;
2149 
2150             pVppInfo->Out.CropX = (mfxU16)((pVppInfo->Out.CropW - dProportionalW) / 2 + 1) & -2;
2151             pVppInfo->Out.CropW = pVppInfo->Out.CropW - 2 * pVppInfo->Out.CropX;
2152         }
2153     }
2154 }
2155 
SEICalcSizeType(std::vector<mfxU8> & data,mfxU16 type,mfxU32 size)2156 void SEICalcSizeType(std::vector<mfxU8>& data, mfxU16 type, mfxU32 size)
2157 {
2158     mfxU32 B = type;
2159 
2160     while (B > 255)
2161     {
2162         data.push_back(255);
2163         B -= 255;
2164     }
2165     data.push_back(mfxU8(B));
2166 
2167     B = size;
2168 
2169     while (B > 255)
2170     {
2171         data.push_back(255);
2172         B -= 255;
2173     }
2174     data.push_back(mfxU8(B));
2175 }
2176 
Char2Hex(msdk_char ch)2177 mfxU8 Char2Hex(msdk_char ch)
2178 {
2179     msdk_char value = ch;
2180     if(value >= MSDK_CHAR('0') && value <= MSDK_CHAR('9'))
2181     {
2182         value -= MSDK_CHAR('0');
2183     }
2184     else if (value >= MSDK_CHAR('a') && value <= MSDK_CHAR('f'))
2185     {
2186         value = value - MSDK_CHAR('a') + 10;
2187     }
2188     else if (value >= MSDK_CHAR('A') && value <= MSDK_CHAR('F'))
2189     {
2190         value = value - MSDK_CHAR('A') + 10;
2191     }
2192     else
2193     {
2194         value = 0;
2195     }
2196     return (mfxU8)value;
2197 }
2198 
2199 namespace {
2200     int g_trace_level = MSDK_TRACE_LEVEL_INFO;
2201 }
2202 
msdk_trace_get_level()2203 int msdk_trace_get_level() {
2204     return g_trace_level;
2205 }
2206 
msdk_trace_set_level(int newLevel)2207 void msdk_trace_set_level(int newLevel) {
2208     g_trace_level = newLevel;
2209 }
2210 
msdk_trace_is_printable(int level)2211 bool msdk_trace_is_printable(int level) {
2212     return g_trace_level >= level;
2213 }
2214 
operator <<(msdk_ostream & os,MsdkTraceLevel tl)2215 msdk_ostream & operator <<(msdk_ostream & os, MsdkTraceLevel tl) {
2216     switch (tl)
2217     {
2218         case MSDK_TRACE_LEVEL_CRITICAL :
2219             os<<MSDK_STRING("CRITICAL");
2220             break;
2221         case MSDK_TRACE_LEVEL_ERROR :
2222             os<<MSDK_STRING("ERROR");
2223             break;
2224         case MSDK_TRACE_LEVEL_WARNING :
2225             os<<MSDK_STRING("WARNING");
2226             break;
2227         case MSDK_TRACE_LEVEL_INFO :
2228             os<<MSDK_STRING("INFO");
2229             break;
2230         case MSDK_TRACE_LEVEL_DEBUG :
2231             os<<MSDK_STRING("DEBUG");
2232             break;
2233         default:
2234             break;
2235     }
2236     return os;
2237 }
2238 
NoFullPath(const msdk_string & file_path)2239 msdk_string NoFullPath(const msdk_string & file_path) {
2240     size_t pos = file_path.find_last_of(MSDK_STRING("\\/"));
2241     if (pos != msdk_string::npos) {
2242         return file_path.substr(pos + 1);
2243     }
2244     return file_path;
2245 }
2246 
2247 template<> mfxStatus
msdk_opt_read(const msdk_char * string,mfxU8 & value)2248 msdk_opt_read(const msdk_char* string, mfxU8& value)
2249 {
2250     msdk_char* stopCharacter;
2251     value = (mfxU8)msdk_strtol(string, &stopCharacter, 10);
2252 
2253     return (msdk_strlen(stopCharacter) == 0)? MFX_ERR_NONE: MFX_ERR_UNKNOWN;
2254 }
2255 
2256 template<> mfxStatus
msdk_opt_read(const msdk_char * string,mfxU16 & value)2257 msdk_opt_read(const msdk_char* string, mfxU16& value)
2258 {
2259     msdk_char* stopCharacter;
2260     value = (mfxU16)msdk_strtol(string, &stopCharacter, 10);
2261 
2262     return (msdk_strlen(stopCharacter) == 0)? MFX_ERR_NONE: MFX_ERR_UNKNOWN;
2263 }
2264 
2265 template<> mfxStatus
msdk_opt_read(const msdk_char * string,mfxU32 & value)2266 msdk_opt_read(const msdk_char* string, mfxU32& value)
2267 {
2268     msdk_char* stopCharacter;
2269     value = (mfxU32)msdk_strtol(string, &stopCharacter, 10);
2270 
2271     return (msdk_strlen(stopCharacter) == 0)? MFX_ERR_NONE: MFX_ERR_UNKNOWN;
2272 }
2273 
2274 template<> mfxStatus
msdk_opt_read(const msdk_char * string,mfxF32 & value)2275 msdk_opt_read(const msdk_char* string, mfxF32& value)
2276 {
2277     msdk_char* stopCharacter;
2278     value = (mfxF32)msdk_strtod(string, &stopCharacter);
2279     return (msdk_strlen(stopCharacter) == 0)? MFX_ERR_NONE: MFX_ERR_UNKNOWN;
2280 }
2281 template<> mfxStatus
msdk_opt_read(const msdk_char * string,mfxF64 & value)2282 msdk_opt_read(const msdk_char* string, mfxF64& value)
2283 {
2284     msdk_char* stopCharacter;
2285     value = (mfxF64)msdk_strtod(string, &stopCharacter);
2286 
2287     return (msdk_strlen(stopCharacter) == 0)? MFX_ERR_NONE: MFX_ERR_UNKNOWN;
2288 }
2289 
2290 mfxStatus msdk_opt_read(const msdk_char* string, mfxU8& value);
2291 mfxStatus msdk_opt_read(const msdk_char* string, mfxU16& value);
2292 mfxStatus msdk_opt_read(const msdk_char* string, mfxU32& value);
2293 mfxStatus msdk_opt_read(const msdk_char* string, mfxF64& value);
2294 mfxStatus msdk_opt_read(const msdk_char* string, mfxF32& value);
2295 
2296 template<> mfxStatus
msdk_opt_read(const msdk_char * string,mfxI16 & value)2297 msdk_opt_read(const msdk_char* string, mfxI16& value)
2298 {
2299     msdk_char* stopCharacter;
2300     value = (mfxI16)msdk_strtol(string, &stopCharacter, 10);
2301 
2302     return (msdk_strlen(stopCharacter) == 0)? MFX_ERR_NONE: MFX_ERR_UNKNOWN;
2303 }
2304 
2305 template<> mfxStatus
msdk_opt_read(const msdk_char * string,mfxI32 & value)2306 msdk_opt_read(const msdk_char* string, mfxI32& value)
2307 {
2308     msdk_char* stopCharacter;
2309     value = (mfxI32)msdk_strtol(string, &stopCharacter, 10);
2310 
2311     return (msdk_strlen(stopCharacter) == 0)? MFX_ERR_NONE: MFX_ERR_UNKNOWN;
2312 }
2313 
2314 mfxStatus msdk_opt_read(const msdk_char* string, mfxI16& value);
2315 mfxStatus msdk_opt_read(const msdk_char* string, mfxI32& value);
2316 
2317 template<> mfxStatus
msdk_opt_read(const msdk_char * string,mfxPriority & value)2318 msdk_opt_read(const msdk_char* string, mfxPriority& value)
2319 {
2320     mfxU32 priority = 0;
2321     mfxStatus sts = msdk_opt_read<>(string, priority);
2322 
2323     if (MFX_ERR_NONE == sts) value = (mfxPriority)priority;
2324     return sts;
2325 }
2326 
2327 mfxStatus msdk_opt_read(msdk_char* string, mfxPriority& value);
2328 
IsDecodeCodecSupported(mfxU32 codecFormat)2329 bool IsDecodeCodecSupported(mfxU32 codecFormat)
2330 {
2331     switch(codecFormat)
2332     {
2333         case MFX_CODEC_MPEG2:
2334         case MFX_CODEC_AVC:
2335         case MFX_CODEC_HEVC:
2336         case MFX_CODEC_VC1:
2337         case CODEC_MVC:
2338         case MFX_CODEC_JPEG:
2339         case MFX_CODEC_VP8:
2340         case MFX_CODEC_VP9:
2341         case MFX_CODEC_AV1:
2342         break;
2343     default:
2344         return false;
2345     }
2346     return true;
2347 }
2348 
IsEncodeCodecSupported(mfxU32 codecFormat)2349 bool IsEncodeCodecSupported(mfxU32 codecFormat)
2350 {
2351     switch(codecFormat)
2352     {
2353         case MFX_CODEC_AVC:
2354         case MFX_CODEC_HEVC:
2355         case MFX_CODEC_MPEG2:
2356         case CODEC_MVC:
2357         case MFX_CODEC_VP8:
2358         case MFX_CODEC_JPEG:
2359         case MFX_CODEC_VP9:
2360         break;
2361     default:
2362         return false;
2363     }
2364     return true;
2365 }
2366 
IsPluginCodecSupported(mfxU32 codecFormat)2367 bool IsPluginCodecSupported(mfxU32 codecFormat)
2368 {
2369     switch(codecFormat)
2370     {
2371         case MFX_CODEC_HEVC:
2372         case MFX_CODEC_AVC:
2373         case MFX_CODEC_MPEG2:
2374         case MFX_CODEC_VC1:
2375         case MFX_CODEC_VP8:
2376         case MFX_CODEC_VP9:
2377         break;
2378     default:
2379         return false;
2380     }
2381     return true;
2382 }
2383 
StrFormatToCodecFormatFourCC(msdk_char * strInput,mfxU32 & codecFormat)2384 mfxStatus StrFormatToCodecFormatFourCC(msdk_char* strInput, mfxU32 &codecFormat)
2385 {
2386     mfxStatus sts = MFX_ERR_NONE;
2387     codecFormat   = 0;
2388 
2389     if (strInput == NULL)
2390         sts = MFX_ERR_NULL_PTR;
2391 
2392     if (sts == MFX_ERR_NONE)
2393     {
2394         if (0 == msdk_strcmp(strInput, MSDK_STRING("mpeg2")))
2395         {
2396             codecFormat = MFX_CODEC_MPEG2;
2397         }
2398         else if (0 == msdk_strcmp(strInput, MSDK_STRING("h264")))
2399         {
2400             codecFormat = MFX_CODEC_AVC;
2401         }
2402         else if (0 == msdk_strcmp(strInput, MSDK_STRING("h265")))
2403         {
2404             codecFormat = MFX_CODEC_HEVC;
2405         }
2406         else if (0 == msdk_strcmp(strInput, MSDK_STRING("vc1")))
2407         {
2408             codecFormat = MFX_CODEC_VC1;
2409         }
2410         else if (0 == msdk_strcmp(strInput, MSDK_STRING("mvc")))
2411         {
2412             codecFormat = CODEC_MVC;
2413         }
2414         else if (0 == msdk_strcmp(strInput, MSDK_STRING("jpeg")))
2415         {
2416             codecFormat = MFX_CODEC_JPEG;
2417         }
2418         else if (0 == msdk_strcmp(strInput, MSDK_STRING("vp8")))
2419         {
2420             codecFormat = MFX_CODEC_VP8;
2421         }
2422         else if (0 == msdk_strcmp(strInput, MSDK_STRING("vp9")))
2423         {
2424             codecFormat = MFX_CODEC_VP9;
2425         }
2426         else if (0 == msdk_strcmp(strInput, MSDK_STRING("av1")))
2427         {
2428             codecFormat = MFX_CODEC_AV1;
2429         }
2430         else if ((0 == msdk_strcmp(strInput, MSDK_STRING("raw"))))
2431         {
2432             codecFormat = MFX_CODEC_DUMP;
2433         }
2434         else if ((0 == msdk_strcmp(strInput, MSDK_STRING("rgb4_frame"))))
2435         {
2436             codecFormat = MFX_CODEC_RGB4;
2437         }
2438         else if ((0 == msdk_strcmp(strInput, MSDK_STRING("nv12"))))
2439         {
2440             codecFormat = MFX_CODEC_NV12;
2441         }
2442         else if ((0 == msdk_strcmp(strInput, MSDK_STRING("i420"))))
2443         {
2444             codecFormat = MFX_CODEC_I420;
2445         }
2446         else if ((0 == msdk_strcmp(strInput, MSDK_STRING("p010")))) {
2447             codecFormat = MFX_CODEC_P010;
2448         }
2449         else
2450             sts = MFX_ERR_UNSUPPORTED;
2451     }
2452 
2453     return sts;
2454 }
2455 
StatusToString(mfxStatus sts)2456 msdk_string StatusToString(mfxStatus sts)
2457 {
2458     switch(sts)
2459     {
2460     case MFX_ERR_NONE:
2461         return msdk_string(MSDK_STRING("MFX_ERR_NONE"));
2462     case MFX_ERR_UNKNOWN:
2463         return msdk_string(MSDK_STRING("MFX_ERR_UNKNOWN"));
2464     case MFX_ERR_NULL_PTR:
2465         return msdk_string(MSDK_STRING("MFX_ERR_NULL_PTR"));
2466     case MFX_ERR_UNSUPPORTED:
2467         return msdk_string(MSDK_STRING("MFX_ERR_UNSUPPORTED"));
2468     case MFX_ERR_MEMORY_ALLOC:
2469         return msdk_string(MSDK_STRING("MFX_ERR_MEMORY_ALLOC"));
2470     case MFX_ERR_NOT_ENOUGH_BUFFER:
2471         return msdk_string(MSDK_STRING("MFX_ERR_NOT_ENOUGH_BUFFER"));
2472     case MFX_ERR_INVALID_HANDLE:
2473         return msdk_string(MSDK_STRING("MFX_ERR_INVALID_HANDLE"));
2474     case MFX_ERR_LOCK_MEMORY:
2475         return msdk_string(MSDK_STRING("MFX_ERR_LOCK_MEMORY"));
2476     case MFX_ERR_NOT_INITIALIZED:
2477         return msdk_string(MSDK_STRING("MFX_ERR_NOT_INITIALIZED"));
2478     case MFX_ERR_NOT_FOUND:
2479         return msdk_string(MSDK_STRING("MFX_ERR_NOT_FOUND"));
2480     case MFX_ERR_MORE_DATA:
2481         return msdk_string(MSDK_STRING("MFX_ERR_MORE_DATA"));
2482     case MFX_ERR_MORE_SURFACE:
2483         return msdk_string(MSDK_STRING("MFX_ERR_MORE_SURFACE"));
2484     case MFX_ERR_ABORTED:
2485         return msdk_string(MSDK_STRING("MFX_ERR_ABORTED"));
2486     case MFX_ERR_DEVICE_LOST:
2487         return msdk_string(MSDK_STRING("MFX_ERR_DEVICE_LOST"));
2488     case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
2489         return msdk_string(MSDK_STRING("MFX_ERR_INCOMPATIBLE_VIDEO_PARAM"));
2490     case MFX_ERR_INVALID_VIDEO_PARAM:
2491         return msdk_string(MSDK_STRING("MFX_ERR_INVALID_VIDEO_PARAM"));
2492     case MFX_ERR_UNDEFINED_BEHAVIOR:
2493         return msdk_string(MSDK_STRING("MFX_ERR_UNDEFINED_BEHAVIOR"));
2494     case MFX_ERR_DEVICE_FAILED:
2495         return msdk_string(MSDK_STRING("MFX_ERR_DEVICE_FAILED"));
2496     case MFX_ERR_MORE_BITSTREAM:
2497         return msdk_string(MSDK_STRING("MFX_ERR_MORE_BITSTREAM"));
2498     case MFX_ERR_INCOMPATIBLE_AUDIO_PARAM:
2499         return msdk_string(MSDK_STRING("MFX_ERR_INCOMPATIBLE_AUDIO_PARAM"));
2500     case MFX_ERR_INVALID_AUDIO_PARAM:
2501         return msdk_string(MSDK_STRING("MFX_ERR_INVALID_AUDIO_PARAM"));
2502     case MFX_ERR_GPU_HANG:
2503         return msdk_string(MSDK_STRING("MFX_ERR_GPU_HANG"));
2504     case MFX_ERR_REALLOC_SURFACE:
2505         return msdk_string(MSDK_STRING("MFX_ERR_REALLOC_SURFACE"));
2506     case MFX_WRN_IN_EXECUTION:
2507         return msdk_string(MSDK_STRING("MFX_WRN_IN_EXECUTION"));
2508     case MFX_WRN_DEVICE_BUSY:
2509         return msdk_string(MSDK_STRING("MFX_WRN_DEVICE_BUSY"));
2510     case MFX_WRN_VIDEO_PARAM_CHANGED:
2511         return msdk_string(MSDK_STRING("MFX_WRN_VIDEO_PARAM_CHANGED"));
2512     case MFX_WRN_PARTIAL_ACCELERATION:
2513         return msdk_string(MSDK_STRING("MFX_WRN_PARTIAL_ACCELERATION"));
2514     case MFX_WRN_INCOMPATIBLE_VIDEO_PARAM:
2515         return msdk_string(MSDK_STRING("MFX_WRN_INCOMPATIBLE_VIDEO_PARAM"));
2516     case MFX_WRN_VALUE_NOT_CHANGED:
2517         return msdk_string(MSDK_STRING("MFX_WRN_VALUE_NOT_CHANGED"));
2518     case MFX_WRN_OUT_OF_RANGE:
2519         return msdk_string(MSDK_STRING("MFX_WRN_OUT_OF_RANGE"));
2520     case MFX_WRN_FILTER_SKIPPED:
2521         return msdk_string(MSDK_STRING("MFX_WRN_FILTER_SKIPPED"));
2522     case MFX_WRN_INCOMPATIBLE_AUDIO_PARAM:
2523         return msdk_string(MSDK_STRING("MFX_WRN_INCOMPATIBLE_AUDIO_PARAM"));
2524     case MFX_TASK_WORKING:
2525         return msdk_string(MSDK_STRING("MFX_TASK_WORKING"));
2526     case MFX_TASK_BUSY:
2527         return msdk_string(MSDK_STRING("MFX_TASK_BUSY"));
2528     case MFX_ERR_MORE_DATA_SUBMIT_TASK:
2529         return msdk_string(MSDK_STRING("MFX_ERR_MORE_DATA_SUBMIT_TASK"));
2530     default:
2531         return msdk_string(MSDK_STRING("[Unknown status]"));
2532     }
2533 }
2534 
getMonitorType(msdk_char * str)2535 mfxI32 getMonitorType(msdk_char* str)
2536 {
2537     struct {
2538       const msdk_char* str;
2539       mfxI32 mfx_type;
2540     } table[] = {
2541 #define __DECLARE(type) { MSDK_STRING(#type), MFX_MONITOR_ ## type }
2542       __DECLARE(Unknown),
2543       __DECLARE(VGA),
2544       __DECLARE(DVII),
2545       __DECLARE(DVID),
2546       __DECLARE(DVIA),
2547       __DECLARE(Composite),
2548       __DECLARE(SVIDEO),
2549       __DECLARE(LVDS),
2550       __DECLARE(Component),
2551       __DECLARE(9PinDIN),
2552       __DECLARE(HDMIA),
2553       __DECLARE(HDMIB),
2554       __DECLARE(eDP),
2555       __DECLARE(TV),
2556       __DECLARE(DisplayPort),
2557 #if defined(DRM_MODE_CONNECTOR_VIRTUAL) // from libdrm 2.4.59
2558       __DECLARE(VIRTUAL),
2559 #endif
2560 #if defined(DRM_MODE_CONNECTOR_DSI) // from libdrm 2.4.59
2561       __DECLARE(DSI)
2562 #endif
2563 #undef __DECLARE
2564     };
2565     for (unsigned int i=0; i < sizeof(table)/sizeof(table[0]); ++i) {
2566       if (0 == msdk_strcmp(str, table[i].str)) {
2567         return table[i].mfx_type;
2568       }
2569     }
2570     return MFX_MONITOR_MAXNUMBER;
2571 }
2572 
CH264FrameReader()2573 CH264FrameReader::CH264FrameReader()
2574 : CSmplBitstreamReader()
2575 , m_processedBS(0)
2576 , m_isEndOfStream(false)
2577 , m_frame(0)
2578 , m_plainBuffer(0)
2579 , m_plainBufferSize(0)
2580 {
2581 }
2582 
~CH264FrameReader()2583 CH264FrameReader::~CH264FrameReader()
2584 {
2585 }
2586 
Close()2587 void CH264FrameReader::Close()
2588 {
2589     CSmplBitstreamReader::Close();
2590 
2591     if (NULL != m_plainBuffer)
2592     {
2593         free(m_plainBuffer);
2594         m_plainBuffer = NULL;
2595         m_plainBufferSize = 0;
2596     }
2597 }
2598 
Init(const msdk_char * strFileName)2599 mfxStatus CH264FrameReader::Init(const msdk_char *strFileName)
2600 {
2601     mfxStatus sts = MFX_ERR_NONE;
2602 
2603     sts = CSmplBitstreamReader::Init(strFileName);
2604     if (sts != MFX_ERR_NONE)
2605         return sts;
2606 
2607     m_isEndOfStream = false;
2608     m_processedBS = NULL;
2609 
2610     m_originalBS.Extend(1024 * 1024);
2611 
2612     m_pNALSplitter.reset(new ProtectedLibrary::AVC_Spl());
2613 
2614     m_frame = 0;
2615     m_plainBuffer = 0;
2616     m_plainBufferSize = 0;
2617 
2618     return sts;
2619 }
2620 
ReadNextFrame(mfxBitstream * pBS)2621 mfxStatus CH264FrameReader::ReadNextFrame(mfxBitstream *pBS)
2622 {
2623     mfxStatus sts = MFX_ERR_NONE;
2624     pBS->DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
2625     //read bit stream from source
2626     while (!m_originalBS.DataLength)
2627     {
2628         sts = CSmplBitstreamReader::ReadNextFrame(&m_originalBS);
2629         if (sts != MFX_ERR_NONE && sts != MFX_ERR_MORE_DATA)
2630             return sts;
2631         if (sts == MFX_ERR_MORE_DATA)
2632         {
2633             m_isEndOfStream = true;
2634             break;
2635         }
2636     }
2637 
2638     do
2639     {
2640         sts = PrepareNextFrame(m_isEndOfStream ? NULL : &m_originalBS, &m_processedBS);
2641 
2642         if (sts == MFX_ERR_MORE_DATA)
2643         {
2644             if (m_isEndOfStream)
2645             {
2646                 break;
2647             }
2648 
2649             sts = CSmplBitstreamReader::ReadNextFrame(&m_originalBS);
2650             if (sts == MFX_ERR_MORE_DATA)
2651                 m_isEndOfStream = true;
2652             continue;
2653         }
2654         else if (MFX_ERR_NONE != sts)
2655             return sts;
2656 
2657     } while (MFX_ERR_NONE != sts);
2658 
2659     // get output stream
2660     if (NULL != m_processedBS)
2661     {
2662         mfxStatus copySts = CopyBitstream2(
2663             pBS,
2664             m_processedBS);
2665         if (copySts < MFX_ERR_NONE)
2666             return copySts;
2667         m_processedBS = NULL;
2668     }
2669 
2670     return sts;
2671 }
2672 
PrepareNextFrame(mfxBitstream * in,mfxBitstream ** out)2673 mfxStatus CH264FrameReader::PrepareNextFrame(mfxBitstream *in, mfxBitstream **out)
2674 {
2675     mfxStatus sts = MFX_ERR_NONE;
2676 
2677     if (NULL == out)
2678         return MFX_ERR_NULL_PTR;
2679 
2680     *out = NULL;
2681 
2682     // get frame if it is not ready yet
2683     if (NULL == m_frame)
2684     {
2685         sts = m_pNALSplitter->GetFrame(in, &m_frame);
2686         if (sts != MFX_ERR_NONE)
2687             return sts;
2688     }
2689 
2690     if (m_plainBufferSize < m_frame->DataLength)
2691     {
2692         if (NULL != m_plainBuffer)
2693         {
2694             free(m_plainBuffer);
2695             m_plainBuffer = NULL;
2696             m_plainBufferSize = 0;
2697         }
2698         m_plainBuffer = (mfxU8*)malloc(m_frame->DataLength);
2699         if (NULL == m_plainBuffer)
2700             return MFX_ERR_MEMORY_ALLOC;
2701         m_plainBufferSize = m_frame->DataLength;
2702     }
2703 
2704     MSDK_MEMCPY_BUF(m_plainBuffer, 0, m_plainBufferSize, m_frame->Data, m_frame->DataLength);
2705 
2706     memset(&m_outBS, 0, sizeof(mfxBitstream));
2707     m_outBS.Data = m_plainBuffer;
2708     m_outBS.DataOffset = 0;
2709     m_outBS.DataLength = m_frame->DataLength;
2710     m_outBS.MaxLength = m_frame->DataLength;
2711     m_outBS.DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
2712     m_outBS.TimeStamp = m_frame->TimeStamp;
2713 
2714     m_pNALSplitter->ResetCurrentState();
2715     m_frame = NULL;
2716 
2717     *out = &m_outBS;
2718 
2719     return sts;
2720 }
2721 
2722 // This function either performs synchronization using provided syncpoint,
2723 // or just waits for predefined time if no available syncpoint
WaitForDeviceToBecomeFree(MFXVideoSession & session,mfxSyncPoint & syncPoint,mfxStatus & currentStatus)2724 void WaitForDeviceToBecomeFree(MFXVideoSession& session, mfxSyncPoint& syncPoint, mfxStatus& currentStatus)
2725 {
2726     if (syncPoint)
2727     {
2728         mfxStatus stsSync = session.SyncOperation(syncPoint, MSDK_WAIT_INTERVAL);
2729         if (MFX_ERR_NONE == stsSync)
2730         {
2731             // Retire completed sync point (otherwise we may start active polling)
2732             syncPoint = NULL;
2733             currentStatus = MFX_ERR_NONE;
2734         }
2735         else
2736         {
2737             MSDK_TRACE_ERROR(MSDK_STRING("WaitForDeviceToBecomeFree: SyncOperation failed, sts = ") << stsSync);
2738             currentStatus = MFX_ERR_ABORTED;
2739         }
2740     }
2741     else
2742     {
2743         MSDK_SLEEP(1);
2744         currentStatus = MFX_ERR_NONE;
2745     }
2746 }
2747 
FourCCToChroma(mfxU32 fourCC)2748 mfxU16 FourCCToChroma(mfxU32 fourCC)
2749 {
2750     switch(fourCC)
2751     {
2752     case MFX_FOURCC_NV12:
2753     case MFX_FOURCC_P010:
2754 #if (MFX_VERSION >= 1031)
2755     case MFX_FOURCC_P016:
2756 #endif
2757         return MFX_CHROMAFORMAT_YUV420;
2758     case MFX_FOURCC_NV16:
2759     case MFX_FOURCC_P210:
2760 #if (MFX_VERSION >= 1027)
2761     case MFX_FOURCC_Y210:
2762 #endif
2763 #if (MFX_VERSION >= 1031)
2764     case MFX_FOURCC_Y216:
2765 #endif
2766     case MFX_FOURCC_YUY2:
2767     case MFX_FOURCC_UYVY:
2768         return MFX_CHROMAFORMAT_YUV422;
2769 #if (MFX_VERSION >= 1027)
2770     case MFX_FOURCC_Y410:
2771     case MFX_FOURCC_A2RGB10:
2772 #endif
2773     case MFX_FOURCC_AYUV:
2774     case MFX_FOURCC_RGB4:
2775         return MFX_CHROMAFORMAT_YUV444;
2776     }
2777 
2778     return MFX_CHROMAFORMAT_YUV420;
2779 }
2780