1 // Copyright (c) 2017-2020 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_FRAMES_H_ 22 #define _MFX_FRAMES_H_ 23 24 #include <memory.h> 25 #include <mutex> 26 #include "mfxdefs.h" 27 #include "mfx_common_int.h" 28 29 #define NUM_TASKS 256 30 31 /*------- Task between sync/async encoder parts (1 entry point in async part)-------------------------*/ 32 33 struct sExtTask1 34 { 35 mfxEncodeInternalParams m_inputInternalParams; 36 mfxFrameSurface1 *m_pInput_surface; 37 mfxBitstream *m_pBs; 38 sExtTask1sExtTask139 sExtTask1() 40 : m_inputInternalParams() 41 { 42 m_pInput_surface = 0; 43 m_pBs = 0; 44 } ~sExtTask1sExtTask145 virtual ~sExtTask1() 46 { 47 } 48 }; 49 50 /*------- Task between sync/async encoder parts (2 entry points in async part: submit and query)------------*/ 51 52 struct sExtTask2 : public sExtTask1 53 { 54 mfxU32 m_nInternalTask; 55 sExtTask2sExtTask256 sExtTask2(): 57 sExtTask1(), 58 m_nInternalTask(0) 59 { 60 } ~sExtTask2sExtTask261 virtual ~sExtTask2() 62 { 63 } 64 }; 65 66 /*------- Tasks between sync/async encoder parts (1 entry point in async part)-------------------------*/ 67 68 class clExtTasks1 69 { 70 public: clExtTasks1()71 clExtTasks1() 72 { 73 m_numTasks = 0; 74 m_currTask = 0; 75 m_maxTasks = NUM_TASKS; 76 m_pTasks = new sExtTask1[m_maxTasks]; 77 } ~clExtTasks1()78 virtual ~clExtTasks1() 79 { 80 if (m_pTasks) 81 { 82 delete [] m_pTasks; 83 } 84 } 85 AddTask(mfxEncodeInternalParams * pParams,mfxFrameSurface1 * input_surface,mfxBitstream * bs,sExtTask1 ** pOutTask)86 mfxStatus AddTask ( mfxEncodeInternalParams *pParams, 87 mfxFrameSurface1 *input_surface, 88 mfxBitstream *bs, 89 sExtTask1 **pOutTask) 90 { 91 std::lock_guard<std::mutex> guard(m_mGuard); 92 if (m_numTasks < m_maxTasks) 93 { 94 sExtTask1 *pTask = &m_pTasks[(m_currTask + m_numTasks)% m_maxTasks]; 95 if (pParams) 96 { 97 pTask->m_inputInternalParams = *pParams; 98 } 99 pTask->m_pInput_surface = input_surface; 100 pTask->m_pBs = bs; 101 *pOutTask = pTask; 102 m_numTasks ++; 103 return MFX_ERR_NONE; 104 } 105 return MFX_WRN_IN_EXECUTION; 106 } CheckTask(sExtTask1 * pInputTask)107 mfxStatus CheckTask (sExtTask1 *pInputTask) 108 { 109 mfxStatus sts = MFX_ERR_MORE_DATA; 110 std::lock_guard<std::mutex> guard(m_mGuard); 111 if (m_numTasks > 0) 112 { 113 /* task for current frame or task for the same frame */ 114 if (pInputTask == &m_pTasks[m_currTask]) 115 { 116 sts = MFX_ERR_NONE; 117 } 118 else 119 { 120 m_currTask = (m_currTask + 1)% m_maxTasks; 121 m_numTasks = m_numTasks - 1; 122 if (m_numTasks > 0 && pInputTask == &m_pTasks[m_currTask]) 123 { 124 sts = MFX_ERR_NONE; 125 } 126 } 127 } 128 return sts; 129 } 130 131 private: 132 sExtTask1* m_pTasks; 133 std::mutex m_mGuard; 134 135 mfxU32 m_maxTasks; 136 mfxU32 m_numTasks; 137 mfxU32 m_currTask; 138 139 140 // Declare private copy constructor to avoid accidental assignment 141 // and klocwork complaining. 142 143 clExtTasks1(const clExtTasks1 &); 144 clExtTasks1 & operator = (const clExtTasks1 &); 145 }; 146 147 /*------- Tasks between sync/async encoder parts (2 entry points in async part: submit and query)------------*/ 148 149 class clExtTasks2 150 { 151 public: clExtTasks2()152 clExtTasks2() 153 { 154 m_numTasks = 0; 155 m_currTask = 0; 156 m_maxTasks = NUM_TASKS; 157 m_pTasks = new sExtTask2[m_maxTasks]; 158 m_numSubmittedTasks = 0; 159 } ~clExtTasks2()160 virtual ~clExtTasks2() 161 { 162 if (m_pTasks) 163 { 164 delete [] m_pTasks; 165 } 166 } 167 AddTask(mfxEncodeInternalParams * pParams,mfxFrameSurface1 * input_surface,mfxBitstream * bs,sExtTask2 ** pOutTask)168 mfxStatus AddTask ( mfxEncodeInternalParams *pParams, 169 mfxFrameSurface1 *input_surface, 170 mfxBitstream *bs, 171 sExtTask2 **pOutTask) 172 { 173 std::lock_guard<std::mutex> guard(m_mGuard); 174 if (m_numTasks < m_maxTasks) 175 { 176 sExtTask2 *pTask = &m_pTasks[(m_currTask + m_numTasks)% m_maxTasks]; 177 if (pParams) 178 { 179 pTask->m_inputInternalParams = *pParams; 180 } 181 pTask->m_pInput_surface = input_surface; 182 pTask->m_pBs = bs; 183 pTask->m_nInternalTask = 0; 184 185 *pOutTask = pTask; 186 m_numTasks ++; 187 return MFX_ERR_NONE; 188 } 189 return MFX_WRN_IN_EXECUTION; 190 } 191 CheckTaskForSubmit(sExtTask2 * pInputTask)192 mfxStatus CheckTaskForSubmit(sExtTask2 *pInputTask) 193 { 194 mfxStatus sts = MFX_ERR_MORE_DATA; 195 std::lock_guard<std::mutex> guard(m_mGuard); 196 if (m_numTasks >= m_numSubmittedTasks) 197 { 198 if (pInputTask == m_pTasks + ((m_currTask + m_numSubmittedTasks - 1)% m_maxTasks)) 199 { 200 sts = MFX_ERR_NONE; 201 } 202 else if (m_numTasks > m_numSubmittedTasks) 203 { 204 m_numSubmittedTasks ++; 205 mfxU32 nTask = (m_currTask + m_numSubmittedTasks - 1)% m_maxTasks; 206 sts = ( pInputTask == &m_pTasks[nTask]) ? MFX_ERR_NONE : MFX_ERR_UNDEFINED_BEHAVIOR; 207 } 208 } 209 return sts; 210 } GetTaskForQuery()211 sExtTask2* GetTaskForQuery () 212 { 213 std::lock_guard<std::mutex> guard(m_mGuard); 214 sExtTask2* task = (m_numTasks > 0 && m_numSubmittedTasks > 0) ? &m_pTasks[m_currTask] : 0; 215 return task; 216 } NextFrame()217 mfxStatus NextFrame () 218 { 219 mfxStatus sts = MFX_ERR_UNDEFINED_BEHAVIOR; 220 std::lock_guard<std::mutex> guard(m_mGuard); 221 if (m_numTasks > 0 && m_numSubmittedTasks > 0) 222 { 223 m_currTask = (m_currTask + 1)% m_maxTasks; 224 m_numTasks = m_numTasks - 1; 225 m_numSubmittedTasks = m_numSubmittedTasks - 1; 226 sts = MFX_ERR_NONE; 227 } 228 return sts; 229 } 230 231 232 private: 233 234 sExtTask2* m_pTasks; 235 std::mutex m_mGuard; 236 237 mfxU32 m_maxTasks; 238 mfxU32 m_numTasks; 239 mfxU32 m_currTask; 240 mfxU32 m_numSubmittedTasks; 241 242 // Declare private copy constructor to avoid accidental assignment 243 // and klocwork complaining. 244 245 clExtTasks2(const clExtTasks2 &); 246 clExtTasks2 & operator = (const clExtTasks2 &); 247 }; 248 249 struct sFrameEx 250 { 251 mfxFrameSurface1* m_pFrame; 252 mfxU16 m_FrameType; 253 mfxU32 m_FrameOrder; 254 mfxEncodeInternalParams m_sEncodeInternalParams; 255 bool m_bAddHeader; 256 bool m_bAddEOS; 257 bool m_bOnlyBwdPrediction; 258 bool m_bOnlyFwdPrediction; 259 }; 260 GetFrameTypeMpeg2(mfxI32 FrameOrder,mfxI32 GOPSize,mfxI32 IPDist,bool bClosedGOP,mfxU16 * FrameType)261 inline void GetFrameTypeMpeg2 (mfxI32 FrameOrder, mfxI32 GOPSize, mfxI32 IPDist, bool bClosedGOP, mfxU16* FrameType) 262 { 263 mfxI32 pos = (GOPSize)? (FrameOrder %(GOPSize)):FrameOrder; 264 265 if (pos == 0 || IPDist == 0 || (*FrameType & MFX_FRAMETYPE_IDR) != 0) 266 { 267 *FrameType = MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_IDR; 268 } 269 else 270 { 271 pos = (bClosedGOP && pos == GOPSize-1)? 0 : pos % (IPDist); 272 *FrameType = ((pos != 0) && ((*FrameType & MFX_FRAMETYPE_REF) == 0)) ? (mfxU16)MFX_FRAMETYPE_B : (mfxU16)(MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF); 273 } 274 } ReleasePlane(mfxFrameSurface1 * pFrame)275 inline mfxStatus ReleasePlane(mfxFrameSurface1* pFrame) 276 { 277 if (pFrame) 278 { 279 //pFrame->Data.Locked= 0; 280 } 281 282 return MFX_ERR_NONE; 283 } 284 isReferenceFrame(mfxU16 FrameType)285 inline bool isReferenceFrame(mfxU16 FrameType) 286 { 287 return ((FrameType & MFX_FRAMETYPE_I) || 288 (FrameType & MFX_FRAMETYPE_P) || 289 (FrameType & MFX_FRAMETYPE_REF)); 290 } isIntraFrame(mfxU16 FrameType)291 inline bool isIntraFrame(mfxU16 FrameType) 292 { 293 return (FrameType & MFX_FRAMETYPE_I); 294 } 295 isReferenceFrame(mfxU16 FrameType,mfxU16 FrameType2)296 inline bool isReferenceFrame(mfxU16 FrameType, mfxU16 FrameType2) 297 { 298 if(!FrameType2) 299 { 300 return ((FrameType & MFX_FRAMETYPE_I) || 301 (FrameType & MFX_FRAMETYPE_P) || 302 (FrameType & MFX_FRAMETYPE_REF)); 303 304 } 305 else 306 { 307 return (((FrameType & MFX_FRAMETYPE_I) || 308 (FrameType & MFX_FRAMETYPE_P) || 309 (FrameType & MFX_FRAMETYPE_REF)) 310 && 311 ((FrameType2 & MFX_FRAMETYPE_I) || 312 (FrameType2 & MFX_FRAMETYPE_P) || 313 (FrameType2 & MFX_FRAMETYPE_REF)) ); 314 } 315 } 316 isPredictedFrame(mfxU16 FrameType)317 inline bool isPredictedFrame(mfxU16 FrameType) 318 { 319 return (FrameType & MFX_FRAMETYPE_P) != 0; 320 } 321 isPredictedFrame(mfxU16 FrameType,mfxU16 FrameType2)322 inline bool isPredictedFrame(mfxU16 FrameType, mfxU16 FrameType2) 323 { 324 return ((FrameType & MFX_FRAMETYPE_P) || (FrameType2 & MFX_FRAMETYPE_P)) != 0; 325 } 326 isBPredictedFrame(mfxU16 FrameType)327 inline bool isBPredictedFrame(mfxU16 FrameType) 328 { 329 return (FrameType & MFX_FRAMETYPE_B) != 0; 330 } 331 isBPredictedFrame(mfxU16 FrameType,mfxU16 FrameType2)332 inline bool isBPredictedFrame(mfxU16 FrameType, mfxU16 FrameType2) 333 { 334 return ((FrameType & MFX_FRAMETYPE_B) || (FrameType2 & MFX_FRAMETYPE_B)) != 0; 335 } 336 337 338 class MFXGOP 339 { 340 public: MFXGOP()341 MFXGOP(): 342 m_maxB(0), 343 m_pFrames(0), 344 m_numBuffB(0), 345 m_iCurr(0), 346 m_bClosedGOP(0), 347 m_nGOPsInSeq(0), 348 m_bAddEOS(0), 349 m_bEncodedOrder(0), 350 m_nGOPs (0) 351 {}; 352 ~MFXGOP()353 virtual ~MFXGOP() 354 { 355 Close(); 356 } 357 GetNumberOfB()358 inline mfxU32 GetNumberOfB() 359 { 360 return m_numBuffB; 361 } 362 protected: 363 mfxI32 m_maxB; 364 sFrameEx * m_pFrames; /* 0 - forward reference frame, 365 1 - backward reference frame 366 other - B frames*/ 367 368 mfxI32 m_numBuffB; 369 mfxI32 m_iCurr; 370 371 bool m_bClosedGOP; 372 mfxI32 m_nGOPsInSeq; 373 bool m_bAddEOS; 374 bool m_bEncodedOrder; 375 376 mfxI32 m_nGOPs; 377 378 379 protected: 380 381 NewGOP()382 inline bool NewGOP () 383 { 384 mfxStatus MFXSts = MFX_ERR_NONE; 385 386 MFXSts = ReleasePlane(m_pFrames[0].m_pFrame); 387 if(MFXSts != MFX_ERR_NONE) 388 return false; 389 390 m_pFrames[0] = m_pFrames[1]; 391 392 memset (&m_pFrames[1], 0, sizeof(sFrameEx)); 393 394 m_iCurr = 1; 395 m_numBuffB = 0; 396 397 return true; 398 } 399 AddBFrame(sFrameEx * pFrameEx)400 inline virtual bool AddBFrame(sFrameEx* pFrameEx) 401 { 402 if (m_numBuffB < m_maxB && m_pFrames[0].m_pFrame != 0 && ((m_bEncodedOrder && m_pFrames[1].m_pFrame != 0)|| (!m_bEncodedOrder && m_pFrames[1].m_pFrame == 0))) 403 { 404 m_pFrames[m_numBuffB+2] = *pFrameEx; 405 m_numBuffB ++; 406 return true; 407 } 408 return false; 409 } 410 AddReferenceFrame(sFrameEx * pFrameEx)411 inline virtual bool AddReferenceFrame(sFrameEx* pFrameEx) 412 { 413 if (m_pFrames[0].m_pFrame && m_pFrames[1].m_pFrame ) return false; 414 415 if (isIntraFrame(pFrameEx->m_FrameType)) 416 { 417 if (!m_nGOPs) 418 { 419 pFrameEx->m_bAddHeader = true; 420 } 421 m_nGOPs ++; 422 if (m_nGOPsInSeq!=0 && m_nGOPs >= m_nGOPsInSeq) 423 { 424 m_nGOPs = 0; 425 } 426 } 427 if (m_pFrames[0].m_pFrame == 0) 428 { 429 m_pFrames[0]= *pFrameEx; 430 return true; 431 } 432 else if (m_pFrames[1].m_pFrame == 0) 433 { 434 m_pFrames[1]= *pFrameEx; 435 return true; 436 } 437 return false; 438 } 439 440 public: 441 AddFrame(sFrameEx * pFrameEx)442 inline bool AddFrame(sFrameEx* pFrameEx) 443 { 444 if (isReferenceFrame(pFrameEx->m_FrameType)) 445 { 446 if (m_iCurr>= m_numBuffB+2 && m_bEncodedOrder) 447 { 448 NewGOP(); 449 } 450 return AddReferenceFrame(pFrameEx); 451 } 452 else 453 { 454 return AddBFrame(pFrameEx); 455 } 456 } 457 Init(mfxU32 maxB,bool bClosedGOP,mfxI32 nGOPsInSeq,bool bAddEOS,bool bEncodedOrder)458 inline virtual mfxStatus Init(mfxU32 maxB, bool bClosedGOP, mfxI32 nGOPsInSeq, bool bAddEOS, bool bEncodedOrder) 459 { 460 Close(); 461 462 m_maxB = maxB; 463 464 m_pFrames = new sFrameEx [m_maxB+2]; 465 466 Reset(bClosedGOP,nGOPsInSeq,bAddEOS, bEncodedOrder); 467 return MFX_ERR_NONE; 468 } GetMaxBFrames()469 inline mfxI32 GetMaxBFrames () 470 { 471 return m_maxB; 472 } 473 Reset(bool bClosedGOP,mfxI32 nGOPsInSeq,bool bAddEOS,bool bEncodedOrder)474 inline virtual void Reset(bool bClosedGOP,mfxI32 nGOPsInSeq, bool bAddEOS, bool bEncodedOrder) 475 { 476 if (m_pFrames) 477 { 478 memset(m_pFrames,0,sizeof(sFrameEx)*(m_maxB+2)); 479 } 480 481 m_iCurr = 0; 482 m_numBuffB = 0; 483 m_nGOPs = 0; 484 485 m_bClosedGOP = bClosedGOP; 486 m_nGOPsInSeq = nGOPsInSeq; 487 m_bAddEOS = bAddEOS; 488 m_bEncodedOrder = bEncodedOrder; 489 490 }; GetFrameExForDecoding(sFrameEx * pFrame,bool bNextRefIntra,bool bNextB,bool bLast)491 inline bool GetFrameExForDecoding(sFrameEx* pFrame, bool bNextRefIntra, bool bNextB, bool bLast) 492 { 493 if (m_iCurr < m_numBuffB + 2 && m_pFrames[m_iCurr].m_pFrame) 494 { 495 *pFrame = m_pFrames[m_iCurr]; 496 if ((m_iCurr > 1) && isIntraFrame(m_pFrames[1].m_FrameType) && (m_bClosedGOP)) 497 { 498 pFrame->m_bOnlyBwdPrediction = true; 499 } 500 if (m_bAddEOS && ((bNextRefIntra && m_nGOPs == 0) || bLast) && 501 ((m_bEncodedOrder && !bNextB ) || (!m_bEncodedOrder && m_iCurr == 2 + m_numBuffB - 1))) 502 { 503 pFrame->m_bAddEOS = true; 504 } 505 506 return true; 507 } 508 if (m_iCurr < m_numBuffB + 2 && !m_pFrames[m_iCurr].m_pFrame && bLast) // check if all next fwd_only && no refs for this one 509 { 510 m_iCurr++; 511 *pFrame = m_pFrames[m_iCurr]; 512 if (m_bAddEOS 513 && ((m_bEncodedOrder && !bNextB) || (!m_bEncodedOrder && m_iCurr == 2 + m_numBuffB - 1))) 514 { 515 pFrame->m_bAddEOS = true; 516 } 517 518 return true; 519 } 520 521 return false; 522 } 523 ReleaseCurrentFrame()524 inline virtual void ReleaseCurrentFrame() 525 { 526 if (!m_pFrames[m_iCurr].m_pFrame) 527 return; 528 529 if (m_iCurr>1) 530 { 531 ReleasePlane(m_pFrames[m_iCurr].m_pFrame); 532 memset (&m_pFrames[m_iCurr], 0, sizeof(sFrameEx)); 533 } 534 m_iCurr++; 535 if (m_iCurr>= m_numBuffB+2 && (!m_bEncodedOrder)) 536 { 537 NewGOP(); 538 } 539 } 540 541 // with strictGop make B w/only forward reference. without - change type to P CloseGop(bool strictGop)542 inline virtual void CloseGop(bool strictGop) 543 { 544 if (m_pFrames[1].m_pFrame == 0 && m_numBuffB>0) 545 { 546 mfxU16 pictureType = 0; 547 548 if (!strictGop) 549 { 550 sFrameEx * pFrame = &m_pFrames[2 + m_numBuffB-1]; 551 m_pFrames[1]= *pFrame; 552 pictureType = (mfxU16)(MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF); 553 554 memset (pFrame, 0, sizeof (sFrameEx)); 555 556 m_numBuffB --; 557 558 m_pFrames[1].m_FrameType = pictureType; 559 m_pFrames[1].m_sEncodeInternalParams.FrameType = pictureType; 560 m_pFrames[1].m_bOnlyFwdPrediction = true; 561 562 if (m_bAddEOS && (m_numBuffB == 0)) 563 { 564 m_pFrames[1].m_bAddEOS = true; 565 } 566 } 567 else 568 { 569 for (int i = 0; i < m_numBuffB; i++) 570 { 571 m_pFrames[2 + i].m_bOnlyFwdPrediction = true; 572 } 573 } 574 } 575 if (m_bAddEOS && (!strictGop || (m_numBuffB != 0))) 576 { 577 m_pFrames[2 + m_numBuffB - 1].m_bAddEOS = true; 578 } 579 580 } 581 inline bool GetFrameExReference(sFrameEx* pFrame, bool bBackward = false) 582 { 583 mfxU32 n = (bBackward)? 1:0; 584 if (m_pFrames[n].m_pFrame) 585 { 586 *pFrame = m_pFrames[n]; 587 return true; 588 } 589 return false; 590 } 591 Close()592 void Close() 593 { 594 if (m_pFrames) 595 { 596 delete [] m_pFrames; 597 m_pFrames = 0; 598 } 599 m_iCurr = 0; 600 m_numBuffB = 0; 601 m_maxB = 0; 602 m_nGOPs = 0; 603 } 604 605 private: 606 // Declare private copy constructor to avoid accidental assignment 607 // and klocwork complaining. 608 MFXGOP(const MFXGOP &); 609 MFXGOP & operator = (const MFXGOP &); 610 }; 611 612 613 class MFXWaitingList 614 { 615 public: MFXWaitingList()616 MFXWaitingList(): 617 m_maxN(0), 618 m_curIndex(0), 619 m_nFrames(0), 620 m_pFrames(0), 621 m_minN(0), 622 m_delay(0) 623 {}; ~MFXWaitingList()624 ~MFXWaitingList() 625 { 626 Close(); 627 } Close()628 void Close() 629 { 630 if (m_pFrames) 631 { 632 delete [] m_pFrames; 633 m_pFrames = 0; 634 } 635 636 m_maxN = 0; 637 m_curIndex = 0; 638 m_nFrames = 0; 639 m_minN=0; 640 m_delay = 0; 641 } 642 Init(mfxU32 maxN,mfxU32 minN,mfxU32 delay)643 mfxStatus Init(mfxU32 maxN, mfxU32 minN, mfxU32 delay) 644 { 645 Close(); 646 647 m_maxN = maxN; 648 m_minN = minN; 649 m_delay = delay; 650 651 if (m_minN > m_maxN) 652 return MFX_ERR_UNSUPPORTED; 653 654 m_pFrames = new sFrameEx [ m_maxN]; 655 if (!m_pFrames) 656 return MFX_ERR_MEMORY_ALLOC; 657 658 memset (m_pFrames,0, sizeof(sFrameEx)*m_maxN); 659 660 return MFX_ERR_NONE; 661 } 662 GetMaxFrames()663 mfxI32 GetMaxFrames () 664 { 665 return m_maxN; 666 } GetDelay()667 mfxI32 GetDelay() 668 { 669 return m_delay; 670 } 671 Reset(mfxI32 minN,mfxU32 delay)672 void Reset(mfxI32 minN, mfxU32 delay) 673 { 674 mfxU32 i = 0; 675 676 if(m_pFrames) 677 { 678 for(i = 0; i < m_maxN; i++) 679 { 680 ReleasePlane(m_pFrames[i].m_pFrame); 681 682 } 683 memset (m_pFrames,0, sizeof(sFrameEx)* m_maxN); 684 } 685 686 m_curIndex = 0; 687 m_nFrames = 0; 688 m_minN = minN; 689 m_delay = delay; 690 } 691 AddFrame(mfxFrameSurface1 * frame,mfxEncodeInternalParams * pInInternalParams)692 bool AddFrame(mfxFrameSurface1* frame, mfxEncodeInternalParams *pInInternalParams) 693 { 694 if (m_nFrames < m_maxN) 695 { 696 mfxU32 ind = (m_curIndex + m_nFrames)%m_maxN; 697 698 m_pFrames[ind].m_pFrame = frame; 699 m_pFrames[ind].m_FrameOrder = pInInternalParams->FrameOrder; 700 m_pFrames[ind].m_FrameType = pInInternalParams->FrameType; 701 702 m_pFrames[ind].m_bAddEOS = false; 703 m_pFrames[ind].m_bAddHeader = false; 704 m_pFrames[ind].m_bOnlyBwdPrediction = false; 705 706 m_pFrames[ind].m_sEncodeInternalParams = *pInInternalParams; 707 m_nFrames ++; 708 return true; 709 } 710 return false; 711 } 712 bool GetFrameEx(sFrameEx* pFrameEx, bool bEOF = false) 713 { 714 if (m_nFrames>0 && (bEOF || (m_nFrames > m_minN && m_nFrames > m_delay))) 715 { 716 *pFrameEx = m_pFrames[m_curIndex]; 717 m_delay = 0; 718 return true; 719 } 720 return false; 721 } 722 MoveOnNextFrame()723 bool MoveOnNextFrame() 724 { 725 if (m_nFrames>0) 726 { 727 m_curIndex = (1+m_curIndex)%m_maxN; 728 m_nFrames--; 729 return true; 730 } 731 return false; 732 } 733 isNextReferenceIntra()734 bool isNextReferenceIntra() 735 { 736 for (mfxU32 i=0; i < m_nFrames; i++) 737 { 738 mfxU32 ind = (m_curIndex+i)%m_maxN; 739 mfxU16 type = m_pFrames[ind].m_FrameType; 740 if (isReferenceFrame(type)) 741 { 742 return isIntraFrame(type)? true:false; 743 } 744 } 745 return false; 746 } isLastFrame()747 bool isLastFrame() 748 { 749 return (m_nFrames < 1); 750 } isNextBFrame()751 bool isNextBFrame() 752 { 753 if (m_nFrames != 0) 754 { 755 mfxU32 ind = (m_curIndex)%m_maxN; 756 mfxU16 type = m_pFrames[ind].m_FrameType; 757 return (isReferenceFrame (type))? false:true; 758 } 759 return false; 760 } 761 762 private: 763 mfxU32 m_maxN; 764 mfxU32 m_curIndex; 765 mfxU32 m_nFrames; 766 sFrameEx* m_pFrames; 767 mfxU32 m_minN; 768 mfxU32 m_delay; 769 770 // Declare private copy constructor to avoid accidental assignment 771 // and klocwork complaining. 772 MFXWaitingList(const MFXWaitingList &); 773 MFXWaitingList & operator = (const MFXWaitingList &); 774 }; 775 776 #endif //_MFX_FRAMES_H_ 777