| /* |
| * 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. |
| */ |
| |
| /* StreamInformation implementation */ |
| |
| #include "sles_allinclusive.h" |
| |
| static XAresult IStreamInformation_QueryMediaContainerInformation( XAStreamInformationItf self, |
| XAMediaContainerInformation * info /* [out] */) |
| { |
| XA_ENTER_INTERFACE |
| |
| if (NULL == info) { |
| result = XA_RESULT_PARAMETER_INVALID; |
| XA_LEAVE_INTERFACE |
| } |
| |
| #ifdef ANDROID |
| IStreamInformation *thiz = (IStreamInformation *) self; |
| interface_lock_shared(thiz); |
| // always storing container info at index 0, as per spec |
| *info = thiz->mStreamInfoTable.itemAt(0).containerInfo; |
| interface_unlock_shared(thiz); |
| // even though the pointer to the media container info is returned, the values aren't set |
| // for the actual container in this version, they are simply initialized to defaults |
| // (see IStreamInformation_init) |
| result = XA_RESULT_SUCCESS; |
| #else |
| SL_LOGE("QueryMediaContainerInformation is unsupported"); |
| memset(info, 0, sizeof(XAMediaContainerInformation)); |
| result = XA_RESULT_FEATURE_UNSUPPORTED; |
| #endif |
| |
| XA_LEAVE_INTERFACE |
| } |
| |
| |
| static XAresult IStreamInformation_QueryStreamType( XAStreamInformationItf self, |
| XAuint32 streamIndex, /* [in] */ |
| XAuint32 *domain) /* [out] */ |
| { |
| XA_ENTER_INTERFACE |
| |
| if (NULL == domain) { |
| result = XA_RESULT_PARAMETER_INVALID; |
| XA_LEAVE_INTERFACE; |
| } |
| |
| #ifndef ANDROID |
| *domain = XA_DOMAINTYPE_UNKNOWN; |
| #else |
| if (0 == streamIndex) { |
| // stream 0 is reserved for the container |
| result = XA_RESULT_PARAMETER_INVALID; |
| *domain = XA_DOMAINTYPE_UNKNOWN; |
| } else { |
| IStreamInformation *thiz = (IStreamInformation *) self; |
| |
| interface_lock_shared(thiz); |
| |
| XAuint32 nbStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams; |
| // streams in the container are numbered 1..nbStreams |
| if (streamIndex <= nbStreams) { |
| result = XA_RESULT_SUCCESS; |
| *domain = thiz->mStreamInfoTable.itemAt(streamIndex).domain; |
| } else { |
| SL_LOGE("Querying stream type for stream %d, only %d streams available", |
| streamIndex, nbStreams); |
| result = XA_RESULT_PARAMETER_INVALID; |
| } |
| |
| interface_unlock_shared(thiz); |
| } |
| #endif |
| |
| XA_LEAVE_INTERFACE |
| } |
| |
| |
| static XAresult IStreamInformation_QueryStreamInformation( XAStreamInformationItf self, |
| XAuint32 streamIndex, /* [in] */ |
| void * info) /* [out] */ |
| { |
| XA_ENTER_INTERFACE |
| |
| if (NULL == info) { |
| result = XA_RESULT_PARAMETER_INVALID; |
| } else { |
| |
| #ifndef ANDROID |
| result = XA_RESULT_FEATURE_UNSUPPORTED; |
| #else |
| |
| IStreamInformation *thiz = (IStreamInformation *) self; |
| |
| interface_lock_shared(thiz); |
| |
| XAuint32 nbStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams; |
| // stream 0 is the container, and other streams in the container are numbered 1..nbStreams |
| if (streamIndex <= nbStreams) { |
| result = XA_RESULT_SUCCESS; |
| const StreamInfo& streamInfo = thiz->mStreamInfoTable.itemAt((size_t)streamIndex); |
| |
| switch (streamInfo.domain) { |
| case XA_DOMAINTYPE_CONTAINER: |
| *(XAMediaContainerInformation *)info = streamInfo.containerInfo; |
| break; |
| case XA_DOMAINTYPE_AUDIO: |
| *(XAAudioStreamInformation *)info = streamInfo.audioInfo; |
| break; |
| case XA_DOMAINTYPE_VIDEO: |
| *(XAVideoStreamInformation *)info = streamInfo.videoInfo; |
| break; |
| case XA_DOMAINTYPE_IMAGE: |
| *(XAImageStreamInformation *)info = streamInfo.imageInfo; |
| break; |
| case XA_DOMAINTYPE_TIMEDTEXT: |
| *(XATimedTextStreamInformation *)info = streamInfo.textInfo; |
| break; |
| case XA_DOMAINTYPE_MIDI: |
| *(XAMIDIStreamInformation *)info = streamInfo.midiInfo; |
| break; |
| case XA_DOMAINTYPE_VENDOR: |
| *(XAVendorStreamInformation *)info = streamInfo.vendorInfo; |
| break; |
| default: |
| SL_LOGE("StreamInformation::QueryStreamInformation index %u has " |
| "unknown domain %u", streamIndex, streamInfo.domain); |
| result = XA_RESULT_INTERNAL_ERROR; |
| break; |
| } |
| |
| } else { |
| SL_LOGE("Querying stream type for stream %d, only %d streams available", |
| streamIndex, nbStreams); |
| result = XA_RESULT_PARAMETER_INVALID; |
| } |
| |
| interface_unlock_shared(thiz); |
| #endif |
| |
| } |
| |
| XA_LEAVE_INTERFACE |
| } |
| |
| |
| static XAresult IStreamInformation_QueryStreamName( XAStreamInformationItf self, |
| XAuint32 streamIndex, /* [in] */ |
| XAuint16 * pNameSize, /* [in/out] */ |
| XAchar * pName) /* [out] */ |
| { |
| XA_ENTER_INTERFACE |
| |
| if (NULL == pNameSize || streamIndex == 0) { |
| result = XA_RESULT_PARAMETER_INVALID; |
| } else { |
| #ifdef ANDROID |
| IStreamInformation *thiz = (IStreamInformation *) self; |
| interface_lock_shared(thiz); |
| |
| XAuint32 nbStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams; |
| // streams in the container are numbered 1..nbStreams |
| if (streamIndex <= nbStreams) { |
| char streamName[16]; // large enough for the fixed format in next line |
| snprintf(streamName, sizeof(streamName), "stream%u", streamIndex); |
| size_t actualNameLength = strlen(streamName); |
| if (NULL == pName) { |
| // application is querying the name length in order to allocate a buffer |
| result = XA_RESULT_SUCCESS; |
| } else { |
| SLuint16 availableNameLength = *pNameSize; |
| if (actualNameLength > availableNameLength) { |
| memcpy(pName, streamName, availableNameLength); |
| result = XA_RESULT_BUFFER_INSUFFICIENT; |
| } else if (actualNameLength == availableNameLength) { |
| memcpy(pName, streamName, availableNameLength); |
| result = XA_RESULT_SUCCESS; |
| } else { // actualNameLength < availableNameLength |
| memcpy(pName, streamName, actualNameLength + 1); |
| result = XA_RESULT_SUCCESS; |
| } |
| } |
| *pNameSize = actualNameLength; |
| } else { |
| result = XA_RESULT_PARAMETER_INVALID; |
| } |
| |
| interface_unlock_shared(thiz); |
| #else |
| SL_LOGE("unsupported XAStreamInformationItf function"); |
| result = XA_RESULT_FEATURE_UNSUPPORTED; |
| #endif |
| } |
| |
| XA_LEAVE_INTERFACE |
| } |
| |
| |
| static XAresult IStreamInformation_RegisterStreamChangeCallback( XAStreamInformationItf self, |
| xaStreamEventChangeCallback callback, /* [in] */ |
| void * pContext) /* [in] */ |
| { |
| XA_ENTER_INTERFACE |
| |
| IStreamInformation *thiz = (IStreamInformation *) self; |
| |
| interface_lock_exclusive(thiz); |
| |
| thiz->mCallback = callback; |
| thiz->mContext = pContext; |
| result = SL_RESULT_SUCCESS; |
| |
| interface_unlock_exclusive(thiz); |
| |
| XA_LEAVE_INTERFACE |
| } |
| |
| |
| static XAresult IStreamInformation_QueryActiveStreams( XAStreamInformationItf self, |
| XAuint32 *numStreams, /* [in/out] */ |
| XAboolean *activeStreams) /* [out] */ |
| { |
| XA_ENTER_INTERFACE |
| |
| if (NULL == numStreams) { |
| result = XA_RESULT_PARAMETER_INVALID; |
| XA_LEAVE_INTERFACE; |
| } |
| |
| #ifdef ANDROID |
| IStreamInformation *thiz = (IStreamInformation *) self; |
| interface_lock_shared(thiz); |
| |
| result = XA_RESULT_SUCCESS; |
| *numStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams; |
| activeStreams = thiz->mActiveStreams; |
| |
| interface_unlock_shared(thiz); |
| #else |
| result = SL_RESULT_FEATURE_UNSUPPORTED; |
| #endif |
| |
| XA_LEAVE_INTERFACE |
| } |
| |
| |
| static XAresult IStreamInformation_SetActiveStream( XAStreamInformationItf self, |
| XAuint32 streamNum, /* [in] */ |
| XAboolean active, /* [in] */ |
| XAboolean commitNow) /* [in] */ |
| { |
| XA_ENTER_INTERFACE |
| |
| SL_LOGE("unsupported XAStreamInformationItf function"); |
| result = XA_RESULT_FEATURE_UNSUPPORTED; |
| |
| XA_LEAVE_INTERFACE |
| } |
| |
| |
| static const struct XAStreamInformationItf_ IStreamInformation_Itf = { |
| IStreamInformation_QueryMediaContainerInformation, |
| IStreamInformation_QueryStreamType, |
| IStreamInformation_QueryStreamInformation, |
| IStreamInformation_QueryStreamName, |
| IStreamInformation_RegisterStreamChangeCallback, |
| IStreamInformation_QueryActiveStreams, |
| IStreamInformation_SetActiveStream |
| }; |
| |
| |
| void IStreamInformation_init(void *self) |
| { |
| SL_LOGV("IStreamInformation_init\n"); |
| IStreamInformation *thiz = (IStreamInformation *) self; |
| thiz->mItf = &IStreamInformation_Itf; |
| |
| thiz->mCallback = NULL; |
| thiz->mContext = NULL; |
| |
| for (int i=0 ; i < NB_SUPPORTED_STREAMS ; i++) { |
| thiz->mActiveStreams[i] = XA_BOOLEAN_FALSE; |
| } |
| |
| #ifdef ANDROID |
| // placement new constructor for C++ field within C struct |
| (void) new (&thiz->mStreamInfoTable) android::Vector<StreamInfo>(); |
| // initialize container info |
| StreamInfo contInf; |
| contInf.domain = XA_DOMAINTYPE_CONTAINER; |
| contInf.containerInfo.containerType = XA_CONTAINERTYPE_UNSPECIFIED; |
| contInf.containerInfo.mediaDuration = XA_TIME_UNKNOWN; |
| // FIXME shouldn't this be 1 ? |
| contInf.containerInfo.numStreams = 0; |
| // always storing container info at index 0, as per spec: here, the table was still empty |
| thiz->mStreamInfoTable.add(contInf); |
| #endif |
| } |
| |
| |
| void IStreamInformation_deinit(void *self) { |
| #ifdef ANDROID |
| IStreamInformation *thiz = (IStreamInformation *) self; |
| // explicit destructor |
| thiz->mStreamInfoTable.~Vector<StreamInfo>(); |
| #endif |
| } |