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 #ifndef __SAMPLE_UTILS_H__ 21 #define __SAMPLE_UTILS_H__ 22 23 #include <stdio.h> 24 #include <string> 25 #include <sstream> 26 #include <vector> 27 #include <map> 28 #include <stdexcept> 29 #include <mutex> 30 #include <algorithm> 31 #include <fstream> 32 33 #include "mfxstructures.h" 34 #include "mfxvideo.h" 35 #include "mfxvideo++.h" 36 #include "mfxjpeg.h" 37 #include "mfxplugin.h" 38 #include "mfxbrc.h" 39 #include "mfxfei.h" 40 #include "mfxfeihevc.h" 41 #include "mfxmvc.h" 42 #include "mfxla.h" 43 44 #include "vm/strings_defs.h" 45 #include "vm/file_defs.h" 46 #include "vm/time_defs.h" 47 #include "vm/atomic_defs.h" 48 #include "vm/thread_defs.h" 49 50 #include "sample_types.h" 51 52 #include "abstract_splitter.h" 53 #include "avc_bitstream.h" 54 #include "avc_spl.h" 55 #include "avc_headers.h" 56 #include "avc_nal_spl.h" 57 58 59 // A macro to disallow the copy constructor and operator= functions 60 // This should be used in the private: declarations for a class 61 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 62 TypeName(const TypeName&); \ 63 void operator=(const TypeName&) 64 65 //! Base class for types that should not be assigned. 66 class no_assign { 67 // Deny assignment 68 void operator=( const no_assign& ); 69 public: 70 #if __GNUC__ 71 //! Explicitly define default construction, because otherwise gcc issues gratuitous warning. no_assign()72 no_assign() {} 73 #endif /* __GNUC__ */ 74 }; 75 76 //! Base class for types that should not be copied or assigned. 77 class no_copy: no_assign { 78 //! Deny copy construction 79 no_copy( const no_copy& ); 80 public: 81 //! Allow default construction no_copy()82 no_copy() {} 83 }; 84 85 enum { 86 CODEC_VP8 = MFX_MAKEFOURCC('V','P','8',' '), 87 CODEC_MVC = MFX_MAKEFOURCC('M','V','C',' '), 88 }; 89 90 #define MFX_CODEC_DUMP MFX_MAKEFOURCC('D','U','M','P') 91 #define MFX_CODEC_RGB4 MFX_FOURCC_RGB4 92 #define MFX_CODEC_NV12 MFX_FOURCC_NV12 93 #define MFX_CODEC_I420 MFX_FOURCC_I420 94 #define MFX_CODEC_P010 MFX_FOURCC_P010 95 96 enum 97 { 98 MFX_FOURCC_IMC3 = MFX_MAKEFOURCC('I','M','C','3'), 99 MFX_FOURCC_YUV400 = MFX_MAKEFOURCC('4','0','0','P'), 100 MFX_FOURCC_YUV411 = MFX_MAKEFOURCC('4','1','1','P'), 101 MFX_FOURCC_YUV422H = MFX_MAKEFOURCC('4','2','2','H'), 102 MFX_FOURCC_YUV422V = MFX_MAKEFOURCC('4','2','2','V'), 103 MFX_FOURCC_YUV444 = MFX_MAKEFOURCC('4','4','4','P'), 104 #if (MFX_VERSION <= 1027) 105 MFX_FOURCC_RGBP = MFX_MAKEFOURCC('R','G','B','P'), 106 #endif 107 MFX_FOURCC_I420 = MFX_MAKEFOURCC('I','4','2','0') 108 }; 109 110 enum ExtBRCType { 111 EXTBRC_DEFAULT, 112 EXTBRC_OFF, 113 EXTBRC_ON, 114 EXTBRC_IMPLICIT 115 }; 116 117 namespace QPFile { 118 119 enum ReaderStatus 120 { 121 READER_ERR_NONE, 122 READER_ERR_NOT_INITIALIZED, 123 READER_ERR_CODEC_UNSUPPORTED, 124 READER_ERR_FILE_NOT_OPEN, 125 READER_ERR_INCORRECT_FILE 126 }; 127 128 struct FrameInfo 129 { 130 mfxU32 displayOrder; 131 mfxU16 QP; 132 mfxU16 frameType; 133 }; 134 135 // QPFile::Reader reads QP and frame type per frame in encoding order 136 // from external text file (for encoding in qpfile mode) 137 class Reader 138 { 139 public: 140 mfxStatus Read(const msdk_string& strFileName, mfxU32 codecid); 141 void ResetState(); 142 143 mfxU32 GetCurrentEncodedOrder() const; 144 mfxU32 GetCurrentDisplayOrder() const; 145 mfxU16 GetCurrentQP() const; 146 mfxU16 GetCurrentFrameType() const; 147 mfxU32 GetFramesNum() const; 148 void NextFrame(); 149 std::string GetErrorMessage() const; 150 151 private: 152 void ResetState(ReaderStatus set_sts); 153 154 ReaderStatus m_ReaderSts = READER_ERR_NOT_INITIALIZED; 155 mfxU32 m_nFrames = std::numeric_limits<mfxU32>::max(); 156 mfxU32 m_CurFrameNum = std::numeric_limits<mfxU32>::max(); 157 std::vector<FrameInfo> m_FrameVals {}; 158 }; 159 get_line(std::ifstream & ifs,std::string & line)160 inline bool get_line(std::ifstream& ifs, std::string& line) 161 { 162 std::getline(ifs, line, '\n'); 163 if (!line.empty() && line.back() == '\r') 164 line.pop_back(); 165 return !ifs.fail(); 166 } find_nth(const std::string & str,size_t pos,const std::string & needle,mfxU32 nth)167 inline size_t find_nth(const std::string& str, size_t pos, const std::string& needle, mfxU32 nth) 168 { 169 size_t found_pos = str.find(needle, pos); 170 for(; nth != 0 && std::string::npos != found_pos; --nth) 171 found_pos = str.find(needle, found_pos + 1); 172 return found_pos; 173 } StringToFrameType(std::string str)174 inline mfxU16 StringToFrameType(std::string str) 175 { 176 if ("IDR_REF" == str) return MFX_FRAMETYPE_I | MFX_FRAMETYPE_IDR | MFX_FRAMETYPE_REF; 177 else if ("I_REF" == str) return MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF; 178 else if ("P_REF" == str) return MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF; 179 else if ("P" == str) return MFX_FRAMETYPE_P; 180 else if ("B_REF" == str) return MFX_FRAMETYPE_B | MFX_FRAMETYPE_REF; 181 else if ("B" == str) return MFX_FRAMETYPE_B; 182 else return MFX_FRAMETYPE_UNKNOWN; 183 } ReaderStatusToString(ReaderStatus sts)184 inline std::string ReaderStatusToString(ReaderStatus sts) 185 { 186 switch (sts) 187 { 188 case READER_ERR_NOT_INITIALIZED: 189 return std::string("reader not initialized (qpfile has not yet read the file)\n"); 190 case READER_ERR_FILE_NOT_OPEN: 191 return std::string("failed to open file contains frame parameters (check provided path in -qpfile <path>)\n"); 192 case READER_ERR_INCORRECT_FILE: 193 return std::string("incorrect file with frame parameters\n"); 194 case READER_ERR_CODEC_UNSUPPORTED: 195 return std::string("codecs, except h264 and h265, are not supported\n"); 196 default: 197 return std::string(); 198 } 199 } ReadDisplayOrder(const std::string & line)200 inline mfxU32 ReadDisplayOrder(const std::string& line) 201 { 202 return std::stoi(line.substr(0, find_nth(line, 0, ",", 0))); 203 } ReadQP(const std::string & line)204 inline mfxU16 ReadQP(const std::string& line) 205 { 206 size_t pos = find_nth(line, 0, ",", 0) + 1; 207 return static_cast<mfxU16>(std::stoi(line.substr(pos, find_nth(line, 0, ",", 1) - pos))); 208 } ReadFrameType(const std::string & line)209 inline mfxU16 ReadFrameType(const std::string& line) 210 { 211 size_t pos = find_nth(line, 0, ",", 1) + 1; 212 return StringToFrameType(line.substr(pos, line.length() - pos)); 213 } 214 } 215 216 namespace TCBRCTestFile { 217 218 enum ReaderStatus 219 { 220 READER_ERR_NONE, 221 READER_ERR_NOT_INITIALIZED, 222 READER_ERR_CODEC_UNSUPPORTED, 223 READER_ERR_FILE_NOT_OPEN, 224 READER_ERR_INCORRECT_FILE 225 }; 226 227 struct FrameInfo 228 { 229 mfxU32 displayOrder; 230 mfxU32 targetFrameSize; 231 }; 232 233 // TCBRCTestFile reads target frame size in display order 234 // from external text file (for encoding in Low delay BRC mode) 235 236 class Reader 237 { 238 public: 239 mfxStatus Read(const msdk_string& strFileName, mfxU32 codecid); 240 void ResetState(); 241 242 mfxU32 GetTargetFrameSize(mfxU32 frameOrder) const; 243 mfxU32 GetFramesNum() const; 244 void NextFrame(); 245 std::string GetErrorMessage() const; 246 247 private: 248 void ResetState(ReaderStatus set_sts); 249 250 ReaderStatus m_ReaderSts = READER_ERR_NOT_INITIALIZED; 251 mfxU32 m_CurFrameNum = std::numeric_limits<mfxU32>::max(); 252 std::vector<FrameInfo> m_FrameVals{}; 253 }; 254 get_line(std::ifstream & ifs,std::string & line)255 inline bool get_line(std::ifstream& ifs, std::string& line) 256 { 257 std::getline(ifs, line, '\n'); 258 if (!line.empty() && line.back() == '\r') 259 line.pop_back(); 260 return !ifs.fail(); 261 } find_nth(const std::string & str,size_t pos,const std::string & needle,mfxU32 nth)262 inline size_t find_nth(const std::string& str, size_t pos, const std::string& needle, mfxU32 nth) 263 { 264 size_t found_pos = str.find(needle, pos); 265 for (; nth != 0 && std::string::npos != found_pos; --nth) 266 found_pos = str.find(needle, found_pos + 1); 267 return found_pos; 268 } 269 ReaderStatusToString(ReaderStatus sts)270 inline std::string ReaderStatusToString(ReaderStatus sts) 271 { 272 switch (sts) 273 { 274 case READER_ERR_NOT_INITIALIZED: 275 return std::string("reader not initialized (TCBRCTestfile has not yet read the file)\n"); 276 case READER_ERR_FILE_NOT_OPEN: 277 return std::string("failed to open file with TargetFrameSize parameters (check provided path in -tcbrcfile <path>)\n"); 278 case READER_ERR_INCORRECT_FILE: 279 return std::string("incorrect file with frame parameters\n"); 280 case READER_ERR_CODEC_UNSUPPORTED: 281 return std::string("h264 and h265 are supported now\n"); 282 default: 283 return std::string(); 284 } 285 } ReadDisplayOrder(const std::string & line)286 inline mfxU32 ReadDisplayOrder(const std::string& line) 287 { 288 size_t pos = find_nth(line, 0, ":", 0); 289 if (pos != std::string::npos) 290 return std::stoi(line.substr(0, pos)); 291 else 292 return 0; 293 } ReadTargetFrameSize(const std::string & line)294 inline mfxU16 ReadTargetFrameSize(const std::string& line) 295 { 296 size_t pos = find_nth(line, 0, ":", 0); 297 pos = (pos != std::string::npos) ? pos + 1 : 0; 298 return static_cast<mfxU16>(std::stoi(line.substr(pos, line.size() - pos))); 299 } 300 } 301 mfxStatus GetFrameLength(mfxU16 width, mfxU16 height, mfxU32 ColorFormat, mfxU32 &length); 302 303 bool IsDecodeCodecSupported(mfxU32 codecFormat); 304 bool IsEncodeCodecSupported(mfxU32 codecFormat); 305 bool IsPluginCodecSupported(mfxU32 codecFormat); 306 307 // class is used as custom exception 308 class mfxError : public std::runtime_error 309 { 310 public: 311 mfxError(mfxStatus status = MFX_ERR_UNKNOWN, std::string msg = "") runtime_error(msg)312 : runtime_error(msg) 313 , m_Status(status) 314 {} 315 GetStatus()316 mfxStatus GetStatus() const 317 { return m_Status; } 318 319 private: 320 mfxStatus m_Status; 321 }; 322 323 //declare used extension buffers 324 template<class T> 325 struct mfx_ext_buffer_id{}; 326 327 template<>struct mfx_ext_buffer_id<mfxExtCodingOption>{ 328 enum {id = MFX_EXTBUFF_CODING_OPTION}; 329 }; 330 template<>struct mfx_ext_buffer_id<mfxExtCodingOption2>{ 331 enum {id = MFX_EXTBUFF_CODING_OPTION2}; 332 }; 333 template<>struct mfx_ext_buffer_id<mfxExtCodingOption3>{ 334 enum {id = MFX_EXTBUFF_CODING_OPTION3}; 335 }; 336 template<>struct mfx_ext_buffer_id<mfxExtAvcTemporalLayers>{ 337 enum {id = MFX_EXTBUFF_AVC_TEMPORAL_LAYERS}; 338 }; 339 template<>struct mfx_ext_buffer_id<mfxExtAVCRefListCtrl>{ 340 enum {id = MFX_EXTBUFF_AVC_REFLIST_CTRL}; 341 }; 342 template<>struct mfx_ext_buffer_id<mfxExtThreadsParam>{ 343 enum {id = MFX_EXTBUFF_THREADS_PARAM}; 344 }; 345 template<>struct mfx_ext_buffer_id<mfxExtFeiParam> { 346 enum {id = MFX_EXTBUFF_FEI_PARAM}; 347 }; 348 template<>struct mfx_ext_buffer_id<mfxExtFeiPreEncCtrl> { 349 enum {id = MFX_EXTBUFF_FEI_PREENC_CTRL}; 350 }; 351 template<>struct mfx_ext_buffer_id<mfxExtFeiPreEncMV>{ 352 enum {id = MFX_EXTBUFF_FEI_PREENC_MV}; 353 }; 354 template<>struct mfx_ext_buffer_id<mfxExtFeiPreEncMBStat>{ 355 enum {id = MFX_EXTBUFF_FEI_PREENC_MB}; 356 }; 357 template<>struct mfx_ext_buffer_id<mfxExtFeiHevcEncFrameCtrl>{ 358 enum {id = MFX_EXTBUFF_HEVCFEI_ENC_CTRL}; 359 }; 360 template<>struct mfx_ext_buffer_id<mfxExtFeiHevcEncMVPredictors>{ 361 enum {id = MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED}; 362 }; 363 template<>struct mfx_ext_buffer_id<mfxExtFeiHevcEncQP>{ 364 enum {id = MFX_EXTBUFF_HEVCFEI_ENC_QP}; 365 }; 366 template<>struct mfx_ext_buffer_id<mfxExtFeiHevcEncCtuCtrl>{ 367 enum {id = MFX_EXTBUFF_HEVCFEI_ENC_CTU_CTRL}; 368 }; 369 template<>struct mfx_ext_buffer_id<mfxExtHEVCRefLists>{ 370 enum {id = MFX_EXTBUFF_HEVC_REFLISTS}; 371 }; 372 template<>struct mfx_ext_buffer_id<mfxExtFeiHevcRepackCtrl>{ 373 enum {id = MFX_EXTBUFF_HEVCFEI_REPACK_CTRL}; 374 }; 375 template<>struct mfx_ext_buffer_id<mfxExtFeiHevcRepackStat>{ 376 enum {id = MFX_EXTBUFF_HEVCFEI_REPACK_STAT}; 377 }; 378 template<>struct mfx_ext_buffer_id<mfxExtBRC> { 379 enum {id = MFX_EXTBUFF_BRC}; 380 }; 381 template<>struct mfx_ext_buffer_id<mfxExtHEVCParam> { 382 enum {id = MFX_EXTBUFF_HEVC_PARAM}; 383 }; 384 template<>struct mfx_ext_buffer_id<mfxExtDecVideoProcessing> { 385 enum {id = MFX_EXTBUFF_DEC_VIDEO_PROCESSING}; 386 }; 387 template<>struct mfx_ext_buffer_id<mfxExtDecodeErrorReport> { 388 enum {id = MFX_EXTBUFF_DECODE_ERROR_REPORT}; 389 }; 390 template<>struct mfx_ext_buffer_id<mfxExtMVCSeqDesc> { 391 enum {id = MFX_EXTBUFF_MVC_SEQ_DESC}; 392 }; 393 template<>struct mfx_ext_buffer_id<mfxExtVPPDoNotUse> { 394 enum {id = MFX_EXTBUFF_VPP_DONOTUSE}; 395 }; 396 template<>struct mfx_ext_buffer_id<mfxExtVPPDoUse> { 397 enum {id = MFX_EXTBUFF_VPP_DOUSE}; 398 }; 399 template<>struct mfx_ext_buffer_id<mfxExtVPPDeinterlacing> { 400 enum {id = MFX_EXTBUFF_VPP_DEINTERLACING}; 401 }; 402 template<>struct mfx_ext_buffer_id<mfxExtCodingOptionSPSPPS> { 403 enum {id = MFX_EXTBUFF_CODING_OPTION_SPSPPS}; 404 }; 405 template<>struct mfx_ext_buffer_id<mfxExtOpaqueSurfaceAlloc> { 406 enum {id = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION}; 407 }; 408 template<>struct mfx_ext_buffer_id<mfxExtVppMctf> { 409 enum {id = MFX_EXTBUFF_VPP_MCTF}; 410 }; 411 template<>struct mfx_ext_buffer_id<mfxExtVPPComposite> { 412 enum {id = MFX_EXTBUFF_VPP_COMPOSITE}; 413 }; 414 template<>struct mfx_ext_buffer_id<mfxExtVPPFieldProcessing> { 415 enum {id = MFX_EXTBUFF_VPP_FIELD_PROCESSING}; 416 }; 417 template<>struct mfx_ext_buffer_id<mfxExtVPPDetail> { 418 enum {id = MFX_EXTBUFF_VPP_DETAIL}; 419 }; 420 template<>struct mfx_ext_buffer_id<mfxExtVPPFrameRateConversion> { 421 enum {id = MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION}; 422 }; 423 template<>struct mfx_ext_buffer_id<mfxExtLAControl> { 424 enum {id = MFX_EXTBUFF_LOOKAHEAD_CTRL}; 425 }; 426 template<>struct mfx_ext_buffer_id<mfxExtMultiFrameControl> { 427 enum {id = MFX_EXTBUFF_MULTI_FRAME_CONTROL}; 428 }; 429 template<>struct mfx_ext_buffer_id<mfxExtMultiFrameParam> { 430 enum {id = MFX_EXTBUFF_MULTI_FRAME_PARAM}; 431 }; 432 template<>struct mfx_ext_buffer_id<mfxExtHEVCTiles> { 433 enum {id = MFX_EXTBUFF_HEVC_TILES}; 434 }; 435 template<>struct mfx_ext_buffer_id<mfxExtVP9Param> { 436 enum {id = MFX_EXTBUFF_VP9_PARAM}; 437 }; 438 template<>struct mfx_ext_buffer_id<mfxExtVideoSignalInfo> { 439 enum {id = MFX_EXTBUFF_VIDEO_SIGNAL_INFO}; 440 }; 441 template<>struct mfx_ext_buffer_id<mfxExtHEVCRegion> { 442 enum {id = MFX_EXTBUFF_HEVC_REGION}; 443 }; 444 template<>struct mfx_ext_buffer_id<mfxExtAVCRoundingOffset> { 445 enum {id = MFX_EXTBUFF_AVC_ROUNDING_OFFSET}; 446 }; 447 template<>struct mfx_ext_buffer_id<mfxExtVPPDenoise> { 448 enum {id = MFX_EXTBUFF_VPP_DENOISE}; 449 }; 450 template<>struct mfx_ext_buffer_id<mfxExtVPPProcAmp> { 451 enum {id = MFX_EXTBUFF_VPP_PROCAMP}; 452 }; 453 template<>struct mfx_ext_buffer_id<mfxExtVPPImageStab> { 454 enum {id = MFX_EXTBUFF_VPP_IMAGE_STABILIZATION}; 455 }; 456 template<>struct mfx_ext_buffer_id<mfxExtVPPVideoSignalInfo> { 457 enum {id = MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO}; 458 }; 459 template<>struct mfx_ext_buffer_id<mfxExtVPPMirroring> { 460 enum {id = MFX_EXTBUFF_VPP_MIRRORING}; 461 }; 462 template<>struct mfx_ext_buffer_id<mfxExtVPPColorFill> { 463 enum {id = MFX_EXTBUFF_VPP_COLORFILL}; 464 }; 465 template<>struct mfx_ext_buffer_id<mfxExtVPPRotation> { 466 enum {id = MFX_EXTBUFF_VPP_ROTATION}; 467 }; 468 template<>struct mfx_ext_buffer_id<mfxExtVPPScaling> { 469 enum {id = MFX_EXTBUFF_VPP_SCALING}; 470 }; 471 template<>struct mfx_ext_buffer_id<mfxExtColorConversion> { 472 enum {id = MFX_EXTBUFF_VPP_COLOR_CONVERSION}; 473 }; 474 template<>struct mfx_ext_buffer_id<mfxExtPredWeightTable> { 475 enum {id = MFX_EXTBUFF_PRED_WEIGHT_TABLE}; 476 }; 477 template<>struct mfx_ext_buffer_id<mfxExtFeiDecStreamOut> { 478 enum {id = MFX_EXTBUFF_FEI_DEC_STREAM_OUT}; 479 }; 480 template<>struct mfx_ext_buffer_id<mfxExtFeiSliceHeader> { 481 enum {id = MFX_EXTBUFF_FEI_SLICE}; 482 }; 483 template<>struct mfx_ext_buffer_id<mfxExtFeiEncFrameCtrl> { 484 enum {id = MFX_EXTBUFF_FEI_ENC_CTRL}; 485 }; 486 template<>struct mfx_ext_buffer_id<mfxExtFeiEncMVPredictors> { 487 enum {id = MFX_EXTBUFF_FEI_ENC_MV_PRED}; 488 }; 489 template<>struct mfx_ext_buffer_id<mfxExtFeiRepackCtrl> { 490 enum {id = MFX_EXTBUFF_FEI_REPACK_CTRL}; 491 }; 492 template<>struct mfx_ext_buffer_id<mfxExtFeiEncMBCtrl> { 493 enum {id = MFX_EXTBUFF_FEI_ENC_MB}; 494 }; 495 template<>struct mfx_ext_buffer_id<mfxExtFeiEncQP> { 496 enum {id = MFX_EXTBUFF_FEI_ENC_QP}; 497 }; 498 template<>struct mfx_ext_buffer_id<mfxExtFeiEncMBStat> { 499 enum {id = MFX_EXTBUFF_FEI_ENC_MB_STAT}; 500 }; 501 template<>struct mfx_ext_buffer_id<mfxExtFeiEncMV> { 502 enum {id = MFX_EXTBUFF_FEI_ENC_MV}; 503 }; 504 template<>struct mfx_ext_buffer_id<mfxExtFeiPakMBCtrl> { 505 enum {id = MFX_EXTBUFF_FEI_PAK_CTRL}; 506 }; 507 template<>struct mfx_ext_buffer_id<mfxExtFeiRepackStat> { 508 enum {id = MFX_EXTBUFF_FEI_REPACK_STAT}; 509 }; 510 template<>struct mfx_ext_buffer_id<mfxExtFeiSPS> { 511 enum {id = MFX_EXTBUFF_FEI_SPS}; 512 }; 513 template<>struct mfx_ext_buffer_id<mfxExtFeiPPS > { 514 enum {id = MFX_EXTBUFF_FEI_PPS}; 515 }; 516 517 constexpr uint16_t max_num_ext_buffers = 63 * 2; // '*2' is for max estimation if all extBuffer were 'paired' 518 519 //helper function to initialize mfx ext buffer structure 520 template <class T> 521 void init_ext_buffer(T & ext_buffer) 522 { 523 memset(&ext_buffer, 0, sizeof(ext_buffer)); 524 reinterpret_cast<mfxExtBuffer*>(&ext_buffer)->BufferId = mfx_ext_buffer_id<T>::id; 525 reinterpret_cast<mfxExtBuffer*>(&ext_buffer)->BufferSz = sizeof(ext_buffer); 526 } 527 528 template <typename T> struct IsPairedMfxExtBuffer : std::false_type {}; 529 template <> struct IsPairedMfxExtBuffer<mfxExtAVCRefListCtrl> : std::true_type {}; 530 template <> struct IsPairedMfxExtBuffer<mfxExtAVCRoundingOffset> : std::true_type {}; 531 template <> struct IsPairedMfxExtBuffer<mfxExtPredWeightTable> : std::true_type {}; 532 template <> struct IsPairedMfxExtBuffer<mfxExtFeiSliceHeader> : std::true_type {}; 533 template <> struct IsPairedMfxExtBuffer<mfxExtFeiEncFrameCtrl> : std::true_type {}; 534 template <> struct IsPairedMfxExtBuffer<mfxExtFeiEncMVPredictors> : std::true_type {}; 535 template <> struct IsPairedMfxExtBuffer<mfxExtFeiRepackCtrl> : std::true_type {}; 536 template <> struct IsPairedMfxExtBuffer<mfxExtFeiEncMBCtrl> : std::true_type {}; 537 template <> struct IsPairedMfxExtBuffer<mfxExtFeiEncQP> : std::true_type {}; 538 template <> struct IsPairedMfxExtBuffer<mfxExtFeiEncMBStat> : std::true_type {}; 539 template <> struct IsPairedMfxExtBuffer<mfxExtFeiEncMV> : std::true_type {}; 540 template <> struct IsPairedMfxExtBuffer<mfxExtFeiPakMBCtrl> : std::true_type {}; 541 template <> struct IsPairedMfxExtBuffer<mfxExtFeiRepackStat> : std::true_type {}; 542 543 template <typename R> 544 struct ExtParamAccessor 545 { 546 private: 547 using mfxExtBufferDoublePtr = mfxExtBuffer**; 548 public: 549 mfxU16& NumExtParam; 550 mfxExtBufferDoublePtr& ExtParam; 551 ExtParamAccessor(const R& r): 552 NumExtParam(const_cast<mfxU16&>(r.NumExtParam)), 553 ExtParam(const_cast<mfxExtBufferDoublePtr&>(r.ExtParam)) {} 554 }; 555 556 template <> 557 struct ExtParamAccessor<mfxFrameSurface1> 558 { 559 private: 560 using mfxExtBufferDoublePtr = mfxExtBuffer**; 561 public: 562 mfxU16& NumExtParam; 563 mfxExtBufferDoublePtr& ExtParam; 564 ExtParamAccessor(const mfxFrameSurface1& r): 565 NumExtParam(const_cast<mfxU16&>(r.Data.NumExtParam)), 566 ExtParam(const_cast<mfxExtBufferDoublePtr&>(r.Data.ExtParam)) {} 567 }; 568 569 /** ExtBufHolder is an utility class which 570 * provide interface for mfxExtBuffer objects management in any mfx structure (e.g. mfxVideoParam) 571 */ 572 template<typename T> 573 class ExtBufHolder : public T 574 { 575 public: 576 ExtBufHolder() : T() 577 { 578 m_ext_buf.reserve(max_num_ext_buffers); 579 } 580 581 ~ExtBufHolder() // only buffers allocated by wrapper can be released 582 { 583 for (auto it = m_ext_buf.begin(); it != m_ext_buf.end(); it++ ) 584 { 585 delete [] (mfxU8*)(*it); 586 } 587 } 588 589 ExtBufHolder(const ExtBufHolder& ref) 590 { 591 m_ext_buf.reserve(max_num_ext_buffers); 592 *this = ref; // call to operator= 593 } 594 595 ExtBufHolder& operator=(const ExtBufHolder& ref) 596 { 597 const T* src_base = &ref; 598 return operator=(*src_base); 599 } 600 601 ExtBufHolder(const T& ref) 602 { 603 *this = ref; // call to operator= 604 } 605 606 ExtBufHolder& operator=(const T& ref) 607 { 608 // copy content of main structure type T 609 T* dst_base = this; 610 const T* src_base = &ref; 611 *dst_base = *src_base; 612 613 //remove all existing extension buffers 614 ClearBuffers(); 615 616 const auto ref_ = ExtParamAccessor<T>(ref); 617 618 //reproduce list of extension buffers and copy its content 619 for (size_t i = 0; i < ref_.NumExtParam; ++i) 620 { 621 const auto src_buf = ref_.ExtParam[i]; 622 if (!src_buf) throw mfxError(MFX_ERR_NULL_PTR, "Null pointer attached to source ExtParam"); 623 if (!IsCopyAllowed(src_buf->BufferId)) 624 { 625 auto msg = "Deep copy of '" + Fourcc2Str(src_buf->BufferId) + "' extBuffer is not allowed"; 626 throw mfxError(MFX_ERR_UNDEFINED_BEHAVIOR, msg); 627 } 628 629 // 'false' below is because here we just copy extBuffer's one by one 630 auto dst_buf = AddExtBuffer(src_buf->BufferId, src_buf->BufferSz, false); 631 // copy buffer content w/o restoring its type 632 memcpy((void*)dst_buf, (void*)src_buf, src_buf->BufferSz); 633 } 634 635 return *this; 636 } 637 638 ExtBufHolder(ExtBufHolder &&) = default; 639 ExtBufHolder & operator= (ExtBufHolder&&) = default; 640 641 // Always returns a valid pointer or throws an exception 642 template<typename TB> 643 TB* AddExtBuffer() 644 { 645 mfxExtBuffer* b = AddExtBuffer(mfx_ext_buffer_id<TB>::id, sizeof(TB), IsPairedMfxExtBuffer<TB>::value); 646 return (TB*)b; 647 } 648 649 template<typename TB> 650 void RemoveExtBuffer() 651 { 652 auto it = std::find_if(m_ext_buf.begin(), m_ext_buf.end(), CmpExtBufById(mfx_ext_buffer_id<TB>::id)); 653 if (it != m_ext_buf.end()) 654 { 655 delete [] (mfxU8*)(*it); 656 it = m_ext_buf.erase(it); 657 658 if (IsPairedMfxExtBuffer<TB>::value) 659 { 660 if (it == m_ext_buf.end() || (*it)->BufferId != mfx_ext_buffer_id<TB>::id) 661 throw mfxError(MFX_ERR_NULL_PTR, "RemoveExtBuffer: ExtBuffer's parity has been broken"); 662 663 delete [] (mfxU8*)(*it); 664 m_ext_buf.erase(it); 665 } 666 667 RefreshBuffers(); 668 } 669 } 670 671 template <typename TB> 672 TB* GetExtBuffer(uint32_t fieldId = 0) const 673 { 674 return (TB*)FindExtBuffer(mfx_ext_buffer_id<TB>::id, fieldId); 675 } 676 677 template <typename TB> 678 operator TB*() 679 { 680 return (TB*)FindExtBuffer(mfx_ext_buffer_id<TB>::id, 0); 681 } 682 683 template <typename TB> 684 operator TB*() const 685 { 686 return (TB*)FindExtBuffer(mfx_ext_buffer_id<TB>::id, 0); 687 } 688 689 private: 690 691 mfxExtBuffer* AddExtBuffer(mfxU32 id, mfxU32 size, bool isPairedExtBuffer) 692 { 693 if (!size || !id) 694 throw mfxError(MFX_ERR_NULL_PTR, "AddExtBuffer: wrong size or id!"); 695 696 auto it = std::find_if(m_ext_buf.begin(), m_ext_buf.end(), CmpExtBufById(id)); 697 if (it == m_ext_buf.end()) 698 { 699 auto buf = (mfxExtBuffer*)new mfxU8[size]; 700 memset(buf, 0, size); 701 m_ext_buf.push_back(buf); 702 703 buf->BufferId = id; 704 buf->BufferSz = size; 705 706 if (isPairedExtBuffer) 707 { 708 // Allocate the other mfxExtBuffer _right_after_ the first one ... 709 buf = (mfxExtBuffer*)new mfxU8[size]; 710 memset(buf, 0, size); 711 m_ext_buf.push_back(buf); 712 713 buf->BufferId = id; 714 buf->BufferSz = size; 715 716 RefreshBuffers(); 717 return m_ext_buf[m_ext_buf.size() - 2]; // ... and return a pointer to the first one 718 } 719 720 RefreshBuffers(); 721 return m_ext_buf.back(); 722 } 723 724 return *it; 725 } 726 727 mfxExtBuffer* FindExtBuffer(mfxU32 id, uint32_t fieldId) const 728 { 729 auto it = std::find_if(m_ext_buf.begin(), m_ext_buf.end(), CmpExtBufById(id)); 730 if (fieldId && it != m_ext_buf.end()) 731 { 732 ++it; 733 return it != m_ext_buf.end() ? *it : nullptr; 734 } 735 return it != m_ext_buf.end() ? *it : nullptr; 736 } 737 738 void RefreshBuffers() 739 { 740 auto this_ = ExtParamAccessor<T>(*this); 741 this_.NumExtParam = static_cast<mfxU16>(m_ext_buf.size()); 742 this_.ExtParam = this_.NumExtParam ? m_ext_buf.data() : nullptr; 743 } 744 745 void ClearBuffers() 746 { 747 if (m_ext_buf.size()) 748 { 749 for (auto it = m_ext_buf.begin(); it != m_ext_buf.end(); it++ ) 750 { 751 delete [] (mfxU8*)(*it); 752 } 753 m_ext_buf.clear(); 754 } 755 RefreshBuffers(); 756 } 757 758 bool IsCopyAllowed(mfxU32 id) 759 { 760 static const mfxU32 allowed[] = { 761 MFX_EXTBUFF_CODING_OPTION, 762 MFX_EXTBUFF_CODING_OPTION2, 763 MFX_EXTBUFF_CODING_OPTION3, 764 MFX_EXTBUFF_FEI_PARAM, 765 MFX_EXTBUFF_BRC, 766 MFX_EXTBUFF_HEVC_PARAM, 767 MFX_EXTBUFF_VP9_PARAM, 768 MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION, 769 MFX_EXTBUFF_FEI_PPS, 770 MFX_EXTBUFF_FEI_SPS, 771 MFX_EXTBUFF_LOOKAHEAD_CTRL, 772 MFX_EXTBUFF_LOOKAHEAD_STAT, 773 MFX_EXTBUFF_DEC_VIDEO_PROCESSING 774 }; 775 776 auto it = std::find_if(std::begin(allowed), std::end(allowed), 777 [&id](const mfxU32 allowed_id) 778 { 779 return allowed_id == id; 780 }); 781 return it != std::end(allowed); 782 } 783 784 struct CmpExtBufById 785 { 786 mfxU32 id; 787 788 CmpExtBufById(mfxU32 _id) 789 : id(_id) 790 { }; 791 792 bool operator () (mfxExtBuffer* b) 793 { 794 return (b && b->BufferId == id); 795 }; 796 }; 797 798 static std::string Fourcc2Str(mfxU32 fourcc) 799 { 800 std::string s; 801 for (size_t i = 0; i < 4; i++) 802 { 803 s.push_back(*(i + (char*)&fourcc)); 804 } 805 return s; 806 } 807 808 std::vector<mfxExtBuffer*> m_ext_buf; 809 }; 810 811 using MfxVideoParamsWrapper = ExtBufHolder<mfxVideoParam>; 812 using mfxEncodeCtrlWrap = ExtBufHolder<mfxEncodeCtrl>; 813 using mfxInitParamlWrap = ExtBufHolder<mfxInitParam>; 814 using mfxFrameSurfaceWrap = ExtBufHolder<mfxFrameSurface1>; 815 816 class mfxBitstreamWrapper : public ExtBufHolder<mfxBitstream> 817 { 818 typedef ExtBufHolder<mfxBitstream> base; 819 public: 820 mfxBitstreamWrapper() 821 : base() 822 {} 823 824 mfxBitstreamWrapper(mfxU32 n_bytes) 825 : base() 826 { 827 Extend(n_bytes); 828 } 829 830 mfxBitstreamWrapper(const mfxBitstreamWrapper & bs_wrapper) 831 : base(bs_wrapper) 832 , m_data(bs_wrapper.m_data) 833 { 834 Data = m_data.data(); 835 } 836 837 mfxBitstreamWrapper& operator=(mfxBitstreamWrapper const& bs_wrapper) 838 { 839 mfxBitstreamWrapper tmp(bs_wrapper); 840 841 *this = std::move(tmp); 842 843 return *this; 844 } 845 846 mfxBitstreamWrapper(mfxBitstreamWrapper && bs_wrapper) = default; 847 mfxBitstreamWrapper & operator= (mfxBitstreamWrapper&& bs_wrapper) = default; 848 ~mfxBitstreamWrapper() = default; 849 850 void Extend(mfxU32 n_bytes) 851 { 852 if (MaxLength >= n_bytes) 853 return; 854 855 m_data.resize(n_bytes); 856 857 Data = m_data.data(); 858 MaxLength = n_bytes; 859 } 860 private: 861 std::vector<mfxU8> m_data; 862 }; 863 864 class CSmplYUVReader 865 { 866 public : 867 typedef std::list<msdk_string>::iterator ls_iterator; 868 CSmplYUVReader(); 869 virtual ~CSmplYUVReader(); 870 871 virtual void Close(); 872 virtual mfxStatus Init(std::list<msdk_string> inputs, mfxU32 ColorFormat, bool shouldShiftP010=false); 873 virtual mfxStatus SkipNframesFromBeginning(mfxU16 w, mfxU16 h, mfxU32 viewId, mfxU32 nframes); 874 virtual mfxStatus LoadNextFrame(mfxFrameSurface1* pSurface); 875 virtual void Reset(); 876 mfxU32 m_ColorFormat; // color format of input YUV data, YUV420 or NV12 877 878 protected: 879 880 std::vector<FILE*> m_files; 881 882 bool shouldShift10BitsHigh; 883 bool m_bInited; 884 }; 885 886 class CSmplBitstreamWriter 887 { 888 public : 889 890 CSmplBitstreamWriter(); 891 virtual ~CSmplBitstreamWriter(); 892 893 virtual mfxStatus Init(const msdk_char *strFileName); 894 virtual mfxStatus WriteNextFrame(mfxBitstream *pMfxBitstream, bool isPrint = true); 895 virtual mfxStatus Reset(); 896 virtual void Close(); 897 mfxU32 m_nProcessedFramesNum; 898 899 protected: 900 FILE* m_fSource; 901 bool m_bInited; 902 msdk_string m_sFile; 903 }; 904 905 class CSmplYUVWriter 906 { 907 public : 908 909 CSmplYUVWriter(); 910 virtual ~CSmplYUVWriter(); 911 912 virtual void Close(); 913 virtual mfxStatus Init(const msdk_char *strFileName, const mfxU32 numViews); 914 virtual mfxStatus Reset(); 915 virtual mfxStatus WriteNextFrame(mfxFrameSurface1 *pSurface); 916 virtual mfxStatus WriteNextFrameI420(mfxFrameSurface1 *pSurface); 917 918 void SetMultiView() { m_bIsMultiView = true; } 919 920 protected: 921 FILE *m_fDest, **m_fDestMVC; 922 bool m_bInited, m_bIsMultiView; 923 mfxU32 m_numCreatedFiles; 924 msdk_string m_sFile; 925 mfxU32 m_nViews; 926 }; 927 928 class CSmplBitstreamReader 929 { 930 public : 931 932 CSmplBitstreamReader(); 933 virtual ~CSmplBitstreamReader(); 934 935 //resets position to file begin 936 virtual void Reset(); 937 virtual void Close(); 938 virtual mfxStatus Init(const msdk_char *strFileName); 939 virtual mfxStatus ReadNextFrame(mfxBitstream *pBS); 940 941 protected: 942 FILE* m_fSource; 943 bool m_bInited; 944 }; 945 946 class CH264FrameReader : public CSmplBitstreamReader 947 { 948 public: 949 CH264FrameReader(); 950 virtual ~CH264FrameReader(); 951 952 /** Free resources.*/ 953 virtual void Close(); 954 virtual mfxStatus Init(const msdk_char *strFileName); 955 virtual mfxStatus ReadNextFrame(mfxBitstream *pBS); 956 957 private: 958 mfxBitstream *m_processedBS; 959 // input bit stream 960 mfxBitstreamWrapper m_originalBS; 961 962 mfxStatus PrepareNextFrame(mfxBitstream *in, mfxBitstream **out); 963 964 // is stream ended 965 bool m_isEndOfStream; 966 967 std::unique_ptr<AbstractSplitter> m_pNALSplitter; 968 FrameSplitterInfo *m_frame; 969 mfxU8 *m_plainBuffer; 970 mfxU32 m_plainBufferSize; 971 mfxBitstream m_outBS; 972 }; 973 974 //provides output bistream with at least 1 frame, reports about error 975 class CJPEGFrameReader : public CSmplBitstreamReader 976 { 977 enum JPEGMarker 978 { 979 SOI=0xD8FF, 980 EOI=0xD9FF 981 }; 982 public: 983 virtual mfxStatus ReadNextFrame(mfxBitstream *pBS); 984 protected: 985 mfxU32 FindMarker(mfxBitstream *pBS,mfxU32 startOffset,JPEGMarker marker); 986 }; 987 988 //appends output bistream with exactly 1 frame, reports about error 989 class CIVFFrameReader : public CSmplBitstreamReader 990 { 991 public: 992 CIVFFrameReader(); 993 virtual void Reset(); 994 virtual mfxStatus Init(const msdk_char *strFileName); 995 virtual mfxStatus ReadNextFrame(mfxBitstream *pBS); 996 997 protected: 998 999 /*bytes 0-3 signature: 'DKIF' 1000 bytes 4-5 version (should be 0) 1001 bytes 6-7 length of header in bytes 1002 bytes 8-11 codec FourCC (e.g., 'VP80') 1003 bytes 12-13 width in pixels 1004 bytes 14-15 height in pixels 1005 bytes 16-19 frame rate 1006 bytes 20-23 time scale 1007 bytes 24-27 number of frames in file 1008 bytes 28-31 unused*/ 1009 1010 struct DKIFHrd 1011 { 1012 mfxU32 dkif; 1013 mfxU16 version; 1014 mfxU16 header_len; 1015 mfxU32 codec_FourCC; 1016 mfxU16 width; 1017 mfxU16 height; 1018 mfxU32 frame_rate; 1019 mfxU32 time_scale; 1020 mfxU32 num_frames; 1021 mfxU32 unused; 1022 }m_hdr; 1023 mfxStatus ReadHeader(); 1024 }; 1025 1026 // writes bitstream to duplicate-file & supports joining 1027 // (for ViewOutput encoder mode) 1028 class CSmplBitstreamDuplicateWriter : public CSmplBitstreamWriter 1029 { 1030 public: 1031 CSmplBitstreamDuplicateWriter(); 1032 1033 virtual mfxStatus InitDuplicate(const msdk_char *strFileName); 1034 virtual mfxStatus JoinDuplicate(CSmplBitstreamDuplicateWriter *pJoinee); 1035 virtual mfxStatus WriteNextFrame(mfxBitstream *pMfxBitstream, bool isPrint = true); 1036 virtual void Close(); 1037 protected: 1038 FILE* m_fSourceDuplicate; 1039 bool m_bJoined; 1040 }; 1041 1042 //timeinterval calculation helper 1043 1044 template <int tag = 0> 1045 class CTimeInterval : private no_copy 1046 { 1047 static double g_Freq; 1048 double &m_start; 1049 double m_own;//reference to this if external counter not required 1050 //since QPC functions are quite slow it makes sense to optionally enable them 1051 bool m_bEnable; 1052 msdk_tick m_StartTick; 1053 1054 public: 1055 CTimeInterval(double &dRef , bool bEnable = true) 1056 : m_start(dRef) 1057 , m_bEnable(bEnable) 1058 , m_StartTick(0) 1059 { 1060 if (!m_bEnable) 1061 return; 1062 Initialize(); 1063 } 1064 CTimeInterval(bool bEnable = true) 1065 : m_start(m_own) 1066 , m_own() 1067 , m_bEnable(bEnable) 1068 , m_StartTick(0) 1069 { 1070 if (!m_bEnable) 1071 return; 1072 Initialize(); 1073 } 1074 1075 //updates external value with current time 1076 double Commit() 1077 { 1078 if (!m_bEnable) 1079 return 0.0; 1080 1081 if (0.0 != g_Freq) 1082 { 1083 m_start = MSDK_GET_TIME(msdk_time_get_tick(), m_StartTick, g_Freq); 1084 } 1085 return m_start; 1086 } 1087 //last comitted value 1088 double Last() 1089 { 1090 return m_start; 1091 } 1092 ~CTimeInterval() 1093 { 1094 Commit(); 1095 } 1096 private: 1097 void Initialize() 1098 { 1099 if (0.0 == g_Freq) 1100 { 1101 g_Freq = (double)msdk_time_get_frequency(); 1102 } 1103 m_StartTick = msdk_time_get_tick(); 1104 } 1105 }; 1106 1107 template <int tag>double CTimeInterval<tag>::g_Freq = 0.0f; 1108 1109 /** Helper class to measure execution time of some code. Use this class 1110 * if you need manual measurements. 1111 * 1112 * Usage example: 1113 * { 1114 * CTimer timer; 1115 * msdk_tick summary_tick; 1116 * 1117 * timer.Start() 1118 * function_to_measure(); 1119 * summary_tick = timer.GetDelta(); 1120 * printf("Elapsed time 1: %f\n", timer.GetTime()); 1121 * ... 1122 * if (condition) timer.Start(); 1123 function_to_measure(); 1124 * if (condition) { 1125 * summary_tick += timer.GetDelta(); 1126 * printf("Elapsed time 2: %f\n", timer.GetTime(); 1127 * } 1128 * printf("Overall time: %f\n", CTimer::ConvertToSeconds(summary_tick); 1129 * } 1130 */ 1131 class CTimer 1132 { 1133 public: 1134 CTimer(): 1135 start(0) 1136 { 1137 } 1138 static msdk_tick GetFrequency() 1139 { 1140 if (!frequency) frequency = msdk_time_get_frequency(); 1141 return frequency; 1142 } 1143 static mfxF64 ConvertToSeconds(msdk_tick elapsed) 1144 { 1145 return MSDK_GET_TIME(elapsed, 0, GetFrequency()); 1146 } 1147 1148 inline void Start() 1149 { 1150 start = msdk_time_get_tick(); 1151 } 1152 inline msdk_tick GetDelta() 1153 { 1154 return msdk_time_get_tick() - start; 1155 } 1156 inline mfxF64 GetTime() 1157 { 1158 return MSDK_GET_TIME(msdk_time_get_tick(), start, GetFrequency()); 1159 } 1160 1161 protected: 1162 static msdk_tick frequency; 1163 msdk_tick start; 1164 private: 1165 CTimer(const CTimer&); 1166 void operator=(const CTimer&); 1167 }; 1168 1169 /** Helper class to measure overall execution time of some code. Use this 1170 * class if you want to measure execution time of the repeatedly executed 1171 * code. 1172 * 1173 * Usage example 1: 1174 * 1175 * msdk_tick summary_tick = 0; 1176 * 1177 * void function() { 1178 * 1179 * { 1180 * CAutoTimer timer(&summary_tick); 1181 * ... 1182 * } 1183 * ... 1184 * int main() { 1185 * for (;condition;) { 1186 * function(); 1187 * } 1188 * printf("Elapsed time: %f\n", CTimer::ConvertToSeconds(summary_tick); 1189 * return 0; 1190 * } 1191 * 1192 * Usage example 2: 1193 * { 1194 * msdk_tick summary_tick = 0; 1195 * 1196 * { 1197 * CAutoTimer timer(&summary_tick); 1198 * 1199 * for (;condition;) { 1200 * ... 1201 * { 1202 * function_to_measure(); 1203 * timer.Sync(); 1204 * printf("Progress: %f\n", CTimer::ConvertToSeconds(summary_tick); 1205 * } 1206 * ... 1207 * } 1208 * } 1209 * printf("Elapsed time: %f\n", CTimer::ConvertToSeconds(summary_tick); 1210 * } 1211 * 1212 */ 1213 class CAutoTimer 1214 { 1215 public: 1216 CAutoTimer(msdk_tick& _elapsed): 1217 elapsed(_elapsed), 1218 start(0) 1219 { 1220 elapsed = _elapsed; 1221 start = msdk_time_get_tick(); 1222 } 1223 ~CAutoTimer() 1224 { 1225 elapsed += msdk_time_get_tick() - start; 1226 } 1227 msdk_tick Sync() 1228 { 1229 msdk_tick cur = msdk_time_get_tick(); 1230 elapsed += cur - start; 1231 start = cur; 1232 return elapsed; 1233 } 1234 protected: 1235 msdk_tick& elapsed; 1236 msdk_tick start; 1237 private: 1238 CAutoTimer(const CAutoTimer&); 1239 void operator=(const CAutoTimer&); 1240 }; 1241 1242 mfxStatus ConvertFrameRate(mfxF64 dFrameRate, mfxU32* pnFrameRateExtN, mfxU32* pnFrameRateExtD); 1243 mfxF64 CalculateFrameRate(mfxU32 nFrameRateExtN, mfxU32 nFrameRateExtD); 1244 1245 template <class T> 1246 mfxU16 GetFreeSurfaceIndex(T* pSurfacesPool, mfxU16 nPoolSize) 1247 { 1248 constexpr mfxU16 MSDK_INVALID_SURF_IDX = 0xffff; 1249 1250 if (pSurfacesPool) 1251 { 1252 for (mfxU16 i = 0; i < nPoolSize; i++) 1253 { 1254 if (0 == pSurfacesPool[i].Data.Locked) 1255 { 1256 return i; 1257 } 1258 } 1259 } 1260 return MSDK_INVALID_SURF_IDX; 1261 } 1262 1263 mfxU16 GetFreeSurface(mfxFrameSurface1* pSurfacesPool, mfxU16 nPoolSize); 1264 void FreeSurfacePool(mfxFrameSurface1* pSurfacesPool, mfxU16 nPoolSize); 1265 1266 mfxU16 CalculateDefaultBitrate(mfxU32 nCodecId, mfxU32 nTargetUsage, mfxU32 nWidth, mfxU32 nHeight, mfxF64 dFrameRate); 1267 1268 //serialization fnc set 1269 std::basic_string<msdk_char> CodecIdToStr(mfxU32 nFourCC); 1270 mfxU16 StrToTargetUsage(msdk_string strInput); 1271 const msdk_char* TargetUsageToStr(mfxU16 tu); 1272 const msdk_char* ColorFormatToStr(mfxU32 format); 1273 const msdk_char* MfxStatusToStr(mfxStatus sts); 1274 1275 // sets bitstream->PicStruct parsing first APP0 marker in bitstream 1276 mfxStatus MJPEG_AVI_ParsePicStruct(mfxBitstream *bitstream); 1277 1278 // For MVC encoding/decoding purposes 1279 std::basic_string<msdk_char> FormMVCFileName(const msdk_char *strFileName, const mfxU32 numView); 1280 1281 //piecewise linear function for bitrate approximation 1282 class PartiallyLinearFNC 1283 { 1284 mfxF64 *m_pX; 1285 mfxF64 *m_pY; 1286 mfxU32 m_nPoints; 1287 mfxU32 m_nAllocated; 1288 1289 public: 1290 PartiallyLinearFNC(); 1291 ~PartiallyLinearFNC(); 1292 1293 void AddPair(mfxF64 x, mfxF64 y); 1294 mfxF64 at(mfxF64); 1295 private: 1296 DISALLOW_COPY_AND_ASSIGN(PartiallyLinearFNC); 1297 }; 1298 1299 // function for getting a pointer to a specific external buffer from the array 1300 mfxExtBuffer* GetExtBuffer(mfxExtBuffer** ebuffers, mfxU32 nbuffers, mfxU32 BufferId); 1301 1302 // returns false if buf length is insufficient, otherwise 1303 // skips step bytes in buf with specified length and returns true 1304 template <typename Buf_t, typename Length_t> 1305 bool skip(const Buf_t *&buf, Length_t &length, Length_t step) 1306 { 1307 if (length < step) 1308 return false; 1309 1310 buf += step; 1311 length -= step; 1312 1313 return true; 1314 } 1315 1316 //do not link MediaSDK dispatched if class not used 1317 struct MSDKAdapter { 1318 // returns the number of adapter associated with MSDK session, 0 for SW session 1319 static mfxU32 GetNumber(mfxSession session, mfxIMPL implVia = 0) { 1320 mfxU32 adapterNum = 0; // default 1321 mfxIMPL impl = MFX_IMPL_SOFTWARE; // default in case no HW IMPL is found 1322 1323 // we don't care for error codes in further code; if something goes wrong we fall back to the default adapter 1324 if (session) 1325 { 1326 MFXQueryIMPL(session, &impl); 1327 } 1328 else 1329 { 1330 // an auxiliary session, internal for this function 1331 mfxSession auxSession; 1332 memset(&auxSession, 0, sizeof(auxSession)); 1333 1334 mfxVersion ver = { {1, 1 }}; // minimum API version which supports multiple devices 1335 MFXInit(MFX_IMPL_HARDWARE_ANY | implVia, &ver, &auxSession); 1336 MFXQueryIMPL(auxSession, &impl); 1337 MFXClose(auxSession); 1338 } 1339 1340 // extract the base implementation type 1341 mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); 1342 1343 const struct 1344 { 1345 // actual implementation 1346 mfxIMPL impl; 1347 // adapter's number 1348 mfxU32 adapterID; 1349 1350 } implTypes[] = { 1351 {MFX_IMPL_HARDWARE, 0}, 1352 {MFX_IMPL_SOFTWARE, 0}, 1353 {MFX_IMPL_HARDWARE2, 1}, 1354 {MFX_IMPL_HARDWARE3, 2}, 1355 {MFX_IMPL_HARDWARE4, 3} 1356 }; 1357 1358 1359 // get corresponding adapter number 1360 for (mfxU8 i = 0; i < sizeof(implTypes)/sizeof(*implTypes); i++) 1361 { 1362 if (implTypes[i].impl == baseImpl) 1363 { 1364 adapterNum = implTypes[i].adapterID; 1365 break; 1366 } 1367 } 1368 1369 return adapterNum; 1370 } 1371 }; 1372 1373 struct APIChangeFeatures { 1374 bool JpegDecode; 1375 bool JpegEncode; 1376 bool MVCDecode; 1377 bool MVCEncode; 1378 bool IntraRefresh; 1379 bool LowLatency; 1380 bool ViewOutput; 1381 bool LookAheadBRC; 1382 bool AudioDecode; 1383 bool SupportCodecPluginAPI; 1384 }; 1385 1386 inline 1387 mfxU32 MakeVersion(mfxU16 major, mfxU16 minor) 1388 { 1389 return major * 1000 + minor; 1390 } 1391 1392 mfxVersion getMinimalRequiredVersion(const APIChangeFeatures &features); 1393 1394 enum msdkAPIFeature { 1395 MSDK_FEATURE_NONE, 1396 MSDK_FEATURE_MVC, 1397 MSDK_FEATURE_JPEG_DECODE, 1398 MSDK_FEATURE_LOW_LATENCY, 1399 MSDK_FEATURE_MVC_VIEWOUTPUT, 1400 MSDK_FEATURE_JPEG_ENCODE, 1401 MSDK_FEATURE_LOOK_AHEAD, 1402 MSDK_FEATURE_PLUGIN_API 1403 }; 1404 1405 /* Returns true if feature is supported in the given API version */ 1406 bool CheckVersion(mfxVersion* version, msdkAPIFeature feature); 1407 1408 void ConfigureAspectRatioConversion(mfxInfoVPP* pVppInfo); 1409 1410 void SEICalcSizeType(std::vector<mfxU8>& data, mfxU16 type, mfxU32 size); 1411 1412 mfxU8 Char2Hex(msdk_char ch); 1413 1414 enum MsdkTraceLevel { 1415 MSDK_TRACE_LEVEL_SILENT = -1, 1416 MSDK_TRACE_LEVEL_CRITICAL = 0, 1417 MSDK_TRACE_LEVEL_ERROR = 1, 1418 MSDK_TRACE_LEVEL_WARNING = 2, 1419 MSDK_TRACE_LEVEL_INFO = 3, 1420 MSDK_TRACE_LEVEL_DEBUG = 4, 1421 }; 1422 1423 msdk_string NoFullPath(const msdk_string &); 1424 int msdk_trace_get_level(); 1425 void msdk_trace_set_level(int); 1426 bool msdk_trace_is_printable(int); 1427 1428 msdk_ostream & operator <<(msdk_ostream & os, MsdkTraceLevel tt); 1429 1430 template<typename T> 1431 mfxStatus msdk_opt_read(const msdk_char* string, T& value); 1432 1433 template<size_t S> 1434 mfxStatus msdk_opt_read(const msdk_char* string, msdk_char (&value)[S]) 1435 { 1436 if (!S) 1437 { 1438 return MFX_ERR_UNKNOWN; 1439 } 1440 value[0]=0; 1441 #if defined(_WIN32) || defined(_WIN64) 1442 value[S - 1] = 0; 1443 return (0 == _tcsncpy_s(value, string,S-1))? MFX_ERR_NONE: MFX_ERR_UNKNOWN; 1444 #else 1445 if (strlen(string) < S) { 1446 strncpy(value, string, S-1); 1447 value[S - 1] = 0; 1448 return MFX_ERR_NONE; 1449 } 1450 return MFX_ERR_UNKNOWN; 1451 #endif 1452 } 1453 1454 template<typename T> 1455 inline mfxStatus msdk_opt_read(const msdk_string& string, T& value) 1456 { 1457 return msdk_opt_read(string.c_str(), value); 1458 } 1459 1460 mfxStatus StrFormatToCodecFormatFourCC(msdk_char* strInput, mfxU32 &codecFormat); 1461 msdk_string StatusToString(mfxStatus sts); 1462 mfxI32 getMonitorType(msdk_char* str); 1463 1464 void WaitForDeviceToBecomeFree(MFXVideoSession& session, mfxSyncPoint& syncPoint, mfxStatus& currentStatus); 1465 1466 mfxU16 FourCCToChroma(mfxU32 fourCC); 1467 1468 class FPSLimiter 1469 { 1470 public: 1471 FPSLimiter() = default; 1472 ~FPSLimiter() = default; 1473 void Reset(mfxU32 fps) 1474 { 1475 m_delayTicks = fps ? msdk_time_get_frequency() / fps : 0; 1476 } 1477 void Work() 1478 { 1479 msdk_tick current_tick = msdk_time_get_tick(); 1480 while( m_delayTicks && (m_startTick + m_delayTicks > current_tick) ) 1481 { 1482 msdk_tick left_tick = m_startTick + m_delayTicks - current_tick; 1483 uint32_t sleepTime = (uint32_t)(left_tick * 1000 / msdk_time_get_frequency()); 1484 MSDK_SLEEP(sleepTime); 1485 current_tick = msdk_time_get_tick(); 1486 }; 1487 m_startTick = msdk_time_get_tick(); 1488 } 1489 1490 protected: 1491 msdk_tick m_startTick = 0; 1492 msdk_tick m_delayTicks = 0; 1493 }; 1494 1495 #endif //__SAMPLE_UTILS_H__ 1496