1 /*
2 * Copyright (c) 2020, 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     decode_internal_target.h
24 //! \brief    Defines the interface for internal dest surface alloacted by driver
25 //!
26 
27 #ifndef __DECODE_INTERNAL_TARGET_H__
28 #define __DECODE_INTERNAL_TARGET_H__
29 
30 #include "decode_allocator.h"
31 #include "decode_utils.h"
32 #include "decode_basic_feature.h"
33 
34 namespace decode {
35 
36 class InternalTargets
37 {
38 public:
39     //!
40     //! \brief  InternalTargets constructor
41     //!
InternalTargets()42     InternalTargets() {};
43 
44     //!
45     //! \brief  InternalTargets deconstructor
46     //!
~InternalTargets()47     virtual ~InternalTargets()
48     {
49         DECODE_FUNC_CALL();
50 
51         if (m_allocator != nullptr)
52         {
53             for (auto &surface : m_activeSurfaces)
54             {
55                 m_allocator->Destroy(surface.second);
56             }
57             m_activeSurfaces.clear();
58 
59             for (auto &surface : m_aviableSurfaces)
60             {
61                 m_allocator->Destroy(surface);
62             }
63         }
64         m_aviableSurfaces.clear();
65     }
66 
67     //!
68     //! \brief  Initialize surfaces
69     //! \param  [in] allocator
70     //!         Reference to decode allocator
71     //! \return MOS_STATUS
72     //!         MOS_STATUS_SUCCESS if success, else fail reason
73     //!
Init(DecodeAllocator & allocator)74     MOS_STATUS Init(DecodeAllocator& allocator)
75     {
76         DECODE_FUNC_CALL();
77 
78         m_allocator    = &allocator;
79         DECODE_ASSERT(m_aviableSurfaces.empty());
80         DECODE_ASSERT(m_activeSurfaces.empty());
81 
82         return MOS_STATUS_SUCCESS;
83     }
84 
85     //!
86     //! \brief  Figure out surface for current picture, and add it to active surface list
87     //! \param  [in] frameIdx
88     //!         The frame index for current picture
89     //! \param  [in] dstSurface
90     //!         The requirement for the current surface
91     //! \param  [in] isMmcEnabled
92     //!         The MMC flag for currrent surface
93     //! \param  [in] resUsageType
94     //!         The resource usage for currrent surface
95     //! \param  [in] accessReq
96     //!         The access requirement for current surface
97     //! \return MOS_STATUS
98     //!         MOS_STATUS_SUCCESS if success, else fail reason
99     //!
100     MOS_STATUS ActiveCurSurf(uint32_t curFrameIdx, PMOS_SURFACE dstSurface, bool isMmcEnabled,
101         ResourceUsage resUsageType = resourceDefault, ResourceAccessReq accessReq = lockableVideoMem)
102     {
103         DECODE_FUNC_CALL();
104 
105         for (auto iter = m_activeSurfaces.begin(); iter!= m_activeSurfaces.end(); iter++)
106         {
107             if (curFrameIdx == iter->first)
108             {
109                 return MOS_STATUS_SUCCESS;
110             }
111         }
112 
113         if (m_aviableSurfaces.size() == 0)
114         {
115             m_currentSurface = m_allocator->AllocateSurface(
116                                             dstSurface->dwWidth,
117                                             MOS_ALIGN_CEIL(dstSurface->dwHeight, 8),
118                                             "Internal target surface",
119                                             dstSurface->Format,
120                                             isMmcEnabled,
121                                             resUsageType,
122                                             accessReq,
123                                             dstSurface->TileModeGMM);
124         }
125         else
126         {
127             auto iter = m_aviableSurfaces.begin();
128             m_currentSurface = *iter;
129             m_aviableSurfaces.erase(iter);
130             DECODE_CHK_STATUS(m_allocator->Resize(m_currentSurface,
131                                 dstSurface->dwWidth,
132                                 MOS_ALIGN_CEIL(dstSurface->dwHeight, 8),
133                                 accessReq,
134                                 false,
135                                 "Internal target surface"));
136         }
137 
138         DECODE_CHK_NULL(m_currentSurface);
139 
140         auto ret = m_activeSurfaces.insert(std::make_pair(curFrameIdx, m_currentSurface));
141         DECODE_CHK_COND(ret.second == false,
142             "Failed to active surface with index %d, maybe it is already existed",
143             ret.first->first);
144 
145         return MOS_STATUS_SUCCESS;
146     }
147 
148     //!
149     //! \brief  Update internal surfaces corresponding to reference list
150     //! \param  [in] curFrameIdx
151     //!         The frame index for current picture
152     //! \param  [in] refFrameList
153     //!         The frame indicies of reference frame list
154     //! \param  [in] fixedFrameIdx
155     //!         The frameIdx user wants to keep into the refFrameList
156     //!         Default value is 0xff
157     //! \return MOS_STATUS
158     //!         MOS_STATUS_SUCCESS if success, else fail reason
159     //!
160     MOS_STATUS UpdateRefList(uint32_t curFrameIdx, const std::vector<uint32_t> &refFrameList, uint32_t fixedFrameIdx = 0xff)
161     {
162         DECODE_FUNC_CALL();
163 
164         auto iter = m_activeSurfaces.begin();
165         while (iter != m_activeSurfaces.end())
166         {
167             if (iter->first == fixedFrameIdx)
168             {
169                 ++iter;
170                 continue;
171             }
172 
173             if (!IsReference(iter->first, curFrameIdx, refFrameList))
174             {
175                 auto buffer = iter->second;
176                 iter = m_activeSurfaces.erase(iter);
177 
178                 m_aviableSurfaces.push_back(buffer);
179             }
180             else
181             {
182                 ++iter;
183             }
184         }
185 
186         return MOS_STATUS_SUCCESS;
187     }
188 
189     //!
190     //! \brief  Return current internal surface for current frame
191     //! \return PMOS_SURFACE*
192     //!         Point to surface for current frame, nullptr if fail
193     //!
GetCurSurf()194     PMOS_SURFACE GetCurSurf() { return m_currentSurface; }
195 
196 protected:
197     //!
198     //! \brief  Check if the index of surface is persent in current reference list
199     //! \param  [in] frameIndex
200     //!         The frame index corresponding to surface
201     //! \param  [in] frameIdx
202     //!         The frame index for current picture
203     //! \param  [in] refFrameList
204     //!         The frame indicies of reference frame list
205     //! \return bool
206     //!         True if surface is using by current frame, false if not
207     //!
IsReference(uint32_t frameIdx,uint32_t curFrameIdx,const std::vector<uint32_t> & refFrameList)208     bool IsReference(uint32_t frameIdx, uint32_t curFrameIdx, const std::vector<uint32_t> &refFrameList)
209     {
210         DECODE_FUNC_CALL();
211 
212         if (frameIdx == curFrameIdx)
213         {
214             return false;
215         }
216 
217         for(auto iter : refFrameList)
218         {
219             if (frameIdx == iter)
220             {
221                 return true;
222             }
223         }
224 
225         return false;
226     }
227 
228 private:
229     std::map<uint32_t, PMOS_SURFACE> m_activeSurfaces;           //!< Active surfaces corresponding to current reference frame list
230     std::vector<PMOS_SURFACE>        m_aviableSurfaces;          //!< Surfaces in idle
231     PMOS_SURFACE                     m_currentSurface = nullptr; //!< Point to surface of current picture
232     DecodeAllocator*                 m_allocator = nullptr;
233 
234 MEDIA_CLASS_DEFINE_END(decode__InternalTargets)
235 };
236 
237 }  // namespace decode
238 #endif // !__DECODE_INTERNAL_TARGET_H__
239