lin
2025-08-20 171e08343a9b6df6c31197f5b4800e8004800f5b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
/* VideoDecoderCapabilities implementation */
 
#include "sles_allinclusive.h"
#ifdef ANDROID
#include "android/VideoCodec_to_android.h"
#endif
 
 
static XAresult IVideoDecoderCapabilities_GetVideoDecoders(XAVideoDecoderCapabilitiesItf self,
    XAuint32 *pNumDecoders, XAuint32 *pDecoderIds)
{
    XA_ENTER_INTERFACE
 
    if (NULL == pNumDecoders) {
        result = XA_RESULT_PARAMETER_INVALID;
    } else {
        if (NULL == pDecoderIds) {
            // If pDecoderIds is NULL, pNumDecoders returns the number of decoders available.
#ifdef ANDROID
            *pNumDecoders = android::android_videoCodec_getNbDecoders();
#else
            *pNumDecoders = kMaxVideoDecoders;
#endif
 
        } else {
            // If pDecodersIds is non-NULL, as an input pNumDecoders specifies the size of the
            // pDecoderIds array and as an output it specifies the number of decoder IDs available
            // within the pDecoderIds array.
            XAuint32 numDecoders = *pNumDecoders;
#ifdef ANDROID
            const XAuint32 androidNbDecoders = android::android_videoCodec_getNbDecoders();
            if (androidNbDecoders < numDecoders) {
                *pNumDecoders = numDecoders = androidNbDecoders;
            }
            android::android_videoCodec_getDecoderIds(numDecoders, pDecoderIds);
#else
            if (kMaxVideoDecoders < numDecoders) {
                *pNumDecoders = numDecoders = kMaxVideoDecoders;
            }
            memcpy(pDecoderIds, VideoDecoderIds, numDecoders * sizeof(XAuint32));
#endif
        }
        result = XA_RESULT_SUCCESS;
    }
 
    XA_LEAVE_INTERFACE
}
 
 
static XAresult IVideoDecoderCapabilities_GetVideoDecoderCapabilities(
    XAVideoDecoderCapabilitiesItf self, XAuint32 decoderId, XAuint32 *pIndex,
    XAVideoCodecDescriptor *pDescriptor)
{
    XA_ENTER_INTERFACE
 
    if (NULL == pIndex) {
        result = XA_RESULT_PARAMETER_INVALID;
    } else {
        if (NULL == pDescriptor) {
            // pIndex returns the number of video decoders capability descriptions.
#ifdef ANDROID
            result = android::android_videoCodec_getProfileLevelCombinationNb(decoderId, pIndex);
#else
            // Generic implementation has zero profile/level combinations for all codecs,
            // but this is not allowed per spec:
            //    "Each decoder must support at least one profile/mode pair
            //    and therefore have at least one Codec Descriptor."
            *pIndex = 0;
            SL_LOGE("Generic implementation has no video decoder capabilities");
            result = XA_RESULT_PARAMETER_INVALID;
#endif
        } else {
            // pIndex is an incrementing value used to enumerate capability descriptions.
#ifdef ANDROID
            result = android::android_videoCodec_getProfileLevelCombination(decoderId, *pIndex,
                    pDescriptor);
#else
            // For the generic implementation, any index >= 0 is out of range
#if 1   // not sure if this is needed, it's not being done for the Android case
            pDescriptor->codecId = decoderId;
#endif
            SL_LOGE("Generic implementation has no video decoder capabilities");
            result = XA_RESULT_PARAMETER_INVALID;
#endif
        }
    }
 
    XA_LEAVE_INTERFACE
}
 
 
static const struct XAVideoDecoderCapabilitiesItf_ IVideoDecoderCapabilities_Itf = {
    IVideoDecoderCapabilities_GetVideoDecoders,
    IVideoDecoderCapabilities_GetVideoDecoderCapabilities
};
 
void IVideoDecoderCapabilities_init(void *self)
{
    IVideoDecoderCapabilities *thiz = (IVideoDecoderCapabilities *) self;
    thiz->mItf = &IVideoDecoderCapabilities_Itf;
}
 
 
bool IVideoDecoderCapabilities_expose(void *self)
{
#ifdef ANDROID
    // This is an Engine object interface, so we allocate the associated resources every time
    //   the interface is exposed on the Engine object and free them when the object is about
    //   to be destroyed (see IVideoDecoderCapabilities_deinit), not just once during the
    //   lifetime of the process.
    return android::android_videoCodec_expose();
#else
    return false;
#endif
}
 
 
void IVideoDecoderCapabilities_deinit(void *self)
{
    SL_LOGV("IVideoDecoderCapabilities_deinit()");
#ifdef ANDROID
    android::android_videoCodec_deinit();
#endif
}