1 /*
2  * Copyright © 2014 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
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *     Zhao Yakui <yakui.zhao@intel.com>
26  *
27  */
28 
29 /*
30  * Copyright (c) 2010, The WebM Project authors. All rights reserved.
31  *
32  * An additional intellectual property rights grant can be found
33  * in the file LIBVPX_PATENTS.  All contributing project authors may
34  * be found in the LIBVPX_AUTHORS file.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions are met:
38 
39  * Redistributions of source code must retain the above copyright
40  * notice, this list of conditions and the following disclaimer.
41  *
42  * Redistributions in binary form must reproduce the above copyright
43  * notice, this list of conditions and the following disclaimer in
44  * the documentation and/or other materials provided with the distribution.
45 
46  * Neither the name of Google, nor the WebM Project, nor the names
47  * of its contributors may be used to endorse or promote products
48  * derived from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  *
62  */
63 
64 #include "intel_hybrid_hostvld_vp9_parser.h"
65 #include "intel_hybrid_hostvld_vp9_loopfilter.h"
66 #include "intel_hybrid_hostvld_vp9_context.h"
67 #include "intel_hybrid_hostvld_vp9_engine.h"
68 
69 
70 #define VP9_SafeFreeMemory(ptr)               \
71     if (ptr) free(ptr);             \
72 
73 #define INTEL_HOSTVLD_VP9_THREAD_NUM     1
74 #define INTEL_HOSTVLD_VP9_HOSTBUF_NUM    2
75 #define INTEL_HOSTVLD_VP9_DDIBUF_NUM     INTEL_MT_DXVA_BUF_NUM
76 #define INTEL_HOSTVLD_VP9_SEM_QUEUE_SIZE 128
77 #define INTEL_HOSTVLD_VP9_PAGE_SIZE      0x1000
78 #define INTEL_HOSTVLD_VP9_EARLY_DECODE_BUFFER_NUM  3
79 
80 #define VP9_ALIGNED_FREE_MEMORY(pAlignedBuffer)                \
81 do {                                                           \
82     if (pAlignedBuffer)                                        \
83     {                                                          \
84         free(pAlignedBuffer);                                  \
85     }                                                          \
86 } while(0)
87 
88 #define VP9_REALLOCATE_ABOVE_CTX_BUFFER(pAboveCtxBuffer, size) \
89 do {                                                           \
90     VP9_ALIGNED_FREE_MEMORY(pAboveCtxBuffer);                                     \
91     pAboveCtxBuffer = (PUINT8)aligned_alloc(INTEL_HOSTVLD_VP9_PAGE_SIZE, size); \
92 } while(0)
93 
94 #define VP9_REALLOCATE_HOSTVLD_1D_BUFFER_UINT8(pHostvldBuffer, dwBufferSize)    \
95 do                                                                              \
96 {                                                                               \
97     VP9_ALIGNED_FREE_MEMORY((pHostvldBuffer)->pu8Buffer);                       \
98     (pHostvldBuffer)->dwSize = dwBufferSize;                                    \
99     (pHostvldBuffer)->pu8Buffer = (PUINT8)aligned_alloc(INTEL_HOSTVLD_VP9_PAGE_SIZE, dwBufferSize); \
100 } while (0)
101 
102 VAStatus Intel_HostvldVp9_Execute_MT (
103     INTEL_HOSTVLD_VP9_HANDLE         hHostVld);
104 
105 VAStatus Intel_HostvldVp9_PostLoopFilter (
106     PVOID                               pVp9FrameState);
107 
Intel_HostvldVp9_GetPartitions(PINTEL_HOSTVLD_VP9_FRAME_INFO pFrameInfo,PINTEL_HOSTVLD_VP9_VIDEO_BUFFER pVideoBuffer,PINTEL_VP9_PIC_PARAMS pPicParams)108 static VAStatus Intel_HostvldVp9_GetPartitions(
109     PINTEL_HOSTVLD_VP9_FRAME_INFO    pFrameInfo,
110     PINTEL_HOSTVLD_VP9_VIDEO_BUFFER  pVideoBuffer,
111     PINTEL_VP9_PIC_PARAMS            pPicParams)
112 {
113     VAStatus  eStatus     = VA_STATUS_SUCCESS;
114 
115 
116     if (pPicParams->UncompressedHeaderLengthInBytes >= 2)
117     pFrameInfo->FirstPartition.pu8Buffer  =
118         pVideoBuffer->pbBitsData + pPicParams->UncompressedHeaderLengthInBytes;
119     pFrameInfo->FirstPartition.dwSize     = pPicParams->FirstPartitionSize;
120 
121     pFrameInfo->SecondPartition.pu8Buffer =
122         pFrameInfo->FirstPartition.pu8Buffer + pFrameInfo->FirstPartition.dwSize;
123     pFrameInfo->SecondPartition.dwSize    =
124         pVideoBuffer->dwBitsSize - pPicParams->UncompressedHeaderLengthInBytes - pFrameInfo->FirstPartition.dwSize;
125 
126     return eStatus;
127 }
128 
Intel_HostvldVp9_FillIntraFrameRefFrame(PINTEL_HOSTVLD_VP9_1D_BUFFER pBufferRefFrame)129 static VAStatus Intel_HostvldVp9_FillIntraFrameRefFrame(
130     PINTEL_HOSTVLD_VP9_1D_BUFFER  pBufferRefFrame)
131 {
132     PINT8       pi8Buffer;
133     UINT        i;
134     VAStatus  eStatus     = VA_STATUS_SUCCESS;
135 
136 
137     pi8Buffer = (PINT8)pBufferRefFrame->pu8Buffer;
138 
139     for(i = 0; i < pBufferRefFrame->dwSize; i++)
140     {
141         *(pi8Buffer++) = VP9_REF_FRAME_INTRA;
142         *(pi8Buffer++) = VP9_REF_FRAME_INTRA;
143     }
144 
145     return eStatus;
146 }
147 
Intel_HostvldVp9_Create(PINTEL_HOSTVLD_VP9_HANDLE phHostVld,PINTEL_HOSTVLD_VP9_CALLBACKS pCallbacks)148 VAStatus Intel_HostvldVp9_Create (
149     PINTEL_HOSTVLD_VP9_HANDLE        phHostVld,
150     PINTEL_HOSTVLD_VP9_CALLBACKS     pCallbacks)
151 {
152     PINTEL_HOSTVLD_VP9_STATE         pVp9HostVld = NULL;
153     PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState;
154     PINTEL_HOSTVLD_VP9_TILE_STATE    pTileState;
155     PINTEL_HOSTVLD_VP9_FRAME_CONTEXT pContext;
156     uint32_t                               dwThreadNumber;
157     uint32_t                                i           = 0;
158     uint32_t                                uiTileIndex = 0;
159     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
160 
161 
162     pVp9HostVld = (PINTEL_HOSTVLD_VP9_STATE)calloc(1, sizeof(*pVp9HostVld));
163     *phHostVld  = (INTEL_HOSTVLD_VP9_HANDLE)pVp9HostVld;
164 
165 
166     dwThreadNumber = INTEL_HOSTVLD_VP9_THREAD_NUM;
167 
168     pVp9HostVld->pfnRenderCb        = pCallbacks->pfnHostVldRenderCb;
169     pVp9HostVld->pfnSyncCb          = pCallbacks->pfnHostVldSyncCb;
170     pVp9HostVld->pvStandardState    = pCallbacks->pvStandardState;
171     pVp9HostVld->dwThreadNumber     = dwThreadNumber;
172     pVp9HostVld->dwBufferNumber     = INTEL_HOSTVLD_VP9_HOSTBUF_NUM;
173     pVp9HostVld->dwDDIBufNumber     = dwThreadNumber;
174     pVp9HostVld->ui8BufNumEarlyDec  = 1; //not early decode for Sinlge thread case
175     pVp9HostVld->PrevParserID       = -1;
176 
177     pthread_mutex_init(&pVp9HostVld->MutexSync, NULL);
178     // Create Frame State
179     pFrameState = (PINTEL_HOSTVLD_VP9_FRAME_STATE)calloc(pVp9HostVld->dwBufferNumber, sizeof(*pFrameState));
180     pVp9HostVld->pFrameStateBase = pFrameState;
181 
182     for (i = 0; i < pVp9HostVld->dwBufferNumber; i++)
183     {
184 
185          // Create Tile State
186         pTileState = (PINTEL_HOSTVLD_VP9_TILE_STATE)calloc(dwThreadNumber, sizeof(*pTileState));
187         pFrameState->pTileStateBase     = pTileState;
188 
189         // Initialize Tile States
190         for (uiTileIndex = 0; uiTileIndex < dwThreadNumber; uiTileIndex++)
191         {
192             pTileState->pFrameState     = pFrameState;
193             pTileState->dwCurrColIndex  = uiTileIndex;
194             pTileState++;
195         }
196 
197         // Create Context Model
198         pFrameState->pVp9HostVld        = pVp9HostVld;
199         pFrameState->dwLastTaskID       = -1; // Invalid ID
200         pFrameState++;
201     }
202 
203     pVp9HostVld->pEarlyDecBufferBase = (PINTEL_HOSTVLD_VP9_EARLY_DEC_BUFFER)calloc(
204                                             pVp9HostVld->ui8BufNumEarlyDec, sizeof(*(pVp9HostVld->pEarlyDecBufferBase)));
205 
206     pVp9HostVld->pLastParserTaskID = (PUINT)malloc(pVp9HostVld->ui8BufNumEarlyDec * sizeof(UINT));
207     memset(pVp9HostVld->pLastParserTaskID, -1, pVp9HostVld->ui8BufNumEarlyDec * sizeof(UINT));
208 
209     for (i = 0; i < pVp9HostVld->ui8BufNumEarlyDec; i++)
210     {
211         pContext                                        = &pVp9HostVld->pEarlyDecBufferBase[i].CurrContext;
212         pContext->TxProbTables[TX_8X8].pui8ProbTable    = &pContext->TxProbTableSet.Tx_8X8[0][0];
213         pContext->TxProbTables[TX_8X8].uiStride         = TX_8X8;
214         pContext->TxProbTables[TX_16X16].pui8ProbTable  = &pContext->TxProbTableSet.Tx_16X16[0][0];
215         pContext->TxProbTables[TX_16X16].uiStride       = TX_16X16;
216         pContext->TxProbTables[TX_32X32].pui8ProbTable  = &pContext->TxProbTableSet.Tx_32X32[0][0];
217         pContext->TxProbTables[TX_32X32].uiStride       = TX_32X32;
218     }
219 
220     return eStatus;
221 }
222 
Intel_HostvldVp9_QueryBufferSize(INTEL_HOSTVLD_VP9_HANDLE hHostVld,uint32_t * pdwBufferSize)223 VAStatus Intel_HostvldVp9_QueryBufferSize (
224     INTEL_HOSTVLD_VP9_HANDLE         hHostVld,
225     uint32_t                             *pdwBufferSize)
226 {
227     PINTEL_HOSTVLD_VP9_STATE pVp9HostVld = NULL;
228     VAStatus                  eStatus     = VA_STATUS_SUCCESS;
229 
230     pVp9HostVld = (PINTEL_HOSTVLD_VP9_STATE)hHostVld;
231 
232     if (pdwBufferSize)
233     {
234         *pdwBufferSize = pVp9HostVld->dwBufferNumber;
235     }
236 
237     return eStatus;
238 }
239 
Intel_HostvldVp9_SetOutputBuffer(INTEL_HOSTVLD_VP9_HANDLE hHostVld,PINTEL_HOSTVLD_VP9_OUTPUT_BUFFER pOutputBuffer)240 VAStatus Intel_HostvldVp9_SetOutputBuffer (
241     INTEL_HOSTVLD_VP9_HANDLE         hHostVld,
242     PINTEL_HOSTVLD_VP9_OUTPUT_BUFFER pOutputBuffer)
243 {
244     PINTEL_HOSTVLD_VP9_STATE pVp9HostVld = NULL;
245     VAStatus                  eStatus     = VA_STATUS_SUCCESS;
246 
247 
248 
249     pVp9HostVld = (PINTEL_HOSTVLD_VP9_STATE)hHostVld;
250 
251     pVp9HostVld->pOutputBufferBase = pOutputBuffer;
252 
253     return eStatus;
254 }
255 
Intel_HostvldVp9_Initialize(INTEL_HOSTVLD_VP9_HANDLE hHostVld,PINTEL_HOSTVLD_VP9_VIDEO_BUFFER pVideoBuffer)256 VAStatus Intel_HostvldVp9_Initialize (
257     INTEL_HOSTVLD_VP9_HANDLE         hHostVld,
258     PINTEL_HOSTVLD_VP9_VIDEO_BUFFER  pVideoBuffer)
259 {
260     PINTEL_HOSTVLD_VP9_STATE         pVp9HostVld = NULL;
261     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
262 
263 
264     pVp9HostVld = (PINTEL_HOSTVLD_VP9_STATE)hHostVld;
265 
266     {
267         PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState = NULL;
268         DWORD                               dwCurrIndex;
269 
270         dwCurrIndex = (pVp9HostVld->dwCurrIndex + 1) % pVp9HostVld->dwBufferNumber;
271         pFrameState = pVp9HostVld->pFrameStateBase + dwCurrIndex;
272 
273         pFrameState->dwPrevIndex    = pVp9HostVld->dwCurrIndex;
274         pFrameState->dwCurrIndex    = dwCurrIndex;
275         pFrameState->pOutputBuffer  = pVp9HostVld->pOutputBufferBase + dwCurrIndex;
276         pFrameState->pVideoBuffer   = pVideoBuffer;
277         pFrameState->LastFrameType  = pVp9HostVld->LastFrameType;
278         pFrameState->FrameInfo.pContext = &pVp9HostVld->pEarlyDecBufferBase[0].CurrContext; //for ST, there is only 1 early dec buffer
279         pFrameState->pLastSegIdBuf      = &pVp9HostVld->pEarlyDecBufferBase[0].LastSegId;
280 
281         pVp9HostVld->dwCurrIndex    = dwCurrIndex;
282     }
283 
284     return eStatus;
285 }
286 
Intel_HostvldVp9_PreParser(PVOID pVp9FrameState)287 VAStatus Intel_HostvldVp9_PreParser (PVOID pVp9FrameState)
288 {
289     PINTEL_HOSTVLD_VP9_STATE         pVp9HostVld     = NULL;
290     PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState     = NULL;
291     PINTEL_HOSTVLD_VP9_FRAME_STATE   pPrevFrameState = NULL;
292     PINTEL_HOSTVLD_VP9_TILE_STATE    pTileState      = NULL;
293     PINTEL_HOSTVLD_VP9_VIDEO_BUFFER  pVideoBuffer;
294     PINTEL_HOSTVLD_VP9_OUTPUT_BUFFER pOutputBuffer;
295     PINTEL_HOSTVLD_VP9_FRAME_INFO    pFrameInfo;
296     PINTEL_VP9_PIC_PARAMS            pPicParams;
297     PINTEL_VP9_SEGMENT_PARAMS        pSegmentData;
298     INT                                 iMarkerBit;
299     DWORD                               dwNumAboveCtx, dwSize, i;
300     DWORD                               dwPrevPicWidth, dwPrevPicHeight;
301     BOOL                                bPrevShowFrame;
302     BOOL                                bResetLastSegId = FALSE;
303     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
304 
305 
306 
307     pFrameState     = (PINTEL_HOSTVLD_VP9_FRAME_STATE)pVp9FrameState;
308     pVp9HostVld     = pFrameState->pVp9HostVld;
309     pVideoBuffer    = pFrameState->pVideoBuffer;
310     pOutputBuffer   = pFrameState->pOutputBuffer;
311     pFrameInfo      = &pFrameState->FrameInfo;
312 
313     pPrevFrameState = pFrameState->pVp9HostVld->pFrameStateBase + pFrameState->dwPrevIndex;
314     dwPrevPicWidth  = pPrevFrameState->FrameInfo.dwPicWidthCropped;
315     dwPrevPicHeight = pPrevFrameState->FrameInfo.dwPicHeightCropped;
316     bPrevShowFrame  = pPrevFrameState->FrameInfo.bShowFrame;
317 
318     pPicParams                      = pVideoBuffer->pVp9PicParams;
319     pSegmentData                    = pVideoBuffer->pVp9SegmentData;
320     pFrameInfo->pPicParams          = pPicParams;
321     pFrameInfo->pSegmentData        = pVideoBuffer->pVp9SegmentData;
322 
323     pFrameInfo->ui8SegEnabled       = pPicParams->PicFlags.fields.segmentation_enabled;
324     pFrameInfo->ui8SegUpdMap        = pPicParams->PicFlags.fields.segmentation_update_map;
325     pFrameInfo->ui8TemporalUpd      = pPicParams->PicFlags.fields.segmentation_temporal_update;
326 
327     pFrameInfo->LastFrameType       = pFrameState->LastFrameType;
328     pFrameInfo->dwPicWidthCropped   = pPicParams->FrameWidthMinus1 + 1;
329     pFrameInfo->dwPicHeightCropped  = pPicParams->FrameHeightMinus1 + 1;
330     pFrameInfo->dwPicWidth          = ALIGN(pPicParams->FrameWidthMinus1 + 1, 8);
331     pFrameInfo->dwPicHeight         = ALIGN(pPicParams->FrameHeightMinus1 + 1, 8);
332     pFrameInfo->dwB8Columns         = pFrameInfo->dwPicWidth >> VP9_LOG2_B8_SIZE;
333     pFrameInfo->dwB8Rows            = pFrameInfo->dwPicHeight >> VP9_LOG2_B8_SIZE;
334     pFrameInfo->dwB8ColumnsAligned  = ALIGN(pFrameInfo->dwB8Columns, VP9_B64_SIZE_IN_B8);
335     pFrameInfo->dwB8RowsAligned     = ALIGN(pFrameInfo->dwB8Rows, VP9_B64_SIZE_IN_B8);
336     pFrameInfo->dwPicWidthAligned   = pFrameInfo->dwB8ColumnsAligned << VP9_LOG2_B8_SIZE;
337     pFrameInfo->dwLog2TileRows      = pPicParams->log2_tile_rows;
338     pFrameInfo->dwLog2TileColumns   = pPicParams->log2_tile_columns;
339     pFrameInfo->dwTileRows          = 1 << pPicParams->log2_tile_rows;
340     pFrameInfo->dwTileColumns       = 1 << pPicParams->log2_tile_columns;
341     pFrameInfo->dwMbStride          = pFrameInfo->dwB8ColumnsAligned;
342     pFrameInfo->bLossLess           = pPicParams->PicFlags.fields.LosslessFlag;
343     pFrameInfo->bShowFrame          = pPicParams->PicFlags.fields.show_frame;
344     pFrameInfo->bIsIntraOnly        =
345         (pPicParams->PicFlags.fields.frame_type == KEY_FRAME) ||
346         (pPicParams->PicFlags.fields.intra_only);
347     pFrameInfo->bFrameParallelDisabled   =
348         !pPicParams->PicFlags.fields.frame_parallel_decoding_mode;
349     pFrameInfo->bErrorResilientMode     =
350         pPicParams->PicFlags.fields.error_resilient_mode;
351     pFrameInfo->uiFrameContextIndex     =
352         pPicParams->PicFlags.fields.frame_context_idx;
353     pFrameInfo->uiResetFrameContext     =
354         pPicParams->PicFlags.fields.reset_frame_context;
355     pFrameInfo->bIsKeyFrame         = pPicParams->PicFlags.fields.frame_type == KEY_FRAME;
356     pFrameInfo->eInterpolationType      =
357         (INTEL_HOSTVLD_VP9_INTERPOLATION_TYPE)pPicParams->PicFlags.fields.mcomp_filter_type;
358 
359     //Inter
360     pFrameInfo->bIsSwitchableInterpolation  =
361         pPicParams->PicFlags.fields.mcomp_filter_type == VP9_INTERP_SWITCHABLE;
362     pFrameInfo->bAllowHighPrecisionMv                   = pPicParams->PicFlags.fields.allow_high_precision_mv;
363     pFrameInfo->RefFrameSignBias[VP9_REF_FRAME_LAST]    = pPicParams->PicFlags.fields.LastRefSignBias;
364     pFrameInfo->RefFrameSignBias[VP9_REF_FRAME_GOLDEN]  = pPicParams->PicFlags.fields.GoldenRefSignBias;
365     pFrameInfo->RefFrameSignBias[VP9_REF_FRAME_ALTREF]  = pPicParams->PicFlags.fields.AltRefSignBias;
366 
367     for (i = 0; i < VP9_MAX_SEGMENTS; i++)
368     {
369         // pack segment QP
370         pFrameInfo->SegQP[INTEL_HOSTVLD_VP9_YUV_PLANE_Y][i]  =
371             (((UINT32)pSegmentData->SegData[i].LumaACQuantScale) << 16) | pSegmentData->SegData[i].LumaDCQuantScale;
372         pFrameInfo->SegQP[INTEL_HOSTVLD_VP9_YUV_PLANE_UV][i] =
373             (((UINT32)pSegmentData->SegData[i].ChromaACQuantScale) << 16) | pSegmentData->SegData[i].ChromaDCQuantScale;
374     }
375 
376     Intel_HostvldVp9_GetPartitions(pFrameInfo, pVideoBuffer, pPicParams);
377 
378     // Initialize BAC engine
379     iMarkerBit = Intel_HostvldVp9_BacEngineInit(
380         &pFrameState->BacEngine,
381         pFrameInfo->FirstPartition.pu8Buffer,
382         pFrameInfo->FirstPartition.dwSize);
383 
384     if (0 != iMarkerBit)
385     {
386         eStatus = VA_STATUS_ERROR_OPERATION_FAILED;
387         goto finish;
388     }
389 
390     pFrameInfo->bResetContext = FALSE;
391     if (pFrameInfo->bIsIntraOnly || pFrameInfo->bErrorResilientMode)
392     {
393         // reset context
394         Intel_HostvldVp9_ResetContext(pVp9HostVld->ContextTable, pFrameInfo);
395     }
396 
397     if (!pFrameInfo->bResetContext)
398     {
399         // If we didn't reset the context, initialize current frame context by copying from context table
400         Intel_HostvldVp9_GetCurrFrameContext(
401             pVp9HostVld->ContextTable,
402             pFrameInfo);
403     }
404 
405         Intel_HostvldVp9_SetupSegmentationProbs(
406             pFrameInfo->pContext,
407             pPicParams->SegTreeProbs,
408             pPicParams->SegPredProbs);
409 
410     pFrameState->dwTileStatesInUse = MIN(pFrameInfo->dwTileColumns, pVp9HostVld->dwThreadNumber);
411     pTileState                     = pFrameState->pTileStateBase;
412     for (i = 0; i < pFrameState->dwTileStatesInUse; i++)
413     {
414         memset(&(pTileState->Count), 0, sizeof(pTileState->Count));
415         pTileState++;
416     }
417 
418     // Only reallocate above context buffers when picture width becomes bigger           //Need To Check
419     dwNumAboveCtx = pFrameInfo->dwPicWidthAligned >> VP9_LOG2_B8_SIZE;
420     if (dwNumAboveCtx > pFrameInfo->dwNumAboveCtx)
421     {
422         pFrameInfo->dwNumAboveCtx = dwNumAboveCtx;
423 
424         // allocate above context
425         dwSize = dwNumAboveCtx * sizeof(*pFrameInfo->pContextAbove);
426         VP9_ALIGNED_FREE_MEMORY(pFrameInfo->pContextAbove);
427         pFrameInfo->pContextAbove =
428             (PINTEL_HOSTVLD_VP9_NEIGHBOR)aligned_alloc(INTEL_HOSTVLD_VP9_PAGE_SIZE, dwSize);
429 
430         dwNumAboveCtx <<= 1;
431         // Entropy context, per 4x4 block. Allocate once for all the planes
432         dwSize = dwNumAboveCtx * sizeof(*pFrameInfo->pEntropyContextAbove[VP9_CODED_YUV_PLANE_Y]) * 2;
433         VP9_REALLOCATE_ABOVE_CTX_BUFFER(pFrameInfo->EntropyContextAbove.pu8Buffer, dwSize);
434         pFrameInfo->EntropyContextAbove.dwSize = dwSize;
435         pFrameInfo->pEntropyContextAbove[VP9_CODED_YUV_PLANE_Y] =
436             pFrameInfo->EntropyContextAbove.pu8Buffer;
437         pFrameInfo->pEntropyContextAbove[VP9_CODED_YUV_PLANE_U] =
438             pFrameInfo->pEntropyContextAbove[VP9_CODED_YUV_PLANE_Y] + (dwSize >> 1);
439         pFrameInfo->pEntropyContextAbove[VP9_CODED_YUV_PLANE_V] =
440             pFrameInfo->pEntropyContextAbove[VP9_CODED_YUV_PLANE_U] + (dwSize >> 2); // we only support 4:2:0 so far.
441     }
442 
443     // Reallocate mode info buffer if changed to bigger resolution
444     dwSize = pFrameInfo->dwB8ColumnsAligned * pFrameInfo->dwB8RowsAligned;
445     if (dwSize > pFrameInfo->ModeInfo.dwSize)
446     {
447         VP9_ALIGNED_FREE_MEMORY(pFrameInfo->ModeInfo.pBuffer);
448         pFrameInfo->ModeInfo.pBuffer = aligned_alloc(INTEL_HOSTVLD_VP9_PAGE_SIZE,
449             dwSize * sizeof(INTEL_HOSTVLD_VP9_MODE_INFO));
450         pFrameInfo->ModeInfo.dwSize  = dwSize;
451     }
452 
453     // Zero last segment id buffer if resolution changed
454     if (dwSize > pFrameState->pLastSegIdBuf->dwSize)
455     {
456         // Per 8x8 block, UINT8
457         VP9_REALLOCATE_HOSTVLD_1D_BUFFER_UINT8(pFrameState->pLastSegIdBuf, dwSize);
458         bResetLastSegId |= TRUE;
459     }
460     if ((pFrameInfo->dwPicWidthCropped  != dwPrevPicWidth) ||
461         (pFrameInfo->dwPicHeightCropped != dwPrevPicHeight) ||
462          pFrameInfo->bIsIntraOnly ||
463          pFrameInfo->bErrorResilientMode)
464     {
465         bResetLastSegId |= TRUE;
466     }
467 
468     if (bResetLastSegId)
469     {
470         memset(pFrameState->pLastSegIdBuf->pu8Buffer, 0, pFrameState->pLastSegIdBuf->dwSize);
471     }
472 
473     if (pVp9HostVld->pfnSyncCb)
474     {
475         pVp9HostVld->pfnSyncCb(
476             pVp9HostVld->pvStandardState,
477             pVideoBuffer,
478             pFrameState->dwCurrIndex,
479             pFrameState->dwPrevIndex);
480     }
481 
482     pFrameInfo->bHasPrevFrame =
483         (pFrameInfo->dwPicWidthCropped == dwPrevPicWidth)   &&
484         (pFrameInfo->dwPicHeightCropped == dwPrevPicHeight) &&
485         !pFrameInfo->bErrorResilientMode                    &&
486         !pFrameInfo->bIsIntraOnly                           &&
487         bPrevShowFrame;
488 
489     if (pFrameInfo->bIsIntraOnly)
490     {
491         Intel_HostvldVp9_FillIntraFrameRefFrame(&pOutputBuffer->ReferenceFrame);
492     }
493 
494     Intel_HostvldVp9_ParseCompressedHeader(pFrameState);
495 
496     Intel_HostvldVp9_PreParseTiles(pFrameState);
497 
498 finish:
499     return eStatus;
500 }
501 
502 
Intel_HostvldVp9_PostParser(PVOID pVp9FrameState)503 VAStatus Intel_HostvldVp9_PostParser (PVOID pVp9FrameState)
504 {
505     PINTEL_HOSTVLD_VP9_STATE         pVp9HostVld = NULL;
506     PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState = NULL;
507     PINTEL_HOSTVLD_VP9_FRAME_INFO    pFrameInfo  = NULL;
508     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
509 
510 
511     pFrameState = (PINTEL_HOSTVLD_VP9_FRAME_STATE)pVp9FrameState;
512     pVp9HostVld = pFrameState->pVp9HostVld;
513     pFrameInfo  = &pFrameState->FrameInfo;
514 
515     Intel_HostvldVp9_PostParseTiles(pFrameState);
516 
517     if (pFrameInfo->bIsIntraOnly || pFrameInfo->bErrorResilientMode)
518     {
519         Intel_HostvldVp9_UpdateContextTables(pVp9HostVld->ContextTable, pFrameInfo);
520     }
521 
522     Intel_HostvldVp9_AdaptProbabilities(pFrameState);
523 
524     Intel_HostvldVp9_RefreshFrameContext(pVp9HostVld->ContextTable, pFrameInfo);
525 
526     pFrameState->ReferenceFrame.pu16Buffer = pFrameState->pOutputBuffer->ReferenceFrame.pu16Buffer;
527     pFrameState->ReferenceFrame.dwSize     = pFrameState->pOutputBuffer->ReferenceFrame.dwSize;
528 
529     if(pFrameState->FrameInfo.dwTileColumns > 1)
530     {
531         Intel_HostvldVp9_PostLoopFilter(pVp9FrameState);
532     }
533 
534     return eStatus;
535 }
536 
Intel_HostvldVp9_TileColumnParser(PVOID pVp9TileState)537 VAStatus Intel_HostvldVp9_TileColumnParser (PVOID pVp9TileState)
538 {
539     PINTEL_HOSTVLD_VP9_TILE_STATE    pTileState  = NULL;
540     DWORD                               dwTileColumns, dwCurrColIndex, dwTileStateNumber;
541     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
542 
543 
544     pTileState     = (PINTEL_HOSTVLD_VP9_TILE_STATE)pVp9TileState;
545     dwTileColumns     = pTileState->pFrameState->FrameInfo.dwTileColumns;
546     dwCurrColIndex    = pTileState->dwCurrColIndex;
547     dwTileStateNumber = pTileState->pFrameState->pVp9HostVld->dwThreadNumber;
548 
549     while(dwCurrColIndex < dwTileColumns)
550     {
551         Intel_HostvldVp9_ParseTileColumn(pTileState, dwCurrColIndex);
552         dwCurrColIndex  += dwTileStateNumber;
553     }
554 
555     return eStatus;
556 }
557 
Intel_HostvldVp9_Parser(PVOID pVp9FrameState)558 VAStatus Intel_HostvldVp9_Parser (PVOID pVp9FrameState)
559 {
560     VAStatus eStatus = VA_STATUS_SUCCESS;
561 
562 
563     eStatus = Intel_HostvldVp9_PreParser(pVp9FrameState);
564 
565     eStatus = Intel_HostvldVp9_ParseTiles((PINTEL_HOSTVLD_VP9_FRAME_STATE)pVp9FrameState);
566 
567     if (((PINTEL_HOSTVLD_VP9_FRAME_STATE)pVp9FrameState)->pVp9HostVld->dwThreadNumber == 1)
568     {
569        eStatus = Intel_HostvldVp9_PostParser(pVp9FrameState);
570     }
571 
572     return eStatus;
573 }
574 
Intel_HostvldVp9_LoopFilterTiles(PVOID pVp9TileState)575 VAStatus Intel_HostvldVp9_LoopFilterTiles (PVOID pVp9TileState)
576 {
577     PINTEL_HOSTVLD_VP9_TILE_STATE    pTileState  = NULL;
578     DWORD                               dwTileColumns, dwCurrColIndex, dwTileStateNumber;
579     VAStatus                            eStatus     = VA_STATUS_SUCCESS;
580 
581     pTileState        = (PINTEL_HOSTVLD_VP9_TILE_STATE)pVp9TileState;
582     dwTileColumns     = pTileState->pFrameState->FrameInfo.dwTileColumns;
583     dwCurrColIndex    = pTileState->dwCurrColIndex;
584     dwTileStateNumber = pTileState->pFrameState->pVp9HostVld->dwThreadNumber;
585 
586     while(dwCurrColIndex < dwTileColumns)
587     {
588         Intel_HostvldVp9_LoopfilterTileColumn(pTileState, dwCurrColIndex);
589         dwCurrColIndex  += dwTileStateNumber;
590     }
591 
592     return eStatus;
593 }
594 
Intel_HostvldVp9_PostLoopFilter(PVOID pVp9FrameState)595 VAStatus Intel_HostvldVp9_PostLoopFilter (PVOID pVp9FrameState)
596 {
597     PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState = NULL;
598     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
599 
600     pFrameState = (PINTEL_HOSTVLD_VP9_FRAME_STATE)pVp9FrameState;
601 
602     // Calc Loop filter threshold
603     Intel_HostvldVp9_LoopfilterCalcThreshold(pFrameState);
604 
605     Intel_HostvldVp9_SetOutOfBoundValues(pFrameState);
606 
607     return eStatus;
608 }
609 
Intel_HostvldVp9_LoopfilterFrame(PVOID pVp9FrameState)610 VAStatus Intel_HostvldVp9_LoopfilterFrame(PVOID pVp9FrameState)
611 {
612     PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState = NULL;
613     PINTEL_HOSTVLD_VP9_FRAME_INFO    pFrameInfo  = NULL;
614     PINTEL_HOSTVLD_VP9_TILE_STATE    pTileState  = NULL;
615     DWORD                               dwTileX;
616     VAStatus                            eStatus     = VA_STATUS_SUCCESS;
617 
618     pFrameState = (PINTEL_HOSTVLD_VP9_FRAME_STATE)pVp9FrameState;
619 
620     pFrameInfo              = &pFrameState->FrameInfo;
621     pTileState              = pFrameState->pTileStateBase;
622     pTileState->pFrameState = pFrameState;
623 
624     // decode tiles
625     for (dwTileX = 0; dwTileX < pFrameInfo->dwTileColumns; dwTileX++)
626     {
627         Intel_HostvldVp9_LoopfilterTileColumn(pTileState,dwTileX);
628     }
629 
630     Intel_HostvldVp9_PostLoopFilter(pFrameState);
631 
632     return eStatus;
633 }
634 
Intel_HostvldVp9_Render(PVOID pVp9FrameState)635 VAStatus Intel_HostvldVp9_Render (PVOID pVp9FrameState)
636 {
637     PINTEL_HOSTVLD_VP9_STATE         pVp9HostVld = NULL;
638     PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState = NULL;
639     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
640 
641     pFrameState     = (PINTEL_HOSTVLD_VP9_FRAME_STATE)pVp9FrameState;
642     pVp9HostVld     = pFrameState->pVp9HostVld;
643 
644     if (pVp9HostVld->pfnRenderCb)
645     {
646         pVp9HostVld->pfnRenderCb(
647             pVp9HostVld->pvStandardState,
648             pFrameState->dwCurrIndex,
649             pFrameState->dwPrevIndex);
650     }
651 
652     return eStatus;
653 }
654 
Intel_HostvldVp9_Execute(INTEL_HOSTVLD_VP9_HANDLE hHostVld)655 VAStatus Intel_HostvldVp9_Execute (
656     INTEL_HOSTVLD_VP9_HANDLE         hHostVld)
657 {
658     PINTEL_HOSTVLD_VP9_STATE         pVp9HostVld = NULL;
659     PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState = NULL;
660     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
661     PINTEL_HOSTVLD_VP9_VIDEO_BUFFER pVp9VideoBuffer = NULL;
662 
663 
664     pVp9HostVld     = (PINTEL_HOSTVLD_VP9_STATE)hHostVld;
665 
666     pFrameState = pVp9HostVld->pFrameStateBase + pVp9HostVld->dwCurrIndex;
667 
668     eStatus = Intel_HostvldVp9_Parser(pFrameState);
669     if (eStatus != VA_STATUS_SUCCESS)
670        goto finish;
671 
672     eStatus = Intel_HostvldVp9_LoopfilterFrame(pFrameState);
673     if (eStatus != VA_STATUS_SUCCESS)
674        goto finish;
675 
676     pVp9VideoBuffer = pFrameState->pVideoBuffer;
677 
678     if (pVp9VideoBuffer->slice_data_bo) {
679         dri_bo_unmap(pVp9VideoBuffer->slice_data_bo);
680 	pVp9VideoBuffer->slice_data_bo = NULL;
681     }
682 
683     eStatus = Intel_HostvldVp9_Render(pFrameState);
684     if (eStatus != VA_STATUS_SUCCESS)
685        goto finish;
686 
687     pVp9HostVld->LastFrameType = (INTEL_HOSTVLD_VP9_FRAME_TYPE)(pFrameState->pVideoBuffer->pVp9PicParams->PicFlags.fields.frame_type);
688 
689 finish:
690     return eStatus;
691 }
692 
693 
Intel_HostvldVp9_InitFrameState(PVOID pInitData,PVOID pData)694 VAStatus Intel_HostvldVp9_InitFrameState (
695     PVOID                      pInitData,
696     PVOID                      pData)
697 {
698     PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState;
699     PINTEL_HOSTVLD_VP9_TASK_USERDATA pTaskUserData;
700     VAStatus                          eStatus     = VA_STATUS_SUCCESS;
701 
702 
703     pFrameState     = (PINTEL_HOSTVLD_VP9_FRAME_STATE)pData;
704     pTaskUserData   = (PINTEL_HOSTVLD_VP9_TASK_USERDATA)pInitData;
705 
706     pFrameState->pVideoBuffer  = pTaskUserData->pVideoBuffer;
707     pFrameState->pOutputBuffer = pTaskUserData->pOutputBuffer;
708     pFrameState->pRenderTarget = pTaskUserData->pVideoBuffer->pRenderTarget;
709     pFrameState->dwCurrIndex   = pTaskUserData->dwCurrIndex;
710     pFrameState->dwPrevIndex   = pTaskUserData->dwPrevIndex;
711     pFrameState->LastFrameType      = pTaskUserData->LastFrameType;
712     pFrameState->FrameInfo.pContext = pTaskUserData->pCurrContext;
713     pFrameState->pLastSegIdBuf      = pTaskUserData->pLastSegIdBuf;
714 
715     return eStatus;
716 }
717 
718 
Intel_HostvldVp9_Destroy(INTEL_HOSTVLD_VP9_HANDLE hHostVld)719 VAStatus Intel_HostvldVp9_Destroy (
720     INTEL_HOSTVLD_VP9_HANDLE         hHostVld)
721 {
722     PINTEL_HOSTVLD_VP9_STATE pVp9HostVld = NULL;
723     VAStatus                  eStatus     = VA_STATUS_SUCCESS;
724     unsigned int                        i           = 0;
725 
726 
727 
728     pVp9HostVld = (PINTEL_HOSTVLD_VP9_STATE)hHostVld;
729 
730     if (pVp9HostVld)
731     {
732         PINTEL_HOSTVLD_VP9_FRAME_STATE   pFrameState;
733         PINTEL_HOSTVLD_VP9_EARLY_DEC_BUFFER pEarlyDecBufferBase;
734 
735         pFrameState = pVp9HostVld->pFrameStateBase;
736         if (pFrameState)
737         {
738             for(i = 0; i < pVp9HostVld->dwBufferNumber; i++)
739             {
740                 if (pFrameState)
741                 {
742                     VP9_ALIGNED_FREE_MEMORY(pFrameState->FrameInfo.pContextAbove);
743                     VP9_ALIGNED_FREE_MEMORY(pFrameState->FrameInfo.EntropyContextAbove.pu8Buffer);
744                     VP9_ALIGNED_FREE_MEMORY(pFrameState->FrameInfo.ModeInfo.pBuffer);
745                     VP9_SafeFreeMemory(pFrameState->pTileStateBase);
746                 }
747                 pFrameState++;
748             }
749 
750             VP9_SafeFreeMemory(pVp9HostVld->pFrameStateBase);
751         }
752         pEarlyDecBufferBase = pVp9HostVld->pEarlyDecBufferBase;
753         for (i = 0; i< pVp9HostVld->ui8BufNumEarlyDec; i++)
754         {
755             VP9_ALIGNED_FREE_MEMORY(pEarlyDecBufferBase->LastSegId.pu8Buffer);
756 
757             pEarlyDecBufferBase++;
758         }
759         VP9_SafeFreeMemory(pVp9HostVld->pEarlyDecBufferBase);
760         VP9_SafeFreeMemory(pVp9HostVld->pLastParserTaskID);
761 
762         pthread_mutex_destroy(&pVp9HostVld->MutexSync);
763 
764         free(pVp9HostVld);
765     }
766 
767     return eStatus;
768 }
769