/* * 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 }