summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/screenrecord/Android.mk2
-rw-r--r--cmds/stagefright/Android.mk16
-rw-r--r--include/media/stagefright/ClockEstimator.h110
-rw-r--r--media/libeffects/downmix/EffectDownmix.c25
-rw-r--r--media/libmedia/AudioTrack.cpp5
-rw-r--r--media/libmedia/IAudioFlinger.cpp28
-rw-r--r--media/libmedia/IAudioFlingerClient.cpp4
-rw-r--r--media/libmedia/IAudioTrack.cpp4
-rw-r--r--media/libmedia/IMediaLogService.cpp4
-rw-r--r--media/libmedia/IMediaMetadataRetriever.cpp6
-rw-r--r--media/libmedia/IOMX.cpp16
-rw-r--r--media/libmedia/IStreamSource.cpp16
-rw-r--r--media/libmedia/MemoryLeakTrackUtil.cpp1
-rw-r--r--media/libnbaio/NBLog.cpp6
-rw-r--r--media/libstagefright/ACodec.cpp7
-rw-r--r--media/libstagefright/Android.mk1
-rw-r--r--media/libstagefright/AwesomePlayer.cpp43
-rw-r--r--media/libstagefright/ClockEstimator.cpp177
-rw-r--r--media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp5
-rw-r--r--media/libstagefright/include/AwesomePlayer.h3
-rw-r--r--services/audioflinger/AudioFlinger.cpp6
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp3
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__);