1 /*
2 * Copyright (c) 2017, 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     codechal_encode_tracked_buffer.h
24 //!
25 //! \brief    Encoder needs to track and store certain surface/resource/buffers, to be used as reference for future frames
26 //!           Given the refFrame list of current frame, a slot is dynamically allocated to index/track these resources
27 //!           Whenever a RefFrame is no longer used, its corresponding slot will be re-used to minimize memory allocation
28 //!           "Tracked buffer" so far includes MbCode/MvData/MvTemporal buffer, and Csc/Ds/DsRecon surface
29 //!
30 
31 #ifndef __CODECHAL_ENCODE_TRACKED_BUFFER_H__
32 #define __CODECHAL_ENCODE_TRACKED_BUFFER_H__
33 
34 #include "codechal.h"
35 #include "codechal_encode_allocator.h"
36 #include "codec_def_common_encode.h"
37 
38 //!
39 //! Tracked buffer
40 //!
41 class CodechalEncodeTrackedBuffer
42 {
43 public:
44     //!
45     //! \brief  Get the buffer index allocated for current frame
46     //!
47     //! \return the buffer index allocated for current frame
48     //!
GetCurrIndex()49     inline uint8_t GetCurrIndex()
50     {
51         return m_trackedBufCurrIdx;
52     }
53 
54     //!
55     //! \brief  Get the buffer index allocated for MbCode
56     //!
57     //! \return the buffer index allocated for MbCode
58     //!
GetCurrIndexMbCode()59     inline uint8_t GetCurrIndexMbCode()
60     {
61         return m_mbCodeCurrIdx;
62     }
63 
64     //!
65     //! \brief  Get the current MbCode buffer
66     //!
67     //! \return the current MbCode buffer
68     //!
GetCurrMbCodeBuffer()69     inline MOS_RESOURCE* GetCurrMbCodeBuffer()
70     {
71         return m_trackedBufCurrMbCode;
72     }
73 
74     //!
75     //! \brief  Get the current MvData buffer
76     //!
77     //! \return the current MvData buffer
78     //!
GetCurrMvDataBuffer()79     inline MOS_RESOURCE* GetCurrMvDataBuffer()
80     {
81         return m_trackedBufCurrMvData;
82     }
83 
84     //!
85     //! \brief  Get the current MV temporal buffer
86     //!
87     //! \return the current MV temporal buffer
88     //!
GetMvTemporalBuffer(uint8_t bufIndex)89     MOS_RESOURCE* GetMvTemporalBuffer(uint8_t bufIndex)
90     {
91         if (bufIndex == CODEC_CURR_TRACKED_BUFFER)
92         {
93             return m_trackedBufCurrMvTemporal;
94         }
95         else
96         {
97             return  (MOS_RESOURCE*)m_allocator->GetResource(m_standard, mvTemporalBuffer, bufIndex);
98         }
99     }
100 
101     //!
102     //! \brief  Get the current CSC surface
103     //!
104     //! \return the current CSC surface
105     //!
GetCscSurface(uint8_t bufIndex)106     MOS_SURFACE* GetCscSurface(uint8_t bufIndex)
107     {
108         if (bufIndex == CODEC_CURR_TRACKED_BUFFER)
109         {
110             return m_trackedBufCurrCsc;
111         }
112         else
113         {
114             return (MOS_SURFACE*)m_allocator->GetResource(m_standard, cscSurface, bufIndex);
115         }
116     }
117 
118     //!
119     //! \brief  Get the current 4x downscaled surface
120     //!
121     //! \return the current 4x downscaled surface
122     //!
Get4xDsSurface(uint8_t bufIndex)123     MOS_SURFACE* Get4xDsSurface(uint8_t bufIndex)
124     {
125         if (bufIndex == CODEC_CURR_TRACKED_BUFFER)
126         {
127             return m_trackedBufCurrDs4x;
128         }
129         else
130         {
131             return  (MOS_SURFACE*)m_allocator->GetResource(m_standard, ds4xSurface, bufIndex);
132         }
133     }
134 
135     //!
136     //! \brief  Get the current 2x downscaled surface
137     //!
138     //! \return the current 2x downscaled surface
139     //!
Get2xDsSurface(uint8_t bufIndex)140     MOS_SURFACE* Get2xDsSurface(uint8_t bufIndex)
141     {
142         if (bufIndex == CODEC_CURR_TRACKED_BUFFER)
143         {
144             return m_trackedBufCurrDs2x;
145         }
146         else
147         {
148             return  (MOS_SURFACE*)m_allocator->GetResource(m_standard, ds2xSurface, bufIndex);
149         }
150     }
151 
152     //!
153     //! \brief  Get the current 16x downscaled surface
154     //!
155     //! \return the current 16x downscaled surface
156     //!
Get16xDsSurface(uint8_t bufIndex)157     MOS_SURFACE* Get16xDsSurface(uint8_t bufIndex)
158     {
159         if (bufIndex == CODEC_CURR_TRACKED_BUFFER)
160         {
161             return m_trackedBufCurrDs16x;
162         }
163         else
164         {
165             return  (MOS_SURFACE*)m_allocator->GetResource(m_standard, ds16xSurface, bufIndex);
166         }
167     }
168 
169     //!
170     //! \brief  Get the current 32x downscaled surface
171     //!
172     //! \return the current 32x downscaled surface
173     //!
Get32xDsSurface(uint8_t bufIndex)174     MOS_SURFACE* Get32xDsSurface(uint8_t bufIndex)
175     {
176         if (bufIndex == CODEC_CURR_TRACKED_BUFFER)
177         {
178             return m_trackedBufCurrDs32x;
179         }
180         else
181         {
182             return  (MOS_SURFACE*)m_allocator->GetResource(m_standard, ds32xSurface, bufIndex);
183         }
184     }
185 
186     //!
187     //! \brief  Get the current 4x DsRecon surface
188     //!
189     //! \return the current 4x DsRecon buffer
190     //!
Get4xDsReconSurface(uint8_t bufIndex)191     inline MOS_SURFACE* Get4xDsReconSurface(uint8_t bufIndex)
192     {
193         if (bufIndex == CODEC_CURR_TRACKED_BUFFER)
194         {
195             return m_trackedBufCurr4xDsRecon;
196         }
197         else
198         {
199             return (MOS_SURFACE*)m_allocator->GetResource(m_standard, ds4xRecon, bufIndex);
200         }
201     }
202 
203     //!
204     //! \brief  Get the current 8x DsRecon surface
205     //!
206     //! \return the current 8x DsRecon buffer
207     //!
Get8xDsReconSurface(uint8_t bufIndex)208     inline MOS_SURFACE* Get8xDsReconSurface(uint8_t bufIndex)
209     {
210         if (bufIndex == CODEC_CURR_TRACKED_BUFFER)
211         {
212             return m_trackedBufCurr8xDsRecon;
213         }
214         else
215         {
216             return (MOS_SURFACE*)m_allocator->GetResource(m_standard, ds8xRecon, bufIndex);
217         }
218     }
219 
220     //!
221     //! \brief  Get the wait flag for tracked buffer
222     //!
GetWait()223     inline bool GetWait()
224     {
225         return m_waitTrackedBuffer;
226     }
227 
228     //!
229     //! \brief  Get the wait flag for CSC surface
230     //!
GetWaitCsc()231     inline bool GetWaitCsc()
232     {
233         return m_waitCscSurface;
234     }
235 
236     //!
237     //! \brief  Get the allocation flag
238     //!
IsMbCodeAllocationNeeded()239     inline bool IsMbCodeAllocationNeeded()
240     {
241         return m_allocateMbCode;
242     }
243 
244     //!
245     //! \brief  Set allocation flag
246     //!
SetAllocationFlag(bool flag)247     inline void SetAllocationFlag(bool flag)
248     {
249         m_allocateMbCode = flag;
250     }
251 
252     //!
253     //! \brief  Allocate resource for current frame
254     //!
255     //! \return MOS_STATUS
256     //!         MOS_STATUS_SUCCESS if success, else fail reason
257     //!
258     MOS_STATUS AllocateForCurrFrame();
259 
260     //!
261     //! \brief  Resize the Tracked Buffer upon resolution change
262     //!
263     //! \return void
264     //!
265     void Resize();
266 
267     //!
268     //! \brief  Release the existing CSC surfaces upon resolution change
269     //!
270     //! \return void
271     //!
272     void ResizeCsc();
273 
274     //!
275     //! \brief    Allocate for Preenc, so far only set the buffer index for DS surface
276     //! \param    [in] bufIndex
277     //!           buffer index for DS surface
278     //!
279     //! \return   void
280     //!
281     void AllocateForCurrFramePreenc(uint8_t bufIndex);
282 
283     //!
284     //! \brief  Reset used for current frame flag
285     //!
286     void ResetUsedForCurrFrame();
287 
288     //!
289     //! \brief    Encoder pre enc look up buffer index
290     //! \param    [in] frameIdx
291     //!           frame Index
292     //! \param    [in] inCache
293     //!           Indicate if it's in cache
294     //! \return   uint8_t
295     //!           emptyEntry
296     //!
297     uint8_t PreencLookUpBufIndex(
298         uint8_t         frameIdx,
299         bool            *inCache);
300 
301     //!
302     //! \brief  Allocate Mb Code Resources
303     //!
304     //! \param  [in] bufIndex
305     //!         buffer index used
306     //!
307     //! \return MOS_STATUS
308     //!         MOS_STATUS_SUCCESS if success, else fail reason
309     //!
310     MOS_STATUS AllocateMbCodeResources(uint8_t bufIndex);
311 
312     //!
313     //! \brief  Allocate Mv Data Resources
314     //!
315     //! \param  [in] bufIndex
316     //!         buffer index used
317     //!
318     //! \return MOS_STATUS
319     //!         MOS_STATUS_SUCCESS if success, else fail reason
320     //!
321     MOS_STATUS AllocateMvDataResources(uint8_t bufIndex);
322 
323     //!
324     //! \brief    Allocate CSC surface or pick an existing one from the pool
325     //!
326     //! \return   MOS_STATUS
327     //!           MOS_STATUS_SUCCESS if success, else fail reason
328     //!
329     MOS_STATUS AllocateSurfaceCsc();
330 
331     //!
332     //! \brief    Allocate Copy surface or pick an existing one from the pool
333     //!
334     //! \return   MOS_STATUS
335     //!           MOS_STATUS_SUCCESS if success, else fail reason
336     //!
337     MOS_STATUS AllocateSurfaceCopy(MOS_FORMAT, uint32_t);
338 
339     MOS_STATUS ResizeSurfaceDS();
340 
341     MOS_STATUS ResizeDsReconSurfacesVdenc();
342 
343     //!
344     //! \brief    Allocate DS surface or pick an existing one from the pool
345     //!
346     //! \return   MOS_STATUS
347     //!           MOS_STATUS_SUCCESS if success, else fail reason
348     //!
349     MOS_STATUS AllocateSurfaceDS();
350 
351     //!
352     //! \brief    Allocate 2xDS surface or pick an existing one from the pool
353     //!
354     //! \return   MOS_STATUS
355     //!           MOS_STATUS_SUCCESS if success, else fail reason
356     //!
357     MOS_STATUS AllocateSurface2xDS();
358 
359     //!
360     //! \brief  Allocate Mv temporal buffer
361     //!
362     //! \param  [in] bufIndex
363     //!         buffer index used
364     //!
365     //! \return MOS_STATUS
366     //!         MOS_STATUS_SUCCESS if success, else fail reason
367     //!
368     virtual MOS_STATUS AllocateMvTemporalBuffer(uint8_t bufIndex);
369 
370     //!
371     //! \brief    Constructor
372     //!
373     CodechalEncodeTrackedBuffer(CodechalEncoderState* encoder);
374 
375     virtual ~CodechalEncodeTrackedBuffer();
376 
377 protected:
378     //!
379     //! \brief  Get slot for current frame
380     //!
381     //! \param  [in] refList
382     //!         Reference frame list
383     //! \param  [in] numRefFrame
384     //!         Number of reference frame
385     //! \param  [in] usedAsRef
386     //!         Current frame is used as reference or not
387     //!
388     //! \return uint8_t
389     //!         Index found
390     //!
391     uint8_t LookUpBufIndex(
392         PCODEC_PICTURE refList,
393         uint8_t        numRefFrame,
394         bool           usedAsRef);
395 
396     //!
397     //! \brief  Get slot for current frame's CSC surface
398     //!
399     //! \return uint8_t
400     //!         Index found
401     //!
402     uint8_t LookUpBufIndexCsc();
403 
404     //!
405     //! \brief  Release MbCode buffer
406     //!
407     //! \param  [in] bufIndex
408     //!         buffer index to be released
409     //!
410     //! \return void
411     //!
412     void ReleaseMbCode(uint8_t bufIndex);
413 
414     //!
415     //! \brief  Release MvData buffer
416     //!
417     //! \param  [in] bufIndex
418     //!         buffer index to be released
419     //!
420     //! \return void
421     //!
422     void ReleaseMvData(uint8_t bufIndex);
423 
424     //!
425     //! \brief    Release CSC surface
426     //!
427     //! \return   MOS_STATUS
428     //!           MOS_STATUS_SUCCESS if success, else fail reason
429     //!
430     void ReleaseSurfaceCsc(uint8_t index);
431 
432     //!
433     //! \brief  Release DS surface
434     //!
435     //! \param  [in] index
436     //!         buffer index to be released
437     //!
438     //! \return void
439     //!
440     void ReleaseSurfaceDS(uint8_t index);
441 
442     //!
443     //! \brief  Release DsRecon buffer
444     //!
445     //! \param  [in] bufIndex
446     //!         buffer index to be released
447     //!
448     //! \return void
449     //!
450     void ReleaseDsRecon(uint8_t bufIndex);
451 
452     //!
453     //! \brief  Defer-deallocate buffer used before resolution reset
454     //!
455     virtual void DeferredDeallocateOnResChange();
456 
457     CodechalEncoderState*           m_encoder = nullptr;                        //!< Pointer to ENCODER base class
458     CodechalEncodeAllocator*        m_allocator = nullptr;                      //!< Pointer to resource allocator
459 
460     MOS_RESOURCE*                   m_trackedBufCurrMbCode = nullptr;           //!< Pointer to current MbCode buffer
461     MOS_RESOURCE*                   m_trackedBufCurrMvData = nullptr;           //!< Pointer to current MvData buffer
462     MOS_RESOURCE*                   m_trackedBufCurrMvTemporal = nullptr;       //!< Pointer to current MV temporal buffer
463     MOS_SURFACE*                    m_trackedBufCurrCsc = nullptr;              //!< Pointer to current CSC surface
464     MOS_SURFACE*                    m_trackedBufCurrDs4x = nullptr;             //!< Pointer to current 4x downscaled surface
465     MOS_SURFACE*                    m_trackedBufCurrDs2x = nullptr;             //!< Pointer to current 2x downscaled surface
466     MOS_SURFACE*                    m_trackedBufCurrDs16x = nullptr;            //!< Pointer to current 16x downscaled surface
467     MOS_SURFACE*                    m_trackedBufCurrDs32x = nullptr;            //!< Pointer to current 32x downscaled surface
468     MOS_SURFACE*                    m_trackedBufCurr4xDsRecon = nullptr;        //!< Pointer to current 4x DsRecon buffer
469     MOS_SURFACE*                    m_trackedBufCurr8xDsRecon = nullptr;        //!< Pointer to current 8x DsRecon buffer
470 
471     uint32_t                        m_standard;                                 //!< The encode state's standard
472     uint8_t                         m_trackedBufCurrIdx = 0;                    //!< current tracked buffer index
473     uint8_t                         m_mbCodeCurrIdx = 0;                        //!< current MbCode buffer index
474     bool                            m_allocateMbCode = false;                   //!< need to allocate MbCode buffer for current frame
475     bool                            m_mbCodeIsTracked = true;                   //!< tracked buffer algorithm used to manage MbCode buffer
476 
477 private:
478     CodechalEncodeTrackedBuffer(const CodechalEncodeTrackedBuffer&) = delete;
479     CodechalEncodeTrackedBuffer& operator=(const CodechalEncodeTrackedBuffer&) = delete;
480 
LookUpBufIndexMbCode()481     virtual void LookUpBufIndexMbCode()
482     {
483         m_mbCodeCurrIdx = m_trackedBufCurrIdx;
484     }
485 
486     //!
487     //! \brief  Allocate Ds Recon Surfaces Vdenc
488     //!
489     //! \param  [in] bufIndex
490     //!         buffer index used
491     //!
492     //! \return MOS_STATUS
493     //!         MOS_STATUS_SUCCESS if success, else fail reason
494     //!
495     MOS_STATUS AllocateDsReconSurfacesVdenc();
496 
497     MOS_INTERFACE*          m_osInterface = nullptr;                            //!< OS interface
498 
499     uint8_t                 m_trackedBufNonRefIdx = 0;                          //!< current tracked buffer index when frame won't be used as ref
500     uint8_t                 m_trackedBufCountNonRef = 0;                        //!< counting number of tracked buffer when ring buffer is used
501     uint8_t                 m_trackedBufCountResize = 0;                        //!< 3 buffers to be delay-destructed during res change
502     uint8_t                 m_trackedBufPenuIdx = 0;                            //!< 2nd-to-last tracked buffer index
503     uint8_t                 m_trackedBufAnteIdx = 0;                            //!< 3rd-to-last tracked buffer index
504     bool                    m_waitTrackedBuffer = false;                        //!< wait to re-use tracked buffer
505 
506     uint8_t                 m_cscBufNonRefIdx = 0;                              //!< current CSC buffer index when ring buffer is used
507     uint8_t                 m_cscBufCountNonRef = 0;                            //!< counting number of CSC surface when ring buffer is used
508     uint8_t                 m_cscBufCurrIdx = 0;                                //!< curr copy buffer index
509     uint8_t                 m_cscBufPenuIdx = 0;                                //!< 2nd-to-last CSC buffer index
510     uint8_t                 m_cscBufAnteIdx = 0;                                //!< 3rd-to-last CSC buffer index
511     bool                    m_waitCscSurface = false;                           //!< wait to re-use CSC surface
512 
513     struct tracker
514     {
515         uint8_t             ucSurfIndex7bits;                                   //!< 0xFF means the entry can be re-used
516         bool                bUsedforCurFrame;                                   //!< Used for FEI Preenc to mark whether this enty can be reused in multi-call case
517     };
518     tracker                 m_tracker[CODEC_NUM_TRACKED_BUFFERS];
519 };
520 
521 #endif  // __CODECHAL_ENCODE_TRACKED_BUFFER_H__