1 /*
2 * Copyright (c) 2019-2020, 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     encode_hevc_dss.cpp
24 //! \brief    Defines the common interface for hevc encode dynamic slice feature
25 //!
26 
27 #include "encode_hevc_basic_feature.h"
28 #include "encode_hevc_dss.h"
29 #include "encode_hevc_vdenc_feature_manager.h"
30 #include "encode_hevc_vdenc_const_settings.h"
31 
32 namespace encode
33 {
HevcEncodeDss(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)34     HevcEncodeDss::HevcEncodeDss(
35         MediaFeatureManager *featureManager,
36         EncodeAllocator *allocator,
37         CodechalHwInterfaceNext *hwInterface,
38         void *constSettings) :
39         MediaFeature(constSettings),
40         m_allocator(allocator),
41         m_hwInterface(hwInterface)
42     {
43         if (!hwInterface || !constSettings || !allocator)
44             return;
45 
46         auto encFeatureManager = dynamic_cast<EncodeHevcVdencFeatureManager *>(featureManager);
47         if (nullptr != encFeatureManager)
48         {
49             m_basicFeature = dynamic_cast<EncodeBasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
50         }
51     }
52     /*
53     HevcEncodeDss::~HevcEncodeDss()
54     {
55         //FreeDSSResources();
56     }
57     */
Init(void * setting)58     MOS_STATUS HevcEncodeDss::Init(void *setting)
59     {
60         ENCODE_FUNC_CALL();
61 
62         m_hcpItf = m_hwInterface->GetHcpInterfaceNext();
63         ENCODE_CHK_NULL_RETURN(m_hcpItf);
64 
65         m_miItf = m_hwInterface->GetMiInterfaceNext();
66         ENCODE_CHK_NULL_RETURN(m_miItf);
67 
68         m_vdencItf = m_hwInterface->GetVdencInterfaceNext();
69         ENCODE_CHK_NULL_RETURN(m_vdencItf);
70 
71         ENCODE_CHK_STATUS_RETURN(AllocateResources());
72 
73         return MOS_STATUS_SUCCESS;
74     }
75 
AllocateResources()76     MOS_STATUS HevcEncodeDss::AllocateResources()
77     {
78         ENCODE_FUNC_CALL();
79         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
80 
81         ENCODE_CHK_NULL_RETURN(m_allocator);
82         ENCODE_CHK_NULL_RETURN(m_basicFeature);
83         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
84         ENCODE_CHK_NULL_RETURN(m_hwInterface);
85         ENCODE_CHK_NULL_RETURN(m_hwInterface->GetOsInterface());
86 
87         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
88         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
89         allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
90         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
91         allocParamsForBufferLinear.Format   = Format_Buffer;
92 
93         // Slice Count buffer 1 DW = 4 Bytes
94         allocParamsForBufferLinear.dwBytes    = MOS_ALIGN_CEIL(4, CODECHAL_CACHELINE_SIZE);
95         allocParamsForBufferLinear.pBufName   = "Slice Count Buffer";
96         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
97         m_resSliceCountBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, false);
98 
99         // VDEncMode Timer buffer 1 DW = 4 Bytes
100         allocParamsForBufferLinear.dwBytes        = MOS_ALIGN_CEIL(4, CODECHAL_CACHELINE_SIZE);
101         allocParamsForBufferLinear.pBufName       = "VDEncMode Timer Buffer";
102         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
103         m_resVDEncModeTimerBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, false);
104 
105         return eStatus;
106     }
107 
Update(void * params)108     MOS_STATUS HevcEncodeDss::Update(void *params)
109     {
110         ENCODE_FUNC_CALL();
111         ENCODE_CHK_NULL_RETURN(params);
112 
113         EncoderParams *encodeParams = (EncoderParams *)params;
114         m_hevcSeqParams             = static_cast<PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
115 
116         uint32_t frameWidth         = (m_hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
117         uint32_t frameHeight        = (m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
118         if (m_hevcSeqParams->SliceSizeControl && frameWidth * frameHeight < ENCODE_HEVC_MIN_DSS_PIC_WIDTH * ENCODE_HEVC_MIN_DSS_PIC_HEIGHT)
119         {
120             MOS_STATUS eStatus = MOS_STATUS_INVALID_PARAMETER;
121             ENCODE_CHK_STATUS_MESSAGE_RETURN(eStatus, "DSS is not supported when frame resolution less than 320p");
122         }
123 
124         return MOS_STATUS_SUCCESS;
125     }
126 
ReadHcpStatus(MHW_VDBOX_NODE_IND vdboxIndex,MOS_COMMAND_BUFFER & cmdBuffer)127     MOS_STATUS HevcEncodeDss::ReadHcpStatus(
128         MHW_VDBOX_NODE_IND  vdboxIndex,
129         MOS_COMMAND_BUFFER &cmdBuffer)
130     {
131         ENCODE_FUNC_CALL();
132 
133         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
134 
135         auto mmioRegisters = m_hcpItf->GetMmioRegisters(vdboxIndex);
136         ENCODE_CHK_NULL_RETURN(mmioRegisters);
137 
138         auto AddMiStoreRegisterMemCmd = [&](PMOS_RESOURCE &res, uint32_t dwRegister) {
139             auto &miStoreRegMemParams           = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)();
140             miStoreRegMemParams                 = {};
141             miStoreRegMemParams.presStoreBuffer = res;
142             miStoreRegMemParams.dwOffset        = 0;
143             miStoreRegMemParams.dwRegister      = dwRegister;
144             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(&cmdBuffer));
145             return MOS_STATUS_SUCCESS;
146         };
147 
148         ENCODE_CHK_STATUS_RETURN(AddMiStoreRegisterMemCmd(m_resSliceCountBuffer, mmioRegisters->hcpEncSliceCountRegOffset));
149         ENCODE_CHK_STATUS_RETURN(AddMiStoreRegisterMemCmd(m_resVDEncModeTimerBuffer, mmioRegisters->hcpEncVdencModeTimerRegOffset));
150 
151         return eStatus;
152     }
153 
ReadSliceSizeForSinglePipe(EncodePipeline * pipeline,MOS_COMMAND_BUFFER & cmdBuffer)154     MOS_STATUS HevcEncodeDss::ReadSliceSizeForSinglePipe(EncodePipeline *pipeline,  MOS_COMMAND_BUFFER &cmdBuffer)
155     {
156         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
157 
158         ENCODE_FUNC_CALL();
159         MediaStatusReport *statusReport = pipeline->GetStatusReportInstance();
160         MOS_RESOURCE *osResource = nullptr;
161         uint32_t      offset = 0;
162         statusReport->GetAddress(statusReportSliceReport, osResource, offset);
163 
164         uint32_t sizeOfSliceSizesBuffer = MOS_ALIGN_CEIL(CODECHAL_HEVC_MAX_NUM_SLICES_LVL_6 * CODECHAL_CACHELINE_SIZE, CODECHAL_PAGE_SIZE);
165 
166         uint32_t currIndex = statusReport->GetIndex(statusReport->GetSubmittedCount());
167 
168         if (pipeline->IsFirstPass())
169         {
170             // Create/ Initialize slice report buffer once per frame, to be used across passes
171             if (Mos_ResourceIsNull(&m_resSliceReport[currIndex]))
172             {
173                 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
174                 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
175                 allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
176                 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
177                 allocParamsForBufferLinear.Format   = Format_Buffer;
178                 allocParamsForBufferLinear.dwBytes  = sizeOfSliceSizesBuffer;
179                 allocParamsForBufferLinear.pBufName = "SliceReport";
180                 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
181                 MOS_RESOURCE *allocatedresource     = m_allocator->AllocateResource(allocParamsForBufferLinear, false);
182                 ENCODE_CHK_NULL_RETURN(allocatedresource);
183                 m_resSliceReport[currIndex] = *allocatedresource;
184             }
185 
186             // Clear slice size structure to be sent in EncodeStatusReport buffer
187             uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(&m_resSliceReport[currIndex]);
188             ENCODE_CHK_NULL_RETURN(data);
189             MOS_ZeroMemory(data, sizeOfSliceSizesBuffer);
190             m_allocator->UnLock(&m_resSliceReport[currIndex]);
191 
192             // Set slice size pointer in slice size structure
193             auto &miFlushDwParams            = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
194             miFlushDwParams                  = {};
195             miFlushDwParams.pOsResource      = osResource;
196             miFlushDwParams.dwResourceOffset = offset + CODECHAL_OFFSETOF(EncodeStatusSliceReport, sliceSize);
197             miFlushDwParams.dwDataDW1        = (uint32_t)((uint64_t)&m_resSliceReport[currIndex] & 0xFFFFFFFF);
198             miFlushDwParams.dwDataDW2        = (uint32_t)(((uint64_t)&m_resSliceReport[currIndex] & 0xFFFFFFFF00000000) >> 32);
199             miFlushDwParams.bQWordEnable     = 1;
200             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer));
201         }
202 
203         // Copy Slize size data buffer from PAK to be sent back to App
204         ENCODE_CHK_STATUS_RETURN(CopyDataBlock(
205             m_basicFeature->m_recycleBuf->GetBuffer(LcuBaseAddressBuffer, 0),
206             0,
207             &m_resSliceReport[currIndex],
208             0,
209             sizeOfSliceSizesBuffer,
210             cmdBuffer));
211 
212         auto &miCpyMemMemParams       = m_miItf->MHW_GETPAR_F(MI_COPY_MEM_MEM)();
213         miCpyMemMemParams             = {};
214         miCpyMemMemParams.presSrc     = m_basicFeature->m_recycleBuf->GetBuffer(FrameStatStreamOutBuffer, 0);  // Slice size overflow is in m_resFrameStatStreamOutBuffer DW0[16]
215         miCpyMemMemParams.dwSrcOffset = 0;
216         miCpyMemMemParams.presDst     = osResource;
217         miCpyMemMemParams.dwDstOffset = offset;
218         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(&cmdBuffer));
219 
220         miCpyMemMemParams             = {};
221         miCpyMemMemParams.presSrc     = m_resSliceCountBuffer;  // Number of slice sizes are stored in this buffer. Updated at runtime
222         miCpyMemMemParams.dwSrcOffset = 0;
223         miCpyMemMemParams.presDst     = osResource;
224         miCpyMemMemParams.dwDstOffset = offset + 1;
225         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(&cmdBuffer));
226 
227         return eStatus;
228     }
229 
ReadSliceSize(EncodePipeline * pipeline,MOS_COMMAND_BUFFER & cmdBuffer)230     MOS_STATUS HevcEncodeDss::ReadSliceSize(EncodePipeline *pipeline, MOS_COMMAND_BUFFER &cmdBuffer)
231     {
232         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
233 
234         ENCODE_FUNC_CALL();
235         MediaStatusReport *statusReport = pipeline->GetStatusReportInstance();
236 
237         // In multi-tile multi-pipe mode, use PAK integration kernel output
238         // PAK integration kernel accumulates frame statistics across tiles, which should be used to setup slice size report
239         MOS_RESOURCE *osResource = nullptr;
240         uint32_t      offset = 0;
241 
242         statusReport->GetAddress(statusReportSliceReport, osResource, offset);
243 
244         uint32_t sizeOfSliceSizesBuffer = MOS_ALIGN_CEIL(CODECHAL_HEVC_MAX_NUM_SLICES_LVL_6 * CODECHAL_CACHELINE_SIZE, CODECHAL_PAGE_SIZE);
245 
246         uint32_t currIndex = statusReport->GetIndex(statusReport->GetSubmittedCount());
247 
248         if (pipeline->IsFirstPipe())
249         {
250             if (pipeline->IsFirstPass())
251             {
252                 // Create/ Initialize slice report buffer once per frame, to be used across passes
253                 if (Mos_ResourceIsNull(&m_resSliceReport[currIndex]))
254                 {
255                     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
256                     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
257                     allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
258                     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
259                     allocParamsForBufferLinear.Format   = Format_Buffer;
260                     allocParamsForBufferLinear.dwBytes  = sizeOfSliceSizesBuffer;
261                     allocParamsForBufferLinear.pBufName = "SliceReport";
262                     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
263                     MOS_RESOURCE *allocatedresource     = m_allocator->AllocateResource(allocParamsForBufferLinear, false);
264                     ENCODE_CHK_NULL_RETURN(allocatedresource);
265                     m_resSliceReport[currIndex] = *allocatedresource;
266                 }
267 
268                 // Clear slice size structure to be sent in EncodeStatusReportNext buffer
269                 uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(&m_resSliceReport[currIndex]);
270                 ENCODE_CHK_NULL_RETURN(data);
271                 MOS_ZeroMemory(data, sizeOfSliceSizesBuffer);
272                 m_allocator->UnLock(&m_resSliceReport[currIndex]);
273 
274                 // Set slice size pointer in slice size structure
275                 auto &miFlushDwParams            = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
276                 miFlushDwParams                  = {};
277                 miFlushDwParams.pOsResource      = osResource;
278                 miFlushDwParams.dwResourceOffset = offset + CODECHAL_OFFSETOF(EncodeStatusSliceReport, sliceSize);
279                 miFlushDwParams.dwDataDW1        = (uint32_t)((uint64_t)&m_resSliceReport[currIndex] & 0xFFFFFFFF);
280                 miFlushDwParams.dwDataDW2        = (uint32_t)(((uint64_t)&m_resSliceReport[currIndex] & 0xFFFFFFFF00000000) >> 32);
281                 miFlushDwParams.bQWordEnable     = 1;
282                 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer));
283             }
284 
285             uint32_t      statBufIdx           = 0;
286             MOS_RESOURCE *tileStatisticsBuffer = nullptr;
287             RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, FeatureIDs::encodeTile, GetStatisticsBufferIndex, statBufIdx);
288             RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, FeatureIDs::encodeTile, GetTileBasedStatisticsBuffer, statBufIdx, tileStatisticsBuffer);
289             ENCODE_CHK_NULL_RETURN(tileStatisticsBuffer);
290 
291             HevcTileStatusInfo hevcTileStatsOffset;
292             HevcTileStatusInfo hevcFrameStatsOffset;
293             HevcTileStatusInfo hevcStatsSize;
294             RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, FeatureIDs::encodeTile, GetTileStatusInfo, hevcTileStatsOffset, hevcFrameStatsOffset, hevcStatsSize);
295 
296             // Copy Slize size data buffer from PAK to be sent back to App
297             ENCODE_CHK_STATUS_RETURN(CopyDataBlock(
298                 tileStatisticsBuffer,
299                 hevcTileStatsOffset.hevcSliceStreamout,
300                 &m_resSliceReport[currIndex],
301                 0,
302                 sizeOfSliceSizesBuffer,
303                 cmdBuffer));
304 
305             MOS_RESOURCE *resHuCPakAggregatedFrameStatsBuffer = nullptr;
306             RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, FeatureIDs::encodeTile, GetHucPakAggregatedFrameStatsBuffer, resHuCPakAggregatedFrameStatsBuffer);
307             ENCODE_CHK_NULL_RETURN(resHuCPakAggregatedFrameStatsBuffer);
308 
309             auto &miCpyMemMemParams       = m_miItf->MHW_GETPAR_F(MI_COPY_MEM_MEM)();
310             miCpyMemMemParams             = {};
311             miCpyMemMemParams.presSrc     = resHuCPakAggregatedFrameStatsBuffer;  // Slice size overflow is in m_resFrameStatStreamOutBuffer DW0[16]
312             miCpyMemMemParams.dwSrcOffset = hevcFrameStatsOffset.hevcPakStatistics;
313             miCpyMemMemParams.presDst     = osResource;
314             miCpyMemMemParams.dwDstOffset = offset;     // Slice size overflow is at DW0 EncodeStatusSliceReport
315             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(&cmdBuffer));
316         }
317 
318         return eStatus;
319     }
320 
CopyDataBlock(PMOS_RESOURCE sourceSurface,uint32_t sourceOffset,PMOS_RESOURCE destSurface,uint32_t destOffset,uint32_t copySize,MOS_COMMAND_BUFFER & cmdBuffer)321     MOS_STATUS HevcEncodeDss::CopyDataBlock(
322         PMOS_RESOURCE       sourceSurface,
323         uint32_t            sourceOffset,
324         PMOS_RESOURCE       destSurface,
325         uint32_t            destOffset,
326         uint32_t            copySize,
327         MOS_COMMAND_BUFFER &cmdBuffer)
328     {
329         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
330 
331         ENCODE_FUNC_CALL();
332 
333         CodechalHucStreamoutParams hucStreamOutParams;
334         MOS_ZeroMemory(&hucStreamOutParams, sizeof(hucStreamOutParams));
335 
336         // Ind Obj Addr command
337         hucStreamOutParams.dataBuffer            = sourceSurface;
338         hucStreamOutParams.dataSize              = copySize + sourceOffset;
339         hucStreamOutParams.dataOffset            = MOS_ALIGN_FLOOR(sourceOffset, CODECHAL_PAGE_SIZE);
340         hucStreamOutParams.streamOutObjectBuffer = destSurface;
341         hucStreamOutParams.streamOutObjectSize   = copySize + destOffset;
342         hucStreamOutParams.streamOutObjectOffset = MOS_ALIGN_FLOOR(destOffset, CODECHAL_PAGE_SIZE);
343 
344         // Stream object params
345         hucStreamOutParams.indStreamInLength    = copySize;
346         hucStreamOutParams.inputRelativeOffset  = sourceOffset - hucStreamOutParams.dataOffset;
347         hucStreamOutParams.outputRelativeOffset = destOffset - hucStreamOutParams.streamOutObjectOffset;
348 
349         ENCODE_CHK_STATUS_RETURN(m_hwInterface->PerformHucStreamOut(
350             &hucStreamOutParams,
351             &cmdBuffer));
352 
353         // wait Huc completion (use HEVC bit for now)
354         auto &vdPipeFlushParams        = m_vdencItf->MHW_GETPAR_F(VD_PIPELINE_FLUSH)();
355         vdPipeFlushParams              = {};
356         vdPipeFlushParams.flushHEVC    = true;
357         vdPipeFlushParams.waitDoneHEVC = true;
358         ENCODE_CHK_STATUS_RETURN(m_vdencItf->MHW_ADDCMD_F(VD_PIPELINE_FLUSH)(&cmdBuffer));
359 
360         // Flush the engine to ensure memory written out
361         auto &flushDwParams                         = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
362         flushDwParams                               = {};
363         flushDwParams.bVideoPipelineCacheInvalidate = true;
364         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer));
365 
366         return eStatus;
367     }
368 
GetDssBuffer(PMOS_RESOURCE & resSliceCountBuffer,PMOS_RESOURCE & resVDEncModeTimerBuffer)369     MOS_STATUS HevcEncodeDss::GetDssBuffer(PMOS_RESOURCE &resSliceCountBuffer, PMOS_RESOURCE &resVDEncModeTimerBuffer)
370     {
371         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
372 
373         ENCODE_FUNC_CALL();
374 
375         ENCODE_CHK_NULL_RETURN(m_resSliceCountBuffer);
376         ENCODE_CHK_NULL_RETURN(m_resVDEncModeTimerBuffer);
377 
378         resSliceCountBuffer = m_resSliceCountBuffer;
379         resVDEncModeTimerBuffer = m_resVDEncModeTimerBuffer;
380 
381         return eStatus;
382     }
383     }