1 // Copyright (c) 2019 Intel Corporation 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in all 11 // copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 // SOFTWARE. 20 21 #ifndef __MFX_MPEG2_ENC_COMMON_H__ 22 #define __MFX_MPEG2_ENC_COMMON_H__ 23 24 // functions for VideoEditing 25 26 #include "mfx_common.h" 27 #include "mfxvideo.h" 28 29 class SHParametersEx 30 { 31 public: SHParametersEx()32 SHParametersEx() 33 { 34 m_pBuffer = 0; 35 m_bufLen = 0; 36 } ~SHParametersEx()37 ~SHParametersEx() 38 { 39 if (m_pBuffer) 40 { 41 delete [] m_pBuffer; 42 } 43 } GetSH(mfxU8 ** pSH,mfxU32 * len)44 void GetSH (mfxU8 **pSH, mfxU32 *len) 45 { 46 *pSH = m_pBuffer; 47 *len = m_bufLen; 48 } CheckSHParameters(mfxU8 * pSH,mfxU32 len,mfxU32 & real_len,mfxVideoParam * par,mfxExtCodingOption * extOpt)49 static bool CheckSHParameters (mfxU8 *pSH, mfxU32 len, mfxU32 &real_len, mfxVideoParam *par, mfxExtCodingOption * extOpt) 50 { 51 real_len = 0; 52 return DecodeSequenceHeader (pSH,len, par, extOpt, real_len); 53 } FillSHParameters(mfxVideoParam * par,mfxExtCodingOption * extOpt)54 mfxStatus FillSHParameters (mfxVideoParam* par, mfxExtCodingOption * extOpt) 55 { 56 mfxU8 *pSH = nullptr; 57 mfxU32 len = 0; 58 mfxU32 real_len = 0; 59 60 if (GetSPSBuffer(par, &pSH, &len)) 61 { 62 if (!DecodeSequenceHeader (pSH,len, par, extOpt, real_len)) 63 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM; 64 65 delete [] m_pBuffer; 66 m_pBuffer = new mfxU8 [real_len]; 67 68 std::copy(pSH, pSH + real_len, m_pBuffer); 69 m_bufLen = real_len; 70 } 71 return MFX_ERR_NONE; 72 } GetSPSBuffer(mfxVideoParam * par,mfxU8 ** ppSH,mfxU32 * pLen)73 static bool GetSPSBuffer(mfxVideoParam* par, mfxU8 **ppSH, mfxU32 *pLen) 74 { 75 mfxExtCodingOptionSPSPPS* pCO = GetExtCodingOptionsSPSPPS(par->ExtParam, par->NumExtParam); 76 if (pCO) 77 { 78 if (pCO->SPSBuffer && pCO->SPSBufSize!=0) 79 { 80 *ppSH = pCO->SPSBuffer; 81 *pLen = pCO->SPSBufSize; 82 return true; 83 } 84 } 85 *ppSH = 0; 86 *pLen = 0; 87 return false; 88 } GetExtCodingOptionsSPSPPS(mfxExtBuffer ** ebuffers,mfxU32 nbuffers)89 static mfxExtCodingOptionSPSPPS* GetExtCodingOptionsSPSPPS(mfxExtBuffer** ebuffers, mfxU32 nbuffers) 90 { 91 if (ebuffers) 92 { 93 for(mfxU32 i=0; i<nbuffers; i++) 94 { 95 if((*(ebuffers+i))->BufferId == MFX_EXTBUFF_CODING_OPTION_SPSPPS) 96 { 97 return (mfxExtCodingOptionSPSPPS*)(*(ebuffers+i)); 98 } 99 } 100 } 101 return 0; 102 } 103 protected: 104 105 // VideoEncode methods 106 #define _GetBits(n,out) \ 107 {\ 108 mfxU32 bitreaded = 0;\ 109 \ 110 out = 0;\ 111 if (ptr - pSH > (mfxI32)len - ((n+7)>>3))\ 112 return false;\ 113 \ 114 while (n > bitreaded)\ 115 {\ 116 mfxU32 t = ((*ptr) << bitpos) &0xff;\ 117 if (n - bitreaded >= 8 - bitpos)\ 118 {\ 119 uint32_t num_bits = 8 - bitpos;\ 120 t = t >> (8-num_bits);\ 121 out = (out <<num_bits)|t;\ 122 bitreaded += num_bits;\ 123 bitpos = 0;\ 124 ptr ++;\ 125 }\ 126 else\ 127 {\ 128 uint32_t num_bits = n - bitreaded;\ 129 t = t >> (8-num_bits);\ 130 out = (out <<num_bits)|t;\ 131 bitpos += num_bits; \ 132 bitreaded += num_bits; \ 133 \ 134 } \ 135 }\ 136 } DARtoPAR(mfxU32 width,mfxU32 height,mfxU32 dar_h,mfxU32 dar_v,mfxU16 * par_h,mfxU16 * par_v)137 static bool DARtoPAR(mfxU32 width, mfxU32 height, mfxU32 dar_h, mfxU32 dar_v, 138 mfxU16 *par_h, mfxU16 *par_v) 139 { 140 // (width*par_h) / (height*par_v) == dar_h/dar_v => 141 // par_h / par_v == dar_h * height / (dar_v * width) 142 mfxU32 simple_tab[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59}; 143 mfxU32 i, denom; 144 145 // suppose no overflow of 32s 146 mfxU32 h = dar_h * height; 147 mfxU32 v = dar_v * width; 148 // remove common multipliers 149 while( ((h|v)&1) == 0 ) { 150 h>>=1; 151 v>>=1; 152 } 153 154 for(i=0;i<sizeof(simple_tab)/sizeof(simple_tab[0]);i++) { 155 denom = simple_tab[i]; 156 while(h%denom==0 && v%denom==0) { 157 v /= denom; 158 h /= denom; 159 } 160 if(v<=denom || h<=denom) 161 break; 162 } 163 *par_h = (mfxU16)h; 164 *par_v = (mfxU16)v; 165 // can don't reach minimum, no problem 166 // if(i<sizeof(simple_tab)/sizeof(simple_tab[0])) 167 // return false; 168 return true; 169 } 170 DecodeSequenceHeader(mfxU8 * pSH,mfxU32 len,mfxVideoParam * par,mfxExtCodingOption * extOpt,mfxU32 & real_len)171 static bool DecodeSequenceHeader( 172 mfxU8 * pSH, 173 mfxU32 len, 174 mfxVideoParam * par, 175 mfxExtCodingOption * extOpt, 176 mfxU32 & real_len) 177 { 178 mfxU32 bitpos = 0; 179 mfxU8* ptr = pSH; 180 mfxU32 temp = 0; 181 mfxU32 w = 0, h = 0; 182 mfxU32 aspect_ratio = 0; 183 mfxU32 frame_rate_code = 0; 184 mfxU32 frame_rate_code_n = 0; 185 mfxU32 frame_rate_code_d = 0; 186 mfxU32 vbv_buffer_size = 0; 187 188 static const mfxU32 frame_rate_value_n [9] = {0, 24000, 24,25,30000,30,50,60000,60}; 189 static const mfxU32 frame_rate_value_d [9] = {0, 1001, 1, 1, 1001, 1, 1, 1001, 1}; 190 191 real_len = 0; 192 193 while ( *ptr == 0 && ptr - pSH < (mfxI32)len) 194 { 195 ptr ++; 196 } 197 _GetBits (8,temp); 198 if (temp != 0x01) 199 return false; 200 201 _GetBits (8,temp); // start code 202 if (temp != 0xB3) 203 return false; 204 205 _GetBits (12, w); // start code 206 _GetBits (12, h); // start code 207 208 if (!w || !h) 209 return false; 210 211 _GetBits (4,aspect_ratio); 212 if (aspect_ratio > 4 || !aspect_ratio) 213 return false; 214 215 216 switch(aspect_ratio) 217 { 218 case 1: 219 par->mfx.FrameInfo.AspectRatioH = 1; 220 par->mfx.FrameInfo.AspectRatioW = 1; 221 break; 222 case 2: 223 DARtoPAR(w, h, 4, 3, &par->mfx.FrameInfo.AspectRatioW , &par->mfx.FrameInfo.AspectRatioH); 224 break; 225 case 3: 226 DARtoPAR(w, h, 16, 9, &par->mfx.FrameInfo.AspectRatioW , &par->mfx.FrameInfo.AspectRatioH); 227 break; 228 case 4: 229 DARtoPAR(w, h, 221, 100, &par->mfx.FrameInfo.AspectRatioW , &par->mfx.FrameInfo.AspectRatioH); 230 break; 231 default: 232 return false; 233 } 234 _GetBits (4,frame_rate_code); 235 if (frame_rate_code > 8 || !frame_rate_code) 236 return false; 237 238 _GetBits (18,temp); //bitrate 239 240 temp = ((temp)*400)/1000; 241 if (temp > 0x0000FFFF) 242 return false; 243 if (temp != 0) 244 { 245 par->mfx.TargetKbps = (mfxU16)temp; 246 par->mfx.RateControlMethod = MFX_RATECONTROL_CBR; 247 } 248 249 _GetBits (1,temp); 250 if (!temp) 251 return false; 252 253 _GetBits (10, vbv_buffer_size); 254 255 _GetBits (1,temp); 256 if (temp) 257 return false; 258 259 _GetBits (1,temp); // intra quant matrix 260 if (temp) 261 return false; 262 263 _GetBits (1,temp); // inter quant matrix 264 if (temp) 265 return false; 266 267 if (bitpos!=0) 268 { 269 ptr ++; 270 bitpos = 0; 271 272 } 273 while ( *ptr == 0 && ptr - pSH < (mfxI32)len) 274 { 275 ptr ++; 276 } 277 temp = 0; 278 if (ptr - pSH >= (mfxI32)len - 3) 279 return false; 280 281 _GetBits (8,temp); 282 if (temp != 0x01) 283 return false; 284 285 _GetBits (12,temp); // start code 286 if (temp != 0x0B51) 287 return false; 288 289 _GetBits (1,temp); // escape bit 290 291 _GetBits (3,temp); // profile 292 293 switch(temp) 294 { 295 case 5: 296 par->mfx.CodecProfile = MFX_PROFILE_MPEG2_SIMPLE; 297 break; 298 case 4: 299 par->mfx.CodecProfile = MFX_PROFILE_MPEG2_MAIN; 300 break; 301 case 6: 302 par->mfx.CodecProfile = MFX_PROFILE_MPEG2_HIGH; 303 break; 304 default: 305 return false; 306 } 307 308 _GetBits (4,temp); // level 309 310 switch(temp) 311 { 312 case 10: 313 par->mfx.CodecLevel = MFX_LEVEL_MPEG2_LOW; 314 break; 315 case 8: 316 par->mfx.CodecLevel = MFX_LEVEL_MPEG2_MAIN; 317 break; 318 case 6: 319 par->mfx.CodecLevel = MFX_LEVEL_MPEG2_HIGH1440; 320 break; 321 case 4: 322 par->mfx.CodecLevel = MFX_LEVEL_MPEG2_HIGH; 323 break; 324 default: 325 return false; 326 } 327 328 _GetBits (1,temp); // progressive 329 330 if (temp == 1) 331 { 332 par->mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; 333 } 334 else 335 { 336 par->mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_UNKNOWN; 337 338 if (extOpt) 339 extOpt->FramePicture = MFX_CODINGOPTION_ON; 340 } 341 342 _GetBits (2,temp); //chroma format 343 if (temp != 1) 344 return false; 345 346 par->mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; 347 348 _GetBits (2,temp); // ext h 349 if (temp != 0) 350 return false; 351 352 _GetBits (2,temp); // ext w 353 if (temp != 0) 354 return false; 355 356 _GetBits (12,temp); //bitrate ex 357 if (temp != 0) 358 return false; 359 360 _GetBits (1,temp); 361 if (temp != 1) 362 return false; 363 364 _GetBits (8,temp); // vbv_buffer_size_ext 365 vbv_buffer_size |= (temp << 10); 366 par->mfx.BufferSizeInKB = mfxU16(std::min<mfxU32>(0xffff, 2 * vbv_buffer_size)); 367 368 _GetBits (1,temp); //low delay 369 if (temp == 1) 370 return false; 371 372 _GetBits (2,frame_rate_code_n); 373 _GetBits (5,frame_rate_code_d); 374 375 if (bitpos!=0) 376 { 377 ptr ++; 378 bitpos = 0; 379 } 380 while ( *ptr == 0 && ptr - pSH < (mfxI32)len) 381 { 382 ptr ++; 383 } 384 temp = 0; 385 if (ptr - pSH < (mfxI32)len - 3) 386 { 387 _GetBits (8,temp); 388 if (temp != 0x01) 389 return false; 390 _GetBits (12,temp); // start code 391 } 392 393 par->mfx.FrameInfo.CropX = 0; 394 par->mfx.FrameInfo.CropY = 0; 395 par->mfx.FrameInfo.CropW = (mfxU16) w; 396 par->mfx.FrameInfo.CropH = (mfxU16) h; 397 398 par->mfx.FrameInfo.Width = par->mfx.FrameInfo.Width > (mfxU16)(((w+15)/16)*16)? par->mfx.FrameInfo.Width : (mfxU16)(((w+15)/16)*16); 399 if (par->mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE) 400 { 401 par->mfx.FrameInfo.Height = par->mfx.FrameInfo.Height> (mfxU16)(((h+15)/16)*16)? par->mfx.FrameInfo.Height: (mfxU16)(((h+15)/16)*16); 402 } 403 else 404 { 405 par->mfx.FrameInfo.Height = par->mfx.FrameInfo.Height> (mfxU16)(((h+31)/32)*32)? par->mfx.FrameInfo.Height: (mfxU16)(((h+31)/32)*32); 406 } 407 par->mfx.FrameInfo.FrameRateExtD = (frame_rate_code_d + 1)*frame_rate_value_d[frame_rate_code]; 408 par->mfx.FrameInfo.FrameRateExtN = (frame_rate_code_n + 1)*frame_rate_value_n[frame_rate_code]; 409 410 if (temp == 0x0B52) 411 { 412 _GetBits (3,temp); //video format 413 if (temp > 5) 414 return false; 415 416 _GetBits (1,temp); //colour_description 417 418 if (temp) 419 { 420 _GetBits (24,temp); 421 } 422 _GetBits (14,temp); 423 if (temp != w) 424 return false; 425 426 _GetBits (1,temp); 427 if (temp != 1) 428 return false; 429 430 _GetBits (14,temp); 431 if (temp != h) 432 return false; 433 434 if (bitpos!=0) 435 { 436 ptr ++; 437 bitpos = 0; 438 } 439 } 440 real_len = (mfxU32)(ptr - pSH); 441 return true; 442 443 } 444 #undef _GetBits 445 446 447 private: 448 mfxU8* m_pBuffer; 449 mfxU32 m_bufLen; 450 451 // Declare private copy constructor to avoid accidental assignment 452 // and klocwork complaining. 453 SHParametersEx (const SHParametersEx &); 454 SHParametersEx & operator = (const SHParametersEx &); 455 }; 456 457 #endif