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     media_ddi_prot.cpp
24 //! \brief    The class implementation of DdiMediaProtected base for all protected session
25 //!
26 
27 #include "codec_def_common_encode.h"
28 #include "codec_def_encode_jpeg.h"
29 #include "media_libva_util.h"
30 #include "media_libva_caps.h"
31 #include "media_libva.h"
32 #include "media_libva_caps_cp_interface.h"
33 #include "media_ddi_prot.h"
34 
35 static bool isDefaultRegistered = DdiProtectedFactory::Register<DdiMediaProtected>(DDI_PROTECTED_DEFAULT);
36 static bool isProtectedContentRegistered = DdiProtectedFactory::Register<DdiMediaProtected>(DDI_PROTECTED_CONTENT);
37 
38 std::map<uint32_t, DdiMediaProtected*> DdiMediaProtected::_impl;
39 
GetInstance(uint32_t id)40 DdiMediaProtected* DdiMediaProtected::GetInstance(uint32_t id)
41 {
42     if (_impl[id] == nullptr)
43     {
44         _impl[id] = DdiProtectedFactory::Create(id);
45         if (_impl[id] == nullptr)
46         {
47             DDI_ASSERTMESSAGE("DdiProtectedFactory::Create fail with id=%d", id);
48             return nullptr;
49         }
50     }
51 
52     return _impl[id];
53 }
54 
FreeInstances()55 void DdiMediaProtected::FreeInstances()
56 {
57     std::map<uint32_t, DdiMediaProtected*>::iterator it;
58     for (it = _impl.begin(); it != _impl.end(); it++)
59     {
60         MOS_Delete(it->second);
61     }
62 }
63 
CheckEntrypointSupported(VAEntrypoint entrypoint)64 bool DdiMediaProtected::CheckEntrypointSupported(VAEntrypoint entrypoint)
65 {
66     return false;
67 }
68 
CheckAttribList(VAProfile profile,VAEntrypoint entrypoint,VAConfigAttrib * attrib,uint32_t numAttribs)69 bool DdiMediaProtected::CheckAttribList(
70     VAProfile profile,
71     VAEntrypoint entrypoint,
72     VAConfigAttrib* attrib,
73     uint32_t numAttribs)
74 {
75     return false;
76 }
77 
DdiMedia_CreateProtectedSession(VADriverContextP ctx,VAConfigID config_id,VAProtectedSessionID * protected_session)78 VAStatus DdiMediaProtected::DdiMedia_CreateProtectedSession(
79     VADriverContextP        ctx,
80     VAConfigID              config_id,
81     VAProtectedSessionID    *protected_session)
82 {
83     DDI_FUNCTION_ENTER();
84 
85     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
86     DDI_CHK_NULL(protected_session, "nullptr protected_session",    VA_STATUS_ERROR_INVALID_PARAMETER);
87 
88     VAStatus vaStatus = VA_STATUS_SUCCESS;
89     PDDI_MEDIA_CONTEXT mediaDrvCtx = DdiMedia_GetMediaContext(ctx);
90     DDI_CHK_NULL(mediaDrvCtx, "nullptr mediaDrvCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
91     DDI_CHK_NULL(mediaDrvCtx->m_caps, "nullptr mediaDrvCtx->m_caps", VA_STATUS_ERROR_INVALID_CONTEXT);
92 
93     MediaLibvaCapsCpInterface *cpCaps = mediaDrvCtx->m_caps->GetCpCaps();
94     DDI_CHK_NULL(cpCaps, "nullptr cpCaps", VA_STATUS_ERROR_INVALID_CONTEXT);
95 
96     if (cpCaps->IsCpConfigId(config_id))
97     {
98         DdiMediaProtected *prot = DdiMediaProtected::GetInstance(DDI_PROTECTED_CONTENT);
99 
100         DDI_CHK_NULL(prot, "nullptr prot", VA_STATUS_ERROR_ALLOCATION_FAILED);
101         vaStatus = prot->CreateProtectedSession(ctx, config_id - DDI_CP_GEN_CONFIG_ATTRIBUTES_BASE, protected_session);
102     }
103     else
104     {
105         DDI_ASSERTMESSAGE("DDI: Invalid config_id");
106         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
107     }
108 
109     DDI_FUNCTION_EXIT(vaStatus);
110     return vaStatus;
111 
112 }
113 
DdiMedia_DestroyProtectedSession(VADriverContextP ctx,VAProtectedSessionID protected_session)114 VAStatus DdiMediaProtected::DdiMedia_DestroyProtectedSession(
115     VADriverContextP        ctx,
116     VAProtectedSessionID    protected_session)
117 {
118     DDI_FUNCTION_ENTER();
119 
120     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
121 
122     VAStatus vaStatus = VA_STATUS_SUCCESS;
123     uint32_t            ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
124     void *ctxPtr = DdiMedia_GetContextFromProtectedSessionID(ctx, protected_session, &ctxType);
125 
126     if (ctxType == DDI_MEDIA_CONTEXT_TYPE_PROTECTED_CONTENT)
127     {
128         DdiMediaProtected *prot = DdiMediaProtected::GetInstance(DDI_PROTECTED_CONTENT);
129 
130         DDI_CHK_NULL(prot, "nullptr prot", VA_STATUS_ERROR_ALLOCATION_FAILED);
131         vaStatus = prot->DestroyProtectedSession(ctx, protected_session);
132     }
133     else
134     {
135         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
136     }
137 
138     DDI_FUNCTION_EXIT(vaStatus);
139     return vaStatus;
140 }
141 
DdiMedia_AttachProtectedSession(VADriverContextP ctx,VAContextID context,VAProtectedSessionID protected_session)142 VAStatus DdiMediaProtected::DdiMedia_AttachProtectedSession(
143     VADriverContextP        ctx,
144     VAContextID             context,
145     VAProtectedSessionID    protected_session)
146 {
147     DDI_FUNCTION_ENTER();
148 
149     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
150 
151     VAStatus vaStatus = VA_STATUS_SUCCESS;
152     uint32_t ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
153     void     *ctxPtr = DdiMedia_GetContextFromProtectedSessionID(ctx, protected_session, &ctxType);
154     DDI_CHK_NULL(ctxPtr,      "nullptr ctxPtr",     VA_STATUS_ERROR_INVALID_CONTEXT);
155 
156     if (ctxType == DDI_MEDIA_CONTEXT_TYPE_PROTECTED_CONTENT)
157     {
158         DdiMediaProtected *prot = DdiMediaProtected::GetInstance(DDI_PROTECTED_CONTENT);
159 
160         DDI_CHK_NULL(prot, "nullptr prot", VA_STATUS_ERROR_ALLOCATION_FAILED);
161         vaStatus = prot->AttachProtectedSession(ctx, context, protected_session);
162     }
163     else
164     {
165         DDI_ASSERTMESSAGE("DDI: Invalid protected_session");
166         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
167     }
168 
169     DDI_FUNCTION_EXIT(vaStatus);
170     return vaStatus;
171 }
172 
DdiMedia_DetachProtectedSession(VADriverContextP ctx,VAContextID context)173 VAStatus DdiMediaProtected::DdiMedia_DetachProtectedSession(
174     VADriverContextP        ctx,
175     VAContextID             context)
176 {
177     DDI_FUNCTION_ENTER();
178 
179     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
180 
181     VAStatus vaStatus = VA_STATUS_SUCCESS;
182     if (context != 0)
183     {
184         uint32_t ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
185         void     *ctxPtr = DdiMedia_GetContextFromContextID(ctx, context, &ctxType);
186         DDI_CHK_NULL(ctxPtr, "nullptr ctxPtr", VA_STATUS_ERROR_INVALID_CONTEXT);
187         if (ctxType != DDI_MEDIA_CONTEXT_TYPE_DECODER &&
188             ctxType != DDI_MEDIA_CONTEXT_TYPE_ENCODER &&
189             ctxType != DDI_MEDIA_CONTEXT_TYPE_VP)
190         {
191             DDI_ASSERTMESSAGE("wrong context type %d", ctxType);
192             return VA_STATUS_ERROR_INVALID_CONTEXT;
193         }
194 
195         DdiMediaProtected *prot = DdiMediaProtected::GetInstance(DDI_PROTECTED_CONTENT);
196         DDI_CHK_NULL(prot, "nullptr prot", VA_STATUS_ERROR_ALLOCATION_FAILED);
197         vaStatus = prot->DetachProtectedSession(ctx, context);
198     }
199 
200     DDI_FUNCTION_EXIT(vaStatus);
201     return vaStatus;
202 }
203 
DdiMedia_ProtectedSessionExecute(VADriverContextP ctx,VAProtectedSessionID protected_session,VABufferID data)204 VAStatus DdiMediaProtected::DdiMedia_ProtectedSessionExecute(
205     VADriverContextP        ctx,
206     VAProtectedSessionID    protected_session,
207     VABufferID              data)
208 {
209     DDI_FUNCTION_ENTER();
210 
211     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
212 
213     VAStatus vaStatus = VA_STATUS_SUCCESS;
214     uint32_t ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
215     void     *ctxPtr = DdiMedia_GetContextFromProtectedSessionID(ctx, protected_session, &ctxType);
216     DDI_CHK_NULL(ctxPtr,      "nullptr ctxPtr",     VA_STATUS_ERROR_INVALID_CONTEXT);
217 
218     if (ctxType == DDI_MEDIA_CONTEXT_TYPE_PROTECTED_CONTENT)
219     {
220         DdiMediaProtected *prot = DdiMediaProtected::GetInstance(DDI_PROTECTED_CONTENT);
221 
222         DDI_CHK_NULL(prot, "nullptr prot", VA_STATUS_ERROR_ALLOCATION_FAILED);
223         vaStatus = prot->ProtectedSessionExecute(ctx, protected_session, data);
224     }
225     else
226     {
227         DDI_ASSERTMESSAGE("DDI: Invalid protected_session");
228         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
229     }
230 
231     return vaStatus;
232 }
233 
DdiMedia_ProtectedSessionCreateBuffer(VADriverContextP ctx,VAContextID context,VABufferType type,uint32_t size,uint32_t num_elements,void * data,VABufferID * bufId)234 VAStatus DdiMediaProtected::DdiMedia_ProtectedSessionCreateBuffer(
235     VADriverContextP        ctx,
236     VAContextID             context,
237     VABufferType            type,
238     uint32_t                size,
239     uint32_t                num_elements,
240     void                    *data,
241     VABufferID              *bufId)
242 {
243     DDI_FUNCTION_ENTER();
244 
245     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
246 
247     VAStatus vaStatus = VA_STATUS_SUCCESS;
248     uint32_t ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
249     void     *ctxPtr = DdiMedia_GetContextFromProtectedSessionID(ctx, context, &ctxType);
250     DDI_CHK_NULL(ctxPtr,      "nullptr ctxPtr",     VA_STATUS_ERROR_INVALID_CONTEXT);
251 
252     if (ctxType == DDI_MEDIA_CONTEXT_TYPE_PROTECTED_CONTENT)
253     {
254         DdiMediaProtected *prot = DdiMediaProtected::GetInstance(DDI_PROTECTED_CONTENT);
255 
256         DDI_CHK_NULL(prot, "nullptr prot", VA_STATUS_ERROR_ALLOCATION_FAILED);
257         vaStatus = prot->ProtectedSessionCreateBuffer(ctx, context, type, size, num_elements, data, bufId);
258     }
259     else
260     {
261         DDI_ASSERTMESSAGE("DDI: Invalid protected_session");
262         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
263     }
264 
265     return vaStatus;
266 }
267 
CreateProtectedSession(VADriverContextP ctx,VAConfigID config_id,VAProtectedSessionID * protected_session)268 VAStatus DdiMediaProtected::CreateProtectedSession(
269     VADriverContextP        ctx,
270     VAConfigID              config_id,
271     VAProtectedSessionID    *protected_session)
272 {
273     return VA_STATUS_ERROR_UNIMPLEMENTED;
274 }
275 
DestroyProtectedSession(VADriverContextP ctx,VAProtectedSessionID protected_session)276 VAStatus DdiMediaProtected::DestroyProtectedSession(
277     VADriverContextP        ctx,
278     VAProtectedSessionID    protected_session)
279 {
280     return VA_STATUS_ERROR_UNIMPLEMENTED;
281 }
282 
AttachProtectedSession(VADriverContextP ctx,VAContextID context,VAProtectedSessionID protected_session)283 VAStatus DdiMediaProtected::AttachProtectedSession(
284     VADriverContextP        ctx,
285     VAContextID             context,
286     VAProtectedSessionID    protected_session)
287 {
288     return VA_STATUS_ERROR_UNIMPLEMENTED;
289 }
290 
DetachProtectedSession(VADriverContextP ctx,VAContextID context)291 VAStatus DdiMediaProtected::DetachProtectedSession(
292     VADriverContextP        ctx,
293     VAContextID             context)
294 {
295     return VA_STATUS_ERROR_UNIMPLEMENTED;
296 }
297 
ProtectedSessionExecute(VADriverContextP ctx,VAProtectedSessionID protected_session,VABufferID data)298 VAStatus DdiMediaProtected::ProtectedSessionExecute(
299     VADriverContextP        ctx,
300     VAProtectedSessionID    protected_session,
301     VABufferID              data)
302 {
303     return VA_STATUS_ERROR_UNIMPLEMENTED;
304 }
305 
ProtectedSessionCreateBuffer(VADriverContextP ctx,VAProtectedSessionID protected_session,VABufferType type,uint32_t size,uint32_t num_elements,void * data,VABufferID * bufId)306 VAStatus DdiMediaProtected::ProtectedSessionCreateBuffer(
307     VADriverContextP        ctx,
308     VAProtectedSessionID    protected_session,
309     VABufferType            type,
310     uint32_t                size,
311     uint32_t                num_elements,
312     void                    *data,
313     VABufferID              *bufId)
314 {
315     return VA_STATUS_ERROR_UNIMPLEMENTED;
316 }
317 
GetProtectedSurfaceTag(PDDI_MEDIA_CONTEXT media_ctx)318 uint64_t DdiMediaProtected::GetProtectedSurfaceTag(PDDI_MEDIA_CONTEXT media_ctx)
319 {
320     return 0;
321 }
322 
DdiMedia_FreeProtectedSessionHeap(VADriverContextP ctx,PDDI_MEDIA_HEAP contextHeap,int32_t vaContextOffset,int32_t ctxNums)323 void DdiMedia_FreeProtectedSessionHeap(
324     VADriverContextP ctx,
325     PDDI_MEDIA_HEAP contextHeap,
326     int32_t vaContextOffset,
327     int32_t ctxNums)
328 {
329     PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT mediaContextHeapBase = (PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT)contextHeap->pHeapBase;
330     if (nullptr == mediaContextHeapBase)
331         return;
332 
333     for (int32_t elementId = 0; elementId < ctxNums; ++elementId)
334     {
335         PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT mediaContextHeapElmt = &mediaContextHeapBase[elementId];
336         if (nullptr == mediaContextHeapElmt->pVaContext)
337             continue;
338         VAContextID vaCtxID = (VAContextID)(mediaContextHeapElmt->uiVaContextID + vaContextOffset);
339         DdiMediaProtected::DdiMedia_DestroyProtectedSession(ctx, vaCtxID);
340     }
341 }
342 
DdiMedia_GetVaContextFromHeap(PDDI_MEDIA_HEAP mediaHeap,uint32_t index,PMEDIA_MUTEX_T mutex)343 static void* DdiMedia_GetVaContextFromHeap(
344     PDDI_MEDIA_HEAP mediaHeap,
345     uint32_t index,
346     PMEDIA_MUTEX_T mutex)
347 {
348     PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT  vaCtxHeapElmt = nullptr;
349     void                              *context = nullptr;
350 
351     DdiMediaUtil_LockMutex(mutex);
352     if(nullptr == mediaHeap || index >= mediaHeap->uiAllocatedHeapElements)
353     {
354         DdiMediaUtil_UnLockMutex(mutex);
355         return nullptr;
356     }
357     vaCtxHeapElmt  = (PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT)mediaHeap->pHeapBase;
358     vaCtxHeapElmt += index;
359     context        = vaCtxHeapElmt->pVaContext;
360     DdiMediaUtil_UnLockMutex(mutex);
361 
362     return context;
363 }
364 
DdiMedia_GetContextFromProtectedSessionID(VADriverContextP ctx,VAProtectedSessionID vaID,uint32_t * ctxType)365 void* DdiMedia_GetContextFromProtectedSessionID(
366     VADriverContextP ctx,
367     VAProtectedSessionID vaID,
368     uint32_t *ctxType)
369 {
370     PDDI_MEDIA_CONTEXT       mediaCtx = nullptr;
371     uint32_t                 heap_index = 0, prot_index = 0;
372     void                     *pSession = nullptr;
373 
374     DDI_CHK_NULL(ctx, "nullptr ctx", nullptr);
375     DDI_CHK_NULL(ctxType, "nullptr ctxType", nullptr);
376 
377     mediaCtx  = DdiMedia_GetMediaContext(ctx);
378     prot_index    = vaID & DDI_MEDIA_MASK_VACONTEXTID;
379     heap_index    = vaID & DDI_MEDIA_MASK_VAPROTECTEDSESSION_ID;
380 
381     if ((vaID&DDI_MEDIA_MASK_VACONTEXT_TYPE) != DDI_MEDIA_VACONTEXTID_OFFSET_PROT)
382     {
383         DDI_ASSERTMESSAGE("Invalid protected session: 0x%x", vaID);
384         *ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
385         return nullptr;
386     }
387 
388     // 0        ~ 0x8000000: LP context
389     // 0x8000000~0x10000000: CP context
390     if (prot_index < DDI_MEDIA_VACONTEXTID_OFFSET_PROT_CP)
391     {
392         DDI_VERBOSEMESSAGE("LP protected session detected: 0x%x", vaID);
393         *ctxType = DDI_MEDIA_CONTEXT_TYPE_PROTECTED_LINK;
394         return DdiMedia_GetVaContextFromHeap(mediaCtx->pProtCtxHeap, heap_index, &mediaCtx->ProtMutex);
395     }
396 
397     DDI_VERBOSEMESSAGE("CP protected session detected: 0x%x", vaID);
398     *ctxType = DDI_MEDIA_CONTEXT_TYPE_PROTECTED_CONTENT;
399     return DdiMedia_GetVaContextFromHeap(mediaCtx->pProtCtxHeap, heap_index, &mediaCtx->ProtMutex);
400 }
401