| /* |
| * Copyright (c) 2011-2020, Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| * OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| //! |
| //! \file codechal_decode_jpeg.cpp |
| //! \brief Implements the decode interface extension for JPEG. |
| //! \details Implements all functions required by CodecHal for JPEG decoding. |
| //! |
| |
| #include "codechal_decode_jpeg.h" |
| #include "codechal_mmc_decode_jpeg.h" |
| #include "hal_oca_interface.h" |
| #if USE_CODECHAL_DEBUG_TOOL |
| #include <sstream> |
| #include "codechal_debug.h" |
| #endif |
| |
| #define CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE 8 |
| #define CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2 16 |
| #define CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X4 32 |
| #define CODECHAL_DECODE_JPEG_ERR_FRAME_WIDTH 32 |
| #define CODECHAL_DECODE_JPEG_ERR_FRAME_HEIGHT 32 |
| |
| CodechalDecodeJpeg::~CodechalDecodeJpeg() |
| { |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectWaContextInUse); |
| m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectVideoContextInUse); |
| |
| if (!Mos_ResourceIsNull(&m_resCopiedDataBuffer)) |
| { |
| m_osInterface->pfnFreeResource( |
| m_osInterface, |
| &m_resCopiedDataBuffer); |
| } |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| if (m_sfcState) |
| { |
| MOS_Delete(m_sfcState); |
| m_sfcState = nullptr; |
| } |
| #endif |
| |
| return; |
| } |
| |
| CodechalDecodeJpeg::CodechalDecodeJpeg( |
| CodechalHwInterface * hwInterface, |
| CodechalDebugInterface *debugInterface, |
| PCODECHAL_STANDARD_INFO standardInfo) : CodechalDecode(hwInterface, debugInterface, standardInfo), |
| m_dataSize(0), |
| m_dataOffset(0), |
| m_copiedDataBufferSize(0), |
| m_nextCopiedDataOffset(0), |
| m_totalDataLength(0), |
| m_preNumScans(0), |
| m_copiedDataBufferInUse(false) |
| |
| { |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| MOS_ZeroMemory(&m_resCopiedDataBuffer, sizeof(m_resCopiedDataBuffer)); |
| MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface)); |
| MOS_ZeroMemory(&m_jpegHuffmanTable, sizeof(m_jpegHuffmanTable)); |
| MOS_ZeroMemory(&m_resDataBuffer, sizeof(m_resDataBuffer)); |
| MOS_ZeroMemory(&m_resSyncObjectWaContextInUse, sizeof(m_resSyncObjectWaContextInUse)); |
| MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(m_resSyncObjectVideoContextInUse)); |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::InitializeBeginFrame() |
| { |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| m_incompletePicture = false; |
| m_incompleteJpegScan = false; |
| m_copiedDataBufferInUse = false; |
| m_nextCopiedDataOffset = 0; |
| m_totalDataLength = 0; |
| m_preNumScans = 0; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::CopyDataSurface() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| if (m_hwInterface->m_noHuC) |
| { |
| uint32_t alignedSize = MOS_ALIGN_CEIL(m_dataSize, 16); // 16 byte aligned |
| CodechalDataCopyParams dataCopyParams; |
| MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); |
| dataCopyParams.srcResource = &m_resDataBuffer; |
| dataCopyParams.srcSize = alignedSize; |
| dataCopyParams.srcOffset = 0; |
| dataCopyParams.dstResource = &m_resCopiedDataBuffer; |
| dataCopyParams.dstSize = alignedSize; |
| dataCopyParams.dstOffset = m_nextCopiedDataOffset; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv( |
| &dataCopyParams)); |
| |
| m_nextCopiedDataOffset += MOS_ALIGN_CEIL(m_dataSize, MHW_CACHELINE_SIZE); // 64-byte aligned |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DECODE_CHK_COND_RETURN( |
| ((m_nextCopiedDataOffset + m_dataSize) > m_copiedDataBufferSize), |
| "Copied data buffer is not large enough."); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext( |
| m_osInterface, |
| m_videoContextForWa)); |
| m_osInterface->pfnResetOsStates(m_osInterface); |
| |
| m_osInterface->pfnSetPerfTag( |
| m_osInterface, |
| (uint16_t)(((m_mode << 4) & 0xF0) | COPY_TYPE)); |
| m_osInterface->pfnResetPerfBufferID(m_osInterface); |
| |
| MOS_COMMAND_BUFFER cmdBuffer; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| 0)); |
| |
| // Send command buffer header at the beginning (OS dependent) |
| CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking( |
| &cmdBuffer, |
| false)); |
| |
| // Use huc stream out to do the copy |
| CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( |
| &cmdBuffer, // pCmdBuffer |
| &m_resDataBuffer, // presSrc |
| &m_resCopiedDataBuffer, // presDst |
| m_dataSize, // u32CopyLength |
| 0, // u32CopyInputOffset |
| m_nextCopiedDataOffset)); // u32CopyOutputOffset |
| |
| m_nextCopiedDataOffset += MOS_ALIGN_CEIL(m_dataSize, MHW_CACHELINE_SIZE); |
| |
| MHW_MI_FLUSH_DW_PARAMS flushDwParams; |
| MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( |
| &cmdBuffer, |
| &flushDwParams)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( |
| &cmdBuffer, |
| nullptr)); |
| |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| |
| if (!m_incompletePicture) |
| { |
| MOS_SYNC_PARAMS syncParams; |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal( |
| m_osInterface, |
| &syncParams)); |
| |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContextForWa; |
| syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait( |
| m_osInterface, |
| &syncParams)); |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| m_videoContextForWaUsesNullHw)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext( |
| m_osInterface, |
| m_videoContext)); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::CheckAndCopyIncompleteBitStream() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| uint32_t maxBufferSize = |
| MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth * m_jpegPicParams->m_frameHeight * 3, 64); |
| |
| if (m_jpegPicParams->m_totalScans == 1) // Single scan |
| { |
| if (!m_incompleteJpegScan) // The first bitstream buffer |
| { |
| m_totalDataLength = |
| m_jpegScanParams->ScanHeader[0].DataOffset + m_jpegScanParams->ScanHeader[0].DataLength; |
| |
| if (m_dataSize < m_totalDataLength) // if the bitstream data is incomplete |
| { |
| CODECHAL_DECODE_CHK_COND_RETURN( |
| m_totalDataLength > maxBufferSize, |
| "The bitstream size exceeds the copied data buffer size."); |
| |
| CODECHAL_DECODE_CHK_COND_RETURN( |
| m_dataSize & 0x3f, |
| "The data size of the incomplete bitstream is not aligned with 64."); |
| |
| // Allocate the copy data buffer. |
| if (Mos_ResourceIsNull(&m_resCopiedDataBuffer)) |
| { |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( |
| &m_resCopiedDataBuffer, |
| maxBufferSize, |
| "CopiedDataBuffer"), |
| "Failed to allocate copied data Buffer."); |
| } |
| m_copiedDataBufferSize = maxBufferSize; |
| |
| // copy the bitstream buffer |
| if (m_dataSize) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface()); |
| m_copiedDataBufferInUse = true; |
| } |
| |
| m_incompleteJpegScan = true; |
| m_incompletePicture = true; |
| } |
| else //the bitstream data is complete |
| { |
| m_incompleteJpegScan = false; |
| m_incompletePicture = false; |
| } |
| } |
| else // the next bitstream buffers |
| { |
| CODECHAL_DECODE_CHK_COND_RETURN( |
| m_nextCopiedDataOffset + m_dataSize > m_copiedDataBufferSize, |
| "The bitstream size exceeds the copied data buffer size.") |
| |
| CODECHAL_DECODE_CHK_COND_RETURN( |
| (m_nextCopiedDataOffset + m_dataSize < m_totalDataLength) && (m_dataSize & 0x3f), |
| "The data size of the incomplete bitstream is not aligned with 64."); |
| |
| // copy the bitstream |
| if (m_dataSize) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface()); |
| } |
| |
| if (m_nextCopiedDataOffset >= m_totalDataLength) |
| { |
| m_incompleteJpegScan = false; |
| m_incompletePicture = false; |
| } |
| |
| } |
| } |
| else // multi-scans |
| { |
| if (!m_incompleteJpegScan) // The first bitstream buffer of each scan; |
| { |
| for (uint32_t idxScan = m_preNumScans; idxScan < m_jpegScanParams->NumScans; idxScan++) |
| { |
| m_jpegScanParams->ScanHeader[idxScan].DataOffset += m_nextCopiedDataOffset; // modify the data offset for the new incoming scan data |
| } |
| m_totalDataLength = m_jpegScanParams->ScanHeader[m_jpegScanParams->NumScans - 1].DataOffset + m_jpegScanParams->ScanHeader[m_jpegScanParams->NumScans - 1].DataLength; |
| m_preNumScans = m_jpegScanParams->NumScans; |
| |
| // judge whether the bitstream is complete in the first execute() call |
| if (IsFirstExecuteCall() && |
| m_dataSize <= m_jpegScanParams->ScanHeader[0].DataOffset + m_jpegScanParams->ScanHeader[0].DataLength) |
| { |
| CODECHAL_DECODE_CHK_COND_RETURN( |
| (m_nextCopiedDataOffset + m_dataSize < m_totalDataLength) && (m_dataSize & 0x3f), |
| "The buffer size of the incomplete bitstream is not aligned with 64."); |
| |
| // Allocate the copy data buffer. |
| if (Mos_ResourceIsNull(&m_resCopiedDataBuffer)) |
| { |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( |
| &m_resCopiedDataBuffer, |
| maxBufferSize, |
| "CopiedDataBuffer"), |
| "Failed to allocate copied data Buffer."); |
| } |
| m_copiedDataBufferSize = maxBufferSize; |
| |
| // copy the bitstream buffer |
| if (m_dataSize) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface()); |
| m_copiedDataBufferInUse = true; |
| } |
| |
| m_incompleteJpegScan = m_nextCopiedDataOffset < m_totalDataLength; |
| m_incompletePicture = m_incompleteJpegScan || m_jpegScanParams->NumScans < m_jpegPicParams->m_totalScans; |
| } |
| else // the bitstream is complete |
| { |
| m_incompleteJpegScan = false; |
| if (m_jpegScanParams->NumScans == m_jpegPicParams->m_totalScans) |
| { |
| m_incompletePicture = false; |
| } |
| else |
| { |
| m_incompletePicture = true; |
| } |
| } |
| } |
| else //The next bitstream buffer of each scan |
| { |
| CODECHAL_DECODE_CHK_COND_RETURN( |
| m_nextCopiedDataOffset + m_dataSize > m_copiedDataBufferSize, |
| "The bitstream size exceeds the copied data buffer size.") |
| |
| CODECHAL_DECODE_CHK_COND_RETURN( |
| (m_nextCopiedDataOffset + m_dataSize < m_totalDataLength) && (m_dataSize & 0x3f), |
| "The data size of the incomplete bitstream is not aligned with 64."); |
| |
| // copy the bitstream buffer |
| if (m_dataSize) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface()); |
| } |
| |
| if (m_nextCopiedDataOffset >= m_totalDataLength) |
| { |
| m_incompleteJpegScan = false; |
| if (m_jpegScanParams->NumScans >= m_jpegPicParams->m_totalScans) |
| { |
| m_incompletePicture = false; |
| } |
| } |
| |
| } |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::CheckSupportedFormat( |
| PMOS_FORMAT format) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| // App must use 420_OPAQUE as DecodeRT for other JPEG output formats except NV12 and YUY2 due to runtime |
| // restriction, so the real JPEG format is passed to driver in PPS data. The code here is just to get the real output format. |
| // On SKL+, app would use AYUV (instead of 420_OPAQUE) as DecodeRT for direct YUV to ARGB8888 conversion; in such case, |
| // real output format (ARGB8888) should also be from JPEG PPS; MSDK would handle the details of treating AYUV as ARGB. |
| if (*format == Format_420O || *format == Format_AYUV) |
| { |
| *format = m_osInterface->pfnFmt_OsToMos((MOS_OS_FORMAT)m_jpegPicParams->m_renderTargetFormat); |
| } |
| |
| //No support for RGBP/BGRP channel swap or YUV/RGB conversion! |
| switch (*format) |
| { |
| case Format_BGRP: |
| if (m_jpegPicParams->m_chromaType == jpegRGB || |
| m_jpegPicParams->m_chromaType == jpegYUV444) |
| { |
| eStatus = MOS_STATUS_PLATFORM_NOT_SUPPORTED; |
| } |
| break; |
| case Format_RGBP: |
| if (m_jpegPicParams->m_chromaType == jpegYUV444) |
| { |
| eStatus = MOS_STATUS_PLATFORM_NOT_SUPPORTED; |
| } |
| break; |
| case Format_Y416: |
| case Format_AYUV: |
| case Format_AUYV: |
| case Format_Y410: |
| if (m_jpegPicParams->m_chromaType == jpegRGB || |
| m_jpegPicParams->m_chromaType == jpegBGR) |
| { |
| eStatus = MOS_STATUS_PLATFORM_NOT_SUPPORTED; |
| } |
| break; |
| default: |
| break; |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::SetFrameStates() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_destSurface); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_dataBuffer); |
| |
| //Set wPerfType as I_TYPE so that PerTag can be recognized by performance reportor |
| m_perfType = I_TYPE; |
| |
| m_dataSize = m_decodeParams.m_dataSize; |
| m_dataOffset = m_decodeParams.m_dataOffset; |
| m_resDataBuffer = *(m_decodeParams.m_dataBuffer); |
| m_jpegPicParams = (CodecDecodeJpegPicParams *)m_decodeParams.m_picParams; |
| m_jpegQMatrix = (CodecJpegQuantMatrix *)m_decodeParams.m_iqMatrixBuffer; |
| m_jpegHuffmanTable = (PCODECHAL_DECODE_JPEG_HUFFMAN_TABLE)m_decodeParams.m_huffmanTable; |
| m_jpegScanParams = (CodecDecodeJpegScanParameter *)m_decodeParams.m_sliceParams; |
| |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_jpegPicParams); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CheckSupportedFormat( |
| &m_decodeParams.m_destSurface->Format)); |
| |
| m_hwInterface->GetCpInterface()->SetCpSecurityType(); |
| |
| if (IsFirstExecuteCall()) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(InitializeBeginFrame()); |
| } |
| |
| // Check whether the bitstream buffer is completed. If not, allocate a larger buffer and copy the bitstream. |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CheckAndCopyIncompleteBitStream()); |
| |
| // if the bitstream is not completed, don't do any decoding work. |
| if (m_incompletePicture) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| uint32_t widthAlign = 0; |
| uint32_t heightAlign = 0; |
| |
| // Overwriting surface width and height of destination surface, so it comes from Picture Parameters struct |
| if (!m_jpegPicParams->m_interleavedData) |
| { |
| widthAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE); |
| heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE); |
| } |
| else |
| { |
| switch (m_jpegPicParams->m_chromaType) |
| { |
| case jpegYUV400: |
| case jpegYUV444: |
| case jpegRGB: |
| case jpegBGR: |
| widthAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE); |
| heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE); |
| break; |
| case jpegYUV422V2Y: |
| widthAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE); |
| heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2); |
| break; |
| case jpegYUV422H2Y: |
| widthAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2); |
| heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE); |
| break; |
| case jpegYUV411: |
| widthAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X4); |
| heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE); |
| break; |
| default: // YUV422H_4Y, YUV422V_4Y & YUV420 |
| widthAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2); |
| heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2); |
| break; |
| } |
| } |
| |
| //BDW has a limitation:Height should aligned by 16 when input is YUV422H_2Y and output is NV12. |
| if (MEDIA_IS_WA(m_waTable, WaJPEGHeightAlignYUV422H2YToNV12) && |
| m_jpegPicParams->m_chromaType == jpegYUV422H2Y && |
| m_decodeParams.m_destSurface->Format == Format_NV12) |
| { |
| heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2); |
| } |
| |
| if ((m_jpegPicParams->m_rotation == jpegRotation90) || (m_jpegPicParams->m_rotation == jpegRotation270)) |
| { |
| // Interchanging picture width and height for 90/270 degree rotation |
| m_decodeParams.m_destSurface->dwWidth = heightAlign; |
| m_decodeParams.m_destSurface->dwHeight = widthAlign; |
| } |
| else |
| { |
| m_decodeParams.m_destSurface->dwWidth = widthAlign; |
| m_decodeParams.m_destSurface->dwHeight = heightAlign; |
| } |
| |
| m_destSurface = *(m_decodeParams.m_destSurface); |
| if (m_copiedDataBufferInUse) |
| { |
| m_resDataBuffer = m_resCopiedDataBuffer; // set resDataBuffer to copy data buffer |
| } |
| |
| m_statusReportFeedbackNumber = m_jpegPicParams->m_statusReportFeedbackNumber; |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| m_sfcState->CheckAndInitialize(&m_destSurface, m_jpegPicParams); |
| #endif |
| |
| CODECHAL_DEBUG_TOOL( |
| if (m_jpegPicParams) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(DumpPicParams(m_jpegPicParams)) |
| } |
| |
| if (m_jpegScanParams) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(DumpScanParams(m_jpegScanParams)) |
| } |
| |
| if (m_jpegHuffmanTable) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(DumpHuffmanTable(m_jpegHuffmanTable)) |
| } |
| |
| if (m_jpegQMatrix) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(DumpIQParams(m_jpegQMatrix)) |
| } |
| |
| if (&(m_resDataBuffer)) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( |
| &m_resDataBuffer, |
| CodechalDbgAttr::attrBitstream, |
| "_DEC", |
| m_dataSize, |
| 0, |
| CODECHAL_NUM_MEDIA_STATES)); |
| }) |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::AllocateResources() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( |
| m_osInterface, |
| &m_resSyncObjectWaContextInUse)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( |
| m_osInterface, |
| &m_resSyncObjectVideoContextInUse)); |
| |
| return eStatus; |
| } |
| |
| void CodechalDecodeJpeg::SetOutputSurfaceLayout( |
| CodecDecodeJpegImageLayout *outputSurfLayout) |
| { |
| uint32_t ucbOffset = MOS_ALIGN_CEIL(m_destSurface.UPlaneOffset.iYOffset, MHW_VDBOX_MFX_UV_PLANE_ALIGNMENT_LEGACY); |
| uint32_t vcrOffset = MOS_ALIGN_CEIL(m_destSurface.VPlaneOffset.iYOffset, MHW_VDBOX_MFX_UV_PLANE_ALIGNMENT_LEGACY); |
| |
| uint32_t ucbOffsetInBytes = ucbOffset * m_destSurface.dwPitch; |
| uint32_t vcrOffsetInBytes = vcrOffset * m_destSurface.dwPitch; |
| |
| outputSurfLayout->m_pitch = m_destSurface.dwPitch; |
| |
| for (uint32_t scanCount = 0; scanCount < m_jpegScanParams->NumScans; scanCount++) |
| { |
| for (uint32_t scanComponent = 0; scanComponent < m_jpegScanParams->ScanHeader[scanCount].NumComponents; scanComponent++) |
| { |
| if (m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent] == m_jpegPicParams->m_componentIdentifier[jpegComponentY]) |
| { |
| outputSurfLayout->m_componentDataOffset[jpegComponentY] = 0; |
| } |
| else if (m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent] == m_jpegPicParams->m_componentIdentifier[jpegComponentU]) |
| { |
| outputSurfLayout->m_componentDataOffset[jpegComponentU] = ucbOffsetInBytes; |
| } |
| else if (m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent] == m_jpegPicParams->m_componentIdentifier[jpegComponentV]) |
| { |
| outputSurfLayout->m_componentDataOffset[jpegComponentV] = vcrOffsetInBytes; |
| } |
| } |
| } |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::DecodeStateLevel() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| MHW_VDBOX_JPEG_DECODE_PIC_STATE jpegPicState; |
| jpegPicState.dwOutputFormat = m_decodeParams.m_destSurface->Format; |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| if (m_sfcState->m_sfcPipeOut) |
| { |
| jpegPicState.dwOutputFormat = m_sfcState->m_sfcInSurface.Format; |
| } |
| #endif |
| |
| //Three new formats from HSW C0,HSW ULT can only be supported in specific conditions. |
| if (jpegPicState.dwOutputFormat == Format_NV12 || |
| jpegPicState.dwOutputFormat == Format_YUY2 || |
| jpegPicState.dwOutputFormat == Format_UYVY) |
| { |
| //Only interleaved single scan are supported. |
| if (m_jpegPicParams->m_totalScans != 1 || |
| m_jpegPicParams->m_interleavedData == 0) |
| { |
| return MOS_STATUS_UNKNOWN; |
| } |
| |
| switch (m_jpegPicParams->m_chromaType) |
| { |
| case jpegYUV420: |
| case jpegYUV422H2Y: |
| case jpegYUV422H4Y: |
| break; |
| case jpegYUV422V2Y: |
| case jpegYUV422V4Y: |
| if (GFX_IS_GEN_8_OR_LATER(m_hwInterface->GetPlatform()) && |
| jpegPicState.dwOutputFormat == Format_NV12) |
| { |
| break; |
| } |
| default: |
| return MOS_STATUS_UNKNOWN; |
| } |
| } |
| |
| MOS_COMMAND_BUFFER cmdBuffer; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| 0)); |
| |
| auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex); |
| HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking( |
| &cmdBuffer, true)); |
| |
| // Set PIPE_MODE_SELECT |
| MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams; |
| pipeModeSelectParams.Mode = CODECHAL_DECODE_MODE_JPEG; |
| pipeModeSelectParams.bStreamOutEnabled = m_streamOutEnabled; |
| pipeModeSelectParams.bDeblockerStreamOutEnable = false; |
| pipeModeSelectParams.bPostDeblockOutEnable = false; |
| pipeModeSelectParams.bPreDeblockOutEnable = true; |
| |
| // Set CMD_MFX_SURFACE_STATE |
| MHW_VDBOX_SURFACE_PARAMS surfaceParams; |
| MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams)); |
| surfaceParams.Mode = CODECHAL_DECODE_MODE_JPEG; |
| surfaceParams.psSurface = &m_destSurface; |
| surfaceParams.ChromaType = m_jpegPicParams->m_chromaType; |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| if (m_sfcState->m_sfcPipeOut) |
| { |
| surfaceParams.psSurface = &m_sfcState->m_sfcInSurface; |
| } |
| #endif |
| |
| // Set MFX_PIPE_BUF_ADDR_STATE_CMD |
| MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams; |
| pipeBufAddrParams.Mode = CODECHAL_DECODE_MODE_JPEG; |
| // Predeblock surface is the same as destination surface here because there is no deblocking for JPEG |
| pipeBufAddrParams.psPreDeblockSurface = &m_destSurface; |
| |
| #ifdef _MMC_SUPPORTED |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&pipeBufAddrParams)); |
| #endif |
| |
| // Set MFX_IND_OBJ_BASE_ADDR_STATE_CMD |
| MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams; |
| MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams)); |
| indObjBaseAddrParams.Mode = CODECHAL_DECODE_MODE_JPEG; |
| indObjBaseAddrParams.dwDataSize = m_copiedDataBufferInUse ? m_nextCopiedDataOffset : m_dataSize; |
| indObjBaseAddrParams.presDataBuffer = &m_resDataBuffer; |
| |
| // Set MFX_JPEG_PIC_STATE_CMD |
| jpegPicState.pJpegPicParams = m_jpegPicParams; |
| if ((m_jpegPicParams->m_rotation == jpegRotation90) || (m_jpegPicParams->m_rotation == jpegRotation270)) |
| { |
| jpegPicState.dwWidthInBlocks = (m_destSurface.dwHeight / CODECHAL_DECODE_JPEG_BLOCK_SIZE) - 1; |
| jpegPicState.dwHeightInBlocks = (m_destSurface.dwWidth / CODECHAL_DECODE_JPEG_BLOCK_SIZE) - 1; |
| } |
| else |
| { |
| jpegPicState.dwWidthInBlocks = (m_destSurface.dwWidth / CODECHAL_DECODE_JPEG_BLOCK_SIZE) - 1; |
| jpegPicState.dwHeightInBlocks = (m_destSurface.dwHeight / CODECHAL_DECODE_JPEG_BLOCK_SIZE) - 1; |
| } |
| |
| // Add commands to command buffer |
| // MI_FLUSH_DW command -> must be before to MFX_PIPE_MODE_SELECT |
| MHW_MI_FLUSH_DW_PARAMS flushDwParams; |
| MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( |
| &cmdBuffer, |
| &flushDwParams)); |
| |
| if (m_statusQueryReportingEnabled) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport( |
| &cmdBuffer)); |
| } |
| |
| // MFX_PIPE_MODE_SELECT_CMD |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd( |
| &cmdBuffer, |
| &pipeModeSelectParams)); |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| // Output decode result through SFC |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_sfcState->AddSfcCommands(&cmdBuffer)); |
| #endif |
| |
| // CMD_MFX_SURFACE_STATE |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd( |
| &cmdBuffer, |
| &surfaceParams)); |
| |
| // MFX_PIPE_BUF_ADDR_STATE_CMD |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd( |
| &cmdBuffer, |
| &pipeBufAddrParams)); |
| |
| // MFX_IND_OBJ_BASE_ADDR_STATE_CMD |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd( |
| &cmdBuffer, |
| &indObjBaseAddrParams)); |
| |
| // MFX_JPEG_PIC_STATE_CMD |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxJpegPicCmd( |
| &cmdBuffer, |
| &jpegPicState)); |
| |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::DecodePrimitiveLevel() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| // if the bitstream is not complete, don't do any decoding work. |
| if (m_incompletePicture) |
| { |
| return MOS_STATUS_SUCCESS; |
| |
| } |
| |
| MOS_COMMAND_BUFFER cmdBuffer; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| 0)); |
| |
| // MFX_QM_STATE_CMD |
| MHW_VDBOX_QM_PARAMS qmParams; |
| MOS_ZeroMemory(&qmParams, sizeof(qmParams)); |
| qmParams.Standard = CODECHAL_JPEG; |
| qmParams.pJpegQuantMatrix = m_jpegQMatrix; |
| |
| // Swapping QM(x,y) to QM(y,x) for 90/270 degree rotation |
| if ((m_jpegPicParams->m_rotation == jpegRotation90) || |
| (m_jpegPicParams->m_rotation == jpegRotation270)) |
| { |
| qmParams.bJpegQMRotation = true; |
| } |
| else |
| { |
| qmParams.bJpegQMRotation = false; |
| } |
| |
| for (uint16_t scanCount = 0; scanCount < m_jpegPicParams->m_numCompInFrame; scanCount++) |
| { |
| // Using scanCount here because the same command is used for JPEG decode and encode |
| uint32_t quantTableSelector = m_jpegPicParams->m_quantTableSelector[scanCount]; |
| qmParams.pJpegQuantMatrix->m_jpegQMTableType[quantTableSelector] = scanCount; |
| qmParams.JpegQMTableSelector = quantTableSelector; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxQmCmd( |
| &cmdBuffer, |
| &qmParams)); |
| } |
| |
| uint32_t dcCurHuffTblIndex[2] = { 0xff, 0xff }; |
| uint32_t acCurHuffTblIndex[2] = { 0xff, 0xff }; |
| |
| for (uint16_t scanCount = 0; scanCount < m_jpegScanParams->NumScans; scanCount++) |
| { |
| // MFX_JPEG_HUFF_TABLE |
| uint16_t numComponents = m_jpegScanParams->ScanHeader[scanCount].NumComponents; |
| for (uint16_t scanComponent = 0; scanComponent < numComponents; scanComponent++) |
| { |
| // Determine which huffman table we will be writing to |
| // For gray image, componentIdentifier[jpegComponentU] and componentIdentifier[jpegComponentV] are initialized to 0, |
| // and when ComponentSelector[scanComponent] is equal 0, variable huffTableID is set to 1, and wrong Huffman table is used, |
| // so it is more reasonable to use componentIdentifier[jpegComponentY] to determine which huffman table we will be writing to. |
| uint8_t ComponentSelector = |
| m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent]; |
| uint16_t huffTableID = 0; |
| if (ComponentSelector == m_jpegPicParams->m_componentIdentifier[jpegComponentY]) |
| { |
| huffTableID = 0; |
| } |
| else |
| { |
| huffTableID = 1; |
| } |
| |
| uint32_t AcTableSelector = |
| m_jpegScanParams->ScanHeader[scanCount].AcHuffTblSelector[scanComponent]; |
| uint32_t DcTableSelector = |
| m_jpegScanParams->ScanHeader[scanCount].DcHuffTblSelector[scanComponent]; |
| |
| // Send the huffman table state command only if the table changed |
| if ((DcTableSelector != dcCurHuffTblIndex[huffTableID]) || |
| (AcTableSelector != acCurHuffTblIndex[huffTableID])) |
| { |
| MHW_VDBOX_HUFF_TABLE_PARAMS huffmanTableParams; |
| MOS_ZeroMemory(&huffmanTableParams, sizeof(huffmanTableParams)); |
| |
| huffmanTableParams.HuffTableID = huffTableID; |
| |
| huffmanTableParams.pACBits = &m_jpegHuffmanTable->HuffTable[AcTableSelector].AC_BITS[0]; |
| huffmanTableParams.pDCBits = &m_jpegHuffmanTable->HuffTable[DcTableSelector].DC_BITS[0]; |
| huffmanTableParams.pACValues = &m_jpegHuffmanTable->HuffTable[AcTableSelector].AC_HUFFVAL[0]; |
| huffmanTableParams.pDCValues = &m_jpegHuffmanTable->HuffTable[DcTableSelector].DC_HUFFVAL[0]; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxJpegHuffTableCmd( |
| &cmdBuffer, |
| &huffmanTableParams)); |
| |
| // Set the current huffman table indices for the next scan |
| dcCurHuffTblIndex[huffTableID] = DcTableSelector; |
| acCurHuffTblIndex[huffTableID] = AcTableSelector; |
| } |
| } |
| |
| MHW_VDBOX_JPEG_BSD_PARAMS jpegBsdObject; |
| MOS_ZeroMemory(&jpegBsdObject, sizeof(jpegBsdObject)); |
| |
| // MFX_JPEG_BSD_OBJECT |
| jpegBsdObject.dwIndirectDataLength = m_jpegScanParams->ScanHeader[scanCount].DataLength; |
| jpegBsdObject.dwDataStartAddress = m_jpegScanParams->ScanHeader[scanCount].DataOffset; |
| jpegBsdObject.dwScanHorizontalPosition = m_jpegScanParams->ScanHeader[scanCount].ScanHoriPosition; |
| jpegBsdObject.dwScanVerticalPosition = m_jpegScanParams->ScanHeader[scanCount].ScanVertPosition; |
| jpegBsdObject.bInterleaved = (numComponents > 1) ? 1 : 0; |
| jpegBsdObject.dwMCUCount = m_jpegScanParams->ScanHeader[scanCount].MCUCount; |
| jpegBsdObject.dwRestartInterval = m_jpegScanParams->ScanHeader[scanCount].RestartInterval; |
| |
| uint16_t scanComponentIndex = 0; |
| |
| for (uint16_t scanComponent = 0; scanComponent < numComponents; scanComponent++) |
| { |
| uint8_t ComponentSelector = |
| m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent]; |
| |
| if (ComponentSelector == m_jpegPicParams->m_componentIdentifier[jpegComponentY]) |
| { |
| scanComponentIndex = 0; |
| } |
| else if (ComponentSelector == m_jpegPicParams->m_componentIdentifier[jpegComponentU]) |
| { |
| scanComponentIndex = 1; |
| } |
| else if (ComponentSelector == m_jpegPicParams->m_componentIdentifier[jpegComponentV]) |
| { |
| scanComponentIndex = 2; |
| } |
| // Add logic for component identifier JPEG_A |
| |
| jpegBsdObject.sScanComponent |= (1 << scanComponentIndex); |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxJpegBsdObjCmd( |
| &cmdBuffer, |
| &jpegBsdObject)); |
| } |
| |
| // Check if destination surface needs to be synchronized |
| MOS_SYNC_PARAMS syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_destSurface.OsResource; |
| syncParams.bReadOnly = false; |
| syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; |
| syncParams.bDisableLockForTranscode = m_disableLockForTranscode; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync( |
| m_osInterface, |
| &syncParams)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait( |
| m_osInterface, |
| &syncParams)); |
| |
| // Update the resource tag (s/w tag) for On-Demand Sync |
| m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); |
| |
| MHW_MI_FLUSH_DW_PARAMS flushDwParams; |
| MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( |
| &cmdBuffer, |
| &flushDwParams)); |
| |
| // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag |
| if (m_osInterface->bTagResourceSync) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource( |
| &cmdBuffer, |
| &syncParams)); |
| } |
| |
| if (m_statusQueryReportingEnabled) |
| { |
| CodechalDecodeStatusReport decodeStatusReport; |
| decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber; |
| decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE; |
| decodeStatusReport.m_currDecodedPicRes = m_destSurface.OsResource; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport( |
| decodeStatusReport, |
| &cmdBuffer)); |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( |
| &cmdBuffer, |
| nullptr)); |
| |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( |
| &cmdBuffer, |
| CODECHAL_NUM_MEDIA_STATES, |
| "_DEC")); |
| ) |
| |
| if (m_copiedDataBufferInUse) |
| { |
| //Sync up complete frame |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContextForWa; |
| syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal( |
| m_osInterface, |
| &syncParams)); |
| |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait( |
| m_osInterface, |
| &syncParams)); |
| } |
| |
| HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| m_videoContextUsesNullHw)); |
| |
| CODECHAL_DEBUG_TOOL( |
| m_mmc->UpdateUserFeatureKey(&m_destSurface);) |
| |
| if (m_statusQueryReportingEnabled) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport( |
| m_videoContextUsesNullHw)); |
| } |
| |
| // Set output surface layout |
| SetOutputSurfaceLayout(&m_decodeParams.m_outputSurfLayout); |
| |
| // Send the signal to indicate decode completion, in case On-Demand Sync is not present |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal( |
| m_osInterface, |
| &syncParams)); |
| |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( |
| &m_destSurface, |
| CodechalDbgAttr::attrDecodeOutputSurface, |
| "DstSurf"));) |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::InitMmcState() |
| { |
| #ifdef _MMC_SUPPORTED |
| m_mmc = MOS_New(CodechalMmcDecodeJpeg, m_hwInterface, this); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc); |
| #endif |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| MOS_STATUS CodechalDecodeJpeg::InitSfcState() |
| { |
| m_sfcState = MOS_New(CodechalJpegSfcState); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_sfcState); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| #endif |
| |
| MOS_STATUS CodechalDecodeJpeg::AllocateStandard( |
| CodechalSetting *settings) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| CODECHAL_DECODE_CHK_NULL_RETURN(settings); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(InitMmcState()); |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| CODECHAL_DECODE_CHK_STATUS_RETURN(InitSfcState()); |
| #endif |
| |
| m_width = settings->width; |
| m_height = settings->height; |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_sfcState->InitializeSfcState( |
| this, |
| m_hwInterface, |
| m_osInterface)); |
| #endif |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResources()); |
| |
| return eStatus; |
| } |
| |
| #if USE_CODECHAL_DEBUG_TOOL |
| MOS_STATUS CodechalDecodeJpeg::DumpIQParams( |
| CodecJpegQuantMatrix *matrixData) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrIqParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(matrixData); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| for (uint32_t j = 0; j < jpegNumComponent; j++) |
| { |
| oss << "Qmatrix " << std::dec << +j << ": " << std::endl; |
| |
| for (int8_t i = 0; i < 56; i += 8) |
| { |
| oss << "Qmatrix[" << std::dec << +i / 8 << "]:"; |
| for (uint8_t k = 0; k < 8; k++) |
| oss << std::hex << +matrixData->m_quantMatrix[j][i + k]<< " "; |
| oss << std::endl; |
| } |
| } |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DEC", |
| CodechalDbgBufferType::bufIqParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::DumpPicParams( |
| CodecDecodeJpegPicParams *picParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(picParams); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| oss.setf(std::ios::hex, std::ios::basefield); |
| |
| oss << "destPic.FrameIdx: " << +picParams->m_destPic.FrameIdx << std::endl; |
| oss << "destPic.PicFlags: " << +picParams->m_destPic.PicFlags << std::endl; |
| oss << "frameWidth: " << +picParams->m_frameWidth << std::endl; |
| oss << "frameHeight: " << +picParams->m_frameHeight << std::endl; |
| oss << "numCompInFrame: " << +picParams->m_numCompInFrame << std::endl; |
| |
| //Dump componentIdentifier[jpegNumComponent] |
| for (uint32_t i = 0; i < jpegNumComponent; ++i) |
| { |
| oss << "componentIdentifier[" << +i << "]: " << +picParams->m_componentIdentifier[i] << std::endl; |
| } |
| |
| //Dump quantTableSelector[jpegNumComponent] |
| for (uint32_t i = 0; i < jpegNumComponent; ++i) |
| { |
| oss << "quantTableSelector[" << +i << "]: " << +picParams->m_quantTableSelector[i] << std::endl; |
| } |
| oss << "chromaType: " << +picParams->m_chromaType << std::endl; |
| oss << "rotation: " << +picParams->m_rotation << std::endl; |
| oss << "totalScans: " << +picParams->m_totalScans << std::endl; |
| oss << "interleavedData: " << +picParams->m_interleavedData << std::endl; |
| oss << "reserved: " << +picParams->m_reserved << std::endl; |
| oss << "statusReportFeedbackNumber: " << +picParams->m_statusReportFeedbackNumber << std::endl; |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DEC", |
| CodechalDbgBufferType::bufPicParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::DumpScanParams( |
| CodecDecodeJpegScanParameter *scanParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrScanParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| CODECHAL_DEBUG_CHK_NULL(scanParams); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| //Dump ScanHeader[jpegNumComponent] |
| for (uint32_t i = 0; i < jpegNumComponent; ++i) |
| { |
| oss << "ScanHeader[" << +i << "].NumComponents: " << +scanParams->ScanHeader[i].NumComponents << std::endl; |
| //Dump ComponentSelector[jpegNumComponent] |
| for (uint32_t j = 0; j < jpegNumComponent; ++j) |
| { |
| oss << "ScanHeader[" << +i << "].ComponentSelector[" << +j << "]: " << +scanParams->ScanHeader[i].ComponentSelector[j] << std::endl; |
| } |
| |
| //Dump DcHuffTblSelector[jpegNumComponent] |
| for (uint32_t j = 0; j < jpegNumComponent; ++j) |
| { |
| oss << "ScanHeader[" << +i << "].DcHuffTblSelector[" << +j << "]: " << +scanParams->ScanHeader[i].DcHuffTblSelector[j] << std::endl; |
| } |
| |
| //Dump AcHuffTblSelector[jpegNumComponent] |
| for (uint32_t j = 0; j < jpegNumComponent; ++j) |
| { |
| oss << "ScanHeader[" << +i << "].AcHuffTblSelector[" << +j << "]: " << +scanParams->ScanHeader[i].AcHuffTblSelector[j] << std::endl; |
| } |
| oss << "ScanHeader[" << +i << "].RestartInterval: " << +scanParams->ScanHeader[i].RestartInterval << std::endl; |
| oss << "ScanHeader[" << +i << "].MCUCount: " << +scanParams->ScanHeader[i].MCUCount << std::endl; |
| oss << "ScanHeader[" << +i << "].ScanHoriPosition: " << +scanParams->ScanHeader[i].ScanHoriPosition << std::endl; |
| oss << "ScanHeader[" << +i << "].ScanVertPosition: " << +scanParams->ScanHeader[i].ScanVertPosition << std::endl; |
| oss << "ScanHeader[" << +i << "].DataOffset: " << +scanParams->ScanHeader[i].DataOffset << std::endl; |
| oss << "ScanHeader[" << +i << "].DataLength: " << +scanParams->ScanHeader[i].DataLength << std::endl; |
| } |
| |
| oss << "NumScans: " << +scanParams->NumScans << std::endl; |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DEC", |
| CodechalDbgBufferType::bufScanParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalDecodeJpeg::DumpHuffmanTable( |
| PCODECHAL_DECODE_JPEG_HUFFMAN_TABLE huffmanTable) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrHuffmanTbl)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| CODECHAL_DEBUG_CHK_NULL(huffmanTable); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| //Dump HuffTable[JPEG_MAX_NUM_HUFF_TABLE_INDEX] |
| for (uint32_t i = 0; i < JPEG_MAX_NUM_HUFF_TABLE_INDEX; ++i) |
| { |
| //Dump DC_BITS[JPEG_NUM_HUFF_TABLE_DC_BITS] |
| oss << "HuffTable[" << +i << "].DC_BITS[0-" << (JPEG_NUM_HUFF_TABLE_DC_BITS - 1) << "]: " << std::endl; |
| |
| for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_DC_BITS; ++j) |
| { |
| oss << +huffmanTable->HuffTable[i].DC_BITS[j] << " "; |
| if (j % 6 == 5 || j == JPEG_NUM_HUFF_TABLE_DC_BITS - 1) |
| { |
| oss << std::endl; |
| } |
| } |
| //Dump DC_HUFFVAL[JPEG_NUM_HUFF_TABLE_DC_HUFFVAL] |
| oss << "HuffTable[" << +i << "].DC_HUFFVAL[0-" << (JPEG_NUM_HUFF_TABLE_DC_HUFFVAL - 1) << "]: " << std::endl; |
| for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_DC_HUFFVAL; ++j) |
| { |
| oss << +huffmanTable->HuffTable[i].DC_HUFFVAL[j] << ' '; |
| if (j % 6 == 5 || j == JPEG_NUM_HUFF_TABLE_DC_HUFFVAL - 1) |
| { |
| oss << std::endl; |
| } |
| } |
| //Dump AC_BITS[JPEG_NUM_HUFF_TABLE_AC_BITS] |
| oss << "HuffTable[" << +i << "].AC_BITS[0-" << (JPEG_NUM_HUFF_TABLE_AC_BITS - 1) << "]: " << std::endl; |
| |
| for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_AC_BITS; ++j) |
| { |
| oss << +huffmanTable->HuffTable[i].AC_BITS[j] << ' '; |
| if (j % 8 == 7 || j == JPEG_NUM_HUFF_TABLE_AC_BITS - 1) |
| { |
| oss << std::endl; |
| } |
| } |
| |
| //Dump AC_HUFFVAL[JPEG_NUM_HUFF_TABLE_AC_HUFFVAL] |
| oss << "HuffTable[" << +i << "].AC_HUFFVAL[0-" << (JPEG_NUM_HUFF_TABLE_AC_HUFFVAL - 1) << "]: " << std::endl; |
| |
| for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_AC_HUFFVAL; ++j) |
| { |
| oss << +huffmanTable->HuffTable[i].AC_HUFFVAL[j] << ' '; |
| if (j % 9 == 8 || j == JPEG_NUM_HUFF_TABLE_AC_HUFFVAL - 1) |
| { |
| oss << std::endl; |
| } |
| } |
| } |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DEC", |
| CodechalDbgBufferType::bufHuffmanTbl, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| #endif |