diff options
22 files changed, 392 insertions, 96 deletions
diff --git a/cmds/screenrecord/Android.mk b/cmds/screenrecord/Android.mk index 6ee2884..6747e60 100644 --- a/cmds/screenrecord/Android.mk +++ b/cmds/screenrecord/Android.mk @@ -41,6 +41,4 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= screenrecord -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index e2e389b..561ce02 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -23,8 +23,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= stagefright -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) ################################################################################ @@ -48,8 +46,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= record -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) ################################################################################ @@ -73,8 +69,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= recordvideo -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) @@ -99,8 +93,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= audioloop -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) ################################################################################ @@ -124,8 +116,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= stream -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) ################################################################################ @@ -149,8 +139,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= sf2 -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) ################################################################################ @@ -175,8 +163,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= codec -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) ################################################################################ @@ -200,6 +186,4 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= muxer -LOCAL_32_BIT_ONLY := true - include $(BUILD_EXECUTABLE) diff --git a/include/media/stagefright/ClockEstimator.h b/include/media/stagefright/ClockEstimator.h new file mode 100644 index 0000000..2fd6e75 --- /dev/null +++ b/include/media/stagefright/ClockEstimator.h @@ -0,0 +1,110 @@ +/* +** +** Copyright 2014, 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. +*/ + +#ifndef CLOCK_ESTIMATOR_H_ + +#define CLOCK_ESTIMATOR_H_ + + +#include <utils/RefBase.h> +#include <utils/Vector.h> + +namespace android { +// --------------------------------------------------------------------------- + +struct ClockEstimator : RefBase { + virtual double estimate(double x, double y) = 0; + virtual void reset() = 0; +}; + +struct WindowedLinearFitEstimator : ClockEstimator { + struct LinearFit { + /** + * Fit y = a * x + b, where each input has a weight + */ + double mX; // sum(w_i * x_i) + double mXX; // sum(w_i * x_i^2) + double mY; // sum(w_i * y_i) + double mYY; // sum(w_i * y_i^2) + double mXY; // sum(w_i * x_i * y_i) + double mW; // sum(w_i) + + LinearFit(); + void reset(); + void combine(const LinearFit &lf); + void add(double x, double y, double w); + void scale(double w); + double interpolate(double x); + double size() const; + + DISALLOW_EVIL_CONSTRUCTORS(LinearFit); + }; + + /** + * Estimator for f(x) = y' where input y' is noisy, but + * theoretically linear: + * + * y' =~ y = a * x + b + * + * It uses linear fit regression over a tapering rolling window + * to get an estimate for y (from the current and past inputs + * (x, y')). + * + * ____________ + * /| |\ + * / | | \ + * / | | \ <--- new data (x, y') + * / | main | \ + * <--><----------><--> + * tail head + * + * weight is 1 under the main window, tapers exponentially by + * the factors given in the head and the tail. + * + * Assuming that x and y' are monotonic, that x is somewhat + * evenly sampled, and that a =~ 1, the estimated y is also + * going to be monotonic. + */ + WindowedLinearFitEstimator( + size_t headLength = 5, double headFactor = 0.5, + size_t mainLength = 0, double tailFactor = 0.99); + + virtual void reset(); + + // add a new sample (x -> y') and return an estimated value for the true y + virtual double estimate(double x, double y); + +private: + Vector<double> mXHistory; // circular buffer + Vector<double> mYHistory; // circular buffer + LinearFit mHead; + LinearFit mMain; + LinearFit mTail; + double mHeadFactorInv; + double mTailFactor; + double mFirstWeight; + size_t mHistoryLength; + size_t mHeadLength; + size_t mNumSamples; + size_t mSampleIx; + + DISALLOW_EVIL_CONSTRUCTORS(WindowedLinearFitEstimator); +}; + +}; // namespace android + +#endif diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c index ed10dea..661fde9 100644 --- a/media/libeffects/downmix/EffectDownmix.c +++ b/media/libeffects/downmix/EffectDownmix.c @@ -30,24 +30,13 @@ #define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896 +// subset of possible audio_channel_mask_t values, and AUDIO_CHANNEL_OUT_* renamed to CHANNEL_MASK_* typedef enum { - CHANNEL_MASK_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD, - // like AUDIO_CHANNEL_OUT_QUAD with *_SIDE_* instead of *_BACK_*, same channel order - CHANNEL_MASK_QUAD_SIDE = - AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT | - AUDIO_CHANNEL_OUT_SIDE_LEFT | - AUDIO_CHANNEL_OUT_SIDE_RIGHT, - CHANNEL_MASK_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1, - // like AUDIO_CHANNEL_OUT_5POINT1 with *_SIDE_* instead of *_BACK_*, same channel order - CHANNEL_MASK_5POINT1_SIDE = - AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT | - AUDIO_CHANNEL_OUT_FRONT_CENTER | - AUDIO_CHANNEL_OUT_LOW_FREQUENCY | - AUDIO_CHANNEL_OUT_SIDE_LEFT | - AUDIO_CHANNEL_OUT_SIDE_RIGHT, - CHANNEL_MASK_7POINT1_SIDE_BACK = AUDIO_CHANNEL_OUT_7POINT1, + CHANNEL_MASK_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD_BACK, + CHANNEL_MASK_QUAD_SIDE = AUDIO_CHANNEL_OUT_QUAD_SIDE, + CHANNEL_MASK_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1_BACK, + CHANNEL_MASK_5POINT1_SIDE = AUDIO_CHANNEL_OUT_5POINT1_SIDE, + CHANNEL_MASK_7POINT1 = AUDIO_CHANNEL_OUT_7POINT1, } downmix_input_channel_mask_t; // effect_handle_t interface implementation for downmix effect @@ -343,7 +332,7 @@ static int Downmix_Process(effect_handle_t self, case CHANNEL_MASK_5POINT1_SIDE: Downmix_foldFrom5Point1(pSrc, pDst, numFrames, accumulate); break; - case CHANNEL_MASK_7POINT1_SIDE_BACK: + case CHANNEL_MASK_7POINT1: Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate); break; default: diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index fbfd3da..dc4f90e 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1005,7 +1005,8 @@ status_t AudioTrack::createTrack_l(size_t epoch) sp<IAudioTrack> track = audioFlinger->createTrack(mStreamType, mSampleRate, // AudioFlinger only sees 16-bit PCM - mFormat == AUDIO_FORMAT_PCM_8_BIT ? + mFormat == AUDIO_FORMAT_PCM_8_BIT && + !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT) ? AUDIO_FORMAT_PCM_16_BIT : mFormat, mChannelMask, &temp, @@ -1820,7 +1821,7 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args __unused) const result.append(" AudioTrack::dump\n"); snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, - mVolume[0], mVolume[1]); + mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]); result.append(buffer); snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%zu)\n", mFormat, mChannelCount, mFrameCount); diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index eb813bd..1940fe7 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -106,7 +106,7 @@ public: data.writeInt32(format); data.writeInt32(channelMask); size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0; - data.writeInt32(frameCount); + data.writeInt64(frameCount); track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; data.writeInt32(lFlags); // haveSharedBuffer @@ -128,7 +128,7 @@ public: if (lStatus != NO_ERROR) { ALOGE("createTrack error: %s", strerror(-lStatus)); } else { - frameCount = reply.readInt32(); + frameCount = reply.readInt64(); if (pFrameCount != NULL) { *pFrameCount = frameCount; } @@ -179,7 +179,7 @@ public: data.writeInt32(format); data.writeInt32(channelMask); size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0; - data.writeInt32(frameCount); + data.writeInt64(frameCount); track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; data.writeInt32(lFlags); data.writeInt32((int32_t) tid); @@ -192,7 +192,7 @@ public: if (lStatus != NO_ERROR) { ALOGE("openRecord error: %s", strerror(-lStatus)); } else { - frameCount = reply.readInt32(); + frameCount = reply.readInt64(); if (pFrameCount != NULL) { *pFrameCount = frameCount; } @@ -248,7 +248,7 @@ public: data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32((int32_t) output); remote()->transact(FRAME_COUNT, data, &reply); - return reply.readInt32(); + return reply.readInt64(); } virtual uint32_t latency(audio_io_handle_t output) const @@ -398,7 +398,7 @@ public: data.writeInt32(format); data.writeInt32(channelMask); remote()->transact(GET_INPUTBUFFERSIZE, data, &reply); - return reply.readInt32(); + return reply.readInt64(); } virtual audio_io_handle_t openOutput(audio_module_handle_t module, @@ -769,7 +769,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); remote()->transact(GET_PRIMARY_OUTPUT_FRAME_COUNT, data, &reply); - return reply.readInt32(); + return reply.readInt64(); } virtual status_t setLowRamDevice(bool isLowRamDevice) @@ -797,7 +797,7 @@ status_t BnAudioFlinger::onTransact( uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); - size_t frameCount = data.readInt32(); + size_t frameCount = data.readInt64(); track_flags_t flags = (track_flags_t) data.readInt32(); bool haveSharedBuffer = data.readInt32() != 0; sp<IMemory> buffer; @@ -821,7 +821,7 @@ status_t BnAudioFlinger::onTransact( &sessionId, clientUid, &status); LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR)); } - reply->writeInt32(frameCount); + reply->writeInt64(frameCount); reply->writeInt32(flags); reply->writeInt32(sessionId); reply->writeInt32(status); @@ -834,7 +834,7 @@ status_t BnAudioFlinger::onTransact( uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); - size_t frameCount = data.readInt32(); + size_t frameCount = data.readInt64(); track_flags_t flags = (track_flags_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); @@ -842,7 +842,7 @@ status_t BnAudioFlinger::onTransact( sp<IAudioRecord> record = openRecord(input, sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId, &status); LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR)); - reply->writeInt32(frameCount); + reply->writeInt64(frameCount); reply->writeInt32(flags); reply->writeInt32(sessionId); reply->writeInt32(status); @@ -861,7 +861,7 @@ status_t BnAudioFlinger::onTransact( } break; case FRAME_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( frameCount((audio_io_handle_t) data.readInt32()) ); + reply->writeInt64( frameCount((audio_io_handle_t) data.readInt32()) ); return NO_ERROR; } break; case LATENCY: { @@ -960,7 +960,7 @@ status_t BnAudioFlinger::onTransact( uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); - reply->writeInt32( getInputBufferSize(sampleRate, format, channelMask) ); + reply->writeInt64( getInputBufferSize(sampleRate, format, channelMask) ); return NO_ERROR; } break; case OPEN_OUTPUT: { @@ -1164,7 +1164,7 @@ status_t BnAudioFlinger::onTransact( } break; case GET_PRIMARY_OUTPUT_FRAME_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32(getPrimaryOutputFrameCount()); + reply->writeInt64(getPrimaryOutputFrameCount()); return NO_ERROR; } break; case SET_LOW_RAM_DEVICE: { diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp index 3c0d4cf..1c299f7 100644 --- a/media/libmedia/IAudioFlingerClient.cpp +++ b/media/libmedia/IAudioFlingerClient.cpp @@ -55,7 +55,7 @@ public: data.writeInt32(desc->samplingRate); data.writeInt32(desc->format); data.writeInt32(desc->channelMask); - data.writeInt32(desc->frameCount); + data.writeInt64(desc->frameCount); data.writeInt32(desc->latency); } remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); @@ -85,7 +85,7 @@ status_t BnAudioFlingerClient::onTransact( desc.samplingRate = data.readInt32(); desc.format = (audio_format_t) data.readInt32(); desc.channelMask = (audio_channel_mask_t) data.readInt32(); - desc.frameCount = data.readInt32(); + desc.frameCount = data.readInt64(); desc.latency = data.readInt32(); param2 = &desc; } diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp index ffc21fc..265bb1b 100644 --- a/media/libmedia/IAudioTrack.cpp +++ b/media/libmedia/IAudioTrack.cpp @@ -118,7 +118,7 @@ public: virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) { Parcel data, reply; data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - data.writeInt32(size); + data.writeInt64(size); status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER, data, &reply); if (status == NO_ERROR) { @@ -238,7 +238,7 @@ status_t BnAudioTrack::onTransact( case ALLOCATE_TIMED_BUFFER: { CHECK_INTERFACE(IAudioTrack, data, reply); sp<IMemory> buffer; - status_t status = allocateTimedBuffer(data.readInt32(), &buffer); + status_t status = allocateTimedBuffer(data.readInt64(), &buffer); reply->writeInt32(status); if (status == NO_ERROR) { reply->writeStrongBinder(buffer->asBinder()); diff --git a/media/libmedia/IMediaLogService.cpp b/media/libmedia/IMediaLogService.cpp index 33239a7..8a66c7c 100644 --- a/media/libmedia/IMediaLogService.cpp +++ b/media/libmedia/IMediaLogService.cpp @@ -43,7 +43,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IMediaLogService::getInterfaceDescriptor()); data.writeStrongBinder(shared->asBinder()); - data.writeInt32((int32_t) size); + data.writeInt64((int64_t) size); data.writeCString(name); status_t status = remote()->transact(REGISTER_WRITER, data, &reply); // FIXME ignores status @@ -71,7 +71,7 @@ status_t BnMediaLogService::onTransact( case REGISTER_WRITER: { CHECK_INTERFACE(IMediaLogService, data, reply); sp<IMemory> shared = interface_cast<IMemory>(data.readStrongBinder()); - size_t size = (size_t) data.readInt32(); + size_t size = (size_t) data.readInt64(); const char *name = data.readCString(); registerWriter(shared, size, name); return NO_ERROR; diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp index c7d9d51..432d890 100644 --- a/media/libmedia/IMediaMetadataRetriever.cpp +++ b/media/libmedia/IMediaMetadataRetriever.cpp @@ -101,7 +101,7 @@ public: data.writeInt32(0); } else { // serialize the headers - data.writeInt32(headers->size()); + data.writeInt64(headers->size()); for (size_t i = 0; i < headers->size(); ++i) { data.writeString8(headers->keyAt(i)); data.writeString8(headers->valueAt(i)); @@ -212,8 +212,8 @@ status_t BnMediaMetadataRetriever::onTransact( const char* srcUrl = data.readCString(); KeyedVector<String8, String8> headers; - int32_t numHeaders = data.readInt32(); - for (int i = 0; i < numHeaders; ++i) { + size_t numHeaders = (size_t) data.readInt64(); + for (size_t i = 0; i < numHeaders; ++i) { String8 key = data.readString8(); String8 value = data.readString8(); headers.add(key, value); diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index 71ce320..9c13848 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -140,7 +140,7 @@ public: data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeIntPtr((intptr_t)node); data.writeInt32(index); - data.writeInt32(size); + data.writeInt64(size); data.write(params, size); remote()->transact(GET_PARAMETER, data, &reply); @@ -161,7 +161,7 @@ public: data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeIntPtr((intptr_t)node); data.writeInt32(index); - data.writeInt32(size); + data.writeInt64(size); data.write(params, size); remote()->transact(SET_PARAMETER, data, &reply); @@ -175,7 +175,7 @@ public: data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeIntPtr((intptr_t)node); data.writeInt32(index); - data.writeInt32(size); + data.writeInt64(size); data.write(params, size); remote()->transact(GET_CONFIG, data, &reply); @@ -196,7 +196,7 @@ public: data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeIntPtr((intptr_t)node); data.writeInt32(index); - data.writeInt32(size); + data.writeInt64(size); data.write(params, size); remote()->transact(SET_CONFIG, data, &reply); @@ -375,7 +375,7 @@ public: data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeIntPtr((intptr_t)node); data.writeInt32(port_index); - data.writeInt32(size); + data.writeInt64(size); remote()->transact(ALLOC_BUFFER, data, &reply); status_t err = reply.readInt32(); @@ -484,7 +484,7 @@ public: data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); data.writeIntPtr((intptr_t)node); data.writeInt32(port_index); - data.writeInt32(size); + data.writeInt64(size); data.write(optionData, size); data.writeInt32(type); remote()->transact(SET_INTERNAL_OPTION, data, &reply); @@ -596,7 +596,7 @@ status_t BnOMX::onTransact( node_id node = (void*)data.readIntPtr(); OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); - size_t size = data.readInt32(); + size_t size = data.readInt64(); void *params = malloc(size); data.read(params, size); @@ -810,7 +810,7 @@ status_t BnOMX::onTransact( node_id node = (void*)data.readIntPtr(); OMX_U32 port_index = data.readInt32(); - size_t size = data.readInt32(); + size_t size = data.readInt64(); buffer_id buffer; void *buffer_data; diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp index 68ffca8..fe2cc61 100644 --- a/media/libmedia/IStreamSource.cpp +++ b/media/libmedia/IStreamSource.cpp @@ -62,7 +62,7 @@ struct BpStreamSource : public BpInterface<IStreamSource> { virtual void setBuffers(const Vector<sp<IMemory> > &buffers) { Parcel data, reply; data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); - data.writeInt32(static_cast<int32_t>(buffers.size())); + data.writeInt64(static_cast<int64_t>(buffers.size())); for (size_t i = 0; i < buffers.size(); ++i) { data.writeStrongBinder(buffers.itemAt(i)->asBinder()); } @@ -72,7 +72,7 @@ struct BpStreamSource : public BpInterface<IStreamSource> { virtual void onBufferAvailable(size_t index) { Parcel data, reply; data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); - data.writeInt32(static_cast<int32_t>(index)); + data.writeInt64(static_cast<int64_t>(index)); remote()->transact( ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); } @@ -102,7 +102,7 @@ status_t BnStreamSource::onTransact( case SET_BUFFERS: { CHECK_INTERFACE(IStreamSource, data, reply); - size_t n = static_cast<size_t>(data.readInt32()); + size_t n = static_cast<size_t>(data.readInt64()); Vector<sp<IMemory> > buffers; for (size_t i = 0; i < n; ++i) { sp<IMemory> mem = @@ -117,7 +117,7 @@ status_t BnStreamSource::onTransact( case ON_BUFFER_AVAILABLE: { CHECK_INTERFACE(IStreamSource, data, reply); - onBufferAvailable(static_cast<size_t>(data.readInt32())); + onBufferAvailable(static_cast<size_t>(data.readInt64())); break; } @@ -145,8 +145,8 @@ struct BpStreamListener : public BpInterface<IStreamListener> { virtual void queueBuffer(size_t index, size_t size) { Parcel data, reply; data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); - data.writeInt32(static_cast<int32_t>(index)); - data.writeInt32(static_cast<int32_t>(size)); + data.writeInt64(static_cast<int64_t>(index)); + data.writeInt64(static_cast<int64_t>(size)); remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); } @@ -177,8 +177,8 @@ status_t BnStreamListener::onTransact( case QUEUE_BUFFER: { CHECK_INTERFACE(IStreamListener, data, reply); - size_t index = static_cast<size_t>(data.readInt32()); - size_t size = static_cast<size_t>(data.readInt32()); + size_t index = static_cast<size_t>(data.readInt64()); + size_t size = static_cast<size_t>(data.readInt64()); queueBuffer(index, size); break; diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp index f004ca4..66f7161 100644 --- a/media/libmedia/MemoryLeakTrackUtil.cpp +++ b/media/libmedia/MemoryLeakTrackUtil.cpp @@ -17,6 +17,7 @@ #include <media/MemoryLeakTrackUtil.h> #include <stdio.h> +#include <stdlib.h> #include <sys/types.h> #include <unistd.h> diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp index 96738a7..4d9a1fa 100644 --- a/media/libnbaio/NBLog.cpp +++ b/media/libnbaio/NBLog.cpp @@ -343,7 +343,7 @@ void NBLog::Reader::dump(int fd, size_t indent) String8 timestamp, body; lost += i; if (lost > 0) { - body.appendFormat("warning: lost %u bytes worth of events", lost); + body.appendFormat("warning: lost %zu bytes worth of events", lost); // TODO timestamp empty here, only other choice to wait for the first timestamp event in the // log to push it out. Consider keeping the timestamp/body between calls to readAt(). dumpLine(timestamp, body); @@ -354,7 +354,7 @@ void NBLog::Reader::dump(int fd, size_t indent) maxSec /= 10; } if (maxSec >= 0) { - timestamp.appendFormat("[%*s]", width + 4, ""); + timestamp.appendFormat("[%*s]", (int) width + 4, ""); } bool deferredTimestamp = false; while (i < avail) { @@ -364,7 +364,7 @@ void NBLog::Reader::dump(int fd, size_t indent) size_t advance = length + 3; switch (event) { case EVENT_STRING: - body.appendFormat("%.*s", length, (const char *) data); + body.appendFormat("%.*s", (int) length, (const char *) data); break; case EVENT_TIMESTAMP: { // already checked that length == sizeof(struct timespec); diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index f11791c..5bca317 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -17,6 +17,8 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "ACodec" +#include <utils/Trace.h> + #include <media/stagefright/ACodec.h> #include <binder/MemoryDealer.h> @@ -3681,6 +3683,7 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { if (mCodec->mNativeWindow != NULL && msg->findInt32("render", &render) && render != 0 && info->mData != NULL && info->mData->size() != 0) { + ATRACE_NAME("render"); // The client wants this buffer to be rendered. status_t err; @@ -3693,6 +3696,10 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { info->mStatus = BufferInfo::OWNED_BY_US; } } else { + if (mCodec->mNativeWindow != NULL && + (info->mData == NULL || info->mData->size() != 0)) { + ATRACE_NAME("frame-drop"); + } info->mStatus = BufferInfo::OWNED_BY_US; } diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 714b5e0..d9e39ff 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -14,6 +14,7 @@ LOCAL_SRC_FILES:= \ AwesomePlayer.cpp \ CameraSource.cpp \ CameraSourceTimeLapse.cpp \ + ClockEstimator.cpp \ DataSource.cpp \ DataURISource.cpp \ DRMExtractor.cpp \ diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 6e5003f..8d3032b 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -42,6 +42,7 @@ #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/timedtext/TimedTextDriver.h> #include <media/stagefright/AudioPlayer.h> +#include <media/stagefright/ClockEstimator.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/FileSource.h> #include <media/stagefright/MediaBuffer.h> @@ -231,6 +232,8 @@ AwesomePlayer::AwesomePlayer() &AwesomePlayer::onAudioTearDownEvent); mAudioTearDownEventPending = false; + mClockEstimator = new WindowedLinearFitEstimator(); + reset(); } @@ -1866,21 +1869,28 @@ void AwesomePlayer::onVideoEvent() { TimeSource *ts = ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED)) ? &mSystemTimeSource : mTimeSource; + int64_t systemTimeUs = mSystemTimeSource.getRealTimeUs(); + int64_t looperTimeUs = ALooper::GetNowUs(); if (mFlags & FIRST_FRAME) { modifyFlags(FIRST_FRAME, CLEAR); mSinceLastDropped = 0; - mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; + mClockEstimator->reset(); + mTimeSourceDeltaUs = estimateRealTimeUs(ts, systemTimeUs) - timeUs; } int64_t realTimeUs, mediaTimeUs; if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { + ALOGV("updating TSdelta (%" PRId64 " => %" PRId64 " change %" PRId64 ")", + mTimeSourceDeltaUs, realTimeUs - mediaTimeUs, + mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)); + ATRACE_INT("TS delta change (ms)", (mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)) / 1E3); mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; } if (wasSeeking == SEEK_VIDEO_ONLY) { - int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; + int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; int64_t latenessUs = nowUs - timeUs; @@ -1891,12 +1901,13 @@ void AwesomePlayer::onVideoEvent() { } } + int64_t latenessUs = 0; if (wasSeeking == NO_SEEK) { // Let's display the first frame after seeking right away. - int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; + int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; - int64_t latenessUs = nowUs - timeUs; + latenessUs = nowUs - timeUs; ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3); @@ -1950,9 +1961,9 @@ void AwesomePlayer::onVideoEvent() { } } - if (latenessUs < -10000) { - // We're more than 10ms early. - postVideoEvent_l(10000); + if (latenessUs < -30000) { + // We're more than 30ms early, schedule at most 20 ms before time due + postVideoEvent_l(latenessUs < -60000 ? 30000 : -latenessUs - 20000); return; } } @@ -1966,6 +1977,8 @@ void AwesomePlayer::onVideoEvent() { if (mVideoRenderer != NULL) { mSinceLastDropped++; + mVideoBuffer->meta_data()->setInt64(kKeyTime, looperTimeUs - latenessUs); + mVideoRenderer->render(mVideoBuffer); if (!mVideoRenderingStarted) { mVideoRenderingStarted = true; @@ -2015,14 +2028,26 @@ void AwesomePlayer::onVideoEvent() { int64_t nextTimeUs; CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs)); - int64_t delayUs = nextTimeUs - ts->getRealTimeUs() + mTimeSourceDeltaUs; - postVideoEvent_l(delayUs > 10000 ? 10000 : delayUs < 0 ? 0 : delayUs); + systemTimeUs = mSystemTimeSource.getRealTimeUs(); + int64_t delayUs = nextTimeUs - estimateRealTimeUs(ts, systemTimeUs) + mTimeSourceDeltaUs; + ATRACE_INT("Frame delta (ms)", (nextTimeUs - timeUs) / 1E3); + ALOGV("next frame in %" PRId64, delayUs); + // try to schedule 30ms before time due + postVideoEvent_l(delayUs > 60000 ? 30000 : (delayUs < 30000 ? 0 : delayUs - 30000)); return; } postVideoEvent_l(); } +int64_t AwesomePlayer::estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs) { + if (ts == &mSystemTimeSource) { + return systemTimeUs; + } else { + return (int64_t)mClockEstimator->estimate(systemTimeUs, ts->getRealTimeUs()); + } +} + void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { ATRACE_CALL(); diff --git a/media/libstagefright/ClockEstimator.cpp b/media/libstagefright/ClockEstimator.cpp new file mode 100644 index 0000000..34d1e42 --- /dev/null +++ b/media/libstagefright/ClockEstimator.cpp @@ -0,0 +1,177 @@ +/* +** +** Copyright 2014, 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. +*/ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "ClockEstimator" +#include <utils/Log.h> + +#include <math.h> +#include <media/stagefright/ClockEstimator.h> + +#include <media/stagefright/foundation/ADebug.h> + +namespace android { + +WindowedLinearFitEstimator::WindowedLinearFitEstimator( + size_t headLength, double headFactor, size_t mainLength, double tailFactor) + : mHeadFactorInv(1. / headFactor), + mTailFactor(tailFactor), + mHistoryLength(mainLength + headLength), + mHeadLength(headLength) { + reset(); + mXHistory.resize(mHistoryLength); + mYHistory.resize(mHistoryLength); + mFirstWeight = pow(headFactor, mHeadLength); +} + +WindowedLinearFitEstimator::LinearFit::LinearFit() { + reset(); +} + +void WindowedLinearFitEstimator::LinearFit::reset() { + mX = mXX = mY = mYY = mXY = mW = 0.; +} + +double WindowedLinearFitEstimator::LinearFit::size() const { + double s = mW * mW + mX * mX + mY * mY + mXX * mXX + mXY * mXY + mYY * mYY; + if (s > 1e72) { + // 1e72 corresponds to clock monotonic time of about 8 years + ALOGW("estimator is overflowing: w=%g x=%g y=%g xx=%g xy=%g yy=%g", + mW, mX, mY, mXX, mXY, mYY); + } + return s; +} + +void WindowedLinearFitEstimator::LinearFit::add(double x, double y, double w) { + mW += w; + mX += w * x; + mY += w * y; + mXX += w * x * x; + mXY += w * x * y; + mYY += w * y * y; +} + +void WindowedLinearFitEstimator::LinearFit::combine(const LinearFit &lf) { + mW += lf.mW; + mX += lf.mX; + mY += lf.mY; + mXX += lf.mXX; + mXY += lf.mXY; + mYY += lf.mYY; +} + +void WindowedLinearFitEstimator::LinearFit::scale(double w) { + mW *= w; + mX *= w; + mY *= w; + mXX *= w; + mXY *= w; + mYY *= w; +} + +double WindowedLinearFitEstimator::LinearFit::interpolate(double x) { + double div = mW * mXX - mX * mX; + if (fabs(div) < 1e-5 * mW * mW) { + // this only should happen on the first value + return x; + // assuming a = 1, we could also return x + (mY - mX) / mW; + } + double a_div = (mW * mXY - mX * mY); + double b_div = (mXX * mY - mX * mXY); + ALOGV("a=%.4g b=%.4g in=%g out=%g", + a_div / div, b_div / div, x, (a_div * x + b_div) / div); + return (a_div * x + b_div) / div; +} + +double WindowedLinearFitEstimator::estimate(double x, double y) { + /* + * TODO: We could update the head by adding the new sample to it + * and amplifying it, but this approach can lead to unbounded + * error. Instead, we recalculate the head at each step, which + * is computationally more expensive. We could balance the two + * methods by recalculating just before the error becomes + * significant. + */ + const bool update_head = false; + if (update_head) { + // add new sample to the head + mHead.scale(mHeadFactorInv); // amplify head + mHead.add(x, y, mFirstWeight); + } + + /* + * TRICKY: place elements into the circular buffer at decreasing + * indices, so that we can access past elements by addition + * (thereby avoiding potentially negative indices.) + */ + if (mNumSamples >= mHeadLength) { + // move last head sample from head to the main window + size_t lastHeadIx = (mSampleIx + mHeadLength) % mHistoryLength; + if (update_head) { + mHead.add(mXHistory[lastHeadIx], mYHistory[lastHeadIx], -1.); // remove + } + mMain.add(mXHistory[lastHeadIx], mYHistory[lastHeadIx], 1.); + if (mNumSamples >= mHistoryLength) { + // move last main sample from main window to tail + mMain.add(mXHistory[mSampleIx], mYHistory[mSampleIx], -1.); // remove + mTail.add(mXHistory[mSampleIx], mYHistory[mSampleIx], 1.); + mTail.scale(mTailFactor); // attenuate tail + } + } + + mXHistory.editItemAt(mSampleIx) = x; + mYHistory.editItemAt(mSampleIx) = y; + if (mNumSamples < mHistoryLength) { + ++mNumSamples; + } + + // recalculate head unless we were using the update method + if (!update_head) { + mHead.reset(); + double w = mFirstWeight; + for (size_t headIx = 0; headIx < mHeadLength && headIx < mNumSamples; ++headIx) { + size_t ix = (mSampleIx + headIx) % mHistoryLength; + mHead.add(mXHistory[ix], mYHistory[ix], w); + w *= mHeadFactorInv; + } + } + + if (mSampleIx > 0) { + --mSampleIx; + } else { + mSampleIx = mHistoryLength - 1; + } + + // return estimation result + LinearFit total; + total.combine(mHead); + total.combine(mMain); + total.combine(mTail); + return total.interpolate(x); +} + +void WindowedLinearFitEstimator::reset() { + mHead.reset(); + mMain.reset(); + mTail.reset(); + mNumSamples = 0; + mSampleIx = mHistoryLength - 1; +} + +}; // namespace android + + diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp index 515e4d3..8f356b6 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp @@ -355,7 +355,12 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) { outHeader->nFlags = 0; int err = vorbis_dsp_synthesis(mState, &pack, 1); if (err != 0) { + // FIXME temporary workaround for log spam +#if !defined(__arm__) && !defined(__aarch64__) + ALOGV("vorbis_dsp_synthesis returned %d", err); +#else ALOGW("vorbis_dsp_synthesis returned %d", err); +#endif } else { numFrames = vorbis_dsp_pcmout( mState, (int16_t *)outHeader->pBuffer, diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index a81bbba..77d65e0 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -32,6 +32,7 @@ namespace android { struct AudioPlayer; +struct ClockEstimator; struct DataSource; struct MediaBuffer; struct MediaExtractor; @@ -236,6 +237,7 @@ private: MediaBuffer *mVideoBuffer; + sp<ClockEstimator> mClockEstimator; sp<HTTPBase> mConnectingDataSource; sp<NuCachedSource2> mCachedSource; @@ -296,6 +298,7 @@ private: bool getBitrate(int64_t *bitrate); + int64_t estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs); void finishSeekIfNecessary(int64_t videoTimeUs); void ensureCacheIsFetching_l(); diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 755d480..eb00c82 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -541,10 +541,8 @@ sp<IAudioTrack> AudioFlinger::createTrack( goto Exit; } - // client is responsible for conversion of 8-bit PCM to 16-bit PCM, - // and we don't yet support 8.24 or 32-bit PCM - if (!audio_is_valid_format(format) || - (audio_is_linear_pcm(format) && format != AUDIO_FORMAT_PCM_16_BIT)) { + // further format checks are performed by createTrack_l() depending on the thread type + if (!audio_is_valid_format(format)) { ALOGE("createTrack() invalid format %#x", format); lStatus = BAD_VALUE; goto Exit; diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 2f874f5..16d6f42 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -1936,9 +1936,6 @@ void Camera3Device::notify(const camera3_notify_msg *msg) { if (msg->message.error.error_code == CAMERA3_MSG_ERROR_DEVICE) { listener->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE, resultExtras); - } else { - listener->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE, - resultExtras); } } else { ALOGE("Camera %d: %s: no listener available", mId, __FUNCTION__); |