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