1 /*
2 * Copyright (c) 2018-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 //!
24 //! \file     encode_pipeline.cpp
25 //! \brief    Defines the common interface for encode pipeline
26 //! \details  The encode pipeline interface is further sub-divided by codec standard,
27 //!           this file is for the base interface which is shared by all codecs.
28 //!
29 #include "encode_pipeline.h"
30 #include "encode_utils.h"
31 #include "media_packet.h"
32 
33 #include "codechal_setting.h"
34 #include "encode_status_report_defs.h"
35 #include "encode_status_report.h"
36 #include "mos_solo_generic.h"
37 
38 namespace encode {
EncodePipeline(CodechalHwInterfaceNext * hwInterface,CodechalDebugInterface * debugInterface)39 EncodePipeline::EncodePipeline(
40     CodechalHwInterfaceNext *hwInterface,
41     CodechalDebugInterface *debugInterface):
42       MediaPipeline(hwInterface ? hwInterface->GetOsInterface() : nullptr),
43       m_hwInterface(hwInterface)
44 {
45 
46 }
47 
Initialize(void * settings)48 MOS_STATUS EncodePipeline::Initialize(void *settings)
49 {
50     ENCODE_FUNC_CALL();
51     ENCODE_CHK_STATUS_RETURN(InitUserSetting(m_userSettingPtr));
52     ENCODE_CHK_STATUS_RETURN(MediaPipeline::InitPlatform());
53     ENCODE_CHK_STATUS_RETURN(MediaPipeline::CreateMediaCopyWrapper());
54     ENCODE_CHK_NULL_RETURN(m_mediaCopyWrapper);
55 
56     ENCODE_CHK_NULL_RETURN(m_hwInterface);
57     ENCODE_CHK_NULL_RETURN(m_hwInterface->GetOsInterface());
58 
59     m_osInterface = m_hwInterface->GetOsInterface();
60     ENCODE_CHK_NULL_RETURN(m_osInterface);
61 
62     if (m_mediaCopyWrapper->MediaCopyStateIsNull())
63     {
64         m_mediaCopyWrapper->SetMediaCopyState(m_hwInterface->CreateMediaCopy(m_osInterface));
65     }
66 
67     m_mediaContext = MOS_New(MediaContext, scalabilityEncoder, m_hwInterface, m_osInterface);
68     ENCODE_CHK_NULL_RETURN(m_mediaContext);
69 
70     m_allocator = MOS_New(EncodeAllocator, m_osInterface);
71     ENCODE_CHK_NULL_RETURN(m_allocator);
72 
73     m_trackedBuf = MOS_New(TrackedBuffer, m_allocator, (uint8_t)CODEC_NUM_REF_BUFFERS, (uint8_t)CODEC_NUM_NON_REF_BUFFERS);
74     ENCODE_CHK_NULL_RETURN(m_trackedBuf);
75 
76     m_recycleBuf = MOS_New(RecycleResource, m_allocator);
77     ENCODE_CHK_NULL_RETURN(m_recycleBuf);
78 
79     CodechalSetting *codecSettings = (CodechalSetting*)settings;
80     m_standard = codecSettings->standard;
81     m_mode = codecSettings->mode;
82     m_codecFunction = codecSettings->codecFunction;
83 
84     CODECHAL_DEBUG_TOOL(
85         m_debugInterface = MOS_New(CodechalDebugInterface);
86         ENCODE_CHK_NULL_RETURN(m_debugInterface);
87         ENCODE_CHK_STATUS_RETURN(
88             m_debugInterface->Initialize(m_hwInterface, m_codecFunction, m_mediaCopyWrapper)
89         );
90 
91         m_statusReportDebugInterface = MOS_New(CodechalDebugInterface);
92         ENCODE_CHK_NULL_RETURN(m_statusReportDebugInterface);
93         ENCODE_CHK_STATUS_RETURN(
94         m_statusReportDebugInterface->Initialize(m_hwInterface, m_codecFunction, m_mediaCopyWrapper));
95     );
96 
97     MediaUserSetting::Value outValue;
98     ReadUserSetting(
99         m_userSettingPtr,
100         outValue,
101         "Single Task Phase Enable",
102         MediaUserSetting::Group::Sequence);
103     m_singleTaskPhaseSupported = outValue.Get<bool>();
104 
105     ENCODE_CHK_STATUS_RETURN(CreateFeatureManager());
106     ENCODE_CHK_NULL_RETURN(m_featureManager);
107 
108     m_encodecp = MOS_New(EncodeCp, m_hwInterface);
109     m_encodecp->RegisterParams(codecSettings);
110     bool cpenable = m_encodecp->isCpEnabled();
111 
112     ENCODE_CHK_STATUS_RETURN(m_featureManager->Init(codecSettings));
113 
114     m_packetUtilities = MOS_New(PacketUtilities, m_hwInterface, m_featureManager);
115     ENCODE_CHK_NULL_RETURN(m_packetUtilities);
116     ENCODE_CHK_STATUS_RETURN(m_packetUtilities->Init());
117 
118     m_statusReport = MOS_New(EncoderStatusReport, m_allocator, m_osInterface, true, true, cpenable);
119     ENCODE_CHK_NULL_RETURN(m_statusReport);
120     ENCODE_CHK_STATUS_RETURN(m_statusReport->Create());
121 
122     m_encodecp->setStatusReport(m_statusReport);
123 
124     return MOS_STATUS_SUCCESS;
125 }
126 
Uninitialize()127 MOS_STATUS EncodePipeline::Uninitialize()
128 {
129     ENCODE_FUNC_CALL();
130 
131     MOS_Delete(m_mediaContext);
132 
133     MOS_Delete(m_encodecp);
134 
135     MOS_Delete(m_statusReport);
136 
137     CODECHAL_DEBUG_TOOL(
138         MOS_Delete(m_debugInterface);
139         MOS_Delete(m_statusReportDebugInterface);
140     );
141 
142     MOS_Delete(m_trackedBuf);
143 
144     MOS_Delete(m_recycleBuf);
145 
146     if (m_featureManager != nullptr)
147     {
148         m_featureManager->Destroy();
149         MOS_Delete(m_featureManager);
150     }
151 
152     // Allocator should not be destroyed until all resources released.
153     if (m_allocator != nullptr)
154     {
155         m_allocator->DestroyAllResources();
156         MOS_Delete(m_allocator);
157     }
158 
159     MOS_Delete(m_packetUtilities);
160 
161     return MOS_STATUS_SUCCESS;
162 }
163 
UserFeatureReport()164 MOS_STATUS EncodePipeline::UserFeatureReport()
165 {
166     ENCODE_FUNC_CALL();
167     ENCODE_CHK_STATUS_RETURN(MediaPipeline::UserFeatureReport());
168 
169     // Encode HW Walker Reporting
170 //    WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_ENCODE_HW_WALKER_ID, m_hwWalker);
171 //    if (m_hwWalker)
172 //    {
173 //        // Encode HW Walker m_mode Reporting
174 //#if (_DEBUG || _RELEASE_INTERNAL)
175 //        WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_ENCODE_HW_WALKER_MODE_ID, m_walkerMode);
176 //#endif // _DEBUG || _RELEASE_INTERNAL
177 //    }
178 //
179 //    if (MEDIA_IS_SKU(m_skuTable, FtrSliceShutdown))
180 //    {
181 //        // SliceShutdownEnable Reporting
182 //        WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_SLICE_SHUTDOWN_ENABLE_ID, m_sliceShutdownEnable);
183 //    }
184 #if (_DEBUG || _RELEASE_INTERNAL)
185     ReportUserSettingForDebug(
186         m_userSettingPtr,
187         "Media Encode Used VDBOX Number",
188         GetPipeNum(),
189         MediaUserSetting::Group::Sequence);
190 
191     ReportUserSettingForDebug(
192         m_userSettingPtr,
193         "Media Encode DDI TargetUsage",
194         GetDDITU(),
195         MediaUserSetting::Group::Sequence);
196 #endif // _DEBUG || _RELEASE_INTERNAL
197 
198     return MOS_STATUS_SUCCESS;
199 }
200 
Prepare(void * params)201 MOS_STATUS EncodePipeline::Prepare(void *params)
202 {
203     ENCODE_FUNC_CALL();
204 
205     ENCODE_CHK_NULL_RETURN(params);
206     ENCODE_CHK_NULL_RETURN(m_hwInterface);
207 
208     ENCODE_CHK_NULL_RETURN(m_featureManager);
209     ENCODE_CHK_STATUS_RETURN(m_featureManager->CheckFeatures(params));
210     ENCODE_CHK_STATUS_RETURN(m_featureManager->Update(params));
211     m_encodecp->UpdateParams(true);
212 
213     ENCODE_CHK_STATUS_RETURN(WaitForBatchBufferComplete());
214 
215     EncoderParams *encodeParams = (EncoderParams *)params;
216     ENCODE_CHK_STATUS_RETURN(Mos_Solo_SetGpuAppTaskEvent(m_osInterface, encodeParams->gpuAppTaskEvent));
217 
218     m_osInterface->pfnIncPerfFrameID(m_osInterface);
219 
220     return MOS_STATUS_SUCCESS;
221 }
222 
ContextSwitchBack()223 MOS_STATUS EncodePipeline::ContextSwitchBack()
224 {
225     ENCODE_FUNC_CALL();
226 
227     ENCODE_CHK_NULL_RETURN(m_scalPars);
228 
229     m_scalPars->IsContextSwitchBack = true;
230     m_mediaContext->SwitchContext(VdboxEncodeFunc, m_scalPars.get(), &m_scalability);
231     m_scalPars->IsContextSwitchBack = false;
232 
233     ENCODE_CHK_NULL_RETURN(m_scalability);
234 
235     m_scalability->SetPassNumber(m_featureManager->GetNumPass());
236 
237     return MOS_STATUS_SUCCESS;
238 }
239 
GetSystemVdboxNumber()240 MOS_STATUS EncodePipeline::GetSystemVdboxNumber()
241 {
242     MEDIA_SYSTEM_INFO *gtSystemInfo = m_osInterface->pfnGetGtSystemInfo(m_osInterface);
243     MEDIA_ENGINE_INFO  mediaSysInfo;
244     MOS_ZeroMemory(&mediaSysInfo, sizeof(MEDIA_ENGINE_INFO));
245     MOS_STATUS eStatus = m_osInterface->pfnGetMediaEngineInfo(m_osInterface, mediaSysInfo);
246 
247     if (eStatus == MOS_STATUS_SUCCESS && (!MEDIA_IS_SKU(m_skuTable, FtrWithSlimVdbox)))
248     {
249         // Both VE mode and media solo mode should be able to get the VDBOX number via the same interface
250         m_numVdbox = (uint8_t)(mediaSysInfo.VDBoxInfo.NumberOfVDBoxEnabled);
251     }
252     else
253     {
254         m_numVdbox = 1;
255     }
256 
257     return MOS_STATUS_SUCCESS;
258 }
259 
WaitForBatchBufferComplete()260 MOS_STATUS EncodePipeline::WaitForBatchBufferComplete()
261 {
262     ENCODE_CHK_NULL_RETURN(m_statusReport);
263 
264     const uint32_t completedFrames = m_statusReport->GetCompletedCount();
265 
266     if (!m_hwInterface->IsSimActive() &&
267         m_recycledBufStatusNum[m_currRecycledBufIdx] > completedFrames)
268     {
269         uint32_t waitMs;
270 
271         // Wait for Batch Buffer complete event OR timeout
272         for (waitMs = MHW_TIMEOUT_MS_DEFAULT; waitMs > 0; waitMs -= MHW_EVENT_TIMEOUT_MS)
273         {
274             if (m_recycledBufStatusNum[m_currRecycledBufIdx] <= completedFrames)
275             {
276                 break;
277             }
278 
279             MosUtilities::MosSleep(MHW_EVENT_TIMEOUT_MS);
280         }
281 
282         ENCODE_VERBOSEMESSAGE("Waited for %d ms", (MHW_TIMEOUT_MS_DEFAULT - waitMs));
283 
284         if (m_recycledBufStatusNum[m_currRecycledBufIdx] > completedFrames)
285         {
286             ENCODE_ASSERTMESSAGE("No recycled buffers available, wait timed out at %d ms!", MHW_TIMEOUT_MS_DEFAULT);
287             ENCODE_ASSERTMESSAGE("m_storeData = %d, m_recycledBufStatusNum[%d] = %d, data = %d",
288                 m_statusReport->GetSubmittedCount(),
289                 m_currRecycledBufIdx,
290                 m_recycledBufStatusNum[m_currRecycledBufIdx],
291                 completedFrames);
292             return MOS_STATUS_CLIENT_AR_NO_SPACE;
293         }
294     }
295 
296     m_recycledBufStatusNum[m_currRecycledBufIdx] = m_statusReport->GetSubmittedCount();
297 
298     return MOS_STATUS_SUCCESS;
299 }
300 
ExecuteActivePackets()301 MOS_STATUS EncodePipeline::ExecuteActivePackets()
302 {
303     ENCODE_FUNC_CALL();
304     MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
305 
306     for (auto prop : m_activePacketList)
307     {
308         prop.stateProperty.singleTaskPhaseSupported = m_singleTaskPhaseSupported;
309         prop.stateProperty.statusReport = m_statusReport;
310         MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_INFO, &prop.packetId, sizeof(uint32_t), nullptr, 0);
311 
312         MediaTask *task = prop.packet->GetActiveTask();
313         ENCODE_CHK_STATUS_RETURN(task->AddPacket(&prop));
314         if (prop.immediateSubmit)
315         {
316             ENCODE_CHK_STATUS_RETURN(task->Submit(true, m_scalability, m_debugInterface));
317         }
318     }
319 
320     m_activePacketList.clear();
321     MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
322     return MOS_STATUS_SUCCESS;
323 }
324 
ExecuteResolveMetaData(PMOS_RESOURCE pInput,PMOS_RESOURCE pOutput)325 MOS_STATUS EncodePipeline::ExecuteResolveMetaData(PMOS_RESOURCE pInput, PMOS_RESOURCE pOutput)
326 {
327     ENCODE_FUNC_CALL();
328     MOS_COMMAND_BUFFER cmdBuffer;
329     MOS_ZeroMemory(&cmdBuffer, sizeof(cmdBuffer));
330 
331     ENCODE_CHK_NULL_RETURN(m_scalability);
332     ENCODE_CHK_STATUS_RETURN(m_scalability->GetCmdBuffer(&cmdBuffer));
333 
334     auto basicFeature = dynamic_cast<EncodeBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
335     ENCODE_CHK_NULL_RETURN(basicFeature);
336     uint32_t bufSize = basicFeature->m_metaDataOffset.dwMetaDataSize + basicFeature->m_numSlices * basicFeature->m_metaDataOffset.dwMetaDataSubRegionSize +
337                        basicFeature->m_metaDataOffset.dwTilePartitionSize + basicFeature->m_metaDataOffset.dwPostFeatueSize;
338     m_packetUtilities->AddMemCopyCmd(&cmdBuffer, pOutput, pInput, bufSize);
339     ENCODE_CHK_STATUS_RETURN(m_scalability->ReturnCmdBuffer(&cmdBuffer));
340     ENCODE_CHK_STATUS_RETURN(m_scalability->SubmitCmdBuffer(&cmdBuffer));
341 
342     return MOS_STATUS_SUCCESS;
343 }
344 
ReportErrorFlag(PMOS_RESOURCE pMetadataBuffer,uint32_t size,uint32_t offset,uint32_t flag)345 MOS_STATUS EncodePipeline::ReportErrorFlag(PMOS_RESOURCE pMetadataBuffer,
346     uint32_t size, uint32_t offset, uint32_t flag)
347 {
348     ENCODE_FUNC_CALL();
349     MOS_COMMAND_BUFFER cmdBuffer;
350     MOS_ZeroMemory(&cmdBuffer, sizeof(cmdBuffer));
351 
352     ENCODE_CHK_NULL_RETURN(m_scalability);
353     ENCODE_CHK_STATUS_RETURN(m_scalability->GetCmdBuffer(&cmdBuffer));
354 
355     auto basicFeature = dynamic_cast<EncodeBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
356     ENCODE_CHK_NULL_RETURN(basicFeature);
357 
358     basicFeature->m_metaDataOffset.dwMetaDataSize = size;
359     m_packetUtilities->AddStoreDataImmCmd(&cmdBuffer, pMetadataBuffer, offset, flag);
360     ENCODE_CHK_STATUS_RETURN(m_scalability->ReturnCmdBuffer(&cmdBuffer));
361     ENCODE_CHK_STATUS_RETURN(m_scalability->SubmitCmdBuffer(&cmdBuffer));
362     return MOS_STATUS_SUCCESS;
363 }
364 
SetFrameTrackingForMultiTaskPhase()365 void EncodePipeline::SetFrameTrackingForMultiTaskPhase()
366 {
367     if (!IsSingleTaskPhaseSupported())
368     {
369         for_each(m_activePacketList.begin(), m_activePacketList.end() - 1, [&](PacketProperty &blk) { blk.frameTrackingRequested = false; });
370     }
371 }
372 
373 }
374