1 /*
2 * Copyright (c) 2019-2021, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     decode_av1_temporal_buffers.cpp
24 //! \brief    Defines temporal buffers related logic for av1 decode
25 //!
26 
27 #include "codec_def_decode_av1.h"
28 #include "decode_av1_basic_feature.h"
29 #include "decode_av1_temporal_buffers.h"
30 #include "decode_utils.h"
31 
32 namespace decode
33 {
Init(void * hwInterface,DecodeAllocator & allocator,Av1BasicFeature & basicFeature)34     MOS_STATUS Av1TempBufferOpInf::Init(void* hwInterface, DecodeAllocator& allocator,
35                                        Av1BasicFeature& basicFeature)
36     {
37         DECODE_CHK_STATUS(BufferOpInf::Init(hwInterface, allocator, basicFeature));
38         if (m_hwInterface != nullptr)
39         {
40             m_avpItf = std::static_pointer_cast<mhw::vdbox::avp::Itf>(((CodechalHwInterfaceNext*)m_hwInterface)->GetAvpInterfaceNext());
41         }
42         m_basicFeature = &basicFeature;
43         return MOS_STATUS_SUCCESS;
44     }
45 
Allocate()46     Av1RefAssociatedBufs* Av1TempBufferOpInf::Allocate()
47     {
48         DECODE_FUNC_CALL();
49 
50         int32_t mibSizeLog2 = av1MinMibSizeLog2;
51         AvpBufferSizePar avpBufSizeParam;
52         SetAvpBufSizeParam(avpBufSizeParam, mibSizeLog2);
53 
54         if (m_avpItf->GetAvpBufSize(mhw::vdbox::avp::mvTemporalBuffer,
55                                             &avpBufSizeParam) != MOS_STATUS_SUCCESS)
56         {
57             DECODE_ASSERTMESSAGE( "Failed to get MvTemporalBuffer size.");
58         }
59 
60         Av1RefAssociatedBufs *bufs = MOS_New(Av1RefAssociatedBufs);
61         bufs->mvBuf = m_allocator->AllocateBuffer(
62             avpBufSizeParam.bufferSize, "MvTemporalBuffer", resourceInternalReadWriteCache, notLockableVideoMem);
63 
64         if (m_avpItf->GetAvpBufSize(mhw::vdbox::avp::segmentIdBuffer,
65                                             &avpBufSizeParam) != MOS_STATUS_SUCCESS)
66         {
67             DECODE_ASSERTMESSAGE( "Failed to get SegmentIdBuffer size.");
68         }
69         bufs->segIdWriteBuf.buffer = m_allocator->AllocateBuffer(
70             avpBufSizeParam.bufferSize, "SegmentIdWriteBuffer", resourceInternalReadWriteCache, notLockableVideoMem);
71 
72         bufs->bwdAdaptCdfBuf.buffer = m_allocator->AllocateBuffer(MOS_ALIGN_CEIL(m_basicFeature->m_cdfMaxNumBytes,
73             CODECHAL_PAGE_SIZE), "CdfTableBuffer", resourceInternalReadWriteCache, notLockableVideoMem);
74         return bufs;
75     }
76 
Resize(Av1RefAssociatedBufs * & buffer)77     MOS_STATUS Av1TempBufferOpInf::Resize(Av1RefAssociatedBufs* &buffer)
78     {
79         DECODE_FUNC_CALL();
80 
81         if (buffer == nullptr)
82         {
83             DECODE_CHK_NULL(buffer = Allocate());
84             return MOS_STATUS_SUCCESS;
85         }
86 
87         int32_t mibSizeLog2 = m_basicFeature->m_av1PicParams->m_seqInfoFlags.m_fields.m_use128x128Superblock ? av1MaxMibSizeLog2 : av1MinMibSizeLog2;
88         AvpBufferSizePar avpBufSizeParam;
89         SetAvpBufSizeParam(avpBufSizeParam, mibSizeLog2);
90 
91         DECODE_CHK_STATUS(m_avpItf->GetAvpBufSize(
92             mhw::vdbox::avp::mvTemporalBuffer,
93             &avpBufSizeParam));
94         DECODE_CHK_STATUS(m_allocator->Resize(
95             buffer->mvBuf, avpBufSizeParam.bufferSize, notLockableVideoMem, false));
96 
97         DECODE_CHK_STATUS(m_avpItf->GetAvpBufSize(
98             mhw::vdbox::avp::segmentIdBuffer,
99             &avpBufSizeParam));
100         DECODE_CHK_STATUS(m_allocator->Resize(
101             buffer->segIdWriteBuf.buffer, avpBufSizeParam.bufferSize, notLockableVideoMem, false));
102 
103         RecordSegIdBufInfo(buffer);
104         RecordCdfTableBufInfo(buffer);
105 
106         return MOS_STATUS_SUCCESS;
107     }
108 
SetAvpBufSizeParam(AvpBufferSizePar & params,int32_t mibSizeLog2)109     void Av1TempBufferOpInf::SetAvpBufSizeParam(AvpBufferSizePar &params, int32_t mibSizeLog2)
110     {
111         int32_t miCols = MOS_ALIGN_CEIL(m_basicFeature->m_width, 8) >> av1MiSizeLog2;
112         int32_t miRows = MOS_ALIGN_CEIL(m_basicFeature->m_height, 8) >> av1MiSizeLog2;
113         miCols         = MOS_ALIGN_CEIL(miCols, 1 << mibSizeLog2);
114         miRows         = MOS_ALIGN_CEIL(miRows, 1 << mibSizeLog2);
115         widthInSb      = miCols >> mibSizeLog2;
116         heightInSb     = miRows >> mibSizeLog2;
117 
118         MOS_ZeroMemory(&params, sizeof(params));
119         params.width       = widthInSb;
120         params.height      = heightInSb;
121         params.isSb128x128 = false;
122         if (m_basicFeature->m_av1PicParams != nullptr)
123         {
124             params.isSb128x128 = m_basicFeature->m_av1PicParams->m_seqInfoFlags.m_fields.m_use128x128Superblock ? true : false;
125         }
126         params.chromaFormat = m_basicFeature->m_chromaFormat;
127     }
128 
RecordSegIdBufInfo(Av1RefAssociatedBufs * buffer)129     void Av1TempBufferOpInf::RecordSegIdBufInfo(Av1RefAssociatedBufs *buffer)
130     {
131         auto    picParams    = m_basicFeature->m_av1PicParams;
132         uint8_t prevFrameIdx = m_basicFeature->m_refFrames.GetPrimaryRefIdx();
133         if (picParams->m_av1SegData.m_enabled)
134         {
135             if (picParams->m_av1SegData.m_updateMap)
136             {
137                 buffer->segIdBuf = RefSharedBuffer(&buffer->segIdWriteBuf);
138             }
139             else
140             {
141                 auto tempBuffers = &(m_basicFeature->m_tempBuffers);
142                 auto prevTempBuffer = tempBuffers->GetBufferByFrameIndex(prevFrameIdx);
143                 if (prevTempBuffer != nullptr)
144                 {
145                     if (m_basicFeature->m_refFrames.CheckSegForPrimFrame(*picParams))
146                     {
147                         buffer->segIdBuf = RefSharedBuffer(prevTempBuffer->segIdBuf);
148                     }
149                     else
150                     {
151                         buffer->segIdBuf = nullptr;
152                     }
153                 }
154             }
155         }
156         else
157         {
158             buffer->segIdBuf = nullptr;
159         }
160     }
161 
RecordCdfTableBufInfo(Av1RefAssociatedBufs * buffer)162     void Av1TempBufferOpInf::RecordCdfTableBufInfo(Av1RefAssociatedBufs *buffer)
163     {
164         auto    picParams              = m_basicFeature->m_av1PicParams;
165         uint8_t prevFrameIdx           = m_basicFeature->m_refFrames.GetPrimaryRefIdx();
166         buffer->disableFrmEndUpdateCdf = picParams->m_picInfoFlags.m_fields.m_disableFrameEndUpdateCdf;
167 
168         if (picParams->m_primaryRefFrame == av1PrimaryRefNone)
169         {
170             buffer->defaultCdfBuf.buffer = m_basicFeature->m_defaultCdfBufferInUse;
171             buffer->initCdfBuf = RefSharedBuffer(&buffer->defaultCdfBuf);
172         }
173         else
174         {
175             auto tempBuffers = &(m_basicFeature->m_tempBuffers);
176             auto prevTempBuffer = tempBuffers->GetBufferByFrameIndex(prevFrameIdx);
177             if (prevTempBuffer != nullptr)
178             {
179                 if (prevTempBuffer->disableFrmEndUpdateCdf)
180                 {
181                     buffer->initCdfBuf = RefSharedBuffer(prevTempBuffer->initCdfBuf);
182                 }
183                 else
184                 {
185                     buffer->initCdfBuf = RefSharedBuffer(&prevTempBuffer->bwdAdaptCdfBuf);
186                 }
187             }
188         }
189     }
190 
Deactive(Av1RefAssociatedBufs * & buffer)191     MOS_STATUS Av1TempBufferOpInf::Deactive(Av1RefAssociatedBufs* &buffer)
192     {
193         DeRefSharedBuffer(buffer->segIdBuf);
194         DeRefSharedBuffer(buffer->initCdfBuf);
195         return MOS_STATUS_SUCCESS;
196     }
197 
IsAvailable(Av1RefAssociatedBufs * & buffer)198     bool Av1TempBufferOpInf::IsAvailable(Av1RefAssociatedBufs* &buffer)
199     {
200         if (buffer == nullptr)
201         {
202             return false;
203         }
204         if (buffer->segIdWriteBuf.refCnt > 0)
205         {
206             return false;
207         }
208         if (buffer->bwdAdaptCdfBuf.refCnt > 0)
209         {
210             return false;
211         }
212         if (buffer->defaultCdfBuf.refCnt > 0)
213         {
214             return false;
215         }
216         return true;
217     }
218 
Destroy(Av1RefAssociatedBufs * & buffer)219     void Av1TempBufferOpInf::Destroy(Av1RefAssociatedBufs* &buffer)
220     {
221         DECODE_FUNC_CALL();
222 
223         if (buffer != nullptr && m_allocator != nullptr)
224         {
225             m_allocator->Destroy(buffer->mvBuf);
226 
227             m_allocator->Destroy(buffer->segIdWriteBuf.buffer);
228             if (buffer->segIdWriteBuf.refCnt != 0)
229             {
230                 DECODE_NORMALMESSAGE("The reference count is %d while destory SegId buffer", buffer->segIdWriteBuf.refCnt);
231             }
232 
233             m_allocator->Destroy(buffer->bwdAdaptCdfBuf.buffer);
234             if (buffer->bwdAdaptCdfBuf.refCnt != 0)
235             {
236                 DECODE_NORMALMESSAGE("The reference count is %d while destory CDF buffer", buffer->bwdAdaptCdfBuf.refCnt);
237             }
238 
239             MOS_Delete(buffer);
240             buffer = nullptr;
241         }
242     }
243 
RefSharedBuffer(Av1SharedBuf * sharedBuf)244     Av1SharedBuf *Av1TempBufferOpInf::RefSharedBuffer(Av1SharedBuf *sharedBuf)
245     {
246         if (sharedBuf != nullptr)
247         {
248             sharedBuf->refCnt++;
249         }
250         return sharedBuf;
251     }
252 
DeRefSharedBuffer(Av1SharedBuf * sharedBuf)253     Av1SharedBuf *Av1TempBufferOpInf::DeRefSharedBuffer(Av1SharedBuf *sharedBuf)
254     {
255         if (sharedBuf != nullptr)
256         {
257             sharedBuf->refCnt--;
258             if (sharedBuf->refCnt < 0)
259             {
260                 DECODE_ASSERTMESSAGE("AV1 shared buffer reference count is %d which should not small than zero.", sharedBuf->refCnt);
261                 sharedBuf->refCnt = 0;
262             }
263         }
264         return sharedBuf;
265     }
266 }  // namespace decode
267