1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* StreamInformation implementation */
18 
19 #include "sles_allinclusive.h"
20 
IStreamInformation_QueryMediaContainerInformation(XAStreamInformationItf self,XAMediaContainerInformation * info)21 static XAresult IStreamInformation_QueryMediaContainerInformation( XAStreamInformationItf self,
22         XAMediaContainerInformation * info /* [out] */)
23 {
24     XA_ENTER_INTERFACE
25 
26     if (NULL == info) {
27         result = XA_RESULT_PARAMETER_INVALID;
28         XA_LEAVE_INTERFACE
29     }
30 
31 #ifdef ANDROID
32     IStreamInformation *thiz = (IStreamInformation *) self;
33     interface_lock_shared(thiz);
34     // always storing container info at index 0, as per spec
35     *info = thiz->mStreamInfoTable.itemAt(0).containerInfo;
36     interface_unlock_shared(thiz);
37     // even though the pointer to the media container info is returned, the values aren't set
38     //  for the actual container in this version, they are simply initialized to defaults
39     //  (see IStreamInformation_init)
40     result = XA_RESULT_SUCCESS;
41 #else
42     SL_LOGE("QueryMediaContainerInformation is unsupported");
43     memset(info, 0, sizeof(XAMediaContainerInformation));
44     result = XA_RESULT_FEATURE_UNSUPPORTED;
45 #endif
46 
47     XA_LEAVE_INTERFACE
48 }
49 
50 
IStreamInformation_QueryStreamType(XAStreamInformationItf self,XAuint32 streamIndex,XAuint32 * domain)51 static XAresult IStreamInformation_QueryStreamType( XAStreamInformationItf self,
52         XAuint32 streamIndex, /* [in] */
53         XAuint32 *domain)     /* [out] */
54 {
55     XA_ENTER_INTERFACE
56 
57     if (NULL == domain) {
58         result = XA_RESULT_PARAMETER_INVALID;
59         XA_LEAVE_INTERFACE;
60     }
61 
62 #ifndef ANDROID
63     *domain = XA_DOMAINTYPE_UNKNOWN;
64 #else
65     if (0 == streamIndex) {
66         // stream 0 is reserved for the container
67         result = XA_RESULT_PARAMETER_INVALID;
68         *domain = XA_DOMAINTYPE_UNKNOWN;
69     } else {
70         IStreamInformation *thiz = (IStreamInformation *) self;
71 
72         interface_lock_shared(thiz);
73 
74         XAuint32 nbStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams;
75         // streams in the container are numbered 1..nbStreams
76         if (streamIndex <= nbStreams) {
77             result = XA_RESULT_SUCCESS;
78             *domain = thiz->mStreamInfoTable.itemAt(streamIndex).domain;
79         } else {
80             SL_LOGE("Querying stream type for stream %d, only %d streams available",
81                     streamIndex, nbStreams);
82             result = XA_RESULT_PARAMETER_INVALID;
83         }
84 
85         interface_unlock_shared(thiz);
86     }
87 #endif
88 
89     XA_LEAVE_INTERFACE
90 }
91 
92 
IStreamInformation_QueryStreamInformation(XAStreamInformationItf self,XAuint32 streamIndex,void * info)93 static XAresult IStreamInformation_QueryStreamInformation( XAStreamInformationItf self,
94         XAuint32 streamIndex, /* [in] */
95         void * info)          /* [out] */
96 {
97     XA_ENTER_INTERFACE
98 
99     if (NULL == info) {
100         result = XA_RESULT_PARAMETER_INVALID;
101     } else {
102 
103 #ifndef ANDROID
104         result = XA_RESULT_FEATURE_UNSUPPORTED;
105 #else
106 
107         IStreamInformation *thiz = (IStreamInformation *) self;
108 
109         interface_lock_shared(thiz);
110 
111         XAuint32 nbStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams;
112         // stream 0 is the container, and other streams in the container are numbered 1..nbStreams
113         if (streamIndex <= nbStreams) {
114             result = XA_RESULT_SUCCESS;
115             const StreamInfo& streamInfo = thiz->mStreamInfoTable.itemAt((size_t)streamIndex);
116 
117             switch (streamInfo.domain) {
118             case XA_DOMAINTYPE_CONTAINER:
119                 *(XAMediaContainerInformation *)info = streamInfo.containerInfo;
120                 break;
121             case XA_DOMAINTYPE_AUDIO:
122                 *(XAAudioStreamInformation *)info = streamInfo.audioInfo;
123                 break;
124             case XA_DOMAINTYPE_VIDEO:
125                 *(XAVideoStreamInformation *)info = streamInfo.videoInfo;
126                 break;
127             case XA_DOMAINTYPE_IMAGE:
128                 *(XAImageStreamInformation *)info = streamInfo.imageInfo;
129                 break;
130             case XA_DOMAINTYPE_TIMEDTEXT:
131                 *(XATimedTextStreamInformation *)info = streamInfo.textInfo;
132                 break;
133             case XA_DOMAINTYPE_MIDI:
134                 *(XAMIDIStreamInformation *)info = streamInfo.midiInfo;
135                 break;
136             case XA_DOMAINTYPE_VENDOR:
137                 *(XAVendorStreamInformation *)info = streamInfo.vendorInfo;
138                 break;
139             default:
140                 SL_LOGE("StreamInformation::QueryStreamInformation index %u has "
141                         "unknown domain %u", streamIndex, streamInfo.domain);
142                 result = XA_RESULT_INTERNAL_ERROR;
143                 break;
144             }
145 
146         } else {
147             SL_LOGE("Querying stream type for stream %d, only %d streams available",
148                     streamIndex, nbStreams);
149             result = XA_RESULT_PARAMETER_INVALID;
150         }
151 
152         interface_unlock_shared(thiz);
153 #endif
154 
155     }
156 
157     XA_LEAVE_INTERFACE
158 }
159 
160 
IStreamInformation_QueryStreamName(XAStreamInformationItf self,XAuint32 streamIndex,XAuint16 * pNameSize,XAchar * pName)161 static XAresult IStreamInformation_QueryStreamName( XAStreamInformationItf self,
162         XAuint32 streamIndex, /* [in] */
163         XAuint16 * pNameSize, /* [in/out] */
164         XAchar * pName)       /* [out] */
165 {
166     XA_ENTER_INTERFACE
167 
168     if (NULL == pNameSize || streamIndex == 0) {
169         result = XA_RESULT_PARAMETER_INVALID;
170     } else {
171 #ifdef ANDROID
172         IStreamInformation *thiz = (IStreamInformation *) self;
173         interface_lock_shared(thiz);
174 
175         XAuint32 nbStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams;
176         // streams in the container are numbered 1..nbStreams
177         if (streamIndex <= nbStreams) {
178             char streamName[16];        // large enough for the fixed format in next line
179             snprintf(streamName, sizeof(streamName), "stream%u", streamIndex);
180             size_t actualNameLength = strlen(streamName);
181             if (NULL == pName) {
182                 // application is querying the name length in order to allocate a buffer
183                 result = XA_RESULT_SUCCESS;
184             } else {
185                 SLuint16 availableNameLength = *pNameSize;
186                 if (actualNameLength > availableNameLength) {
187                     memcpy(pName, streamName, availableNameLength);
188                     result = XA_RESULT_BUFFER_INSUFFICIENT;
189                 } else if (actualNameLength == availableNameLength) {
190                     memcpy(pName, streamName, availableNameLength);
191                     result = XA_RESULT_SUCCESS;
192                 } else { // actualNameLength < availableNameLength
193                     memcpy(pName, streamName, actualNameLength + 1);
194                     result = XA_RESULT_SUCCESS;
195                 }
196             }
197             *pNameSize = actualNameLength;
198         } else {
199             result = XA_RESULT_PARAMETER_INVALID;
200         }
201 
202         interface_unlock_shared(thiz);
203 #else
204         SL_LOGE("unsupported XAStreamInformationItf function");
205         result = XA_RESULT_FEATURE_UNSUPPORTED;
206 #endif
207     }
208 
209     XA_LEAVE_INTERFACE
210 }
211 
212 
IStreamInformation_RegisterStreamChangeCallback(XAStreamInformationItf self,xaStreamEventChangeCallback callback,void * pContext)213 static XAresult IStreamInformation_RegisterStreamChangeCallback( XAStreamInformationItf self,
214         xaStreamEventChangeCallback callback, /* [in] */
215         void * pContext)                      /* [in] */
216 {
217     XA_ENTER_INTERFACE
218 
219     IStreamInformation *thiz = (IStreamInformation *) self;
220 
221     interface_lock_exclusive(thiz);
222 
223     thiz->mCallback = callback;
224     thiz->mContext = pContext;
225     result = SL_RESULT_SUCCESS;
226 
227     interface_unlock_exclusive(thiz);
228 
229     XA_LEAVE_INTERFACE
230 }
231 
232 
IStreamInformation_QueryActiveStreams(XAStreamInformationItf self,XAuint32 * numStreams,XAboolean * activeStreams)233 static XAresult IStreamInformation_QueryActiveStreams( XAStreamInformationItf self,
234         XAuint32 *numStreams,      /* [in/out] */
235         XAboolean *activeStreams)  /* [out] */
236 {
237     XA_ENTER_INTERFACE
238 
239     if (NULL == numStreams) {
240         result = XA_RESULT_PARAMETER_INVALID;
241         XA_LEAVE_INTERFACE;
242     }
243 
244 #ifdef ANDROID
245     IStreamInformation *thiz = (IStreamInformation *) self;
246     interface_lock_shared(thiz);
247 
248     result = XA_RESULT_SUCCESS;
249     *numStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams;
250     // FIXME not setting activeStreams
251 
252     interface_unlock_shared(thiz);
253 #else
254     result = SL_RESULT_FEATURE_UNSUPPORTED;
255 #endif
256 
257     XA_LEAVE_INTERFACE
258 }
259 
260 
IStreamInformation_SetActiveStream(XAStreamInformationItf self,XAuint32 streamNum,XAboolean active,XAboolean commitNow)261 static XAresult IStreamInformation_SetActiveStream( XAStreamInformationItf self,
262         XAuint32   streamNum, /* [in] */
263         XAboolean  active,    /* [in] */
264         XAboolean  commitNow) /* [in] */
265 {
266     XA_ENTER_INTERFACE
267 
268     SL_LOGE("unsupported XAStreamInformationItf function");
269     result = XA_RESULT_FEATURE_UNSUPPORTED;
270 
271     XA_LEAVE_INTERFACE
272 }
273 
274 
275 static const struct XAStreamInformationItf_ IStreamInformation_Itf = {
276     IStreamInformation_QueryMediaContainerInformation,
277     IStreamInformation_QueryStreamType,
278     IStreamInformation_QueryStreamInformation,
279     IStreamInformation_QueryStreamName,
280     IStreamInformation_RegisterStreamChangeCallback,
281     IStreamInformation_QueryActiveStreams,
282     IStreamInformation_SetActiveStream
283 };
284 
285 
IStreamInformation_init(void * self)286 void IStreamInformation_init(void *self)
287 {
288     SL_LOGV("IStreamInformation_init\n");
289     IStreamInformation *thiz = (IStreamInformation *) self;
290     thiz->mItf = &IStreamInformation_Itf;
291 
292     thiz->mCallback = NULL;
293     thiz->mContext = NULL;
294 
295     for (int i=0 ; i < NB_SUPPORTED_STREAMS ; i++) {
296         thiz->mActiveStreams[i] = XA_BOOLEAN_FALSE;
297     }
298 
299 #ifdef ANDROID
300     // placement new constructor for C++ field within C struct
301     (void) new (&thiz->mStreamInfoTable) android::Vector<StreamInfo>();
302     // initialize container info
303     StreamInfo contInf;
304     contInf.domain = XA_DOMAINTYPE_CONTAINER;
305     contInf.containerInfo.containerType = XA_CONTAINERTYPE_UNSPECIFIED;
306     contInf.containerInfo.mediaDuration = XA_TIME_UNKNOWN;
307     // FIXME shouldn't this be 1 ?
308     contInf.containerInfo.numStreams = 0;
309     // always storing container info at index 0, as per spec: here, the table was still empty
310     thiz->mStreamInfoTable.add(contInf);
311 #endif
312 }
313 
314 
IStreamInformation_deinit(void * self)315 void IStreamInformation_deinit(void *self) {
316 #ifdef ANDROID
317     IStreamInformation *thiz = (IStreamInformation *) self;
318     // explicit destructor
319     thiz->mStreamInfoTable.~Vector<StreamInfo>();
320 #endif
321 }
322