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 21static 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 51static 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 93static 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 161static 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 213static 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 233static 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 activeStreams = thiz->mActiveStreams; 251 252 interface_unlock_shared(thiz); 253#else 254 result = SL_RESULT_FEATURE_UNSUPPORTED; 255#endif 256 257 XA_LEAVE_INTERFACE 258} 259 260 261static 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 275static 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 286void 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 315void IStreamInformation_deinit(void *self) { 316#ifdef ANDROID 317 IStreamInformation *thiz = (IStreamInformation *) self; 318 // explicit destructor 319 thiz->mStreamInfoTable.~Vector<StreamInfo>(); 320#endif 321} 322