1 /*
2 * Copyright (c) 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     encode_jpeg_packet.cpp
24 //! \brief    Defines the interface for jpeg encode packet
25 //!
26 
27 #include "encode_jpeg_packet.h"
28 #include "codec_def_encode_jpeg.h"
29 #include "mos_solo_generic.h"
30 #include "media_jpeg_feature_defs.h"
31 
32 namespace encode {
33 
JpegPkt(MediaPipeline * pipeline,MediaTask * task,CodechalHwInterfaceNext * hwInterface)34     JpegPkt::JpegPkt(
35         MediaPipeline *pipeline,
36         MediaTask *task,
37         CodechalHwInterfaceNext *hwInterface) :
38         CmdPacket(task),
39         m_pipeline(dynamic_cast<JpegPipeline *>(pipeline)),
40         m_hwInterface(dynamic_cast<CodechalHwInterfaceNext *>(hwInterface))
41     {
42         ENCODE_CHK_NULL_NO_STATUS_RETURN(hwInterface);
43         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_pipeline);
44         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hwInterface);
45 
46         m_osInterface    = hwInterface->GetOsInterface();
47         m_statusReport   = m_pipeline->GetStatusReportInstance();
48         m_featureManager = m_pipeline->GetFeatureManager();
49         m_encodecp       = m_pipeline->GetEncodeCp();
50 
51         CODECHAL_DEBUG_TOOL(
52             m_debugInterface = m_pipeline->GetDebugInterface();
53             ENCODE_CHK_NULL_NO_STATUS_RETURN(m_debugInterface);)
54 
55         m_mfxItf = std::static_pointer_cast<mhw::vdbox::mfx::Itf>(m_hwInterface->GetMfxInterfaceNext());
56         m_miItf  = std::static_pointer_cast<mhw::mi::Itf>(m_hwInterface->GetMiInterfaceNext());
57     }
58 
Init()59     MOS_STATUS JpegPkt::Init()
60     {
61         ENCODE_FUNC_CALL();
62         ENCODE_CHK_NULL_RETURN(m_statusReport);
63 
64         ENCODE_CHK_STATUS_RETURN(CmdPacket::Init());
65 
66         m_basicFeature = dynamic_cast<JpegBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
67         ENCODE_CHK_NULL_RETURN(m_basicFeature);
68 
69         m_jpgPkrFeature = dynamic_cast<JpegPackerFeature *>(m_featureManager->GetFeature(JpegFeatureIDs::jpegPackerFeature));
70         ENCODE_CHK_NULL_RETURN(m_jpgPkrFeature);
71 
72 #ifdef _MMC_SUPPORTED
73         m_mmcState = m_pipeline->GetMmcState();
74         ENCODE_CHK_NULL_RETURN(m_mmcState);
75         m_basicFeature->m_mmcState = m_mmcState;
76 #endif
77 
78         ENCODE_CHK_STATUS_RETURN(m_statusReport->RegistObserver(this));
79 
80         m_usePatchList = m_osInterface->bUsesPatchList;
81 
82         return MOS_STATUS_SUCCESS;
83     }
84 
Prepare()85     MOS_STATUS JpegPkt::Prepare()
86     {
87         ENCODE_FUNC_CALL();
88 
89         JpegPipeline *pipeline = dynamic_cast<JpegPipeline *>(m_pipeline);
90         ENCODE_CHK_NULL_RETURN(pipeline);
91 
92         m_jpegPicParams       = m_basicFeature->m_jpegPicParams;
93         m_jpegScanParams      = m_basicFeature->m_jpegScanParams;
94         m_jpegQuantTables     = m_basicFeature->m_jpegQuantTables;
95         m_jpegHuffmanTable    = m_basicFeature->m_jpegHuffmanTable;
96         m_applicationData     = m_basicFeature->m_applicationData;
97         m_numHuffBuffers      = m_basicFeature->m_numHuffBuffers;
98 
99         return MOS_STATUS_SUCCESS;
100     }
101 
Destroy()102     MOS_STATUS JpegPkt::Destroy()
103     {
104         ENCODE_FUNC_CALL();
105         ENCODE_CHK_STATUS_RETURN(m_statusReport->UnregistObserver(this));
106 
107         return MOS_STATUS_SUCCESS;
108     }
109 
Submit(MOS_COMMAND_BUFFER * commandBuffer,uint8_t packetPhase)110     MOS_STATUS JpegPkt::Submit(
111         MOS_COMMAND_BUFFER* commandBuffer,
112         uint8_t packetPhase)
113     {
114         ENCODE_FUNC_CALL();
115 
116         MOS_COMMAND_BUFFER &cmdBuffer = *commandBuffer;
117         ENCODE_CHK_STATUS_RETURN(Mos_Solo_PreProcessEncode(m_osInterface, &m_basicFeature->m_resBitstreamBuffer, &m_basicFeature->m_reconSurface));
118 
119         // Ensure the input is ready to be read.
120         // Currently, mos RegisterResource has sync limitation for Raw resource.
121         // Temporaly, call Resource Wait to do the sync explicitly.
122         // TODO, Refine it when MOS refactor ready.
123         MOS_SYNC_PARAMS syncParams;
124         syncParams                  = g_cInitSyncParams;
125         syncParams.GpuContext       = m_osInterface->pfnGetGpuContext(m_osInterface);
126         syncParams.presSyncResource = &m_basicFeature->m_rawSurface.OsResource;
127         syncParams.bReadOnly        = true;
128         ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
129         m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
130 
131         ENCODE_CHK_STATUS_RETURN(PatchPictureLevelCommands(packetPhase, cmdBuffer));
132         ENCODE_CHK_STATUS_RETURN(PatchSliceLevelCommands(cmdBuffer, packetPhase));
133 
134         ENCODE_CHK_STATUS_RETURN(Mos_Solo_PostProcessEncode(m_osInterface, &m_basicFeature->m_resBitstreamBuffer, &m_basicFeature->m_reconSurface));
135 
136         return MOS_STATUS_SUCCESS;
137     }
138 
Completed(void * mfxStatus,void * rcsStatus,void * statusReport)139     MOS_STATUS JpegPkt::Completed(void *mfxStatus, void *rcsStatus, void *statusReport)
140     {
141         ENCODE_FUNC_CALL();
142 
143         ENCODE_CHK_NULL_RETURN(mfxStatus);
144         ENCODE_CHK_NULL_RETURN(statusReport);
145 
146         EncodeStatusMfx        *encodeStatusMfx  = (EncodeStatusMfx *)mfxStatus;
147         EncodeStatusReportData *statusReportData = (EncodeStatusReportData *)statusReport;
148 
149         if (statusReportData->hwCtr)
150         {
151             m_encodecp->UpdateCpStatusReport(statusReport);
152         }
153 
154         statusReportData->codecStatus = CODECHAL_STATUS_SUCCESSFUL;
155 
156         CODECHAL_DEBUG_TOOL(
157             ENCODE_CHK_STATUS_RETURN(DumpResources(encodeStatusMfx, statusReportData)););
158 
159         return MOS_STATUS_SUCCESS;
160     }
161 
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)162     MOS_STATUS JpegPkt::CalculateCommandSize(
163         uint32_t &commandBufferSize,
164         uint32_t &requestedPatchListSize)
165     {
166         ENCODE_FUNC_CALL();
167 
168         ENCODE_CHK_STATUS_RETURN(CalculateMfxCommandsSize());
169         commandBufferSize      = CalculateCommandBufferSize();
170         requestedPatchListSize = CalculatePatchListSize();
171         return MOS_STATUS_SUCCESS;
172     }
173 
CalculateMfxCommandsSize()174     MOS_STATUS JpegPkt::CalculateMfxCommandsSize()
175     {
176         ENCODE_FUNC_CALL();
177 
178         // Picture Level Commands
179         ENCODE_CHK_STATUS_RETURN(
180             GetMfxStateCommandsDataSize(
181                 &m_pictureStatesSize,
182                 &m_picturePatchListSize));
183 
184         // Slice Level Commands (cannot be placed in 2nd level batch)
185         ENCODE_CHK_STATUS_RETURN(
186             GetMfxPrimitiveCommandsDataSize(
187                 &m_sliceStatesSize,
188                 &m_slicePatchListSize));
189 
190         return MOS_STATUS_SUCCESS;
191     }
192 
GetMfxPrimitiveCommandsDataSize(uint32_t * commandsSize,uint32_t * patchListSize)193     MOS_STATUS JpegPkt::GetMfxPrimitiveCommandsDataSize(
194         uint32_t *commandsSize,
195         uint32_t *patchListSize)
196     {
197         ENCODE_FUNC_CALL()
198         uint32_t cpCmdsize       = 0;
199         uint32_t cpPatchListSize = 0;
200 
201         if (m_mfxItf)
202         {
203             uint32_t maxSize = 0;
204 
205             maxSize =
206                 m_mfxItf->MHW_GETSIZE_F(MFX_FQM_STATE)() * 3 +
207                 m_mfxItf->MHW_GETSIZE_F(MFC_JPEG_HUFF_TABLE_STATE)() * 2 +
208                 m_mfxItf->MHW_GETSIZE_F(MFC_JPEG_SCAN_OBJECT)() +
209                 m_mfxItf->MHW_GETSIZE_F(MFX_PAK_INSERT_OBJECT)() * 10;
210 
211             *commandsSize  = maxSize;
212             *patchListSize = 0;
213 
214             m_hwInterface->GetCpInterface()->GetCpSliceLevelCmdSize(cpCmdsize, cpPatchListSize);
215         }
216 
217         *commandsSize += cpCmdsize;
218         *patchListSize += cpPatchListSize;
219 
220         return MOS_STATUS_SUCCESS;
221     }
222 
GetMfxStateCommandsDataSize(uint32_t * commandsSize,uint32_t * patchListSize)223     MOS_STATUS JpegPkt::GetMfxStateCommandsDataSize(
224         uint32_t *commandsSize,
225         uint32_t *patchListSize)
226     {
227         ENCODE_FUNC_CALL()
228         ENCODE_CHK_NULL_RETURN(commandsSize);
229         ENCODE_CHK_NULL_RETURN(patchListSize);
230 
231         uint32_t cpCmdsize       = 0;
232         uint32_t cpPatchListSize = 0;
233 
234         if (m_mfxItf && m_miItf)
235         {
236             uint32_t maxSize =
237                 m_miItf->MHW_GETSIZE_F(MI_FLUSH_DW)() +
238                 m_mfxItf->MHW_GETSIZE_F(MFX_PIPE_MODE_SELECT)() +
239                 m_mfxItf->MHW_GETSIZE_F(MFX_SURFACE_STATE)() +
240                 m_mfxItf->MHW_GETSIZE_F(MFX_PIPE_BUF_ADDR_STATE)() +
241                 m_mfxItf->MHW_GETSIZE_F(MFX_IND_OBJ_BASE_ADDR_STATE)() +
242                 2 * m_miItf->MHW_GETSIZE_F(MI_STORE_DATA_IMM)() +
243                 2 * m_miItf->MHW_GETSIZE_F(MI_STORE_REGISTER_MEM)() +
244                 8 * m_miItf->MHW_GETSIZE_F(MI_LOAD_REGISTER_REG)();
245 
246             uint32_t patchListMaxSize =
247                 PATCH_LIST_COMMAND(mhw::vdbox::huc::Itf::MI_FLUSH_DW_CMD) +
248                 PATCH_LIST_COMMAND(mhw::vdbox::mfx::Itf::MFX_PIPE_MODE_SELECT_CMD) +
249                 PATCH_LIST_COMMAND(mhw::vdbox::mfx::Itf::MFX_SURFACE_STATE_CMD) +
250                 PATCH_LIST_COMMAND(mhw::vdbox::mfx::Itf::MFX_PIPE_BUF_ADDR_STATE_CMD) +
251                 PATCH_LIST_COMMAND(mhw::vdbox::mfx::Itf::MFX_IND_OBJ_BASE_ADDR_STATE_CMD) +
252                 (2 * PATCH_LIST_COMMAND(mhw::vdbox::huc::Itf::MI_STORE_DATA_IMM_CMD)) +
253                 (2 * PATCH_LIST_COMMAND(mhw::vdbox::huc::Itf::MI_STORE_REGISTER_MEM_CMD));
254 
255             *commandsSize  = maxSize;
256             *patchListSize = patchListMaxSize;
257 
258             m_hwInterface->GetCpInterface()->GetCpStateLevelCmdSize(cpCmdsize, cpPatchListSize);
259         }
260 
261         *commandsSize += cpCmdsize;
262         *patchListSize += cpPatchListSize;
263 
264         return MOS_STATUS_SUCCESS;
265     }
266 
SelectVdboxAndGetMmioRegister(MHW_VDBOX_NODE_IND index,PMOS_COMMAND_BUFFER pCmdBuffer)267     MmioRegistersMfx *JpegPkt::SelectVdboxAndGetMmioRegister(
268         MHW_VDBOX_NODE_IND  index,
269         PMOS_COMMAND_BUFFER pCmdBuffer)
270     {
271         if (m_hwInterface->m_getVdboxNodeByUMD)
272         {
273             pCmdBuffer->iVdboxNodeIndex = m_osInterface->pfnGetVdboxNodeId(m_osInterface, pCmdBuffer);
274             switch (pCmdBuffer->iVdboxNodeIndex)
275             {
276             case MOS_VDBOX_NODE_1:
277                 index = MHW_VDBOX_NODE_1;
278                 break;
279             case MOS_VDBOX_NODE_2:
280                 index = MHW_VDBOX_NODE_2;
281                 break;
282             case MOS_VDBOX_NODE_INVALID:
283                 // That's a legal case meaning that we were not assigned with per-bb index because
284                 // balancing algorithm can't work (forcedly diabled or miss kernel support).
285                 // If that's the case we just proceed with the further static context assignment.
286                 break;
287             default:
288                 // That's the case when MHW and MOS enumerations mismatch. We again proceed with the
289                 // best effort (static context assignment, but provide debug note).
290                 MHW_ASSERTMESSAGE("MOS and MHW VDBOX enumerations mismatch! Adjust HW description!");
291                 break;
292             }
293         }
294 
295         auto vdencItf = m_hwInterface->GetVdencInterfaceNext();
296         if (vdencItf)
297         {
298             return vdencItf->GetMmioRegisters(index);
299         }
300         else
301         {
302             MHW_ASSERTMESSAGE("Get vdenc interface failed!");
303             return nullptr;
304         }
305     }
306 
SetPerfTag(uint16_t type,uint16_t mode,uint16_t picCodingType)307     void JpegPkt::SetPerfTag(uint16_t type, uint16_t mode, uint16_t picCodingType)
308     {
309         ENCODE_FUNC_CALL();
310 
311         PerfTagSetting perfTag;
312         perfTag.Value             = 0;
313         perfTag.Mode              = mode & CODECHAL_ENCODE_MODE_BIT_MASK;
314         perfTag.CallType          = type;
315         perfTag.PictureCodingType = picCodingType > 3 ? 0 : picCodingType;
316         m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value);
317         m_osInterface->pfnIncPerfBufferID(m_osInterface);
318     }
319 
AddPictureMfxCommands(MOS_COMMAND_BUFFER & cmdBuffer)320     MOS_STATUS JpegPkt::AddPictureMfxCommands(
321         MOS_COMMAND_BUFFER & cmdBuffer)
322     {
323         ENCODE_FUNC_CALL();
324 
325         SETPAR_AND_ADDCMD(MFX_WAIT, m_miItf, &cmdBuffer);
326         SETPAR_AND_ADDCMD(MFX_PIPE_MODE_SELECT, m_mfxItf, &cmdBuffer);
327         SETPAR_AND_ADDCMD(MFX_WAIT, m_miItf, &cmdBuffer);
328 
329         SETPAR_AND_ADDCMD(MFX_SURFACE_STATE, m_mfxItf, &cmdBuffer);
330         SETPAR_AND_ADDCMD(MFX_PIPE_BUF_ADDR_STATE, m_mfxItf, &cmdBuffer);
331         SETPAR_AND_ADDCMD(MFX_IND_OBJ_BASE_ADDR_STATE, m_mfxItf, &cmdBuffer);
332         SETPAR_AND_ADDCMD(MFX_JPEG_PIC_STATE, m_mfxItf, &cmdBuffer);
333 
334         return MOS_STATUS_SUCCESS;
335     }
336 
SendPrologCmds(MOS_COMMAND_BUFFER & cmdBuffer)337     MOS_STATUS JpegPkt::SendPrologCmds(MOS_COMMAND_BUFFER &cmdBuffer)
338     {
339         ENCODE_FUNC_CALL();
340         MOS_GPU_CONTEXT gpuContext = m_osInterface->pfnGetGpuContext(m_osInterface);
341 
342         // initialize command buffer attributes
343         cmdBuffer.Attributes.bTurboMode               = m_hwInterface->m_turboMode;
344         cmdBuffer.Attributes.bMediaPreemptionEnabled   = 0;
345         cmdBuffer.Attributes.dwNumRequestedEUSlices    = m_hwInterface->m_numRequestedEuSlices;
346         cmdBuffer.Attributes.dwNumRequestedSubSlices   = m_hwInterface->m_numRequestedSubSlices;
347         cmdBuffer.Attributes.dwNumRequestedEUs         = m_hwInterface->m_numRequestedEus;
348         cmdBuffer.Attributes.bValidPowerGatingRequest  = true;
349 
350 #ifdef _MMC_SUPPORTED
351         ENCODE_CHK_NULL_RETURN(m_mmcState);
352         ENCODE_CHK_STATUS_RETURN(m_mmcState->SendPrologCmd(&cmdBuffer, false));
353 #endif
354 
355         MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
356         MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
357         genericPrologParams.pOsInterface     = m_osInterface;
358         genericPrologParams.pvMiInterface    = nullptr;
359         genericPrologParams.bMmcEnabled      = m_mmcState ? m_mmcState->IsMmcEnabled() : false;
360         ENCODE_CHK_STATUS_RETURN(Mhw_SendGenericPrologCmdNext(&cmdBuffer, &genericPrologParams, m_miItf));
361 
362         return MOS_STATUS_SUCCESS;
363     }
364 
StartStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)365     MOS_STATUS JpegPkt::StartStatusReport(
366         uint32_t            srType,
367         MOS_COMMAND_BUFFER *cmdBuffer)
368     {
369         ENCODE_FUNC_CALL();
370         ENCODE_CHK_NULL_RETURN(cmdBuffer);
371 
372         ENCODE_CHK_STATUS_RETURN(MediaPacket::StartStatusReportNext(srType, cmdBuffer));
373         m_encodecp->StartCpStatusReport(cmdBuffer);
374 
375         MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
376         ENCODE_CHK_NULL_RETURN(perfProfiler);
377         ENCODE_CHK_STATUS_RETURN(perfProfiler->AddPerfCollectStartCmd(
378             (void *)m_pipeline, m_osInterface, m_miItf, cmdBuffer));
379 
380         return MOS_STATUS_SUCCESS;
381     }
382 
ReadMfcStatus(MOS_COMMAND_BUFFER & cmdBuffer)383     MOS_STATUS JpegPkt::ReadMfcStatus(MOS_COMMAND_BUFFER &cmdBuffer)
384     {
385         ENCODE_FUNC_CALL();
386 
387         ENCODE_CHK_NULL_RETURN(m_hwInterface);
388 
389         MOS_RESOURCE *osResource = nullptr;
390         uint32_t      offset = 0;
391 
392         EncodeStatusReadParams params;
393         MOS_ZeroMemory(&params, sizeof(params));
394 
395         ENCODE_CHK_STATUS_RETURN(m_statusReport->GetAddress(encode::statusReportMfxBitstreamByteCountPerFrame, osResource, offset));
396         params.resBitstreamByteCountPerFrame    = osResource;
397         params.bitstreamByteCountPerFrameOffset = offset;
398 
399         ENCODE_CHK_STATUS_RETURN(m_statusReport->GetAddress(encode::statusReportMfxBitstreamSyntaxElementOnlyBitCount, osResource, offset));
400         params.resBitstreamSyntaxElementOnlyBitCount    = osResource;
401         params.bitstreamSyntaxElementOnlyBitCountOffset = offset;
402 
403         ENCODE_CHK_STATUS_RETURN(m_statusReport->GetAddress(encode::statusReportQPStatusCount, osResource, offset));
404         params.resQpStatusCount    = osResource;
405         params.qpStatusCountOffset = offset;
406 
407         ENCODE_CHK_STATUS_RETURN(m_statusReport->GetAddress(encode::statusReportImageStatusMask, osResource, offset));
408         params.resImageStatusMask    = osResource;
409         params.imageStatusMaskOffset = offset;
410 
411         ENCODE_CHK_STATUS_RETURN(m_statusReport->GetAddress(encode::statusReportImageStatusCtrl, osResource, offset));
412         params.resImageStatusCtrl    = osResource;
413         params.imageStatusCtrlOffset = offset;
414 
415         ENCODE_CHK_STATUS_RETURN(m_statusReport->GetAddress(encode::statusReportNumSlices, osResource, offset));
416         params.resNumSlices    = osResource;
417         params.numSlicesOffset = offset;
418 
419         ENCODE_CHK_COND_RETURN((m_vdboxIndex > m_mfxItf->GetMaxVdboxIndex()), "ERROR - vdbox index exceeds the maximum");
420 
421         SETPAR_AND_ADDCMD(MI_FLUSH_DW, m_miItf, &cmdBuffer);
422 
423         MmioRegistersMfx *mmioRegisters = SelectVdboxAndGetMmioRegister(m_vdboxIndex, &cmdBuffer);
424         CODEC_HW_CHK_NULL_RETURN(mmioRegisters);
425         m_pResource                     = params.resBitstreamByteCountPerFrame;
426         m_dwOffset                      = params.bitstreamByteCountPerFrameOffset;
427         m_dwValue                       = mmioRegisters->mfcBitstreamBytecountFrameRegOffset;
428         SETPAR_AND_ADDCMD(MI_STORE_REGISTER_MEM, m_miItf, &cmdBuffer);
429 
430         m_pResource = params.resBitstreamSyntaxElementOnlyBitCount;
431         m_dwOffset  = params.bitstreamSyntaxElementOnlyBitCountOffset;
432         m_dwValue   = mmioRegisters->mfcBitstreamSeBitcountFrameRegOffset;
433         SETPAR_AND_ADDCMD(MI_STORE_REGISTER_MEM, m_miItf, &cmdBuffer);
434 
435         m_pResource = params.resQpStatusCount;
436         m_dwOffset  = params.qpStatusCountOffset;
437         m_dwValue   = mmioRegisters->mfcQPStatusCountOffset;
438         SETPAR_AND_ADDCMD(MI_STORE_REGISTER_MEM, m_miItf, &cmdBuffer);
439 
440         ENCODE_CHK_STATUS_RETURN(ReadImageStatus(params, &cmdBuffer))
441         return MOS_STATUS_SUCCESS;
442     }
443 
ReadImageStatus(const EncodeStatusReadParams & params,PMOS_COMMAND_BUFFER cmdBuffer)444     MOS_STATUS JpegPkt::ReadImageStatus(
445         const EncodeStatusReadParams &params,
446         PMOS_COMMAND_BUFFER           cmdBuffer)
447     {
448         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
449 
450         CODEC_HW_FUNCTION_ENTER;
451 
452         CODEC_HW_CHK_NULL_RETURN(cmdBuffer);
453 
454         CODEC_HW_CHK_COND_RETURN((m_vdboxIndex > m_mfxItf->GetMaxVdboxIndex()), "ERROR - vdbox index exceeds the maximum");
455 
456         MmioRegistersMfx *mmioRegisters = SelectVdboxAndGetMmioRegister(m_vdboxIndex, cmdBuffer);
457         CODEC_HW_CHK_NULL_RETURN(mmioRegisters);
458         m_pResource                     = params.resImageStatusMask;
459         m_dwOffset                      = params.imageStatusMaskOffset;
460         m_dwValue                       = mmioRegisters->mfcImageStatusMaskRegOffset;
461         SETPAR_AND_ADDCMD(MI_STORE_REGISTER_MEM, m_miItf, cmdBuffer);
462 
463         m_pResource = params.resImageStatusCtrl;
464         m_dwOffset  = params.imageStatusCtrlOffset;
465         m_dwValue   = mmioRegisters->mfcImageStatusCtrlRegOffset;
466         SETPAR_AND_ADDCMD(MI_STORE_REGISTER_MEM, m_miItf, cmdBuffer);
467 
468         SETPAR_AND_ADDCMD(MI_FLUSH_DW, m_miItf, cmdBuffer);
469 
470         return eStatus;
471     }
472 
EndStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)473     MOS_STATUS JpegPkt::EndStatusReport(
474         uint32_t            srType,
475         MOS_COMMAND_BUFFER *cmdBuffer)
476     {
477         ENCODE_FUNC_CALL();
478         ENCODE_CHK_NULL_RETURN(cmdBuffer);
479 
480         ENCODE_CHK_STATUS_RETURN(MediaPacket::EndStatusReportNext(srType, cmdBuffer));
481 
482         MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
483         ENCODE_CHK_NULL_RETURN(perfProfiler);
484         ENCODE_CHK_STATUS_RETURN(perfProfiler->AddPerfCollectEndCmd(
485             (void *)m_pipeline, m_osInterface, m_miItf, cmdBuffer));
486 
487         return MOS_STATUS_SUCCESS;
488     }
489 
PatchPictureLevelCommands(const uint8_t & packetPhase,MOS_COMMAND_BUFFER & cmdBuffer)490     MOS_STATUS JpegPkt::PatchPictureLevelCommands(const uint8_t &packetPhase, MOS_COMMAND_BUFFER  &cmdBuffer)
491     {
492         ENCODE_FUNC_CALL();
493 
494         ENCODE_CHK_STATUS_RETURN(m_miItf->SetWatchdogTimerThreshold(m_basicFeature->m_frameWidth, m_basicFeature->m_frameHeight, true));
495 
496         SetPerfTag(CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE, (uint16_t)m_basicFeature->m_mode, m_basicFeature->m_pictureCodingType);
497 
498         SETPAR_AND_ADDCMD(MI_FORCE_WAKEUP, m_miItf, &cmdBuffer);
499 
500         // Send command buffer header at the beginning (OS dependent)
501         ENCODE_CHK_STATUS_RETURN(SendPrologCmds(cmdBuffer));
502 
503         if (m_pipeline->IsFirstPipe())
504         {
505             ENCODE_CHK_STATUS_RETURN(StartStatusReport(statusReportMfx, &cmdBuffer));
506         }
507 
508         ENCODE_CHK_STATUS_RETURN(AddPictureMfxCommands(cmdBuffer));
509 
510         return MOS_STATUS_SUCCESS;
511     }
512 
PatchSliceLevelCommands(MOS_COMMAND_BUFFER & cmdBuffer,uint8_t packetPhase)513     MOS_STATUS JpegPkt::PatchSliceLevelCommands(MOS_COMMAND_BUFFER &cmdBuffer, uint8_t packetPhase)
514     {
515         ENCODE_FUNC_CALL();
516 
517         if (m_basicFeature->m_numSlices != 1)
518         {
519             ENCODE_ASSERTMESSAGE("JPEG encode only one scan is supported.");
520         }
521 
522         static_assert(JPEG_MAX_NUM_QUANT_TABLE_INDEX <= JPEG_MAX_NUM_OF_QUANTMATRIX,
523             "access to CodecJpegQuantMatrix is controlled by numQuantTables");
524 
525         for (uint32_t scanCount = 0; scanCount < m_basicFeature->m_numSlices; scanCount++)
526         {
527             m_numQuantTables = JPEG_MAX_NUM_QUANT_TABLE_INDEX;
528             ENCODE_CHK_STATUS_RETURN(InitMissedQuantTables());
529 
530             ENCODE_CHK_STATUS_RETURN(InitQuantMatrix());
531 
532             ENCODE_CHK_STATUS_RETURN(AddAllCmds_MFX_FQM_STATE(&cmdBuffer));
533 
534             ENCODE_CHK_STATUS_RETURN(InitHuffTable());
535 
536             ENCODE_CHK_STATUS_RETURN(AddAllCmds_MFC_JPEG_HUFF_TABLE_STATE(&cmdBuffer));
537 
538             SETPAR_AND_ADDCMD(MFC_JPEG_SCAN_OBJECT, m_mfxItf, &cmdBuffer);
539 
540             ENCODE_CHK_STATUS_RETURN(AddAllCmds_MFX_PAK_INSERT_OBJECT(&cmdBuffer));
541         }
542 
543         ENCODE_CHK_STATUS_RETURN(ReadMfcStatus(cmdBuffer));
544 
545         if (m_pipeline->IsFirstPipe())
546         {
547             ENCODE_CHK_STATUS_RETURN(EndStatusReport(statusReportMfx, &cmdBuffer));
548         }
549 
550         if (!m_pipeline->IsSingleTaskPhaseSupported() || m_pipeline->IsLastPass())
551         {
552              ENCODE_CHK_STATUS_RETURN(UpdateStatusReportNext(statusReportGlobalCount, &cmdBuffer));
553         }
554 
555         ENCODE_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
556 
557         std::string pakPassName = "PAK_PASS" + std::to_string(static_cast<uint32_t>(m_pipeline->GetCurrentPass()));
558         CODECHAL_DEBUG_TOOL(
559             CodechalDebugInterface *debugInterface = m_pipeline->GetDebugInterface();
560             ENCODE_CHK_NULL_RETURN(debugInterface);
561             ENCODE_CHK_STATUS_RETURN(debugInterface->DumpCmdBuffer(
562                 &cmdBuffer,
563                 CODECHAL_NUM_MEDIA_STATES,
564                 pakPassName.data()));
565         )
566 
567         return MOS_STATUS_SUCCESS;
568     }
569 
InitMissedQuantTables()570     MOS_STATUS JpegPkt::InitMissedQuantTables()
571     {
572         ENCODE_FUNC_CALL();
573 
574         MOS_SURFACE *surface = m_basicFeature->m_rawSurfaceToPak;
575         bool useSingleDefaultQuantTable = (m_basicFeature->m_jpegQuantMatrixSent == false &&
576                                            ((surface->Format == Format_A8R8G8B8) ||
577                                             (surface->Format == Format_X8R8G8B8) ||
578                                             (surface->Format == Format_A8B8G8R8) ||
579                                             (surface->Format == Format_X8B8G8R8)));
580 
581         // For monochrome inputs there will be only 1 quantization table and huffman table sent
582         if (m_jpegPicParams->m_inputSurfaceFormat == codechalJpegY8)
583         {
584             m_numQuantTables = 1;
585             m_numHuffBuffers = 2;  //for Y8 only 2 huff tables
586         }
587         // If there is only 1 quantization table copy over the table to 2nd and 3rd table in JPEG state (used for frame header)
588         // OR For RGB input surfaces, if the app does not send quantization tables, then use luma quant table for all 3 components
589         else if (m_jpegPicParams->m_numQuantTable == 1 || useSingleDefaultQuantTable)
590         {
591             for (auto i = 1; i < JPEG_MAX_NUM_QUANT_TABLE_INDEX; i++)
592             {
593                 m_jpegQuantTables->m_quantTable[i].m_precision = m_jpegQuantTables->m_quantTable[0].m_precision;
594                 m_jpegQuantTables->m_quantTable[i].m_tableID   = m_jpegQuantTables->m_quantTable[0].m_tableID;
595 
596                 ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
597                     &m_jpegQuantTables->m_quantTable[i].m_qm[0],
598                     JPEG_NUM_QUANTMATRIX * sizeof(uint16_t),
599                     &m_jpegQuantTables->m_quantTable[0].m_qm[0],
600                     JPEG_NUM_QUANTMATRIX * sizeof(uint16_t)));
601             }
602         }
603         // If there are 2 quantization tables copy over the second table to 3rd table in JPEG state since U and V share the same table (used for frame header)
604         else if (m_jpegPicParams->m_numQuantTable == 2)
605         {
606             m_jpegQuantTables->m_quantTable[2].m_precision = m_jpegQuantTables->m_quantTable[1].m_precision;
607             m_jpegQuantTables->m_quantTable[2].m_tableID   = m_jpegQuantTables->m_quantTable[1].m_tableID;
608 
609             ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
610                 &m_jpegQuantTables->m_quantTable[2].m_qm[0],
611                 JPEG_NUM_QUANTMATRIX * sizeof(uint16_t),
612                 &m_jpegQuantTables->m_quantTable[1].m_qm[0],
613                 JPEG_NUM_QUANTMATRIX * sizeof(uint16_t)));
614         }
615         // else 3 quantization tables are sent by the application for non monochrome input formats. In that case, do nothing.
616 
617         return MOS_STATUS_SUCCESS;
618     }
619 
InitQuantMatrix()620     MOS_STATUS JpegPkt::InitQuantMatrix()
621     {
622         ENCODE_FUNC_CALL();
623 
624         m_jpegQuantMatrix = {};
625 
626         for (uint8_t i = 0; i < m_numQuantTables; i++)
627         {
628             for (auto j = 0; j < JPEG_NUM_QUANTMATRIX; j++)
629             {
630                 uint32_t k = jpeg_qm_scan_8x8[j];
631 
632                 // copy over Quant matrix in raster order from zig zag
633                 m_jpegQuantMatrix.m_quantMatrix[i][k] = (uint8_t)m_jpegQuantTables->m_quantTable[i].m_qm[j];
634             }
635         }
636 
637         return MOS_STATUS_SUCCESS;
638     }
639 
InitHuffTable()640     MOS_STATUS JpegPkt::InitHuffTable()
641     {
642         ENCODE_FUNC_CALL();
643 
644         for (uint32_t i = 0; i < m_numHuffBuffers; i++)
645         {
646             EncodeJpegHuffTable huffmanTable;  // intermediate table for each AC/DC component which will be copied to m_huffTableParams
647             MOS_ZeroMemory(&huffmanTable, sizeof(huffmanTable));
648 
649             ENCODE_CHK_STATUS_RETURN(ConvertHuffDataToTable(m_jpegHuffmanTable->m_huffmanData[i], &huffmanTable));
650 
651             m_huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].HuffTableID = m_jpegHuffmanTable->m_huffmanData[i].m_tableID;
652 
653             if (m_jpegHuffmanTable->m_huffmanData[i].m_tableClass == 0)  // DC table
654             {
655                 ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
656                     m_huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pDCCodeValues,
657                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint16_t),
658                     &huffmanTable.m_huffCode,
659                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint16_t)));
660 
661                 ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(m_huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pDCCodeLength,
662                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint8_t),
663                     &huffmanTable.m_huffSize,
664                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint8_t)));
665             }
666             else  // AC Table
667             {
668                 ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(m_huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pACCodeValues,
669                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t),
670                     &huffmanTable.m_huffCode,
671                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t)));
672 
673                 ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(m_huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pACCodeLength,
674                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t),
675                     &huffmanTable.m_huffSize,
676                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t)));
677             }
678         }
679 
680         // Send 2 huffman table commands - 1 for Luma and one for chroma for non-monchrome input formats
681         // If only one table is sent by the app (2 buffers), send the same table for Luma and chroma
682         m_repeatHuffTable = false;
683         if ((m_numHuffBuffers / 2 < JPEG_MAX_NUM_HUFF_TABLE_INDEX) && (m_jpegPicParams->m_inputSurfaceFormat != codechalJpegY8))
684         {
685             m_repeatHuffTable = true;
686 
687             // Copy over huffman data to the other two data buffers for JPEG picture header
688             for (uint32_t i = 0; i < m_numHuffBuffers; i++)
689             {
690                 if ((i + 2) >= JPEG_NUM_ENCODE_HUFF_BUFF)
691                 {
692                     return MOS_STATUS_INVALID_PARAMETER;
693                 }
694                 m_jpegHuffmanTable->m_huffmanData[i + 2].m_tableClass = m_jpegHuffmanTable->m_huffmanData[i].m_tableClass;
695                 m_jpegHuffmanTable->m_huffmanData[i + 2].m_tableID    = m_jpegHuffmanTable->m_huffmanData[i].m_tableID;
696 
697                 ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(&m_jpegHuffmanTable->m_huffmanData[i + 2].m_bits[0],
698                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_BITS,
699                     &m_jpegHuffmanTable->m_huffmanData[i].m_bits[0],
700                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_BITS));
701 
702                 ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(&m_jpegHuffmanTable->m_huffmanData[i + 2].m_huffVal[0],
703                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_HUFFVAL,
704                     &m_jpegHuffmanTable->m_huffmanData[i].m_huffVal[0],
705                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_HUFFVAL));
706             }
707         }
708 
709         return MOS_STATUS_SUCCESS;
710     }
711 
AddSOI(PMOS_COMMAND_BUFFER cmdBuffer) const712     MOS_STATUS JpegPkt::AddSOI(PMOS_COMMAND_BUFFER cmdBuffer) const
713     {
714         ENCODE_FUNC_CALL();
715         ENCODE_CHK_NULL_RETURN(cmdBuffer);
716 
717         BSBuffer bsBuffer = {};
718         ENCODE_CHK_STATUS_RETURN(m_jpgPkrFeature->PackSOI(&bsBuffer));
719 
720         uint32_t byteSize = (bsBuffer.BufferSize + 7) >> 3;
721         uint32_t dataBitsInLastDw = bsBuffer.BufferSize % 32;
722         if (dataBitsInLastDw == 0)
723         {
724             dataBitsInLastDw = 32;
725         }
726 
727         auto &params = m_mfxItf->MHW_GETPAR_F(MFX_PAK_INSERT_OBJECT)();
728         params = {};
729         params.dwPadding = ((byteSize + 3) >> 2);
730         params.bitstreamstartresetResetbitstreamstartingpos = 1;
731         params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
732 
733         m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
734 
735         // Add actual data
736         uint8_t* data = (uint8_t*)(bsBuffer.pBase);
737         MOS_STATUS eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
738 
739         MOS_SafeFreeMemory(bsBuffer.pBase);
740 
741         return eStatus;
742     }
743 
AddApplicationData(PMOS_COMMAND_BUFFER cmdBuffer) const744     MOS_STATUS JpegPkt::AddApplicationData(PMOS_COMMAND_BUFFER cmdBuffer) const
745     {
746         ENCODE_FUNC_CALL();
747         ENCODE_CHK_NULL_RETURN(cmdBuffer);
748 
749         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
750 
751         BSBuffer bsBuffer         = {};
752         uint32_t appDataChunkSize = m_basicFeature->m_appDataSize;
753         auto    &params           = m_mfxItf->MHW_GETPAR_F(MFX_PAK_INSERT_OBJECT)();
754 
755         // We can write a maximum of 1020 words per command, so if the size of the app data is
756         // more than 1020 we need to send multiple commands for writing out app data
757         uint32_t numAppDataCmdsNeeded  = 1;
758         uint32_t appDataCmdSizeResidue = 0;
759         if (m_basicFeature->m_appDataSize > 1020)
760         {
761             numAppDataCmdsNeeded  = m_basicFeature->m_appDataSize / 1020;
762             appDataCmdSizeResidue = m_basicFeature->m_appDataSize % 1020;
763 
764             appDataChunkSize = 1020;
765         }
766 
767         uint8_t *appDataChunk = (uint8_t *)MOS_AllocAndZeroMemory(appDataChunkSize);
768         ENCODE_CHK_NULL_RETURN(appDataChunk)
769 
770         for (uint32_t i = 0; i < numAppDataCmdsNeeded; i++)
771         {
772             uint8_t *copyAddress = (uint8_t *)(m_applicationData) + (i * appDataChunkSize);
773 
774             MOS_SecureMemcpy(appDataChunk, appDataChunkSize, copyAddress, appDataChunkSize);
775             eStatus = m_jpgPkrFeature->PackApplicationData(&bsBuffer, appDataChunk, appDataChunkSize);
776             if (eStatus != MOS_STATUS_SUCCESS)
777             {
778                 MOS_SafeFreeMemory(appDataChunk);
779                 ENCODE_CHK_STATUS_RETURN(eStatus);
780             }
781 
782             uint32_t byteSize = (bsBuffer.BufferSize + 7) >> 3;
783             uint32_t dataBitsInLastDw = bsBuffer.BufferSize % 32;
784             if (dataBitsInLastDw == 0)
785             {
786                 dataBitsInLastDw = 32;
787             }
788 
789             params = {};
790             params.dwPadding = ((byteSize + 3) >> 2);
791             params.bitstreamstartresetResetbitstreamstartingpos = 1;
792             //if full header is included in application data, it will be the last header to insert and last chunk of it should be marked with EndOfSlice
793             if ((appDataCmdSizeResidue == 0) && m_basicFeature->m_fullHeaderInAppData && (i == numAppDataCmdsNeeded - 1))
794             {
795                 params.endofsliceflagLastdstdatainsertcommandflag = true;
796                 params.lastheaderflagLastsrcheaderdatainsertcommandflag = true;
797             }
798             else
799             {
800                 params.endofsliceflagLastdstdatainsertcommandflag = false;
801                 params.lastheaderflagLastsrcheaderdatainsertcommandflag = false;
802             }
803             params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
804 
805             m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
806 
807             // Add actual data
808             uint8_t* data = (uint8_t*)(bsBuffer.pBase);
809             eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
810             if (eStatus != MOS_STATUS_SUCCESS)
811             {
812                 MOS_SafeFreeMemory(appDataChunk);
813                 ENCODE_CHK_STATUS_RETURN(eStatus);
814             }
815         }
816 
817         if (appDataCmdSizeResidue != 0)
818         {
819             uint8_t *lastAddress = (uint8_t *)(m_applicationData) + (numAppDataCmdsNeeded * appDataChunkSize);
820             appDataChunkSize     = appDataCmdSizeResidue;
821 
822             MOS_SecureMemcpy(appDataChunk, appDataChunkSize, lastAddress, appDataChunkSize);
823 
824             eStatus = m_jpgPkrFeature->PackApplicationData(&bsBuffer, appDataChunk, appDataChunkSize);
825             if (eStatus != MOS_STATUS_SUCCESS)
826             {
827                 MOS_SafeFreeMemory(appDataChunk);
828                 ENCODE_CHK_STATUS_RETURN(eStatus);
829             }
830 
831             uint32_t byteSize = (bsBuffer.BufferSize + 7) >> 3;
832             uint32_t dataBitsInLastDw = bsBuffer.BufferSize % 32;
833             if (dataBitsInLastDw == 0)
834             {
835                 dataBitsInLastDw = 32;
836             }
837 
838             params = {};
839             params.dwPadding = ((byteSize + 3) >> 2);
840             params.bitstreamstartresetResetbitstreamstartingpos = 1;
841             //if full header is included in application data, it will be the last insert headers
842             if (m_basicFeature->m_fullHeaderInAppData)
843             {
844                 params.endofsliceflagLastdstdatainsertcommandflag = true;
845                 params.lastheaderflagLastsrcheaderdatainsertcommandflag = true;
846             }
847             else
848             {
849                 params.endofsliceflagLastdstdatainsertcommandflag = false;
850                 params.lastheaderflagLastsrcheaderdatainsertcommandflag = false;
851             }
852             params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
853 
854             m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
855 
856             // Add actual data
857             uint8_t* data = (uint8_t*)(bsBuffer.pBase);
858             eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
859             if (eStatus != MOS_STATUS_SUCCESS)
860             {
861                 MOS_SafeFreeMemory(appDataChunk);
862                 ENCODE_CHK_STATUS_RETURN(eStatus);
863             }
864         }
865 
866         MOS_FreeMemory(appDataChunk);
867 
868         return eStatus;
869     }
870 
AddQuantTable(PMOS_COMMAND_BUFFER cmdBuffer,bool useSingleDefaultQuantTable) const871     MOS_STATUS JpegPkt::AddQuantTable(PMOS_COMMAND_BUFFER cmdBuffer, bool useSingleDefaultQuantTable) const
872     {
873         ENCODE_FUNC_CALL();
874         ENCODE_CHK_NULL_RETURN(cmdBuffer);
875 
876         // Add Quant Table for Y
877         BSBuffer bsBuffer = {};
878         ENCODE_CHK_STATUS_RETURN(m_jpgPkrFeature->PackQuantTable(&bsBuffer, jpegComponentY));
879 
880         uint32_t byteSize = (bsBuffer.BufferSize + 7) >> 3;
881         uint32_t dataBitsInLastDw = bsBuffer.BufferSize % 32;
882         if (dataBitsInLastDw == 0)
883         {
884             dataBitsInLastDw = 32;
885         }
886 
887         auto &params = m_mfxItf->MHW_GETPAR_F(MFX_PAK_INSERT_OBJECT)();
888         params = {};
889         params.dwPadding = ((byteSize + 3) >> 2);
890         params.bitstreamstartresetResetbitstreamstartingpos = 1;
891         params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
892 
893         m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
894 
895         // Add actual data
896         uint8_t* data = (uint8_t*)(bsBuffer.pBase);
897         MOS_STATUS eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
898 
899         MOS_SafeFreeMemory(bsBuffer.pBase);
900 
901         ENCODE_CHK_STATUS_RETURN(eStatus);
902 
903         if (!useSingleDefaultQuantTable)
904         {
905             // Since there is no U and V in monochrome format, donot add Quantization table header for U and V components
906             if (m_jpegPicParams->m_inputSurfaceFormat != codechalJpegY8)
907             {
908                 // Add quant table for U
909                 ENCODE_CHK_STATUS_RETURN(m_jpgPkrFeature->PackQuantTable(&bsBuffer, jpegComponentU));
910 
911                 byteSize = (bsBuffer.BufferSize + 7) >> 3;
912                 dataBitsInLastDw = bsBuffer.BufferSize % 32;
913                 if (dataBitsInLastDw == 0)
914                 {
915                     dataBitsInLastDw = 32;
916                 }
917 
918                 params = {};
919                 params.dwPadding = ((byteSize + 3) >> 2);
920                 params.bitstreamstartresetResetbitstreamstartingpos = 1;
921                 params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
922 
923                 m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
924 
925                 // Add actual data
926                 data = (uint8_t*)(bsBuffer.pBase);
927                 eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
928 
929                 MOS_SafeFreeMemory(bsBuffer.pBase);
930 
931                 ENCODE_CHK_STATUS_RETURN(eStatus);
932 
933                 // Add quant table for V
934                 ENCODE_CHK_STATUS_RETURN(m_jpgPkrFeature->PackQuantTable(&bsBuffer, jpegComponentV));
935 
936                 byteSize = (bsBuffer.BufferSize + 7) >> 3;
937                 dataBitsInLastDw = bsBuffer.BufferSize % 32;
938                 if (dataBitsInLastDw == 0)
939                 {
940                     dataBitsInLastDw = 32;
941                 }
942 
943                 params = {};
944                 params.dwPadding = ((byteSize + 3) >> 2);
945                 params.bitstreamstartresetResetbitstreamstartingpos = 1;
946                 params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
947 
948                 m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
949 
950                 // Add actual data
951                 data = (uint8_t*)(bsBuffer.pBase);
952                 eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
953 
954                 MOS_SafeFreeMemory(bsBuffer.pBase);
955 
956                 ENCODE_CHK_STATUS_RETURN(eStatus);
957             }
958         }
959 
960         return eStatus;
961     }
962 
AddFrameHeader(PMOS_COMMAND_BUFFER cmdBuffer,bool useSingleDefaultQuantTable) const963     MOS_STATUS JpegPkt::AddFrameHeader(PMOS_COMMAND_BUFFER cmdBuffer, bool useSingleDefaultQuantTable) const
964     {
965         ENCODE_FUNC_CALL();
966         ENCODE_CHK_NULL_RETURN(cmdBuffer);
967 
968         BSBuffer bsBuffer = {};
969         ENCODE_CHK_STATUS_RETURN(m_jpgPkrFeature->PackFrameHeader(&bsBuffer, useSingleDefaultQuantTable));
970 
971         uint32_t byteSize = (bsBuffer.BufferSize + 7) >> 3;
972         uint32_t dataBitsInLastDw = bsBuffer.BufferSize % 32;
973         if (dataBitsInLastDw == 0)
974         {
975             dataBitsInLastDw = 32;
976         }
977 
978         auto &params = m_mfxItf->MHW_GETPAR_F(MFX_PAK_INSERT_OBJECT)();
979         params = {};
980         params.dwPadding = ((byteSize + 3) >> 2);
981         params.bitstreamstartresetResetbitstreamstartingpos = 1;
982         params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
983 
984         m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
985 
986         // Add actual data
987         uint8_t* data = (uint8_t*)(bsBuffer.pBase);
988         MOS_STATUS eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
989 
990         MOS_SafeFreeMemory(bsBuffer.pBase);
991 
992         return eStatus;
993     }
994 
AddHuffmanTable(PMOS_COMMAND_BUFFER cmdBuffer,uint32_t tblInd) const995     MOS_STATUS JpegPkt::AddHuffmanTable(PMOS_COMMAND_BUFFER cmdBuffer, uint32_t tblInd) const
996     {
997         ENCODE_FUNC_CALL();
998         ENCODE_CHK_NULL_RETURN(cmdBuffer);
999 
1000         BSBuffer bsBuffer = {};
1001         ENCODE_CHK_STATUS_RETURN(m_jpgPkrFeature->PackHuffmanTable(&bsBuffer, tblInd));
1002 
1003         uint32_t byteSize = (bsBuffer.BufferSize + 7) >> 3;
1004         uint32_t dataBitsInLastDw = bsBuffer.BufferSize % 32;
1005         if (dataBitsInLastDw == 0)
1006         {
1007             dataBitsInLastDw = 32;
1008         }
1009 
1010         auto &params = m_mfxItf->MHW_GETPAR_F(MFX_PAK_INSERT_OBJECT)();
1011         params = {};
1012         params.dwPadding = ((byteSize + 3) >> 2);
1013         params.bitstreamstartresetResetbitstreamstartingpos = 1;
1014         params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
1015 
1016         m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
1017 
1018         // Add actual data
1019         uint8_t* data = (uint8_t*)(bsBuffer.pBase);
1020         MOS_STATUS eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
1021 
1022         MOS_SafeFreeMemory(bsBuffer.pBase);
1023 
1024         return eStatus;
1025     }
1026 
AddRestartInterval(PMOS_COMMAND_BUFFER cmdBuffer) const1027     MOS_STATUS JpegPkt::AddRestartInterval(PMOS_COMMAND_BUFFER cmdBuffer) const
1028     {
1029         ENCODE_FUNC_CALL();
1030         ENCODE_CHK_NULL_RETURN(cmdBuffer);
1031 
1032         BSBuffer bsBuffer = {};
1033         ENCODE_CHK_STATUS_RETURN(m_jpgPkrFeature->PackRestartInterval(&bsBuffer));
1034 
1035         uint32_t byteSize = (bsBuffer.BufferSize + 7) >> 3;
1036         uint32_t dataBitsInLastDw = bsBuffer.BufferSize % 32;
1037         if (dataBitsInLastDw == 0)
1038         {
1039             dataBitsInLastDw = 32;
1040         }
1041 
1042         auto &params = m_mfxItf->MHW_GETPAR_F(MFX_PAK_INSERT_OBJECT)();
1043         params = {};
1044         params.dwPadding = ((byteSize + 3) >> 2);
1045         params.bitstreamstartresetResetbitstreamstartingpos = 1;
1046         params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
1047 
1048         m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
1049 
1050         // Add actual data
1051         uint8_t* data = (uint8_t*)(bsBuffer.pBase);
1052         MOS_STATUS eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
1053 
1054         MOS_SafeFreeMemory(bsBuffer.pBase);
1055 
1056         return eStatus;
1057     }
1058 
AddScanHeader(PMOS_COMMAND_BUFFER cmdBuffer) const1059     MOS_STATUS JpegPkt::AddScanHeader(PMOS_COMMAND_BUFFER cmdBuffer) const
1060     {
1061         ENCODE_FUNC_CALL();
1062         ENCODE_CHK_NULL_RETURN(cmdBuffer);
1063 
1064         BSBuffer bsBuffer = {};
1065         ENCODE_CHK_STATUS_RETURN(m_jpgPkrFeature->PackScanHeader(&bsBuffer));
1066 
1067         uint32_t byteSize = (bsBuffer.BufferSize + 7) >> 3;
1068         uint32_t dataBitsInLastDw = bsBuffer.BufferSize % 32;
1069         if (dataBitsInLastDw == 0)
1070         {
1071             dataBitsInLastDw = 32;
1072         }
1073 
1074         auto &params = m_mfxItf->MHW_GETPAR_F(MFX_PAK_INSERT_OBJECT)();
1075         params = {};
1076         params.dwPadding = ((byteSize + 3) >> 2);
1077         params.bitstreamstartresetResetbitstreamstartingpos = 1;
1078         params.endofsliceflagLastdstdatainsertcommandflag = true;
1079         params.lastheaderflagLastsrcheaderdatainsertcommandflag = true;
1080         params.databitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
1081 
1082         m_mfxItf->MHW_ADDCMD_F(MFX_PAK_INSERT_OBJECT)(cmdBuffer);
1083 
1084         // Add actual data
1085         uint8_t* data = (uint8_t*)(bsBuffer.pBase);
1086         MOS_STATUS eStatus = Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize);
1087 
1088         MOS_SafeFreeMemory(bsBuffer.pBase);
1089 
1090         return eStatus;
1091     }
1092 
1093     // Implemented based on table K.5 in JPEG spec
MapHuffValIndex(uint8_t huffValIndex)1094     uint8_t JpegPkt::MapHuffValIndex(uint8_t huffValIndex)
1095     {
1096         ENCODE_FUNC_CALL();
1097 
1098         uint8_t mappedIndex = 0;
1099 
1100         if (huffValIndex < 0xF0)
1101         {
1102             mappedIndex = (((huffValIndex >> 4) & 0x0F) * 0xA) + (huffValIndex & 0x0F);
1103         }
1104         else
1105         {
1106             mappedIndex = (((huffValIndex >> 4) & 0x0F) * 0xA) + (huffValIndex & 0x0F) + 1;
1107         }
1108 
1109         return mappedIndex;
1110     }
1111 
1112     // Implemented based on Flowchart in figure C.1 in JPEG spec
GenerateSizeTable(uint8_t bits[],uint8_t huffSize[],uint8_t & lastK)1113     MOS_STATUS JpegPkt::GenerateSizeTable(
1114         uint8_t  bits[],
1115         uint8_t  huffSize[],
1116         uint8_t &lastK)
1117     {
1118         ENCODE_FUNC_CALL();
1119 
1120         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1121 
1122         uint8_t i = 1, j = 1;
1123         uint8_t k = 0;
1124         while (i <= 16)
1125         {
1126             while (j <= (int8_t)bits[i - 1])  // bits index is from 0 to 15
1127             {
1128                 huffSize[k] = i;
1129                 k           = k + 1;
1130                 j           = j + 1;
1131             }
1132 
1133             i++;
1134             j = 1;
1135         }
1136 
1137         huffSize[k] = 0;
1138         lastK       = k;
1139 
1140         return eStatus;
1141     }
1142 
1143     // Implemented based on Flowchart in figure C.2 in JPEG spec
GenerateCodeTable(uint8_t huffSize[],uint16_t huffCode[])1144     MOS_STATUS JpegPkt::GenerateCodeTable(
1145         uint8_t  huffSize[],
1146         uint16_t huffCode[])
1147     {
1148         ENCODE_FUNC_CALL();
1149 
1150         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1151 
1152         uint8_t  k    = 0;
1153         uint8_t  si   = huffSize[0];
1154         uint16_t code = 0;
1155         while (huffSize[k] != 0)
1156         {
1157             while (huffSize[k] == si)
1158             {
1159                 if (code == 0xFFFF)
1160                 {
1161                     // Invalid code generated - replace with all zeroes
1162                     code = 0x0000;
1163                 }
1164 
1165                 huffCode[k] = code;
1166                 code        = code + 1;
1167                 k           = k + 1;
1168             }
1169 
1170             code <<= 1;
1171             si = si + 1;
1172         }
1173 
1174         return eStatus;
1175     }
1176 
1177     // Implemented based on Flowchart in figure C.3 in JPEG spec
OrderCodes(uint8_t huffVal[],uint8_t huffSize[],uint16_t huffCode[],uint8_t lastK)1178     MOS_STATUS JpegPkt::OrderCodes(
1179         uint8_t  huffVal[],
1180         uint8_t  huffSize[],
1181         uint16_t huffCode[],
1182         uint8_t  lastK)
1183     {
1184         ENCODE_FUNC_CALL();
1185 
1186         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1187 
1188         uint16_t eHuffCo[JPEG_NUM_HUFF_TABLE_AC_HUFFVAL];
1189         uint8_t  eHuffSi[JPEG_NUM_HUFF_TABLE_AC_HUFFVAL];
1190         MOS_ZeroMemory(&eHuffCo[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t));
1191         MOS_ZeroMemory(&eHuffSi[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t));
1192 
1193         uint8_t k = 0;
1194         do
1195         {
1196             uint8_t i = MapHuffValIndex((uint8_t)huffVal[k]);
1197             if (i >= JPEG_NUM_HUFF_TABLE_AC_HUFFVAL)
1198             {
1199                 ENCODE_ASSERT(false);
1200                 return MOS_STATUS_UNKNOWN;
1201             }
1202             eHuffCo[i] = huffCode[k];
1203             eHuffSi[i] = huffSize[k];
1204             k++;
1205         } while (k < lastK);
1206 
1207         // copy over the first 162 values of reordered arrays to Huffman Code and size arrays
1208         ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(&huffCode[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t), &eHuffCo[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t)));
1209         ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(&huffSize[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t), &eHuffSi[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t)));
1210 
1211         return eStatus;
1212     }
1213 
ConvertHuffDataToTable(CodecEncodeJpegHuffData huffmanData,EncodeJpegHuffTable * huffmanTable)1214     MOS_STATUS JpegPkt::ConvertHuffDataToTable(
1215         CodecEncodeJpegHuffData      huffmanData,
1216         EncodeJpegHuffTable *   huffmanTable)
1217     {
1218         ENCODE_FUNC_CALL();
1219 
1220         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1221 
1222         huffmanTable->m_tableClass = huffmanData.m_tableClass;
1223         huffmanTable->m_tableID    = huffmanData.m_tableID;
1224 
1225         uint8_t lastK = 0;
1226 
1227         // Step 1 : Generate size table
1228         ENCODE_CHK_STATUS_RETURN(GenerateSizeTable(huffmanData.m_bits, huffmanTable->m_huffSize, lastK));
1229 
1230         // Step2: Generate code table
1231         ENCODE_CHK_STATUS_RETURN(GenerateCodeTable(huffmanTable->m_huffSize, huffmanTable->m_huffCode));
1232 
1233         // Step 3: Order codes
1234         ENCODE_CHK_STATUS_RETURN(OrderCodes(huffmanData.m_huffVal, huffmanTable->m_huffSize, huffmanTable->m_huffCode, lastK));
1235 
1236         return eStatus;
1237     }
1238 
CalculateCommandBufferSize()1239     uint32_t JpegPkt::CalculateCommandBufferSize()
1240     {
1241         ENCODE_FUNC_CALL();
1242         uint32_t commandBufferSize =
1243             m_pictureStatesSize        +
1244             (m_sliceStatesSize * m_basicFeature->m_numSlices);
1245 
1246         // For JPEG encoder, add the size of PAK_INSERT_OBJ commands which is also part of command buffer
1247         if (m_basicFeature->m_standard == CODECHAL_JPEG)
1248         {
1249             // Add PAK_INSERT_OBJ for app data
1250             // PAK_INSERT_OBJ contains 2 DWORDS + bytes of payload data
1251             // There is a max of 1024 payload bytes of app data per PAK_INSERT_OBJ command, so adding 2 DWORDS for each of them
1252             // Total payload data is the same size as app data
1253             commandBufferSize += (m_basicFeature->m_appDataSize + (2 * sizeof(uint32_t) * (m_basicFeature->m_appDataSize / 1020 + 1)));  //to be consistent with how we split app data into chunks.
1254 
1255             // Add number of bytes of data added through PAK_INSERT_OBJ command
1256             commandBufferSize += (2 + // SOI = 2 bytes
1257                     // Frame header - add sizes of each component of CodechalEncodeJpegFrameHeader
1258                     (2 * sizeof(uint8_t)) + (4 * sizeof(uint16_t)) + 3 * sizeof(uint8_t)*  jpegNumComponent +
1259                     // AC and DC Huffman tables - 2 Huffman tables for each component, and 3 components
1260                     (2 * 3 * sizeof(EncodeJpegHuffmanHeader)) +
1261                     // Quant tables - 1 for Quant table of each component, so 3 quant tables per frame
1262                     (3 * sizeof(EncodeJpegQuantHeader)) +
1263                     // Restart interval - 1 per frame
1264                     sizeof(EncodeJpegRestartHeader) +
1265                     // Scan header - 1 per frame
1266                     sizeof(EncodeJpegScanHeader));
1267         }
1268 
1269         if (m_pipeline->IsSingleTaskPhaseSupported())
1270         {
1271             commandBufferSize *= (m_pipeline->GetPassNum() + 1);
1272         }
1273 
1274         // 4K align since allocation is in chunks of 4K bytes.
1275         commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, 0x1000);
1276 
1277         return commandBufferSize;
1278     }
1279 
CalculatePatchListSize()1280     uint32_t JpegPkt::CalculatePatchListSize()
1281     {
1282         ENCODE_FUNC_CALL();
1283         uint32_t requestedPatchListSize = 0;
1284         if (m_usePatchList)
1285         {
1286             requestedPatchListSize =
1287                 m_picturePatchListSize +
1288                 (m_slicePatchListSize * m_basicFeature->m_numSlices);
1289 
1290             if (m_pipeline->IsSingleTaskPhaseSupported())
1291             {
1292                 requestedPatchListSize *= m_pipeline->GetPassNum();
1293             }
1294         }
1295         return requestedPatchListSize;
1296     }
1297 
AddAllCmds_MFX_FQM_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const1298     MOS_STATUS JpegPkt::AddAllCmds_MFX_FQM_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const
1299     {
1300         ENCODE_FUNC_CALL();
1301         ENCODE_CHK_NULL_RETURN(cmdBuffer);
1302 
1303         auto &params = m_mfxItf->MHW_GETPAR_F(MFX_FQM_STATE)();
1304 
1305         for (uint8_t i = 0; i < m_numQuantTables; i++)
1306         {
1307             params = {};
1308             params.qmType = i;
1309 
1310             auto j = 0;
1311             // Copy over 32 uint32_t worth of values - Each uint32_t will contain 2 16 bit quantizer values
1312             // where for the DWordx Bits [15: 0] = 1/QM[0][x] Bits[32:16] = 1/QM[1][x]
1313             for (auto k = 0; k < 8; k++)
1314             {
1315                 for (auto l = k; l < 64; l += 16)
1316                 {
1317                     params.quantizermatrix[j] = ((GetReciprocalScalingValue(m_jpegQuantMatrix.m_quantMatrix[i][l + 8]) << 16) |
1318                                                   GetReciprocalScalingValue(m_jpegQuantMatrix.m_quantMatrix[i][l]));
1319                     j++;
1320                 }
1321             }
1322 
1323             m_mfxItf->MHW_ADDCMD_F(MFX_FQM_STATE)(cmdBuffer);
1324         }
1325 
1326         return MOS_STATUS_SUCCESS;
1327     }
1328 
AddAllCmds_MFC_JPEG_HUFF_TABLE_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const1329     MOS_STATUS JpegPkt::AddAllCmds_MFC_JPEG_HUFF_TABLE_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const
1330     {
1331         ENCODE_FUNC_CALL();
1332         ENCODE_CHK_NULL_RETURN(cmdBuffer);
1333 
1334         auto &params = m_mfxItf->MHW_GETPAR_F(MFC_JPEG_HUFF_TABLE_STATE)();
1335 
1336         // the number of huffman commands is half of the huffman buffers sent by the app, since AC and DC buffers are combined into one command
1337         for (uint32_t i = 0; i < m_numHuffBuffers / 2; i++)
1338         {
1339             params = {};
1340             params.huffTableId = (uint8_t)m_huffTableParams[i].HuffTableID;
1341 
1342             // cmd DWORDS 2:13 for DC Table
1343             // Format- 3Bytes: Byte0 for Code length, Byte1 and Byte2 for Code word, and Byte3 for dummy
1344             for (auto j = 0; j < JPEG_NUM_HUFF_TABLE_DC_HUFFVAL; j++)
1345             {
1346                 params.dcTable[j] = 0;
1347                 params.dcTable[j] = (m_huffTableParams[i].pDCCodeLength[j] & 0xFF) |
1348                                     ((m_huffTableParams[i].pDCCodeValues[j] & 0xFFFF) << 8);
1349             }
1350 
1351             // cmd DWORDS 14:175 for AC table
1352             // Format- 3Bytes: Byte0 for Code length, Byte1 and Byte2 for Code word, and Byte3 for dummy
1353             for (auto j = 0; j < JPEG_NUM_HUFF_TABLE_AC_HUFFVAL; j++)
1354             {
1355                 params.acTable[j] = 0;
1356                 params.acTable[j] = (m_huffTableParams[i].pACCodeLength[j] & 0xFF) |
1357                                     ((m_huffTableParams[i].pACCodeValues[j] & 0xFFFF) << 8);
1358             }
1359 
1360             if (m_repeatHuffTable)
1361             {
1362                 m_mfxItf->MHW_ADDCMD_F(MFC_JPEG_HUFF_TABLE_STATE)(cmdBuffer);
1363             }
1364             m_mfxItf->MHW_ADDCMD_F(MFC_JPEG_HUFF_TABLE_STATE)(cmdBuffer);
1365         }
1366 
1367         return MOS_STATUS_SUCCESS;
1368     }
1369 
AddAllCmds_MFX_PAK_INSERT_OBJECT(PMOS_COMMAND_BUFFER cmdBuffer) const1370     MOS_STATUS JpegPkt::AddAllCmds_MFX_PAK_INSERT_OBJECT(PMOS_COMMAND_BUFFER cmdBuffer) const
1371     {
1372         ENCODE_FUNC_CALL();
1373         ENCODE_CHK_NULL_RETURN(cmdBuffer);
1374 
1375         MOS_SURFACE *surface = m_basicFeature->m_rawSurfaceToPak;
1376         bool useSingleDefaultQuantTable = (m_basicFeature->m_jpegQuantMatrixSent == false &&
1377                                            ((surface->Format == Format_A8R8G8B8) ||
1378                                             (surface->Format == Format_X8R8G8B8) ||
1379                                             (surface->Format == Format_A8B8G8R8) ||
1380                                             (surface->Format == Format_X8B8G8R8)));
1381 
1382         if (!m_basicFeature->m_fullHeaderInAppData)
1383         {
1384             // Add SOI (0xFFD8) (only if it was sent by the application)
1385             ENCODE_CHK_STATUS_RETURN(AddSOI(cmdBuffer));
1386         }
1387         // Add Application data if it was sent by application
1388         if (m_applicationData != nullptr)
1389         {
1390             ENCODE_CHK_STATUS_RETURN(AddApplicationData(cmdBuffer));
1391         }
1392         if (!m_basicFeature->m_fullHeaderInAppData)
1393         {
1394             ENCODE_CHK_STATUS_RETURN(AddQuantTable(cmdBuffer, useSingleDefaultQuantTable));
1395 
1396             ENCODE_CHK_STATUS_RETURN(AddFrameHeader(cmdBuffer, useSingleDefaultQuantTable));
1397 
1398             // Add Huffman Table for Y - DC table, Y- AC table, U/V - DC table, U/V - AC table
1399             for (uint32_t i = 0; i < m_numHuffBuffers; i++)
1400             {
1401                 ENCODE_CHK_STATUS_RETURN(AddHuffmanTable(cmdBuffer, i));
1402             }
1403 
1404             // Restart Interval - Add only if the restart interval is not zero
1405             if (m_jpegScanParams->m_restartInterval != 0)
1406             {
1407                 ENCODE_CHK_STATUS_RETURN(AddRestartInterval(cmdBuffer));
1408             }
1409 
1410             ENCODE_CHK_STATUS_RETURN(AddScanHeader(cmdBuffer));
1411         }
1412 
1413         return MOS_STATUS_SUCCESS;
1414     }
1415 
MHW_SETPAR_DECL_SRC(MI_STORE_REGISTER_MEM,JpegPkt)1416     MHW_SETPAR_DECL_SRC(MI_STORE_REGISTER_MEM, JpegPkt)
1417     {
1418         params.presStoreBuffer = m_pResource;
1419         params.dwOffset        = m_dwOffset;
1420         params.dwRegister      = m_dwValue;
1421 
1422         return MOS_STATUS_SUCCESS;
1423     }
1424 
1425 #if USE_CODECHAL_DEBUG_TOOL
DumpResources(EncodeStatusMfx * encodeStatusMfx,EncodeStatusReportData * statusReportData)1426     MOS_STATUS JpegPkt::DumpResources(
1427         EncodeStatusMfx *       encodeStatusMfx,
1428         EncodeStatusReportData *statusReportData)
1429     {
1430         ENCODE_FUNC_CALL();
1431 
1432         ENCODE_CHK_NULL_RETURN(encodeStatusMfx);
1433         ENCODE_CHK_NULL_RETURN(statusReportData);
1434         ENCODE_CHK_NULL_RETURN(m_pipeline);
1435         ENCODE_CHK_NULL_RETURN(m_statusReport);
1436         ENCODE_CHK_NULL_RETURN(m_basicFeature);
1437         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_trackedBuf);
1438 
1439         if (m_jpegPicParams)
1440         {
1441             ENCODE_CHK_STATUS_RETURN(DumpPicParams(
1442                 m_jpegPicParams));
1443         }
1444 
1445         if (m_jpegScanParams)
1446         {
1447             ENCODE_CHK_STATUS_RETURN(DumpScanParams(
1448                 m_jpegScanParams));
1449         }
1450 
1451         if (m_jpegHuffmanTable)
1452         {
1453             ENCODE_CHK_STATUS_RETURN(DumpHuffmanTable(
1454                 m_jpegHuffmanTable));
1455         }
1456 
1457         if (m_jpegQuantTables)
1458         {
1459             ENCODE_CHK_STATUS_RETURN(DumpQuantTables(
1460                 m_jpegQuantTables));
1461         }
1462 
1463         CodechalDebugInterface *debugInterface = m_pipeline->GetStatusReportDebugInterface();
1464         ENCODE_CHK_NULL_RETURN(debugInterface);
1465 
1466         CODEC_REF_LIST currRefList = *((CODEC_REF_LIST *)statusReportData->currRefList);
1467         currRefList.RefPic         = statusReportData->currOriginalPic;
1468 
1469         debugInterface->m_currPic            = statusReportData->currOriginalPic;
1470         debugInterface->m_bufferDumpFrameNum = m_statusReport->GetReportedCount() + 1;  // ToDo: for debug purpose
1471         debugInterface->m_frameType          = encodeStatusMfx->pictureCodingType;
1472 
1473         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
1474             &currRefList.resBitstreamBuffer,
1475             CodechalDbgAttr::attrBitstream,
1476             "_PAK",
1477             statusReportData->bitstreamSize,
1478             0,
1479             CODECHAL_NUM_MEDIA_STATES));
1480 
1481         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpData(
1482             statusReportData,
1483             sizeof(EncodeStatusReportData),
1484             CodechalDbgAttr::attrStatusReport,
1485             "EncodeStatusReport_Buffer"));
1486 
1487         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpYUVSurface(
1488             &currRefList.sRefRawBuffer,
1489             CodechalDbgAttr::attrEncodeRawInputSurface,
1490             "SrcSurf"))
1491 
1492         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpEncodeStatusReport(
1493             statusReportData));
1494 
1495         return MOS_STATUS_SUCCESS;
1496     }
1497 
DumpHuffmanTable(CodecEncodeJpegHuffmanDataArray * huffmanTable)1498     MOS_STATUS JpegPkt::DumpHuffmanTable(
1499         CodecEncodeJpegHuffmanDataArray *huffmanTable)
1500     {
1501         ENCODE_FUNC_CALL();
1502 
1503         if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrHuffmanTbl))
1504         {
1505             return MOS_STATUS_SUCCESS;
1506         }
1507 
1508         ENCODE_CHK_NULL_RETURN(huffmanTable);
1509 
1510         std::ostringstream oss;
1511         oss.setf(std::ios::showbase | std::ios::uppercase);
1512 
1513         //Dump HuffTable[JPEG_MAX_NUM_HUFF_TABLE_INDEX]
1514         for (uint32_t i = 0; i < JPEG_NUM_ENCODE_HUFF_BUFF; ++i)
1515         {
1516             // Dump Table Class
1517             oss << "TableClass: " << +huffmanTable->m_huffmanData[i].m_tableClass << std::endl;
1518             // Dump Table ID
1519             oss << "TableID: " << +huffmanTable->m_huffmanData[i].m_tableID << std::endl;
1520             //Dump ucBits[JPEG_NUM_HUFF_TABLE_AC_BITS]
1521             oss << "HuffTable[" << +i << "].ucBits[0-" << (JPEG_NUM_HUFF_TABLE_AC_BITS - 1) << "]: " << std::endl;
1522 
1523             for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_AC_BITS; ++j)
1524             {
1525                 oss << +huffmanTable->m_huffmanData[i].m_bits[j];
1526                 if (j % 6 == 5 || j == JPEG_NUM_HUFF_TABLE_AC_BITS - 1)
1527                 {
1528                     oss << std::endl;
1529                 }
1530             }
1531 
1532             //Dump ucHuffVal[JPEG_NUM_HUFF_TABLE_AC_HUFFVAL]
1533             oss << "HuffTable[" << +i << "].ucHuffVal[0-" << (JPEG_NUM_HUFF_TABLE_AC_HUFFVAL - 1) << "]: " << std::endl;
1534 
1535             for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_AC_HUFFVAL; ++j)
1536             {
1537                 oss << +huffmanTable->m_huffmanData[i].m_huffVal[j];
1538                 if (j % 6 == 5 || j == JPEG_NUM_HUFF_TABLE_AC_HUFFVAL - 1)
1539                 {
1540                     oss << std::endl;
1541                 }
1542             }
1543         }
1544 
1545         const char *fileName = m_debugInterface->CreateFileName(
1546             "_ENC",
1547             CodechalDbgBufferType::bufHuffmanTbl,
1548             CodechalDbgExtType::txt);
1549 
1550         std::ofstream ofs(fileName, std::ios::out);
1551         ofs << oss.str();
1552         ofs.close();
1553         return MOS_STATUS_SUCCESS;
1554     }
1555 
DumpPicParams(CodecEncodeJpegPictureParams * picParams)1556     MOS_STATUS JpegPkt::DumpPicParams(
1557         CodecEncodeJpegPictureParams *picParams)
1558     {
1559         ENCODE_FUNC_CALL();
1560         if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
1561         {
1562             return MOS_STATUS_SUCCESS;
1563         }
1564 
1565         ENCODE_CHK_NULL_RETURN(picParams);
1566 
1567         std::ostringstream oss;
1568         oss.setf(std::ios::showbase | std::ios::uppercase);
1569 
1570         oss << "Profile: " << +picParams->m_profile << std::endl;
1571         oss << "Progressive: " << +picParams->m_progressive << std::endl;
1572         oss << "Huffman: " << +picParams->m_huffman << std::endl;
1573         oss << "Interleaved: " << +picParams->m_interleaved << std::endl;
1574         oss << "Differential: " << +picParams->m_differential << std::endl;
1575         oss << "PicWidth: " << +picParams->m_picWidth << std::endl;
1576         oss << "PicHeight: " << +picParams->m_picHeight << std::endl;
1577         oss << "InputSurfaceFormat: " << +picParams->m_inputSurfaceFormat << std::endl;
1578         oss << "SampleBitDepth: " << +picParams->m_sampleBitDepth << std::endl;
1579         oss << "uiNumComponent: " << +picParams->m_numComponent << std::endl;
1580 
1581         //Dump componentIdentifier[jpegNumComponent]
1582         for (uint32_t i = 0; i < jpegNumComponent; ++i)
1583         {
1584             oss << "ComponentIdentifier[" << +i << "]: " << +picParams->m_componentID[i] << std::endl;
1585         }
1586 
1587         //Dump quantTableSelector[jpegNumComponent]
1588         for (uint32_t i = 0; i < jpegNumComponent; ++i)
1589         {
1590             oss << "QuantTableSelector[" << +i << "]: " << +picParams->m_quantTableSelector[i] << std::endl;
1591         }
1592         oss << "Quality: " << +picParams->m_quality << std::endl;
1593         oss << "NumScan: " << +picParams->m_numScan << std::endl;
1594         oss << "NumQuantTable: " << +picParams->m_numQuantTable << std::endl;
1595         oss << "NumCodingTable: " << +picParams->m_numCodingTable << std::endl;
1596         oss << "StatusReportFeedbackNumber: " << +picParams->m_statusReportFeedbackNumber << std::endl;
1597 
1598         const char *fileName = m_debugInterface->CreateFileName(
1599             "_ENC",
1600             CodechalDbgBufferType::bufPicParams,
1601             CodechalDbgExtType::txt);
1602 
1603         std::ofstream ofs(fileName, std::ios::out);
1604         ofs << oss.str();
1605         ofs.close();
1606         return MOS_STATUS_SUCCESS;
1607     }
1608 
DumpScanParams(CodecEncodeJpegScanHeader * scanParams)1609     MOS_STATUS JpegPkt::DumpScanParams(
1610         CodecEncodeJpegScanHeader *scanParams)
1611     {
1612         ENCODE_FUNC_CALL();
1613 
1614         if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrScanParams))
1615         {
1616             return MOS_STATUS_SUCCESS;
1617         }
1618 
1619         ENCODE_CHK_NULL_RETURN(scanParams);
1620 
1621         std::ostringstream oss;
1622         oss.setf(std::ios::showbase | std::ios::uppercase);
1623 
1624         oss << "RestartInterval: " << +scanParams->m_restartInterval << std::endl;
1625         oss << "NumComponents: " << +scanParams->m_numComponent << std::endl;
1626 
1627         //Dump ComponentSelector[jpegNumComponent]
1628         for (uint32_t i = 0; i < jpegNumComponent; ++i)
1629         {
1630             oss << "ComponentSelector[" << +i << "]: " << +scanParams->m_componentSelector[i] << std::endl;
1631         }
1632 
1633         //Dump DcHuffTblSelector[jpegNumComponent]
1634         for (uint32_t i = 0; i < jpegNumComponent; ++i)
1635         {
1636             oss << "DcHuffTblSelector[" << +i << "]: " << +scanParams->m_dcCodingTblSelector[i] << std::endl;
1637         }
1638 
1639         //Dump AcHuffTblSelector[jpegNumComponent]
1640         for (uint32_t i = 0; i < jpegNumComponent; ++i)
1641         {
1642             oss << "AcHuffTblSelector[" << +i << "]: " << +scanParams->m_acCodingTblSelector[i] << std::endl;
1643         }
1644 
1645         const char *fileName = m_debugInterface->CreateFileName(
1646             "_ENC",
1647             CodechalDbgBufferType::bufScanParams,
1648             CodechalDbgExtType::txt);
1649 
1650         std::ofstream ofs(fileName, std::ios::out);
1651         ofs << oss.str();
1652         ofs.close();
1653 
1654         return MOS_STATUS_SUCCESS;
1655     }
1656 
DumpQuantTables(CodecEncodeJpegQuantTable * quantTable)1657     MOS_STATUS JpegPkt::DumpQuantTables(
1658         CodecEncodeJpegQuantTable *quantTable)
1659     {
1660         ENCODE_FUNC_CALL();
1661 
1662         if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrIqParams))
1663         {
1664             return MOS_STATUS_SUCCESS;
1665         }
1666 
1667         ENCODE_CHK_NULL_RETURN(quantTable);
1668 
1669         std::ostringstream oss;
1670         oss.setf(std::ios::showbase | std::ios::uppercase);
1671 
1672         //Dump quantTable[JPEG_MAX_NUM_QUANT_TABLE_INDEX]
1673         for (uint32_t i = 0; i < JPEG_MAX_NUM_QUANT_TABLE_INDEX; ++i)
1674         {
1675             // Dump Table ID
1676             oss << "TableID: " << +quantTable->m_quantTable[i].m_tableID << std::endl;
1677             // Dump Precision
1678             oss << "TableID: " << +quantTable->m_quantTable[i].m_precision << std::endl;
1679             //Dump usQm[JPEG_NUM_QUANTMATRIX];
1680             oss << "quantTable[" << +i << "].usQm[0-" << (JPEG_NUM_QUANTMATRIX - 1) << "]: " << std::endl;
1681 
1682             for (uint32_t j = 0; j < JPEG_NUM_QUANTMATRIX; ++j)
1683             {
1684                 oss << +quantTable->m_quantTable[i].m_qm[j];
1685                 if (j % 6 == 5 || j == JPEG_NUM_QUANTMATRIX - 1)
1686                 {
1687                     oss << std::endl;
1688                 }
1689             }
1690         }
1691         const char *fileName = m_debugInterface->CreateFileName(
1692             "_ENC",
1693             CodechalDbgBufferType::bufIqParams,
1694             CodechalDbgExtType::txt);
1695 
1696         std::ofstream ofs(fileName, std::ios::out);
1697         ofs << oss.str();
1698         ofs.close();
1699 
1700         return MOS_STATUS_SUCCESS;
1701     }
1702 #endif
1703 
1704 }
1705