diff --git a/_studio/shared/umc/codec/h264_dec/include/umc_h264_frame.h b/_studio/shared/umc/codec/h264_dec/include/umc_h264_frame.h index 2f2a748740..ffe8c04811 100644 --- a/_studio/shared/umc/codec/h264_dec/include/umc_h264_frame.h +++ b/_studio/shared/umc/codec/h264_dec/include/umc_h264_frame.h @@ -1,15 +1,15 @@ -// Copyright (c) 2017 Intel Corporation -// +// Copyright (c) 2018 Intel Corporation +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -125,6 +125,7 @@ class H264DecoderFrame bool m_isInterViewRef[2]; bool m_bIDRFlag; + bool m_bIFlag; bool IsFullFrame() const; void SetFullFrame(bool isFull); diff --git a/_studio/shared/umc/codec/h264_dec/include/umc_h264_task_supplier.h b/_studio/shared/umc/codec/h264_dec/include/umc_h264_task_supplier.h index 642677d80f..69bcb8cad4 100644 --- a/_studio/shared/umc/codec/h264_dec/include/umc_h264_task_supplier.h +++ b/_studio/shared/umc/codec/h264_dec/include/umc_h264_task_supplier.h @@ -597,7 +597,6 @@ class TaskSupplier : public Skipping, public AU_Splitter, public SVC_Extension, virtual void OnFullFrame(H264DecoderFrame * pFrame); virtual bool ProcessNonPairedField(H264DecoderFrame * pFrame) = 0; - void DPBSanitize(H264DecoderFrame * pDPBHead, const H264DecoderFrame * pFrame); void DBPUpdate(H264DecoderFrame * pFrame, int32_t field); virtual void AddFakeReferenceFrame(H264Slice * pSlice); diff --git a/_studio/shared/umc/codec/h264_dec/src/umc_h264_frame.cpp b/_studio/shared/umc/codec/h264_dec/src/umc_h264_frame.cpp index fa234df266..4a68472695 100644 --- a/_studio/shared/umc/codec/h264_dec/src/umc_h264_frame.cpp +++ b/_studio/shared/umc/codec/h264_dec/src/umc_h264_frame.cpp @@ -1,15 +1,15 @@ -// Copyright (c) 2017 Intel Corporation -// +// Copyright (c) 2018 Intel Corporation +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -85,6 +85,7 @@ H264DecoderFrame::H264DecoderFrame(MemoryAllocator *pMemoryAllocator, H264_Heap_ m_LongTermPicNum[0] = m_PicNum[1] = -1; m_PicOrderCnt[0] = m_PicOrderCnt[1] = 0; m_bIDRFlag = false; + m_bIFlag = false; // set memory managment tools m_pMemoryAllocator = pMemoryAllocator; @@ -160,6 +161,7 @@ void H264DecoderFrame::Reset() post_procces_complete = false; m_bIDRFlag = false; + m_bIFlag = false; m_RefPicListResetCount[0] = m_RefPicListResetCount[1] = 0; m_PicNum[0] = m_PicNum[1] = -1; diff --git a/_studio/shared/umc/codec/h264_dec/src/umc_h264_task_supplier.cpp b/_studio/shared/umc/codec/h264_dec/src/umc_h264_task_supplier.cpp index 8f10fbae2b..9508dbb156 100644 --- a/_studio/shared/umc/codec/h264_dec/src/umc_h264_task_supplier.cpp +++ b/_studio/shared/umc/codec/h264_dec/src/umc_h264_task_supplier.cpp @@ -632,6 +632,18 @@ Status DecReferencePictureMarking::UpdateRefPicMarking(ViewItem &view, H264Decod // set MVC 'inter view flag' pFrame->SetInterViewRef(0 != sliceHeader->nal_ext.mvc.inter_view_flag, field_index); + // corruption recovery + if (pFrame->m_bIFlag) + { + for (H264DecoderFrame *pCurr = view.GetDPBList(0)->head(); pCurr; pCurr = pCurr->future()) + { + if (pCurr->GetError() & ERROR_FRAME_SHORT_TERM_STUCK) + { + AddItemAndRun(pFrame, pCurr, UNSET_REFERENCE | FULL_FRAME | SHORT_TERM); + } + } + } + if (pFrame->m_bIDRFlag) { // mark all reference pictures as unused @@ -3659,14 +3671,6 @@ Status TaskSupplier::AddSlice(H264Slice * pSlice, bool force) ViewItem &view = GetView(m_currentView); view.pCurFrame = setOfSlices->m_frame; - if (lastSlice->GetSeqParam()->gaps_in_frame_num_value_allowed_flag != 1) - { - // Check if DPB has ST frames with frame_num duplicating frame_num of new slice_type - // If so, unmark such frames as ST - H264DecoderFrame * pHead = view.GetDPBList(0)->head(); - DPBSanitize(pHead, view.pCurFrame); - } - const H264SliceHeader *sliceHeader = lastSlice->GetSliceHeader(); uint32_t field_index = setOfSlices->m_frame->GetNumberByParity(sliceHeader->bottom_field_flag); if (!setOfSlices->m_frame->GetAU(field_index)->GetSliceCount()) @@ -3957,9 +3961,24 @@ void TaskSupplier::InitFrameCounter(H264DecoderFrame * pFrame, const H264Slice * uint32_t NumShortTerm, NumLongTerm; dpb->countActiveRefs(NumShortTerm, NumLongTerm); - //set error flag only we have some references in DPB if ((NumShortTerm + NumLongTerm > 0)) + { + //set error flag only we have some references in DPB pFrame->SetErrorFlagged(ERROR_FRAME_REFERENCE_FRAME); + + // Leaving aside a legal frame_num wrapping cases, when a rapid _decrease_ of frame_num occurs due to frame gaps, + // frames marked as short-term prior the gap may get stuck in DPB for a very long sequence (up to '(1 << log2_max_frame_num) - 1'). + // Reference lists are generated incorrectly. A potential recovery point can be at next I frame (if GOP is closed). + // So let's mark these potentially dangereous ST frames + // to remove them later from DPB in UpdateRefPicMarking() (if they're still there) at next I frame or SEI recovery point. + for (H264DecoderFrame *pFrm = view.GetDPBList(0)->head(); pFrm; pFrm = pFrm->future()) + { + if ((pFrm->FrameNum() > sliceHeader->frame_num) && pFrm->isShortTermRef()) + { + pFrm->SetErrorFlagged(ERROR_FRAME_SHORT_TERM_STUCK); + } + } + } } if (sliceHeader->IdrPicFlag) @@ -3971,6 +3990,9 @@ void TaskSupplier::InitFrameCounter(H264DecoderFrame * pFrame, const H264Slice * pFrame->m_bIDRFlag = (sliceHeader->IdrPicFlag != 0); + const int32_t recoveryFrameNum = view.GetDPBList(0)->GetRecoveryFrameCnt(); + pFrame->m_bIFlag = (sliceHeader->slice_type == INTRASLICE) || (recoveryFrameNum != -1 && pFrame->FrameNum() == recoveryFrameNum); + if (pFrame->m_bIDRFlag) { view.GetDPBList(0)->IncreaseRefPicListResetCount(pFrame); @@ -4022,19 +4044,6 @@ void TaskSupplier::AddSliceToFrame(H264DecoderFrame *pFrame, H264Slice *pSlice) au_info->AddSlice(pSlice); } -void TaskSupplier::DPBSanitize(H264DecoderFrame * pDPBHead, const H264DecoderFrame * pFrame) -{ - for (H264DecoderFrame *pFrm = pDPBHead; pFrm; pFrm = pFrm->future()) - { - if ((pFrm != pFrame) && - (pFrm->FrameNum() == pFrame->FrameNum()) && - pFrm->isShortTermRef()) - { - AddItemAndRun(pFrm, pFrm, UNSET_REFERENCE | FULL_FRAME | SHORT_TERM); - } - } -} - void TaskSupplier::DBPUpdate(H264DecoderFrame * pFrame, int32_t field) { H264DecoderFrameInfo *slicesInfo = pFrame->GetAU(field); diff --git a/_studio/shared/umc/core/umc/include/umc_structures.h b/_studio/shared/umc/core/umc/include/umc_structures.h index ddaa05e02a..2ca155d7f8 100644 --- a/_studio/shared/umc/core/umc/include/umc_structures.h +++ b/_studio/shared/umc/core/umc/include/umc_structures.h @@ -1,15 +1,15 @@ // Copyright (c) 2018 Intel Corporation -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -681,6 +681,7 @@ namespace UMC ERROR_FRAME_RECOVERY = 0x00000010, // major artifacts at recovery point ERROR_FRAME_TOP_FIELD_ABSENT = 0x00000020, ERROR_FRAME_BOTTOM_FIELD_ABSENT = 0x00000040, + ERROR_FRAME_SHORT_TERM_STUCK = 0x00000100, // used to mark ST which potentially can get stuck in DPB due to frame gaps ERROR_FRAME_DEVICE_FAILURE = 0x80000000 //if this bit is set, this means the error is [UMC::Status] code };