diff options
Diffstat (limited to 'media/libmedia')
-rw-r--r-- | media/libmedia/Android.mk | 4 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 169 | ||||
-rw-r--r-- | media/libmedia/IOMX.cpp | 85 | ||||
-rw-r--r-- | media/libmedia/IResourceManagerService.cpp | 2 | ||||
-rw-r--r-- | media/libmedia/MediaProfiles.cpp | 126 |
5 files changed, 183 insertions, 203 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 0c18828..a3c3d3c 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -7,7 +7,7 @@ LOCAL_SRC_FILES:= \ LOCAL_MODULE:= libmedia_helper LOCAL_MODULE_TAGS := optional -LOCAL_C_FLAGS += -Werror -Wall +LOCAL_C_FLAGS += -Werror -Wno-error=deprecated-declarations -Wall LOCAL_CLANG := true include $(BUILD_STATIC_LIBRARY) @@ -87,7 +87,7 @@ LOCAL_C_INCLUDES := \ $(call include-path-for, audio-effects) \ $(call include-path-for, audio-utils) -LOCAL_CFLAGS += -Werror -Wall +LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall LOCAL_CLANG := true include $(BUILD_SHARED_LIBRARY) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index faf5935..81ae6d7 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -38,11 +38,23 @@ static const int kMaxLoopCountNotifications = 32; namespace android { // --------------------------------------------------------------------------- +// TODO: Move to a separate .h + template <typename T> -const T &min(const T &x, const T &y) { +static inline const T &min(const T &x, const T &y) { return x < y ? x : y; } +template <typename T> +static inline const T &max(const T &x, const T &y) { + return x > y ? x : y; +} + +static inline nsecs_t framesToNanoseconds(ssize_t frames, uint32_t sampleRate, float speed) +{ + return ((double)frames * 1000000000) / ((double)sampleRate * speed); +} + static int64_t convertTimespecToUs(const struct timespec &tv) { return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000; @@ -480,6 +492,8 @@ status_t AudioTrack::set( mObservedSequence = mSequence; mInUnderrun = false; mPreviousTimestampValid = false; + mTimestampStartupGlitchReported = false; + mRetrogradeMotionReported = false; return NO_ERROR; } @@ -507,6 +521,8 @@ status_t AudioTrack::start() // reset current position as seen by client to 0 mPosition = 0; mPreviousTimestampValid = false; + mTimestampStartupGlitchReported = false; + mRetrogradeMotionReported = false; // For offloaded tracks, we don't know if the hardware counters are really zero here, // since the flush is asynchronous and stop may not fully drain. @@ -1111,31 +1127,27 @@ status_t AudioTrack::createTrack_l() // we must release it ourselves if anything goes wrong. // Not all of these values are needed under all conditions, but it is easier to get them all - - uint32_t afLatency; - status = AudioSystem::getLatency(output, &afLatency); + status = AudioSystem::getLatency(output, &mAfLatency); if (status != NO_ERROR) { ALOGE("getLatency(%d) failed status %d", output, status); goto release; } - ALOGV("createTrack_l() output %d afLatency %u", output, afLatency); + ALOGV("createTrack_l() output %d afLatency %u", output, mAfLatency); - size_t afFrameCount; - status = AudioSystem::getFrameCount(output, &afFrameCount); + status = AudioSystem::getFrameCount(output, &mAfFrameCount); if (status != NO_ERROR) { ALOGE("getFrameCount(output=%d) status %d", output, status); goto release; } - uint32_t afSampleRate; - status = AudioSystem::getSamplingRate(output, &afSampleRate); + status = AudioSystem::getSamplingRate(output, &mAfSampleRate); if (status != NO_ERROR) { ALOGE("getSamplingRate(output=%d) status %d", output, status); goto release; } if (mSampleRate == 0) { - mSampleRate = afSampleRate; - mOriginalSampleRate = afSampleRate; + mSampleRate = mAfSampleRate; + mOriginalSampleRate = mAfSampleRate; } // Client decides whether the track is TIMED (see below), but can only express a preference // for FAST. Server will perform additional tests. @@ -1148,9 +1160,9 @@ status_t AudioTrack::createTrack_l() // use case 3: obtain/release mode (mTransfer == TRANSFER_OBTAIN)) && // matching sample rate - (mSampleRate == afSampleRate))) { + (mSampleRate == mAfSampleRate))) { ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client; transfer %d, track %u Hz, output %u Hz", - mTransfer, mSampleRate, afSampleRate); + mTransfer, mSampleRate, mAfSampleRate); // once denied, do not request again if IAudioTrack is re-created mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST); } @@ -1171,7 +1183,7 @@ status_t AudioTrack::createTrack_l() // Same comment as below about ignoring frameCount parameter for set() frameCount = mSharedBuffer->size(); } else if (frameCount == 0) { - frameCount = afFrameCount; + frameCount = mAfFrameCount; } if (mNotificationFramesAct != frameCount) { mNotificationFramesAct = frameCount; @@ -1207,7 +1219,7 @@ status_t AudioTrack::createTrack_l() if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) { // for normal tracks precompute the frame count based on speed. const size_t minFrameCount = calculateMinFrameCount( - afLatency, afFrameCount, afSampleRate, mSampleRate, + mAfLatency, mAfFrameCount, mAfSampleRate, mSampleRate, mPlaybackRate.mSpeed); if (frameCount < minFrameCount) { frameCount = minFrameCount; @@ -1357,7 +1369,7 @@ status_t AudioTrack::createTrack_l() mAudioTrack->attachAuxEffect(mAuxEffectId); // FIXME doesn't take into account speed or future sample rate changes (until restoreTrack) // FIXME don't believe this lie - mLatency = afLatency + (1000*frameCount) / mSampleRate; + mLatency = mAfLatency + (1000*frameCount) / mSampleRate; mFrameCount = frameCount; // If IAudioTrack is re-created, don't let the requested frameCount @@ -1763,7 +1775,7 @@ nsecs_t AudioTrack::processAudioBuffer() // Cache other fields that will be needed soon uint32_t sampleRate = mSampleRate; float speed = mPlaybackRate.mSpeed; - uint32_t notificationFrames = mNotificationFramesAct; + const uint32_t notificationFrames = mNotificationFramesAct; if (mRefreshRemaining) { mRefreshRemaining = false; mRemainingFrames = notificationFrames; @@ -1801,7 +1813,14 @@ nsecs_t AudioTrack::processAudioBuffer() mLock.unlock(); + // get anchor time to account for callbacks. + const nsecs_t timeBeforeCallbacks = systemTime(); + if (waitStreamEnd) { + // FIXME: Instead of blocking in proxy->waitStreamEndDone(), Callback thread + // should wait on proxy futex and handle CBLK_STREAM_END_DONE within this function + // (and make sure we don't callback for more data while we're stopping). + // This helps with position, marker notifications, and track invalidation. struct timespec timeout; timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC; timeout.tv_nsec = 0; @@ -1886,12 +1905,17 @@ nsecs_t AudioTrack::processAudioBuffer() minFrames = kPoll * notificationFrames; } + // This "fudge factor" avoids soaking CPU, and compensates for late progress by server + static const nsecs_t kWaitPeriodNs = WAIT_PERIOD_MS * 1000000LL; + const nsecs_t timeAfterCallbacks = systemTime(); + // Convert frame units to time units nsecs_t ns = NS_WHENEVER; if (minFrames != (uint32_t) ~0) { - // This "fudge factor" avoids soaking CPU, and compensates for late progress by server - static const nsecs_t kFudgeNs = 10000000LL; // 10 ms - ns = ((double)minFrames * 1000000000) / ((double)sampleRate * speed) + kFudgeNs; + ns = framesToNanoseconds(minFrames, sampleRate, speed) + kWaitPeriodNs; + ns -= (timeAfterCallbacks - timeBeforeCallbacks); // account for callback time + // TODO: Should we warn if the callback time is too long? + if (ns < 0) ns = 0; } // If not supplying data by EVENT_MORE_DATA, then we're done @@ -1899,6 +1923,13 @@ nsecs_t AudioTrack::processAudioBuffer() return ns; } + // EVENT_MORE_DATA callback handling. + // Timing for linear pcm audio data formats can be derived directly from the + // buffer fill level. + // Timing for compressed data is not directly available from the buffer fill level, + // rather indirectly from waiting for blocking mode callbacks or waiting for obtain() + // to return a certain fill level. + struct timespec timeout; const struct timespec *requested = &ClientProxy::kForever; if (ns != NS_WHENEVER) { @@ -1929,12 +1960,15 @@ nsecs_t AudioTrack::processAudioBuffer() return NS_NEVER; } - if (mRetryOnPartialBuffer && !isOffloaded()) { + if (mRetryOnPartialBuffer && audio_is_linear_pcm(mFormat)) { mRetryOnPartialBuffer = false; if (avail < mRemainingFrames) { - int64_t myns = ((double)(mRemainingFrames - avail) * 1100000000) - / ((double)sampleRate * speed); - if (ns < 0 || myns < ns) { + if (ns > 0) { // account for obtain time + const nsecs_t timeNow = systemTime(); + ns = max((nsecs_t)0, ns - (timeNow - timeAfterCallbacks)); + } + nsecs_t myns = framesToNanoseconds(mRemainingFrames - avail, sampleRate, speed); + if (ns < 0 /* NS_WHENEVER */ || myns < ns) { ns = myns; } return ns; @@ -1957,7 +1991,42 @@ nsecs_t AudioTrack::processAudioBuffer() // Keep this thread going to handle timed events and // still try to get more data in intervals of WAIT_PERIOD_MS // but don't just loop and block the CPU, so wait - return WAIT_PERIOD_MS * 1000000LL; + + // mCbf(EVENT_MORE_DATA, ...) might either + // (1) Block until it can fill the buffer, returning 0 size on EOS. + // (2) Block until it can fill the buffer, returning 0 data (silence) on EOS. + // (3) Return 0 size when no data is available, does not wait for more data. + // + // (1) and (2) occurs with AudioPlayer/AwesomePlayer; (3) occurs with NuPlayer. + // We try to compute the wait time to avoid a tight sleep-wait cycle, + // especially for case (3). + // + // The decision to support (1) and (2) affect the sizing of mRemainingFrames + // and this loop; whereas for case (3) we could simply check once with the full + // buffer size and skip the loop entirely. + + nsecs_t myns; + if (audio_is_linear_pcm(mFormat)) { + // time to wait based on buffer occupancy + const nsecs_t datans = mRemainingFrames <= avail ? 0 : + framesToNanoseconds(mRemainingFrames - avail, sampleRate, speed); + // audio flinger thread buffer size (TODO: adjust for fast tracks) + const nsecs_t afns = framesToNanoseconds(mAfFrameCount, mAfSampleRate, speed); + // add a half the AudioFlinger buffer time to avoid soaking CPU if datans is 0. + myns = datans + (afns / 2); + } else { + // FIXME: This could ping quite a bit if the buffer isn't full. + // Note that when mState is stopping we waitStreamEnd, so it never gets here. + myns = kWaitPeriodNs; + } + if (ns > 0) { // account for obtain and callback time + const nsecs_t timeNow = systemTime(); + ns = max((nsecs_t)0, ns - (timeNow - timeAfterCallbacks)); + } + if (ns < 0 /* NS_WHENEVER */ || myns < ns) { + ns = myns; + } + return ns; } size_t releasedFrames = writtenSize / mFrameSize; @@ -2089,30 +2158,8 @@ bool AudioTrack::isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) co if (mStaticProxy != 0) { return true; // static tracks do not have issues with buffer sizing. } - status_t status; - uint32_t afLatency; - status = AudioSystem::getLatency(mOutput, &afLatency); - if (status != NO_ERROR) { - ALOGE("getLatency(%d) failed status %d", mOutput, status); - return false; - } - - size_t afFrameCount; - status = AudioSystem::getFrameCount(mOutput, &afFrameCount); - if (status != NO_ERROR) { - ALOGE("getFrameCount(output=%d) status %d", mOutput, status); - return false; - } - - uint32_t afSampleRate; - status = AudioSystem::getSamplingRate(mOutput, &afSampleRate); - if (status != NO_ERROR) { - ALOGE("getSamplingRate(output=%d) status %d", mOutput, status); - return false; - } - const size_t minFrameCount = - calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, speed); + calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed); ALOGV("isSampleRateSpeedAllowed_l mFrameCount %zu minFrameCount %zu", mFrameCount, minFrameCount); return mFrameCount >= minFrameCount; @@ -2175,7 +2222,12 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) } // Check whether a pending flush or stop has completed, as those commands may - // be asynchronous or return near finish. + // be asynchronous or return near finish or exhibit glitchy behavior. + // + // Originally this showed up as the first timestamp being a continuation of + // the previous song under gapless playback. + // However, we sometimes see zero timestamps, then a glitch of + // the previous song's position, and then correct timestamps afterwards. if (mStartUs != 0 && mSampleRate != 0) { static const int kTimeJitterUs = 100000; // 100 ms static const int k1SecUs = 1000000; @@ -2193,16 +2245,29 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) if (deltaPositionByUs > deltaTimeUs + kTimeJitterUs) { // Verify that the counter can't count faster than the sample rate - // since the start time. If greater, then that means we have failed + // since the start time. If greater, then that means we may have failed // to completely flush or stop the previous playing track. - ALOGW("incomplete flush or stop:" + ALOGW_IF(!mTimestampStartupGlitchReported, + "getTimestamp startup glitch detected" " deltaTimeUs(%lld) deltaPositionUs(%lld) tsmPosition(%u)", (long long)deltaTimeUs, (long long)deltaPositionByUs, timestamp.mPosition); + mTimestampStartupGlitchReported = true; + if (previousTimestampValid + && mPreviousTimestamp.mPosition == 0 /* should be true if valid */) { + timestamp = mPreviousTimestamp; + mPreviousTimestampValid = true; + return NO_ERROR; + } return WOULD_BLOCK; } + if (deltaPositionByUs != 0) { + mStartUs = 0; // don't check again, we got valid nonzero position. + } + } else { + mStartUs = 0; // don't check again, start time expired. } - mStartUs = 0; // no need to check again, start timestamp has either expired or unneeded. + mTimestampStartupGlitchReported = false; } } else { // Update the mapping between local consumed (mPosition) and server consumed (mServer) diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index c14debf..ca1cdc7 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -245,12 +245,13 @@ public: virtual status_t useBuffer( node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, - buffer_id *buffer) { + buffer_id *buffer, OMX_U32 allottedSize) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeStrongBinder(IInterface::asBinder(params)); + data.writeInt32(allottedSize); remote()->transact(USE_BUFFER, data, &reply); status_t err = reply.readInt32(); @@ -305,7 +306,7 @@ public: virtual status_t createInputSurface( node_id node, OMX_U32 port_index, - sp<IGraphicBufferProducer> *bufferProducer) { + sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) { Parcel data, reply; status_t err; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); @@ -317,6 +318,12 @@ public: return err; } + // read type even if createInputSurface failed + int negotiatedType = reply.readInt32(); + if (type != NULL) { + *type = (MetadataBufferType)negotiatedType; + } + err = reply.readInt32(); if (err != OK) { return err; @@ -355,7 +362,7 @@ public: virtual status_t setInputSurface( node_id node, OMX_U32 port_index, - const sp<IGraphicBufferConsumer> &bufferConsumer) { + const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); status_t err; @@ -369,6 +376,13 @@ public: ALOGW("binder transaction failed: %d", err); return err; } + + // read type even if setInputSurface failed + int negotiatedType = reply.readInt32(); + if (type != NULL) { + *type = (MetadataBufferType)negotiatedType; + } + return reply.readInt32(); } @@ -387,7 +401,7 @@ public: } virtual status_t storeMetaDataInBuffers( - node_id node, OMX_U32 port_index, OMX_BOOL enable) { + node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeInt32((int32_t)node); @@ -395,8 +409,13 @@ public: data.writeInt32((uint32_t)enable); remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply); - status_t err = reply.readInt32(); - return err; + // read type even storeMetaDataInBuffers failed + int negotiatedType = reply.readInt32(); + if (type != NULL) { + *type = (MetadataBufferType)negotiatedType; + } + + return reply.readInt32(); } virtual status_t prepareForAdaptivePlayback( @@ -459,12 +478,13 @@ public: virtual status_t allocateBufferWithBackup( node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, - buffer_id *buffer) { + buffer_id *buffer, OMX_U32 allottedSize) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeStrongBinder(IInterface::asBinder(params)); + data.writeInt32(allottedSize); remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); status_t err = reply.readInt32(); @@ -491,11 +511,15 @@ public: return reply.readInt32(); } - virtual status_t fillBuffer(node_id node, buffer_id buffer) { + virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeInt32((int32_t)node); data.writeInt32((int32_t)buffer); + data.writeInt32(fenceFd >= 0); + if (fenceFd >= 0) { + data.writeFileDescriptor(fenceFd, true /* takeOwnership */); + } remote()->transact(FILL_BUFFER, data, &reply); return reply.readInt32(); @@ -505,7 +529,7 @@ public: node_id node, buffer_id buffer, OMX_U32 range_offset, OMX_U32 range_length, - OMX_U32 flags, OMX_TICKS timestamp) { + OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeInt32((int32_t)node); @@ -514,6 +538,10 @@ public: data.writeInt32(range_length); data.writeInt32(flags); data.writeInt64(timestamp); + data.writeInt32(fenceFd >= 0); + if (fenceFd >= 0) { + data.writeFileDescriptor(fenceFd, true /* takeOwnership */); + } remote()->transact(EMPTY_BUFFER, data, &reply); return reply.readInt32(); @@ -757,9 +785,10 @@ status_t BnOMX::onTransact( OMX_U32 port_index = data.readInt32(); sp<IMemory> params = interface_cast<IMemory>(data.readStrongBinder()); + OMX_U32 allottedSize = data.readInt32(); buffer_id buffer; - status_t err = useBuffer(node, port_index, params, &buffer); + status_t err = useBuffer(node, port_index, params, &buffer, allottedSize); reply->writeInt32(err); if (err == OK) { @@ -815,9 +844,10 @@ status_t BnOMX::onTransact( OMX_U32 port_index = data.readInt32(); sp<IGraphicBufferProducer> bufferProducer; - status_t err = createInputSurface(node, port_index, - &bufferProducer); + MetadataBufferType type; + status_t err = createInputSurface(node, port_index, &bufferProducer, &type); + reply->writeInt32(type); reply->writeInt32(err); if (err == OK) { @@ -856,8 +886,10 @@ status_t BnOMX::onTransact( sp<IGraphicBufferConsumer> bufferConsumer = interface_cast<IGraphicBufferConsumer>(data.readStrongBinder()); - status_t err = setInputSurface(node, port_index, bufferConsumer); + MetadataBufferType type; + status_t err = setInputSurface(node, port_index, bufferConsumer, &type); + reply->writeInt32(type); reply->writeInt32(err); return NO_ERROR; } @@ -882,7 +914,9 @@ status_t BnOMX::onTransact( OMX_U32 port_index = data.readInt32(); OMX_BOOL enable = (OMX_BOOL)data.readInt32(); - status_t err = storeMetaDataInBuffers(node, port_index, enable); + MetadataBufferType type; + status_t err = storeMetaDataInBuffers(node, port_index, enable, &type); + reply->writeInt32(type); reply->writeInt32(err); return NO_ERROR; @@ -953,10 +987,11 @@ status_t BnOMX::onTransact( OMX_U32 port_index = data.readInt32(); sp<IMemory> params = interface_cast<IMemory>(data.readStrongBinder()); + OMX_U32 allottedSize = data.readInt32(); buffer_id buffer; status_t err = allocateBufferWithBackup( - node, port_index, params, &buffer); + node, port_index, params, &buffer, allottedSize); reply->writeInt32(err); @@ -985,7 +1020,9 @@ status_t BnOMX::onTransact( node_id node = (node_id)data.readInt32(); buffer_id buffer = (buffer_id)data.readInt32(); - reply->writeInt32(fillBuffer(node, buffer)); + bool haveFence = data.readInt32(); + int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1; + reply->writeInt32(fillBuffer(node, buffer, fenceFd)); return NO_ERROR; } @@ -1000,11 +1037,10 @@ status_t BnOMX::onTransact( OMX_U32 range_length = data.readInt32(); OMX_U32 flags = data.readInt32(); OMX_TICKS timestamp = data.readInt64(); - - reply->writeInt32( - emptyBuffer( - node, buffer, range_offset, range_length, - flags, timestamp)); + bool haveFence = data.readInt32(); + int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1; + reply->writeInt32(emptyBuffer( + node, buffer, range_offset, range_length, flags, timestamp, fenceFd)); return NO_ERROR; } @@ -1045,7 +1081,9 @@ public: Parcel data, reply; data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); data.write(&msg, sizeof(msg)); - + if (msg.fenceFd >= 0) { + data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */); + } ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg)); remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); @@ -1063,6 +1101,9 @@ status_t BnOMXObserver::onTransact( omx_message msg; data.read(&msg, sizeof(msg)); + if (msg.fenceFd >= 0) { + msg.fenceFd = ::dup(data.readFileDescriptor()); + } ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg)); diff --git a/media/libmedia/IResourceManagerService.cpp b/media/libmedia/IResourceManagerService.cpp index 7cb0f79..6902e99 100644 --- a/media/libmedia/IResourceManagerService.cpp +++ b/media/libmedia/IResourceManagerService.cpp @@ -48,7 +48,7 @@ static void writeToParcel(Parcel *data, const Vector<T> &items) { template <typename T> static void readFromParcel(const Parcel &data, Vector<T> *items) { size_t size = (size_t)data.readUint32(); - for (size_t i = 0; i < size; i++) { + for (size_t i = 0; i < size && data.dataAvail() > 0; i++) { T item; item.readFromParcel(data); items->add(item); diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index ae0061f..c5790fb 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -152,16 +152,6 @@ MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap UNUS ALOGV("codec = %d", cap.mCodec); } -/*static*/ void -MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap UNUSED) -{ - ALOGV("videoeditor cap:"); - ALOGV("mMaxInputFrameWidth = %d", cap.mMaxInputFrameWidth); - ALOGV("mMaxInputFrameHeight = %d", cap.mMaxInputFrameHeight); - ALOGV("mMaxOutputFrameWidth = %d", cap.mMaxOutputFrameWidth); - ALOGV("mMaxOutputFrameHeight = %d", cap.mMaxOutputFrameHeight); -} - /*static*/ int MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name) @@ -398,42 +388,6 @@ void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts) ALOGV("%s: cameraId=%d, offset=%d ms", __func__, cameraId, offsetTimeMs); mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs); } -/*static*/ MediaProfiles::ExportVideoProfile* -MediaProfiles::createExportVideoProfile(const char **atts) -{ - CHECK(!strcmp("name", atts[0]) && - !strcmp("profile", atts[2]) && - !strcmp("level", atts[4])); - - const size_t nMappings = - sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]); - const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]); - CHECK(codec != -1); - - MediaProfiles::ExportVideoProfile *profile = - new MediaProfiles::ExportVideoProfile( - codec, atoi(atts[3]), atoi(atts[5])); - - return profile; -} -/*static*/ MediaProfiles::VideoEditorCap* -MediaProfiles::createVideoEditorCap(const char **atts, MediaProfiles *profiles) -{ - CHECK(!strcmp("maxInputFrameWidth", atts[0]) && - !strcmp("maxInputFrameHeight", atts[2]) && - !strcmp("maxOutputFrameWidth", atts[4]) && - !strcmp("maxOutputFrameHeight", atts[6]) && - !strcmp("maxPrefetchYUVFrames", atts[8])); - - MediaProfiles::VideoEditorCap *pVideoEditorCap = - new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]), - atoi(atts[5]), atoi(atts[7]), atoi(atts[9])); - - logVideoEditorCap(*pVideoEditorCap); - profiles->mVideoEditorCap = pVideoEditorCap; - - return pVideoEditorCap; -} /*static*/ void MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts) @@ -465,10 +419,6 @@ MediaProfiles::startElementHandler(void *userData, const char *name, const char createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds)); } else if (strcmp("ImageEncoding", name) == 0) { profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts); - } else if (strcmp("VideoEditorCap", name) == 0) { - createVideoEditorCap(atts, profiles); - } else if (strcmp("ExportVideoProfile", name) == 0) { - profiles->mVideoEditorExportProfiles.add(createExportVideoProfile(atts)); } } @@ -873,32 +823,6 @@ MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles) profiles->mImageEncodingQualityLevels.add(levels); } -/*static*/ void -MediaProfiles::createDefaultVideoEditorCap(MediaProfiles *profiles) -{ - profiles->mVideoEditorCap = - new MediaProfiles::VideoEditorCap( - VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH, - VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT, - VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH, - VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT, - VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES); -} -/*static*/ void -MediaProfiles::createDefaultExportVideoProfiles(MediaProfiles *profiles) -{ - // Create default video export profiles - profiles->mVideoEditorExportProfiles.add( - new ExportVideoProfile(VIDEO_ENCODER_H263, - OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10)); - profiles->mVideoEditorExportProfiles.add( - new ExportVideoProfile(VIDEO_ENCODER_MPEG_4_SP, - OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1)); - profiles->mVideoEditorExportProfiles.add( - new ExportVideoProfile(VIDEO_ENCODER_H264, - OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13)); -} - /*static*/ MediaProfiles* MediaProfiles::createDefaultInstance() { @@ -910,8 +834,6 @@ MediaProfiles::createDefaultInstance() createDefaultAudioDecoders(profiles); createDefaultEncoderOutputFileFormats(profiles); createDefaultImageEncodingQualityLevels(profiles); - createDefaultVideoEditorCap(profiles); - createDefaultExportVideoProfiles(profiles); return profiles; } @@ -1009,54 +931,6 @@ int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder co ALOGE("The given video encoder param name %s is not found", name); return -1; } -int MediaProfiles::getVideoEditorExportParamByName( - const char *name, int codec) const -{ - ALOGV("getVideoEditorExportParamByName: name %s codec %d", name, codec); - ExportVideoProfile *exportProfile = NULL; - int index = -1; - for (size_t i =0; i < mVideoEditorExportProfiles.size(); i++) { - exportProfile = mVideoEditorExportProfiles[i]; - if (exportProfile->mCodec == codec) { - index = i; - break; - } - } - if (index == -1) { - ALOGE("The given video decoder %d is not found", codec); - return -1; - } - if (!strcmp("videoeditor.export.profile", name)) - return exportProfile->mProfile; - if (!strcmp("videoeditor.export.level", name)) - return exportProfile->mLevel; - - ALOGE("The given video editor export param name %s is not found", name); - return -1; -} -int MediaProfiles::getVideoEditorCapParamByName(const char *name) const -{ - ALOGV("getVideoEditorCapParamByName: %s", name); - - if (mVideoEditorCap == NULL) { - ALOGE("The mVideoEditorCap is not created, then create default cap."); - createDefaultVideoEditorCap(sInstance); - } - - if (!strcmp("videoeditor.input.width.max", name)) - return mVideoEditorCap->mMaxInputFrameWidth; - if (!strcmp("videoeditor.input.height.max", name)) - return mVideoEditorCap->mMaxInputFrameHeight; - if (!strcmp("videoeditor.output.width.max", name)) - return mVideoEditorCap->mMaxOutputFrameWidth; - if (!strcmp("videoeditor.output.height.max", name)) - return mVideoEditorCap->mMaxOutputFrameHeight; - if (!strcmp("maxPrefetchYUVFrames", name)) - return mVideoEditorCap->mMaxPrefetchYUVFrames; - - ALOGE("The given video editor param name %s is not found", name); - return -1; -} Vector<audio_encoder> MediaProfiles::getAudioEncoders() const { |