Merge "opus: Support for > 2 channels"
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index 35345d2..277b5db 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -107,7 +107,7 @@
}
}
- if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+ if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
res = FAILED_TRANSACTION;
}
return res;
@@ -147,7 +147,7 @@
resFrameNumber = reply.readInt64(lastFrameNumber);
}
}
- if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+ if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
res = FAILED_TRANSACTION;
}
return res;
@@ -167,7 +167,7 @@
status_t resFrameNumber = BAD_VALUE;
if (reply.readInt32() != 0) {
if (lastFrameNumber != NULL) {
- res = reply.readInt64(lastFrameNumber);
+ resFrameNumber = reply.readInt64(lastFrameNumber);
}
}
if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
@@ -296,7 +296,7 @@
status_t resFrameNumber = BAD_VALUE;
if (reply.readInt32() != 0) {
if (lastFrameNumber != NULL) {
- res = reply.readInt64(lastFrameNumber);
+ resFrameNumber = reply.readInt64(lastFrameNumber);
}
}
if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
diff --git a/cmds/screenrecord/TextRenderer.cpp b/cmds/screenrecord/TextRenderer.cpp
index 6a9176b..01f73e0 100644
--- a/cmds/screenrecord/TextRenderer.cpp
+++ b/cmds/screenrecord/TextRenderer.cpp
@@ -21,6 +21,8 @@
#include "TextRenderer.h"
#include <assert.h>
+#include <malloc.h>
+#include <string.h>
namespace android {
#include "FontBitmap.h"
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index 1b2f792..4b2f980 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -332,7 +332,7 @@
size_t j = 0;
sp<ABuffer> buffer;
- while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) {
+ while (format->findBuffer(AStringPrintf("csd-%d", j).c_str(), &buffer)) {
state->mCSD.push_back(buffer);
++j;
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
index 48b0afe..933464f 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -58,8 +58,7 @@
$(base)/drm/libdrmframework/plugins/forward-lock/internal-format/common \
$(base)/drm/libdrmframework/plugins/forward-lock/internal-format/converter \
$(base)/drm/libdrmframework/plugins/forward-lock/internal-format/decoder \
- $(LOCAL_PATH)/include \
- external/openssl/include
+ $(LOCAL_PATH)/include
LOCAL_MODULE_RELATIVE_PATH := drm
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
index 6c5d3cf..3b4c8b4 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
@@ -20,9 +20,6 @@
LOCAL_SRC_FILES := \
FwdLockGlue.c
-LOCAL_C_INCLUDES := \
- external/openssl/include
-
LOCAL_SHARED_LIBRARIES := libcrypto
LOCAL_MODULE := libfwdlock-common
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
index 8f08c88..2f51f0c 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
@@ -21,8 +21,7 @@
FwdLockConv.c
LOCAL_C_INCLUDES := \
- frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common \
- external/openssl/include
+ frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common
LOCAL_SHARED_LIBRARIES := libcrypto
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
index 7b493c3..3399ae5 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
@@ -21,8 +21,7 @@
FwdLockFile.c
LOCAL_C_INCLUDES := \
- frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common \
- external/openssl/include
+ frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common
LOCAL_SHARED_LIBRARIES := libcrypto
diff --git a/drm/mediadrm/plugins/clearkey/Android.mk b/drm/mediadrm/plugins/clearkey/Android.mk
index b713a7f..2efdcf5 100644
--- a/drm/mediadrm/plugins/clearkey/Android.mk
+++ b/drm/mediadrm/plugins/clearkey/Android.mk
@@ -32,7 +32,6 @@
LOCAL_C_INCLUDES := \
external/jsmn \
- external/openssl/include \
frameworks/av/drm/mediadrm/plugins/clearkey \
frameworks/av/include \
frameworks/native/include \
diff --git a/drm/mediadrm/plugins/clearkey/tests/Android.mk b/drm/mediadrm/plugins/clearkey/tests/Android.mk
index 80f94e0..392f218 100644
--- a/drm/mediadrm/plugins/clearkey/tests/Android.mk
+++ b/drm/mediadrm/plugins/clearkey/tests/Android.mk
@@ -29,7 +29,6 @@
LOCAL_C_INCLUDES := \
external/jsmn \
- external/openssl/include \
frameworks/av/drm/mediadrm/plugins/clearkey \
frameworks/av/include \
frameworks/native/include \
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 843a354..2ab3dd6 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -201,7 +201,7 @@
// IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
//
static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state,
- const char *device_address);
+ const char *device_address, const char *device_name);
static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address);
static status_t setPhoneState(audio_mode_t state);
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index c98c475..fecc6f1 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -44,7 +44,8 @@
//
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address) = 0;
+ const char *device_address,
+ const char *device_name) = 0;
virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address) = 0;
virtual status_t setPhoneState(audio_mode_t state) = 0;
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index dd62b56..49a3d61 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -52,17 +52,6 @@
virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0)
= 0;
- virtual status_t decode(
- const sp<IMediaHTTPService> &httpService,
- const char* url,
- uint32_t *pSampleRate,
- int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap, size_t *pSize) = 0;
-
- virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
- int* pNumChannels, audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap, size_t *pSize) = 0;
virtual sp<IOMX> getOMX() = 0;
virtual sp<ICrypto> makeCrypto() = 0;
virtual sp<IDrm> makeDrm() = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 0fc7dcf..4a6bf28 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -88,7 +88,6 @@
virtual ~AudioSink() {}
virtual bool ready() const = 0; // audio output is open and ready
- virtual bool realtime() const = 0; // audio output is real-time output
virtual ssize_t bufferSize() const = 0;
virtual ssize_t frameCount() const = 0;
virtual ssize_t channelCount() const = 0;
diff --git a/include/media/SoundPool.h b/include/media/SoundPool.h
deleted file mode 100644
index 5830475..0000000
--- a/include/media/SoundPool.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2007 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 SOUNDPOOL_H_
-#define SOUNDPOOL_H_
-
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-#include <media/AudioTrack.h>
-#include <binder/MemoryHeapBase.h>
-#include <binder/MemoryBase.h>
-
-namespace android {
-
-static const int IDLE_PRIORITY = -1;
-
-// forward declarations
-class SoundEvent;
-class SoundPoolThread;
-class SoundPool;
-
-// for queued events
-class SoundPoolEvent {
-public:
- SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
- mMsg(msg), mArg1(arg1), mArg2(arg2) {}
- int mMsg;
- int mArg1;
- int mArg2;
- enum MessageType { INVALID, SAMPLE_LOADED };
-};
-
-// callback function prototype
-typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
-
-// tracks samples used by application
-class Sample : public RefBase {
-public:
- enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
- Sample(int sampleID, const char* url);
- Sample(int sampleID, int fd, int64_t offset, int64_t length);
- ~Sample();
- int sampleID() { return mSampleID; }
- int numChannels() { return mNumChannels; }
- int sampleRate() { return mSampleRate; }
- audio_format_t format() { return mFormat; }
- size_t size() { return mSize; }
- int state() { return mState; }
- uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
- status_t doLoad();
- void startLoad() { mState = LOADING; }
- sp<IMemory> getIMemory() { return mData; }
-
- // hack
- void init(int numChannels, int sampleRate, audio_format_t format, size_t size,
- sp<IMemory> data ) {
- mNumChannels = numChannels; mSampleRate = sampleRate; mFormat = format; mSize = size;
- mData = data; }
-
-private:
- void init();
-
- size_t mSize;
- volatile int32_t mRefCount;
- uint16_t mSampleID;
- uint16_t mSampleRate;
- uint8_t mState : 3;
- uint8_t mNumChannels : 2;
- audio_format_t mFormat;
- int mFd;
- int64_t mOffset;
- int64_t mLength;
- char* mUrl;
- sp<IMemory> mData;
- sp<MemoryHeapBase> mHeap;
-};
-
-// stores pending events for stolen channels
-class SoundEvent
-{
-public:
- SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
- mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
- void set(const sp<Sample>& sample, int channelID, float leftVolume,
- float rightVolume, int priority, int loop, float rate);
- sp<Sample> sample() { return mSample; }
- int channelID() { return mChannelID; }
- float leftVolume() { return mLeftVolume; }
- float rightVolume() { return mRightVolume; }
- int priority() { return mPriority; }
- int loop() { return mLoop; }
- float rate() { return mRate; }
- void clear() { mChannelID = 0; mSample.clear(); }
-
-protected:
- sp<Sample> mSample;
- int mChannelID;
- float mLeftVolume;
- float mRightVolume;
- int mPriority;
- int mLoop;
- float mRate;
-};
-
-// for channels aka AudioTracks
-class SoundChannel : public SoundEvent {
-public:
- enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
- SoundChannel() : mState(IDLE), mNumChannels(1),
- mPos(0), mToggle(0), mAutoPaused(false) {}
- ~SoundChannel();
- void init(SoundPool* soundPool);
- void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
- int priority, int loop, float rate);
- void setVolume_l(float leftVolume, float rightVolume);
- void setVolume(float leftVolume, float rightVolume);
- void stop_l();
- void stop();
- void pause();
- void autoPause();
- void resume();
- void autoResume();
- void setRate(float rate);
- int state() { return mState; }
- void setPriority(int priority) { mPriority = priority; }
- void setLoop(int loop);
- int numChannels() { return mNumChannels; }
- void clearNextEvent() { mNextEvent.clear(); }
- void nextEvent();
- int nextChannelID() { return mNextEvent.channelID(); }
- void dump();
-
-private:
- static void callback(int event, void* user, void *info);
- void process(int event, void *info, unsigned long toggle);
- bool doStop_l();
-
- SoundPool* mSoundPool;
- sp<AudioTrack> mAudioTrack;
- SoundEvent mNextEvent;
- Mutex mLock;
- int mState;
- int mNumChannels;
- int mPos;
- int mAudioBufferSize;
- unsigned long mToggle;
- bool mAutoPaused;
-};
-
-// application object for managing a pool of sounds
-class SoundPool {
- friend class SoundPoolThread;
- friend class SoundChannel;
-public:
- SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
- ~SoundPool();
- int load(const char* url, int priority);
- int load(int fd, int64_t offset, int64_t length, int priority);
- bool unload(int sampleID);
- int play(int sampleID, float leftVolume, float rightVolume, int priority,
- int loop, float rate);
- void pause(int channelID);
- void autoPause();
- void resume(int channelID);
- void autoResume();
- void stop(int channelID);
- void setVolume(int channelID, float leftVolume, float rightVolume);
- void setPriority(int channelID, int priority);
- void setLoop(int channelID, int loop);
- void setRate(int channelID, float rate);
- const audio_attributes_t* attributes() { return &mAttributes; }
-
- // called from SoundPoolThread
- void sampleLoaded(int sampleID);
-
- // called from AudioTrack thread
- void done_l(SoundChannel* channel);
-
- // callback function
- void setCallback(SoundPoolCallback* callback, void* user);
- void* getUserData() { return mUserData; }
-
-private:
- SoundPool() {} // no default constructor
- bool startThreads();
- void doLoad(sp<Sample>& sample);
- sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
- SoundChannel* findChannel (int channelID);
- SoundChannel* findNextChannel (int channelID);
- SoundChannel* allocateChannel_l(int priority);
- void moveToFront_l(SoundChannel* channel);
- void notify(SoundPoolEvent event);
- void dump();
-
- // restart thread
- void addToRestartList(SoundChannel* channel);
- void addToStopList(SoundChannel* channel);
- static int beginThread(void* arg);
- int run();
- void quit();
-
- Mutex mLock;
- Mutex mRestartLock;
- Condition mCondition;
- SoundPoolThread* mDecodeThread;
- SoundChannel* mChannelPool;
- List<SoundChannel*> mChannels;
- List<SoundChannel*> mRestart;
- List<SoundChannel*> mStop;
- DefaultKeyedVector< int, sp<Sample> > mSamples;
- int mMaxChannels;
- audio_attributes_t mAttributes;
- int mAllocated;
- int mNextSampleID;
- int mNextChannelID;
- bool mQuit;
-
- // callback
- Mutex mCallbackLock;
- SoundPoolCallback* mCallback;
- void* mUserData;
-};
-
-} // end namespace android
-
-#endif /*SOUNDPOOL_H_*/
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 9cc208e..5830933 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -232,17 +232,6 @@
bool isLooping();
status_t setVolume(float leftVolume, float rightVolume);
void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
- static status_t decode(
- const sp<IMediaHTTPService> &httpService,
- const char* url,
- uint32_t *pSampleRate,
- int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap,
- size_t *pSize);
- static status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
- int* pNumChannels, audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap, size_t *pSize);
status_t invoke(const Parcel& request, Parcel *reply);
status_t setMetadataFilter(const Parcel& filter);
status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 371e2c8..595ace8 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -78,7 +78,7 @@
static bool isFlexibleColorFormat(
const sp<IOMX> &omx, IOMX::node_id node,
- uint32_t colorFormat, OMX_U32 *flexibleEquivalent);
+ uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent);
// Returns 0 if configuration is not supported. NOTE: this is treated by
// some OMX components as auto level, and by others as invalid level.
@@ -251,12 +251,13 @@
status_t setVideoPortFormatType(
OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE compressionFormat,
- OMX_COLOR_FORMATTYPE colorFormat);
+ OMX_COLOR_FORMATTYPE colorFormat,
+ bool usingNativeBuffers = false);
- status_t setSupportedOutputFormat();
+ status_t setSupportedOutputFormat(bool getLegacyFlexibleFormat);
status_t setupVideoDecoder(
- const char *mime, const sp<AMessage> &msg);
+ const char *mime, const sp<AMessage> &msg, bool usingNativeBuffers);
status_t setupVideoEncoder(
const char *mime, const sp<AMessage> &msg);
@@ -264,7 +265,7 @@
status_t setVideoFormatOnPort(
OMX_U32 portIndex,
int32_t width, int32_t height,
- OMX_VIDEO_CODINGTYPE compressionFormat);
+ OMX_VIDEO_CODINGTYPE compressionFormat, float frameRate = -1.0);
typedef struct drcParams {
int32_t drcCut;
diff --git a/include/media/stagefright/foundation/AString.h b/include/media/stagefright/foundation/AString.h
index c3a68e1..822dbb3 100644
--- a/include/media/stagefright/foundation/AString.h
+++ b/include/media/stagefright/foundation/AString.h
@@ -102,7 +102,7 @@
void makeMutable();
};
-AString StringPrintf(const char *format, ...);
+AString AStringPrintf(const char *format, ...);
} // namespace android
diff --git a/media/libcpustats/ThreadCpuUsage.cpp b/media/libcpustats/ThreadCpuUsage.cpp
index 7b5b661..b43b36c 100644
--- a/media/libcpustats/ThreadCpuUsage.cpp
+++ b/media/libcpustats/ThreadCpuUsage.cpp
@@ -19,6 +19,7 @@
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <time.h>
#include <utils/Log.h>
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 4215b89..5378bf2 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -58,8 +58,6 @@
AudioEffect.cpp \
Visualizer.cpp \
MemoryLeakTrackUtil.cpp \
- SoundPool.cpp \
- SoundPoolThread.cpp \
StringArray.cpp \
AudioPolicy.cpp
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 7a18cba..f5a5712 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -590,18 +590,22 @@
status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address)
+ const char *device_address,
+ const char *device_name)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
const char *address = "";
+ const char *name = "";
if (aps == 0) return PERMISSION_DENIED;
if (device_address != NULL) {
address = device_address;
}
-
- return aps->setDeviceConnectionState(device, state, address);
+ if (device_name != NULL) {
+ name = device_name;
+ }
+ return aps->setDeviceConnectionState(device, state, address, name);
}
audio_policy_dev_state_t AudioSystem::getDeviceConnectionState(audio_devices_t device,
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index dbc7a9e..b175055 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -84,13 +84,15 @@
virtual status_t setDeviceConnectionState(
audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address)
+ const char *device_address,
+ const char *device_name)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(static_cast <uint32_t>(device));
data.writeInt32(static_cast <uint32_t>(state));
data.writeCString(device_address);
+ data.writeCString(device_name);
remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
@@ -726,9 +728,11 @@
audio_policy_dev_state_t state =
static_cast <audio_policy_dev_state_t>(data.readInt32());
const char *device_address = data.readCString();
+ const char *device_name = data.readCString();
reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
state,
- device_address)));
+ device_address,
+ device_name)));
return NO_ERROR;
} break;
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 4d33d40..feea267 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -39,8 +39,6 @@
enum {
CREATE = IBinder::FIRST_CALL_TRANSACTION,
- DECODE_URL,
- DECODE_FD,
CREATE_MEDIA_RECORDER,
CREATE_METADATA_RETRIEVER,
GET_OMX,
@@ -88,59 +86,6 @@
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
}
- virtual status_t decode(
- const sp<IMediaHTTPService> &httpService,
- const char* url,
- uint32_t *pSampleRate,
- int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap,
- size_t *pSize)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
- data.writeInt32(httpService != NULL);
- if (httpService != NULL) {
- data.writeStrongBinder(IInterface::asBinder(httpService));
- }
- data.writeCString(url);
- data.writeStrongBinder(IInterface::asBinder(heap));
- status_t status = remote()->transact(DECODE_URL, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- if (status == NO_ERROR) {
- *pSampleRate = uint32_t(reply.readInt32());
- *pNumChannels = reply.readInt32();
- *pFormat = (audio_format_t)reply.readInt32();
- *pSize = (size_t)reply.readInt32();
- }
- }
- return status;
- }
-
- virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
- int* pNumChannels, audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap, size_t *pSize)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
- data.writeFileDescriptor(fd);
- data.writeInt64(offset);
- data.writeInt64(length);
- data.writeStrongBinder(IInterface::asBinder(heap));
- status_t status = remote()->transact(DECODE_FD, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- if (status == NO_ERROR) {
- *pSampleRate = uint32_t(reply.readInt32());
- *pNumChannels = reply.readInt32();
- *pFormat = (audio_format_t)reply.readInt32();
- *pSize = (size_t)reply.readInt32();
- }
- }
- return status;
- }
-
virtual sp<IOMX> getOMX() {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -219,58 +164,6 @@
reply->writeStrongBinder(IInterface::asBinder(player));
return NO_ERROR;
} break;
- case DECODE_URL: {
- CHECK_INTERFACE(IMediaPlayerService, data, reply);
- sp<IMediaHTTPService> httpService;
- if (data.readInt32()) {
- httpService =
- interface_cast<IMediaHTTPService>(data.readStrongBinder());
- }
- const char* url = data.readCString();
- sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
- uint32_t sampleRate;
- int numChannels;
- audio_format_t format;
- size_t size;
- status_t status =
- decode(httpService,
- url,
- &sampleRate,
- &numChannels,
- &format,
- heap,
- &size);
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->writeInt32(sampleRate);
- reply->writeInt32(numChannels);
- reply->writeInt32((int32_t)format);
- reply->writeInt32((int32_t)size);
- }
- return NO_ERROR;
- } break;
- case DECODE_FD: {
- CHECK_INTERFACE(IMediaPlayerService, data, reply);
- int fd = dup(data.readFileDescriptor());
- int64_t offset = data.readInt64();
- int64_t length = data.readInt64();
- sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
- uint32_t sampleRate;
- int numChannels;
- audio_format_t format;
- size_t size;
- status_t status = decode(fd, offset, length, &sampleRate, &numChannels, &format,
- heap, &size);
- ::close(fd);
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->writeInt32(sampleRate);
- reply->writeInt32(numChannels);
- reply->writeInt32((int32_t)format);
- reply->writeInt32((int32_t)size);
- }
- return NO_ERROR;
- } break;
case CREATE_MEDIA_RECORDER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaRecorder> recorder = createMediaRecorder();
diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp
index 66f7161..d31f721 100644
--- a/media/libmedia/MemoryLeakTrackUtil.cpp
+++ b/media/libmedia/MemoryLeakTrackUtil.cpp
@@ -18,6 +18,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index 2181111..5197ce2 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -48,6 +48,8 @@
}
MidiIoWrapper::MidiIoWrapper(const sp<DataSource> &source) {
+ ALOGV("MidiIoWrapper(DataSource)");
+ mFd = -1;
mDataSource = source;
off64_t l;
if (mDataSource->getSize(&l) == OK) {
@@ -76,7 +78,7 @@
}
int MidiIoWrapper::size() {
- ALOGV("size() = %d", mLength);
+ ALOGV("size() = %d", int(mLength));
return mLength;
}
diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp
deleted file mode 100644
index 76f11dc..0000000
--- a/media/libmedia/SoundPool.cpp
+++ /dev/null
@@ -1,922 +0,0 @@
-/*
- * Copyright (C) 2007 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 "SoundPool"
-
-#include <inttypes.h>
-
-#include <utils/Log.h>
-
-#define USE_SHARED_MEM_BUFFER
-
-#include <media/AudioTrack.h>
-#include <media/IMediaHTTPService.h>
-#include <media/mediaplayer.h>
-#include <media/SoundPool.h>
-#include "SoundPoolThread.h"
-#include <media/AudioPolicyHelper.h>
-
-namespace android
-{
-
-int kDefaultBufferCount = 4;
-uint32_t kMaxSampleRate = 48000;
-uint32_t kDefaultSampleRate = 44100;
-uint32_t kDefaultFrameCount = 1200;
-size_t kDefaultHeapSize = 1024 * 1024; // 1MB
-
-
-SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes)
-{
- ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s",
- maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags);
-
- // check limits
- mMaxChannels = maxChannels;
- if (mMaxChannels < 1) {
- mMaxChannels = 1;
- }
- else if (mMaxChannels > 32) {
- mMaxChannels = 32;
- }
- ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels);
-
- mQuit = false;
- mDecodeThread = 0;
- memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
- mAllocated = 0;
- mNextSampleID = 0;
- mNextChannelID = 0;
-
- mCallback = 0;
- mUserData = 0;
-
- mChannelPool = new SoundChannel[mMaxChannels];
- for (int i = 0; i < mMaxChannels; ++i) {
- mChannelPool[i].init(this);
- mChannels.push_back(&mChannelPool[i]);
- }
-
- // start decode thread
- startThreads();
-}
-
-SoundPool::~SoundPool()
-{
- ALOGV("SoundPool destructor");
- mDecodeThread->quit();
- quit();
-
- Mutex::Autolock lock(&mLock);
-
- mChannels.clear();
- if (mChannelPool)
- delete [] mChannelPool;
- // clean up samples
- ALOGV("clear samples");
- mSamples.clear();
-
- if (mDecodeThread)
- delete mDecodeThread;
-}
-
-void SoundPool::addToRestartList(SoundChannel* channel)
-{
- Mutex::Autolock lock(&mRestartLock);
- if (!mQuit) {
- mRestart.push_back(channel);
- mCondition.signal();
- }
-}
-
-void SoundPool::addToStopList(SoundChannel* channel)
-{
- Mutex::Autolock lock(&mRestartLock);
- if (!mQuit) {
- mStop.push_back(channel);
- mCondition.signal();
- }
-}
-
-int SoundPool::beginThread(void* arg)
-{
- SoundPool* p = (SoundPool*)arg;
- return p->run();
-}
-
-int SoundPool::run()
-{
- mRestartLock.lock();
- while (!mQuit) {
- mCondition.wait(mRestartLock);
- ALOGV("awake");
- if (mQuit) break;
-
- while (!mStop.empty()) {
- SoundChannel* channel;
- ALOGV("Getting channel from stop list");
- List<SoundChannel* >::iterator iter = mStop.begin();
- channel = *iter;
- mStop.erase(iter);
- mRestartLock.unlock();
- if (channel != 0) {
- Mutex::Autolock lock(&mLock);
- channel->stop();
- }
- mRestartLock.lock();
- if (mQuit) break;
- }
-
- while (!mRestart.empty()) {
- SoundChannel* channel;
- ALOGV("Getting channel from list");
- List<SoundChannel*>::iterator iter = mRestart.begin();
- channel = *iter;
- mRestart.erase(iter);
- mRestartLock.unlock();
- if (channel != 0) {
- Mutex::Autolock lock(&mLock);
- channel->nextEvent();
- }
- mRestartLock.lock();
- if (mQuit) break;
- }
- }
-
- mStop.clear();
- mRestart.clear();
- mCondition.signal();
- mRestartLock.unlock();
- ALOGV("goodbye");
- return 0;
-}
-
-void SoundPool::quit()
-{
- mRestartLock.lock();
- mQuit = true;
- mCondition.signal();
- mCondition.wait(mRestartLock);
- ALOGV("return from quit");
- mRestartLock.unlock();
-}
-
-bool SoundPool::startThreads()
-{
- createThreadEtc(beginThread, this, "SoundPool");
- if (mDecodeThread == NULL)
- mDecodeThread = new SoundPoolThread(this);
- return mDecodeThread != NULL;
-}
-
-SoundChannel* SoundPool::findChannel(int channelID)
-{
- for (int i = 0; i < mMaxChannels; ++i) {
- if (mChannelPool[i].channelID() == channelID) {
- return &mChannelPool[i];
- }
- }
- return NULL;
-}
-
-SoundChannel* SoundPool::findNextChannel(int channelID)
-{
- for (int i = 0; i < mMaxChannels; ++i) {
- if (mChannelPool[i].nextChannelID() == channelID) {
- return &mChannelPool[i];
- }
- }
- return NULL;
-}
-
-int SoundPool::load(const char* path, int priority __unused)
-{
- ALOGV("load: path=%s, priority=%d", path, priority);
- Mutex::Autolock lock(&mLock);
- sp<Sample> sample = new Sample(++mNextSampleID, path);
- mSamples.add(sample->sampleID(), sample);
- doLoad(sample);
- return sample->sampleID();
-}
-
-int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused)
-{
- ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d",
- fd, offset, length, priority);
- Mutex::Autolock lock(&mLock);
- sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
- mSamples.add(sample->sampleID(), sample);
- doLoad(sample);
- return sample->sampleID();
-}
-
-void SoundPool::doLoad(sp<Sample>& sample)
-{
- ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
- sample->startLoad();
- mDecodeThread->loadSample(sample->sampleID());
-}
-
-bool SoundPool::unload(int sampleID)
-{
- ALOGV("unload: sampleID=%d", sampleID);
- Mutex::Autolock lock(&mLock);
- return mSamples.removeItem(sampleID);
-}
-
-int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
- int priority, int loop, float rate)
-{
- ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
- sampleID, leftVolume, rightVolume, priority, loop, rate);
- sp<Sample> sample;
- SoundChannel* channel;
- int channelID;
-
- Mutex::Autolock lock(&mLock);
-
- if (mQuit) {
- return 0;
- }
- // is sample ready?
- sample = findSample(sampleID);
- if ((sample == 0) || (sample->state() != Sample::READY)) {
- ALOGW(" sample %d not READY", sampleID);
- return 0;
- }
-
- dump();
-
- // allocate a channel
- channel = allocateChannel_l(priority);
-
- // no channel allocated - return 0
- if (!channel) {
- ALOGV("No channel allocated");
- return 0;
- }
-
- channelID = ++mNextChannelID;
-
- ALOGV("play channel %p state = %d", channel, channel->state());
- channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
- return channelID;
-}
-
-SoundChannel* SoundPool::allocateChannel_l(int priority)
-{
- List<SoundChannel*>::iterator iter;
- SoundChannel* channel = NULL;
-
- // allocate a channel
- if (!mChannels.empty()) {
- iter = mChannels.begin();
- if (priority >= (*iter)->priority()) {
- channel = *iter;
- mChannels.erase(iter);
- ALOGV("Allocated active channel");
- }
- }
-
- // update priority and put it back in the list
- if (channel) {
- channel->setPriority(priority);
- for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
- if (priority < (*iter)->priority()) {
- break;
- }
- }
- mChannels.insert(iter, channel);
- }
- return channel;
-}
-
-// move a channel from its current position to the front of the list
-void SoundPool::moveToFront_l(SoundChannel* channel)
-{
- for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
- if (*iter == channel) {
- mChannels.erase(iter);
- mChannels.push_front(channel);
- break;
- }
- }
-}
-
-void SoundPool::pause(int channelID)
-{
- ALOGV("pause(%d)", channelID);
- Mutex::Autolock lock(&mLock);
- SoundChannel* channel = findChannel(channelID);
- if (channel) {
- channel->pause();
- }
-}
-
-void SoundPool::autoPause()
-{
- ALOGV("autoPause()");
- Mutex::Autolock lock(&mLock);
- for (int i = 0; i < mMaxChannels; ++i) {
- SoundChannel* channel = &mChannelPool[i];
- channel->autoPause();
- }
-}
-
-void SoundPool::resume(int channelID)
-{
- ALOGV("resume(%d)", channelID);
- Mutex::Autolock lock(&mLock);
- SoundChannel* channel = findChannel(channelID);
- if (channel) {
- channel->resume();
- }
-}
-
-void SoundPool::autoResume()
-{
- ALOGV("autoResume()");
- Mutex::Autolock lock(&mLock);
- for (int i = 0; i < mMaxChannels; ++i) {
- SoundChannel* channel = &mChannelPool[i];
- channel->autoResume();
- }
-}
-
-void SoundPool::stop(int channelID)
-{
- ALOGV("stop(%d)", channelID);
- Mutex::Autolock lock(&mLock);
- SoundChannel* channel = findChannel(channelID);
- if (channel) {
- channel->stop();
- } else {
- channel = findNextChannel(channelID);
- if (channel)
- channel->clearNextEvent();
- }
-}
-
-void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
-{
- Mutex::Autolock lock(&mLock);
- SoundChannel* channel = findChannel(channelID);
- if (channel) {
- channel->setVolume(leftVolume, rightVolume);
- }
-}
-
-void SoundPool::setPriority(int channelID, int priority)
-{
- ALOGV("setPriority(%d, %d)", channelID, priority);
- Mutex::Autolock lock(&mLock);
- SoundChannel* channel = findChannel(channelID);
- if (channel) {
- channel->setPriority(priority);
- }
-}
-
-void SoundPool::setLoop(int channelID, int loop)
-{
- ALOGV("setLoop(%d, %d)", channelID, loop);
- Mutex::Autolock lock(&mLock);
- SoundChannel* channel = findChannel(channelID);
- if (channel) {
- channel->setLoop(loop);
- }
-}
-
-void SoundPool::setRate(int channelID, float rate)
-{
- ALOGV("setRate(%d, %f)", channelID, rate);
- Mutex::Autolock lock(&mLock);
- SoundChannel* channel = findChannel(channelID);
- if (channel) {
- channel->setRate(rate);
- }
-}
-
-// call with lock held
-void SoundPool::done_l(SoundChannel* channel)
-{
- ALOGV("done_l(%d)", channel->channelID());
- // if "stolen", play next event
- if (channel->nextChannelID() != 0) {
- ALOGV("add to restart list");
- addToRestartList(channel);
- }
-
- // return to idle state
- else {
- ALOGV("move to front");
- moveToFront_l(channel);
- }
-}
-
-void SoundPool::setCallback(SoundPoolCallback* callback, void* user)
-{
- Mutex::Autolock lock(&mCallbackLock);
- mCallback = callback;
- mUserData = user;
-}
-
-void SoundPool::notify(SoundPoolEvent event)
-{
- Mutex::Autolock lock(&mCallbackLock);
- if (mCallback != NULL) {
- mCallback(event, this, mUserData);
- }
-}
-
-void SoundPool::dump()
-{
- for (int i = 0; i < mMaxChannels; ++i) {
- mChannelPool[i].dump();
- }
-}
-
-
-Sample::Sample(int sampleID, const char* url)
-{
- init();
- mSampleID = sampleID;
- mUrl = strdup(url);
- ALOGV("create sampleID=%d, url=%s", mSampleID, mUrl);
-}
-
-Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
-{
- init();
- mSampleID = sampleID;
- mFd = dup(fd);
- mOffset = offset;
- mLength = length;
- ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64,
- mSampleID, mFd, mLength, mOffset);
-}
-
-void Sample::init()
-{
- mSize = 0;
- mRefCount = 0;
- mSampleID = 0;
- mState = UNLOADED;
- mFd = -1;
- mOffset = 0;
- mLength = 0;
- mUrl = 0;
-}
-
-Sample::~Sample()
-{
- ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
- if (mFd > 0) {
- ALOGV("close(%d)", mFd);
- ::close(mFd);
- }
- free(mUrl);
-}
-
-status_t Sample::doLoad()
-{
- uint32_t sampleRate;
- int numChannels;
- audio_format_t format;
- status_t status;
- mHeap = new MemoryHeapBase(kDefaultHeapSize);
-
- ALOGV("Start decode");
- if (mUrl) {
- status = MediaPlayer::decode(
- NULL /* httpService */,
- mUrl,
- &sampleRate,
- &numChannels,
- &format,
- mHeap,
- &mSize);
- } else {
- status = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format,
- mHeap, &mSize);
- ALOGV("close(%d)", mFd);
- ::close(mFd);
- mFd = -1;
- }
- if (status != NO_ERROR) {
- ALOGE("Unable to load sample: %s", mUrl);
- goto error;
- }
- ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d",
- mHeap->getBase(), mSize, sampleRate, numChannels);
-
- if (sampleRate > kMaxSampleRate) {
- ALOGE("Sample rate (%u) out of range", sampleRate);
- status = BAD_VALUE;
- goto error;
- }
-
- if ((numChannels < 1) || (numChannels > 2)) {
- ALOGE("Sample channel count (%d) out of range", numChannels);
- status = BAD_VALUE;
- goto error;
- }
-
- mData = new MemoryBase(mHeap, 0, mSize);
- mSampleRate = sampleRate;
- mNumChannels = numChannels;
- mFormat = format;
- mState = READY;
- return NO_ERROR;
-
-error:
- mHeap.clear();
- return status;
-}
-
-
-void SoundChannel::init(SoundPool* soundPool)
-{
- mSoundPool = soundPool;
-}
-
-// call with sound pool lock held
-void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
- float rightVolume, int priority, int loop, float rate)
-{
- sp<AudioTrack> oldTrack;
- sp<AudioTrack> newTrack;
- status_t status;
-
- { // scope for the lock
- Mutex::Autolock lock(&mLock);
-
- ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
- " priority=%d, loop=%d, rate=%f",
- this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
- priority, loop, rate);
-
- // if not idle, this voice is being stolen
- if (mState != IDLE) {
- ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
- mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
- stop_l();
- return;
- }
-
- // initialize track
- size_t afFrameCount;
- uint32_t afSampleRate;
- audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes());
- if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
- afFrameCount = kDefaultFrameCount;
- }
- if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
- afSampleRate = kDefaultSampleRate;
- }
- int numChannels = sample->numChannels();
- uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
- uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
- uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
- size_t frameCount = 0;
-
- if (loop) {
- frameCount = sample->size()/numChannels/
- ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
- }
-
-#ifndef USE_SHARED_MEM_BUFFER
- // Ensure minimum audio buffer size in case of short looped sample
- if(frameCount < totalFrames) {
- frameCount = totalFrames;
- }
-#endif
-
- // mToggle toggles each time a track is started on a given channel.
- // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
- // as callback user data. This enables the detection of callbacks received from the old
- // audio track while the new one is being started and avoids processing them with
- // wrong audio audio buffer size (mAudioBufferSize)
- unsigned long toggle = mToggle ^ 1;
- void *userData = (void *)((unsigned long)this | toggle);
- audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels);
-
- // do not create a new audio track if current track is compatible with sample parameters
-#ifdef USE_SHARED_MEM_BUFFER
- newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
- channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
-#else
- newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
- channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
- bufferFrames);
-#endif
- oldTrack = mAudioTrack;
- status = newTrack->initCheck();
- if (status != NO_ERROR) {
- ALOGE("Error creating AudioTrack");
- goto exit;
- }
- ALOGV("setVolume %p", newTrack.get());
- newTrack->setVolume(leftVolume, rightVolume);
- newTrack->setLoop(0, frameCount, loop);
-
- // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
- mToggle = toggle;
- mAudioTrack = newTrack;
- mPos = 0;
- mSample = sample;
- mChannelID = nextChannelID;
- mPriority = priority;
- mLoop = loop;
- mLeftVolume = leftVolume;
- mRightVolume = rightVolume;
- mNumChannels = numChannels;
- mRate = rate;
- clearNextEvent();
- mState = PLAYING;
- mAudioTrack->start();
- mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
- }
-
-exit:
- ALOGV("delete oldTrack %p", oldTrack.get());
- if (status != NO_ERROR) {
- mAudioTrack.clear();
- }
-}
-
-void SoundChannel::nextEvent()
-{
- sp<Sample> sample;
- int nextChannelID;
- float leftVolume;
- float rightVolume;
- int priority;
- int loop;
- float rate;
-
- // check for valid event
- {
- Mutex::Autolock lock(&mLock);
- nextChannelID = mNextEvent.channelID();
- if (nextChannelID == 0) {
- ALOGV("stolen channel has no event");
- return;
- }
-
- sample = mNextEvent.sample();
- leftVolume = mNextEvent.leftVolume();
- rightVolume = mNextEvent.rightVolume();
- priority = mNextEvent.priority();
- loop = mNextEvent.loop();
- rate = mNextEvent.rate();
- }
-
- ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
- play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-}
-
-void SoundChannel::callback(int event, void* user, void *info)
-{
- SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
-
- channel->process(event, info, (unsigned long)user & 1);
-}
-
-void SoundChannel::process(int event, void *info, unsigned long toggle)
-{
- //ALOGV("process(%d)", mChannelID);
-
- Mutex::Autolock lock(&mLock);
-
- AudioTrack::Buffer* b = NULL;
- if (event == AudioTrack::EVENT_MORE_DATA) {
- b = static_cast<AudioTrack::Buffer *>(info);
- }
-
- if (mToggle != toggle) {
- ALOGV("process wrong toggle %p channel %d", this, mChannelID);
- if (b != NULL) {
- b->size = 0;
- }
- return;
- }
-
- sp<Sample> sample = mSample;
-
-// ALOGV("SoundChannel::process event %d", event);
-
- if (event == AudioTrack::EVENT_MORE_DATA) {
-
- // check for stop state
- if (b->size == 0) return;
-
- if (mState == IDLE) {
- b->size = 0;
- return;
- }
-
- if (sample != 0) {
- // fill buffer
- uint8_t* q = (uint8_t*) b->i8;
- size_t count = 0;
-
- if (mPos < (int)sample->size()) {
- uint8_t* p = sample->data() + mPos;
- count = sample->size() - mPos;
- if (count > b->size) {
- count = b->size;
- }
- memcpy(q, p, count);
-// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size,
-// count);
- } else if (mPos < mAudioBufferSize) {
- count = mAudioBufferSize - mPos;
- if (count > b->size) {
- count = b->size;
- }
- memset(q, 0, count);
-// ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
- }
-
- mPos += count;
- b->size = count;
- //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
- }
- } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) {
- ALOGV("process %p channel %d event %s",
- this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" :
- "BUFFER_END");
- mSoundPool->addToStopList(this);
- } else if (event == AudioTrack::EVENT_LOOP_END) {
- ALOGV("End loop %p channel %d", this, mChannelID);
- } else if (event == AudioTrack::EVENT_NEW_IAUDIOTRACK) {
- ALOGV("process %p channel %d NEW_IAUDIOTRACK", this, mChannelID);
- } else {
- ALOGW("SoundChannel::process unexpected event %d", event);
- }
-}
-
-
-// call with lock held
-bool SoundChannel::doStop_l()
-{
- if (mState != IDLE) {
- setVolume_l(0, 0);
- ALOGV("stop");
- mAudioTrack->stop();
- mSample.clear();
- mState = IDLE;
- mPriority = IDLE_PRIORITY;
- return true;
- }
- return false;
-}
-
-// call with lock held and sound pool lock held
-void SoundChannel::stop_l()
-{
- if (doStop_l()) {
- mSoundPool->done_l(this);
- }
-}
-
-// call with sound pool lock held
-void SoundChannel::stop()
-{
- bool stopped;
- {
- Mutex::Autolock lock(&mLock);
- stopped = doStop_l();
- }
-
- if (stopped) {
- mSoundPool->done_l(this);
- }
-}
-
-//FIXME: Pause is a little broken right now
-void SoundChannel::pause()
-{
- Mutex::Autolock lock(&mLock);
- if (mState == PLAYING) {
- ALOGV("pause track");
- mState = PAUSED;
- mAudioTrack->pause();
- }
-}
-
-void SoundChannel::autoPause()
-{
- Mutex::Autolock lock(&mLock);
- if (mState == PLAYING) {
- ALOGV("pause track");
- mState = PAUSED;
- mAutoPaused = true;
- mAudioTrack->pause();
- }
-}
-
-void SoundChannel::resume()
-{
- Mutex::Autolock lock(&mLock);
- if (mState == PAUSED) {
- ALOGV("resume track");
- mState = PLAYING;
- mAutoPaused = false;
- mAudioTrack->start();
- }
-}
-
-void SoundChannel::autoResume()
-{
- Mutex::Autolock lock(&mLock);
- if (mAutoPaused && (mState == PAUSED)) {
- ALOGV("resume track");
- mState = PLAYING;
- mAutoPaused = false;
- mAudioTrack->start();
- }
-}
-
-void SoundChannel::setRate(float rate)
-{
- Mutex::Autolock lock(&mLock);
- if (mAudioTrack != NULL && mSample != 0) {
- uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5);
- mAudioTrack->setSampleRate(sampleRate);
- mRate = rate;
- }
-}
-
-// call with lock held
-void SoundChannel::setVolume_l(float leftVolume, float rightVolume)
-{
- mLeftVolume = leftVolume;
- mRightVolume = rightVolume;
- if (mAudioTrack != NULL)
- mAudioTrack->setVolume(leftVolume, rightVolume);
-}
-
-void SoundChannel::setVolume(float leftVolume, float rightVolume)
-{
- Mutex::Autolock lock(&mLock);
- setVolume_l(leftVolume, rightVolume);
-}
-
-void SoundChannel::setLoop(int loop)
-{
- Mutex::Autolock lock(&mLock);
- if (mAudioTrack != NULL && mSample != 0) {
- uint32_t loopEnd = mSample->size()/mNumChannels/
- ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
- mAudioTrack->setLoop(0, loopEnd, loop);
- mLoop = loop;
- }
-}
-
-SoundChannel::~SoundChannel()
-{
- ALOGV("SoundChannel destructor %p", this);
- {
- Mutex::Autolock lock(&mLock);
- clearNextEvent();
- doStop_l();
- }
- // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack
- // callback thread to exit which may need to execute process() and acquire the mLock.
- mAudioTrack.clear();
-}
-
-void SoundChannel::dump()
-{
- ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d",
- mState, mChannelID, mNumChannels, mPos, mPriority, mLoop);
-}
-
-void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
- float rightVolume, int priority, int loop, float rate)
-{
- mSample = sample;
- mChannelID = channelID;
- mLeftVolume = leftVolume;
- mRightVolume = rightVolume;
- mPriority = priority;
- mLoop = loop;
- mRate =rate;
-}
-
-} // end namespace android
diff --git a/media/libmedia/SoundPoolThread.cpp b/media/libmedia/SoundPoolThread.cpp
deleted file mode 100644
index ba3b482..0000000
--- a/media/libmedia/SoundPoolThread.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2007 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 "SoundPoolThread"
-#include "utils/Log.h"
-
-#include "SoundPoolThread.h"
-
-namespace android {
-
-void SoundPoolThread::write(SoundPoolMsg msg) {
- Mutex::Autolock lock(&mLock);
- while (mMsgQueue.size() >= maxMessages) {
- mCondition.wait(mLock);
- }
-
- // if thread is quitting, don't add to queue
- if (mRunning) {
- mMsgQueue.push(msg);
- mCondition.signal();
- }
-}
-
-const SoundPoolMsg SoundPoolThread::read() {
- Mutex::Autolock lock(&mLock);
- while (mMsgQueue.size() == 0) {
- mCondition.wait(mLock);
- }
- SoundPoolMsg msg = mMsgQueue[0];
- mMsgQueue.removeAt(0);
- mCondition.signal();
- return msg;
-}
-
-void SoundPoolThread::quit() {
- Mutex::Autolock lock(&mLock);
- if (mRunning) {
- mRunning = false;
- mMsgQueue.clear();
- mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
- mCondition.signal();
- mCondition.wait(mLock);
- }
- ALOGV("return from quit");
-}
-
-SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
- mSoundPool(soundPool)
-{
- mMsgQueue.setCapacity(maxMessages);
- if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
- mRunning = true;
- }
-}
-
-SoundPoolThread::~SoundPoolThread()
-{
- quit();
-}
-
-int SoundPoolThread::beginThread(void* arg) {
- ALOGV("beginThread");
- SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
- return soundPoolThread->run();
-}
-
-int SoundPoolThread::run() {
- ALOGV("run");
- for (;;) {
- SoundPoolMsg msg = read();
- ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
- switch (msg.mMessageType) {
- case SoundPoolMsg::KILL:
- ALOGV("goodbye");
- return NO_ERROR;
- case SoundPoolMsg::LOAD_SAMPLE:
- doLoadSample(msg.mData);
- break;
- default:
- ALOGW("run: Unrecognized message %d\n",
- msg.mMessageType);
- break;
- }
- }
-}
-
-void SoundPoolThread::loadSample(int sampleID) {
- write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
-}
-
-void SoundPoolThread::doLoadSample(int sampleID) {
- sp <Sample> sample = mSoundPool->findSample(sampleID);
- status_t status = -1;
- if (sample != 0) {
- status = sample->doLoad();
- }
- mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
-}
-
-} // end namespace android
diff --git a/media/libmedia/SoundPoolThread.h b/media/libmedia/SoundPoolThread.h
deleted file mode 100644
index 7e96900..0000000
--- a/media/libmedia/SoundPoolThread.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007 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 SOUNDPOOLTHREAD_H_
-#define SOUNDPOOLTHREAD_H_
-
-#include <utils/threads.h>
-#include <utils/Vector.h>
-#include <media/AudioTrack.h>
-
-#include <media/SoundPool.h>
-
-namespace android {
-
-class SoundPoolMsg {
-public:
- enum MessageType { INVALID, KILL, LOAD_SAMPLE };
- SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
- SoundPoolMsg(MessageType MessageType, int data) :
- mMessageType(MessageType), mData(data) {}
- uint16_t mMessageType;
- uint16_t mData;
-};
-
-/*
- * This class handles background requests from the SoundPool
- */
-class SoundPoolThread {
-public:
- SoundPoolThread(SoundPool* SoundPool);
- ~SoundPoolThread();
- void loadSample(int sampleID);
- void quit();
- void write(SoundPoolMsg msg);
-
-private:
- static const size_t maxMessages = 5;
-
- static int beginThread(void* arg);
- int run();
- void doLoadSample(int sampleID);
- const SoundPoolMsg read();
-
- Mutex mLock;
- Condition mCondition;
- Vector<SoundPoolMsg> mMsgQueue;
- SoundPool* mSoundPool;
- bool mRunning;
-};
-
-} // end namespace android
-
-#endif /*SOUNDPOOLTHREAD_H_*/
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 9bfd813..432ecda 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -838,53 +838,12 @@
}
}
-/*static*/ status_t MediaPlayer::decode(
- const sp<IMediaHTTPService> &httpService,
- const char* url,
- uint32_t *pSampleRate,
- int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap,
- size_t *pSize)
-{
- ALOGV("decode(%s)", url);
- status_t status;
- const sp<IMediaPlayerService>& service = getMediaPlayerService();
- if (service != 0) {
- status = service->decode(httpService, url, pSampleRate, pNumChannels, pFormat, heap, pSize);
- } else {
- ALOGE("Unable to locate media service");
- status = DEAD_OBJECT;
- }
- return status;
-
-}
-
void MediaPlayer::died()
{
ALOGV("died");
notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
}
-/*static*/ status_t MediaPlayer::decode(int fd, int64_t offset, int64_t length,
- uint32_t *pSampleRate, int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap, size_t *pSize)
-{
- ALOGV("decode(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
- status_t status;
- const sp<IMediaPlayerService>& service = getMediaPlayerService();
- if (service != 0) {
- status = service->decode(fd, offset, length, pSampleRate,
- pNumChannels, pFormat, heap, pSize);
- } else {
- ALOGE("Unable to locate media service");
- status = DEAD_OBJECT;
- }
- return status;
-
-}
-
status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
if (mPlayer == NULL) {
return NO_INIT;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index cf6771e..1936218 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -384,28 +384,6 @@
return new RemoteDisplay(client, iface.string());
}
-status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& /*args*/) const
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- result.append(" AudioCache\n");
- if (mHeap != 0) {
- snprintf(buffer, 255, " heap base(%p), size(%zu), flags(%d)\n",
- mHeap->getBase(), mHeap->getSize(), mHeap->getFlags());
- result.append(buffer);
- }
- snprintf(buffer, 255, " msec per frame(%f), channel count(%d), format(%d), frame count(%zd)\n",
- mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
- result.append(buffer);
- snprintf(buffer, 255, " sample rate(%d), size(%d), error(%d), command complete(%s)\n",
- mSampleRate, mSize, mError, mCommandComplete?"true":"false");
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
{
const size_t SIZE = 256;
@@ -1279,128 +1257,6 @@
}
#endif
-status_t MediaPlayerService::decode(
- const sp<IMediaHTTPService> &httpService,
- const char* url,
- uint32_t *pSampleRate,
- int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap,
- size_t *pSize)
-{
- ALOGV("decode(%s)", url);
- sp<MediaPlayerBase> player;
- status_t status = BAD_VALUE;
-
- // Protect our precious, precious DRMd ringtones by only allowing
- // decoding of http, but not filesystem paths or content Uris.
- // If the application wants to decode those, it should open a
- // filedescriptor for them and use that.
- if (url != NULL && strncmp(url, "http://", 7) != 0) {
- ALOGD("Can't decode %s by path, use filedescriptor instead", url);
- return BAD_VALUE;
- }
-
- player_type playerType =
- MediaPlayerFactory::getPlayerType(NULL /* client */, url);
- ALOGV("player type = %d", playerType);
-
- // create the right type of player
- sp<AudioCache> cache = new AudioCache(heap);
- player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
- if (player == NULL) goto Exit;
- if (player->hardwareOutput()) goto Exit;
-
- static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
-
- // set data source
- if (player->setDataSource(httpService, url) != NO_ERROR) goto Exit;
-
- ALOGV("prepare");
- player->prepareAsync();
-
- ALOGV("wait for prepare");
- if (cache->wait() != NO_ERROR) goto Exit;
-
- ALOGV("start");
- player->start();
-
- ALOGV("wait for playback complete");
- cache->wait();
- // in case of error, return what was successfully decoded.
- if (cache->size() == 0) {
- goto Exit;
- }
-
- *pSize = cache->size();
- *pSampleRate = cache->sampleRate();
- *pNumChannels = cache->channelCount();
- *pFormat = cache->format();
- ALOGV("return size %d sampleRate=%u, channelCount = %d, format = %d",
- *pSize, *pSampleRate, *pNumChannels, *pFormat);
- status = NO_ERROR;
-
-Exit:
- if (player != 0) player->reset();
- return status;
-}
-
-status_t MediaPlayerService::decode(int fd, int64_t offset, int64_t length,
- uint32_t *pSampleRate, int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap, size_t *pSize)
-{
- ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
- sp<MediaPlayerBase> player;
- status_t status = BAD_VALUE;
-
- player_type playerType = MediaPlayerFactory::getPlayerType(NULL /* client */,
- fd,
- offset,
- length);
- ALOGV("player type = %d", playerType);
-
- // create the right type of player
- sp<AudioCache> cache = new AudioCache(heap);
- player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
- if (player == NULL) goto Exit;
- if (player->hardwareOutput()) goto Exit;
-
- static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
-
- // set data source
- if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
-
- ALOGV("prepare");
- player->prepareAsync();
-
- ALOGV("wait for prepare");
- if (cache->wait() != NO_ERROR) goto Exit;
-
- ALOGV("start");
- player->start();
-
- ALOGV("wait for playback complete");
- cache->wait();
- // in case of error, return what was successfully decoded.
- if (cache->size() == 0) {
- goto Exit;
- }
-
- *pSize = cache->size();
- *pSampleRate = cache->sampleRate();
- *pNumChannels = cache->channelCount();
- *pFormat = cache->format();
- ALOGV("return size %d, sampleRate=%u, channelCount = %d, format = %d",
- *pSize, *pSampleRate, *pNumChannels, *pFormat);
- status = NO_ERROR;
-
-Exit:
- if (player != 0) player->reset();
- return status;
-}
-
-
#undef LOG_TAG
#define LOG_TAG "AudioSink"
MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid,
@@ -1950,47 +1806,6 @@
return mTrack->getSampleRate();
}
-#undef LOG_TAG
-#define LOG_TAG "AudioCache"
-MediaPlayerService::AudioCache::AudioCache(const sp<IMemoryHeap>& heap) :
- mHeap(heap), mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
- mFrameSize(1), mError(NO_ERROR), mCommandComplete(false)
-{
-}
-
-uint32_t MediaPlayerService::AudioCache::latency () const
-{
- return 0;
-}
-
-float MediaPlayerService::AudioCache::msecsPerFrame() const
-{
- return mMsecsPerFrame;
-}
-
-status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const
-{
- if (position == 0) return BAD_VALUE;
- *position = mSize / mFrameSize;
- return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::getTimestamp(AudioTimestamp &ts) const
-{
- ts.mPosition = mSize / mFrameSize;
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- ts.mTime.tv_sec = now / 1000000000LL;
- ts.mTime.tv_nsec = now - (1000000000LL * ts.mTime.tv_sec);
- return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
-{
- if (written == 0) return BAD_VALUE;
- *written = mSize / mFrameSize;
- return NO_ERROR;
-}
-
////////////////////////////////////////////////////////////////////////////////
struct CallbackThread : public Thread {
@@ -2058,139 +1873,6 @@
////////////////////////////////////////////////////////////////////////////////
-status_t MediaPlayerService::AudioCache::open(
- uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
- audio_format_t format, int bufferCount,
- AudioCallback cb, void *cookie, audio_output_flags_t /*flags*/,
- const audio_offload_info_t* /*offloadInfo*/)
-{
- ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount);
- if (mHeap->getHeapID() < 0) {
- return NO_INIT;
- }
-
- mSampleRate = sampleRate;
- mChannelCount = (uint16_t)channelCount;
- mFormat = format;
- mMsecsPerFrame = 1.e3 / (float) sampleRate;
- mFrameSize = audio_is_linear_pcm(mFormat)
- ? mChannelCount * audio_bytes_per_sample(mFormat) : 1;
- mFrameCount = mHeap->getSize() / mFrameSize;
-
- if (cb != NULL) {
- mCallbackThread = new CallbackThread(this, cb, cookie);
- }
- return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::start() {
- if (mCallbackThread != NULL) {
- mCallbackThread->run("AudioCache callback");
- }
- return NO_ERROR;
-}
-
-void MediaPlayerService::AudioCache::stop() {
- if (mCallbackThread != NULL) {
- mCallbackThread->requestExitAndWait();
- }
-}
-
-ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
-{
- ALOGV("write(%p, %u)", buffer, size);
- if ((buffer == 0) || (size == 0)) return size;
-
- uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
- if (p == NULL) return NO_INIT;
- p += mSize;
- ALOGV("memcpy(%p, %p, %u)", p, buffer, size);
-
- bool overflow = mSize + size > mHeap->getSize();
- if (overflow) {
- ALOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
- size = mHeap->getSize() - mSize;
- }
- size -= size % mFrameSize; // consume only integral amounts of frame size
- memcpy(p, buffer, size);
- mSize += size;
-
- if (overflow) {
- // Signal heap filled here (last frame may be truncated).
- // After this point, no more data should be written as the
- // heap is filled and the AudioCache should be effectively
- // immutable with respect to future writes.
- //
- // It is thus safe for another thread to read the AudioCache.
- Mutex::Autolock lock(mLock);
- mCommandComplete = true;
- mSignal.signal();
- }
- return size;
-}
-
-// call with lock held
-status_t MediaPlayerService::AudioCache::wait()
-{
- Mutex::Autolock lock(mLock);
- while (!mCommandComplete) {
- mSignal.wait(mLock);
- }
- mCommandComplete = false;
-
- if (mError == NO_ERROR) {
- ALOGV("wait - success");
- } else {
- ALOGV("wait - error");
- }
- return mError;
-}
-
-void MediaPlayerService::AudioCache::notify(
- void* cookie, int msg, int ext1, int ext2, const Parcel* /*obj*/)
-{
- ALOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
- AudioCache* p = static_cast<AudioCache*>(cookie);
-
- // ignore buffering messages
- switch (msg)
- {
- case MEDIA_ERROR:
- ALOGE("Error %d, %d occurred", ext1, ext2);
- break;
- case MEDIA_PREPARED:
- ALOGV("prepared");
- break;
- case MEDIA_PLAYBACK_COMPLETE:
- ALOGV("playback complete");
- break;
- default:
- ALOGV("ignored");
- return;
- }
-
- // wake up thread
- Mutex::Autolock lock(p->mLock);
- if (msg == MEDIA_ERROR) {
- p->mError = ext1;
- }
- p->mCommandComplete = true;
- p->mSignal.signal();
-}
-
-int MediaPlayerService::AudioCache::getSessionId() const
-{
- return 0;
-}
-
-uint32_t MediaPlayerService::AudioCache::getSampleRate() const
-{
- if (mMsecsPerFrame == 0) {
- return 0;
- }
- return (uint32_t)(1.e3 / mMsecsPerFrame);
-}
-
void MediaPlayerService::addBatteryData(uint32_t params)
{
Mutex::Autolock lock(mLock);
@@ -2234,7 +1916,7 @@
return;
}
- // an sudio stream is started
+ // an audio stream is started
if (params & kBatteryDataAudioFlingerStart) {
// record the start time only if currently no other audio
// is being played
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 3b96e88..fad3447 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -77,7 +77,6 @@
virtual ~AudioOutput();
virtual bool ready() const { return mTrack != 0; }
- virtual bool realtime() const { return true; }
virtual ssize_t bufferSize() const;
virtual ssize_t frameCount() const;
virtual ssize_t channelCount() const;
@@ -184,75 +183,6 @@
}; // AudioOutput
- class AudioCache : public MediaPlayerBase::AudioSink
- {
- public:
- AudioCache(const sp<IMemoryHeap>& heap);
- virtual ~AudioCache() {}
-
- virtual bool ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); }
- virtual bool realtime() const { return false; }
- virtual ssize_t bufferSize() const { return frameSize() * mFrameCount; }
- virtual ssize_t frameCount() const { return mFrameCount; }
- virtual ssize_t channelCount() const { return (ssize_t)mChannelCount; }
- virtual ssize_t frameSize() const { return (ssize_t)mFrameSize; }
- virtual uint32_t latency() const;
- virtual float msecsPerFrame() const;
- virtual status_t getPosition(uint32_t *position) const;
- virtual status_t getTimestamp(AudioTimestamp &ts) const;
- virtual status_t getFramesWritten(uint32_t *frameswritten) const;
- virtual int getSessionId() const;
- virtual uint32_t getSampleRate() const;
-
- virtual status_t open(
- uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
- audio_format_t format, int bufferCount = 1,
- AudioCallback cb = NULL, void *cookie = NULL,
- audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
- const audio_offload_info_t *offloadInfo = NULL);
-
- virtual status_t start();
- virtual ssize_t write(const void* buffer, size_t size);
- virtual void stop();
- virtual void flush() {}
- virtual void pause() {}
- virtual void close() {}
- void setAudioStreamType(audio_stream_type_t streamType __unused) {}
- // stream type is not used for AudioCache
- virtual audio_stream_type_t getAudioStreamType() const { return AUDIO_STREAM_DEFAULT; }
-
- void setVolume(float left __unused, float right __unused) {}
- virtual status_t setPlaybackRatePermille(int32_t ratePermille __unused) { return INVALID_OPERATION; }
- uint32_t sampleRate() const { return mSampleRate; }
- audio_format_t format() const { return mFormat; }
- size_t size() const { return mSize; }
- status_t wait();
-
- sp<IMemoryHeap> getHeap() const { return mHeap; }
-
- static void notify(void* cookie, int msg,
- int ext1, int ext2, const Parcel *obj);
- virtual status_t dump(int fd, const Vector<String16>& args) const;
-
- private:
- AudioCache();
-
- Mutex mLock;
- Condition mSignal;
- sp<IMemoryHeap> mHeap;
- float mMsecsPerFrame;
- uint16_t mChannelCount;
- audio_format_t mFormat;
- ssize_t mFrameCount;
- uint32_t mSampleRate;
- uint32_t mSize;
- size_t mFrameSize;
- int mError;
- bool mCommandComplete;
-
- sp<Thread> mCallbackThread;
- }; // AudioCache
-
public:
static void instantiate();
@@ -263,19 +193,6 @@
virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId);
- virtual status_t decode(
- const sp<IMediaHTTPService> &httpService,
- const char* url,
- uint32_t *pSampleRate,
- int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap,
- size_t *pSize);
-
- virtual status_t decode(int fd, int64_t offset, int64_t length,
- uint32_t *pSampleRate, int* pNumChannels,
- audio_format_t* pFormat,
- const sp<IMemoryHeap>& heap, size_t *pSize);
virtual sp<IMediaCodecList> getCodecList() const;
virtual sp<IOMX> getOMX();
virtual sp<ICrypto> makeCrypto();
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 6609874..e2c72ed 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -4,6 +4,7 @@
LOCAL_SRC_FILES:= \
GenericSource.cpp \
HTTPLiveSource.cpp \
+ MediaClock.cpp \
NuPlayer.cpp \
NuPlayerCCDecoder.cpp \
NuPlayerDecoder.cpp \
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 76b80bb..9b446b8 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -40,6 +40,11 @@
namespace android {
+static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
+static int64_t kHighWaterMarkUs = 5000000ll; // 5secs
+static const ssize_t kLowWaterMarkBytes = 40000;
+static const ssize_t kHighWaterMarkBytes = 200000;
+
NuPlayer::GenericSource::GenericSource(
const sp<AMessage> ¬ify,
bool uidValid,
@@ -55,6 +60,7 @@
mAudioIsVorbis(false),
mIsWidevine(false),
mIsSecure(false),
+ mIsStreaming(false),
mUIDValid(uidValid),
mUID(uid),
mFd(-1),
@@ -62,7 +68,9 @@
mMetaDataSize(-1ll),
mBitrate(-1ll),
mPollBufferingGeneration(0),
- mPendingReadBufferTypes(0) {
+ mPendingReadBufferTypes(0),
+ mBuffering(false),
+ mPrepareBuffering(false) {
resetDataSource();
DataSource::RegisterDefaultSniffers();
}
@@ -254,6 +262,20 @@
}
}
+ // Start the selected A/V tracks now before we start buffering.
+ // Widevine sources might re-initialize crypto when starting, if we delay
+ // this to start(), all data buffered during prepare would be wasted.
+ // (We don't actually start reading until start().)
+ if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
+ ALOGE("failed to start audio track!");
+ return UNKNOWN_ERROR;
+ }
+
+ if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
+ ALOGE("failed to start video track!");
+ return UNKNOWN_ERROR;
+ }
+
mBitrate = totalBitrate;
return OK;
@@ -352,9 +374,13 @@
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
- if (mIsWidevine || mCachedSource != NULL) {
- schedulePollBuffering();
- }
+ // For widevine or other cached streaming cases, we need to wait for
+ // enough buffering before reporting prepared.
+ // Note that even when URL doesn't start with widevine://, mIsWidevine
+ // could still be set to true later, if the streaming or file source
+ // is sniffed to be widevine. We don't want to buffer for file source
+ // in that case, so must check the flag now.
+ mIsStreaming = (mIsWidevine || mCachedSource != NULL);
}
// check initial caching status
@@ -397,7 +423,14 @@
| FLAG_CAN_SEEK_FORWARD
| FLAG_CAN_SEEK);
- notifyPrepared();
+ if (mIsStreaming) {
+ mPrepareBuffering = true;
+
+ ensureCacheIsFetching();
+ restartPollBuffering();
+ } else {
+ notifyPrepared();
+ }
}
void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
@@ -489,19 +522,17 @@
mStopRead = false;
if (mAudioTrack.mSource != NULL) {
- CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
-
postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
}
if (mVideoTrack.mSource != NULL) {
- CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
-
postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
}
setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
mStarted = true;
+
+ (new AMessage(kWhatStart, id()))->post();
}
void NuPlayer::GenericSource::stop() {
@@ -526,6 +557,8 @@
// nothing to do, just account for DRM playback status
setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
mStarted = true;
+
+ (new AMessage(kWhatResume, id()))->post();
}
void NuPlayer::GenericSource::disconnect() {
@@ -558,22 +591,98 @@
}
void NuPlayer::GenericSource::cancelPollBuffering() {
+ mBuffering = false;
++mPollBufferingGeneration;
}
+void NuPlayer::GenericSource::restartPollBuffering() {
+ if (mIsStreaming) {
+ cancelPollBuffering();
+ onPollBuffering();
+ }
+}
+
void NuPlayer::GenericSource::notifyBufferingUpdate(int percentage) {
+ ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
+
sp<AMessage> msg = dupNotify();
msg->setInt32("what", kWhatBufferingUpdate);
msg->setInt32("percentage", percentage);
msg->post();
}
-void NuPlayer::GenericSource::onPollBuffering() {
- status_t finalStatus = UNKNOWN_ERROR;
- int64_t cachedDurationUs = 0ll;
+void NuPlayer::GenericSource::startBufferingIfNecessary() {
+ ALOGV("startBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d",
+ mPrepareBuffering, mBuffering);
+
+ if (mPrepareBuffering) {
+ return;
+ }
+
+ if (!mBuffering) {
+ mBuffering = true;
+
+ ensureCacheIsFetching();
+ sendCacheStats();
+
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatPauseOnBufferingStart);
+ notify->post();
+ }
+}
+
+void NuPlayer::GenericSource::stopBufferingIfNecessary() {
+ ALOGV("stopBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d",
+ mPrepareBuffering, mBuffering);
+
+ if (mPrepareBuffering) {
+ mPrepareBuffering = false;
+ notifyPrepared();
+ return;
+ }
+
+ if (mBuffering) {
+ mBuffering = false;
+
+ sendCacheStats();
+
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatResumeOnBufferingEnd);
+ notify->post();
+ }
+}
+
+void NuPlayer::GenericSource::sendCacheStats() {
+ int32_t kbps = 0;
+ status_t err = UNKNOWN_ERROR;
if (mCachedSource != NULL) {
- size_t cachedDataRemaining =
+ err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
+ } else if (mWVMExtractor != NULL) {
+ err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps);
+ }
+
+ if (err == OK) {
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatCacheStats);
+ notify->setInt32("bandwidth", kbps);
+ notify->post();
+ }
+}
+
+void NuPlayer::GenericSource::ensureCacheIsFetching() {
+ if (mCachedSource != NULL) {
+ mCachedSource->resumeFetchingIfNecessary();
+ }
+}
+
+void NuPlayer::GenericSource::onPollBuffering() {
+ status_t finalStatus = UNKNOWN_ERROR;
+ int64_t cachedDurationUs = -1ll;
+ ssize_t cachedDataRemaining = -1;
+
+ if (mCachedSource != NULL) {
+ cachedDataRemaining =
mCachedSource->approxDataRemaining(&finalStatus);
if (finalStatus == OK) {
@@ -593,23 +702,48 @@
= mWVMExtractor->getCachedDurationUs(&finalStatus);
}
- if (finalStatus == ERROR_END_OF_STREAM) {
- notifyBufferingUpdate(100);
- cancelPollBuffering();
- return;
- } else if (cachedDurationUs > 0ll && mDurationUs > 0ll) {
- int percentage = 100.0 * cachedDurationUs / mDurationUs;
- if (percentage > 100) {
- percentage = 100;
+ if (finalStatus != OK) {
+ ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);
+
+ if (finalStatus == ERROR_END_OF_STREAM) {
+ notifyBufferingUpdate(100);
}
- notifyBufferingUpdate(percentage);
+ stopBufferingIfNecessary();
+ return;
+ } else if (cachedDurationUs >= 0ll) {
+ if (mDurationUs > 0ll) {
+ int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
+ int percentage = 100.0 * cachedPosUs / mDurationUs;
+ if (percentage > 100) {
+ percentage = 100;
+ }
+
+ notifyBufferingUpdate(percentage);
+ }
+
+ ALOGV("onPollBuffering: cachedDurationUs %.1f sec",
+ cachedDurationUs / 1000000.0f);
+
+ if (cachedDurationUs < kLowWaterMarkUs) {
+ startBufferingIfNecessary();
+ } else if (cachedDurationUs > kHighWaterMarkUs) {
+ stopBufferingIfNecessary();
+ }
+ } else if (cachedDataRemaining >= 0) {
+ ALOGV("onPollBuffering: cachedDataRemaining %d bytes",
+ cachedDataRemaining);
+
+ if (cachedDataRemaining < kLowWaterMarkBytes) {
+ startBufferingIfNecessary();
+ } else if (cachedDataRemaining > kHighWaterMarkBytes) {
+ stopBufferingIfNecessary();
+ }
}
schedulePollBuffering();
}
-
void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatPrepareAsync:
@@ -688,6 +822,14 @@
break;
}
+
+ case kWhatStart:
+ case kWhatResume:
+ {
+ restartPollBuffering();
+ break;
+ }
+
case kWhatPollBuffering:
{
int32_t generation;
@@ -1201,6 +1343,13 @@
if (!mStarted) {
setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0);
}
+
+ // If currently buffering, post kWhatBufferingEnd first, so that
+ // NuPlayer resumes. Otherwise, if cache hits high watermark
+ // before new polling happens, no one will resume the playback.
+ stopBufferingIfNecessary();
+ restartPollBuffering();
+
return OK;
}
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 1b63a1f..385d73a 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -94,16 +94,17 @@
kWhatSeek,
kWhatReadBuffer,
kWhatStopWidevine,
+ kWhatStart,
+ kWhatResume,
};
- Vector<sp<MediaSource> > mSources;
-
struct Track {
size_t mIndex;
sp<MediaSource> mSource;
sp<AnotherPacketSource> mPackets;
};
+ Vector<sp<MediaSource> > mSources;
Track mAudioTrack;
int64_t mAudioTimeUs;
int64_t mAudioLastDequeueTimeUs;
@@ -119,6 +120,7 @@
bool mAudioIsVorbis;
bool mIsWidevine;
bool mIsSecure;
+ bool mIsStreaming;
bool mUIDValid;
uid_t mUID;
sp<IMediaHTTPService> mHTTPService;
@@ -143,6 +145,8 @@
int64_t mBitrate;
int32_t mPollBufferingGeneration;
uint32_t mPendingReadBufferTypes;
+ bool mBuffering;
+ bool mPrepareBuffering;
mutable Mutex mReadBufferLock;
sp<ALooper> mLooper;
@@ -194,8 +198,13 @@
void schedulePollBuffering();
void cancelPollBuffering();
+ void restartPollBuffering();
void onPollBuffering();
void notifyBufferingUpdate(int percentage);
+ void startBufferingIfNecessary();
+ void stopBufferingIfNecessary();
+ void sendCacheStats();
+ void ensureCacheIsFetching();
DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
};
diff --git a/media/libmediaplayerservice/nuplayer/MediaClock.cpp b/media/libmediaplayerservice/nuplayer/MediaClock.cpp
new file mode 100644
index 0000000..7bfff13
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/MediaClock.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2015 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 "MediaClock"
+#include <utils/Log.h>
+
+#include "MediaClock.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+
+namespace android {
+
+// Maximum time change between two updates.
+static const int64_t kMaxAnchorFluctuationUs = 1000ll;
+
+MediaClock::MediaClock()
+ : mAnchorTimeMediaUs(-1),
+ mAnchorTimeRealUs(-1),
+ mMaxTimeMediaUs(INT64_MAX),
+ mStartingTimeMediaUs(-1),
+ mPaused(false) {
+}
+
+MediaClock::~MediaClock() {
+}
+
+void MediaClock::setStartingTimeMedia(int64_t startingTimeMediaUs) {
+ Mutex::Autolock autoLock(mLock);
+ mStartingTimeMediaUs = startingTimeMediaUs;
+}
+
+void MediaClock::clearAnchor() {
+ Mutex::Autolock autoLock(mLock);
+ mAnchorTimeMediaUs = -1;
+ mAnchorTimeRealUs = -1;
+}
+
+void MediaClock::updateAnchor(
+ int64_t anchorTimeMediaUs,
+ int64_t anchorTimeRealUs,
+ int64_t maxTimeMediaUs) {
+ if (anchorTimeMediaUs < 0 || anchorTimeRealUs < 0) {
+ ALOGW("reject anchor time since it is negative.");
+ return;
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+ int64_t nowMediaUs = anchorTimeMediaUs + nowUs - anchorTimeRealUs;
+ if (nowMediaUs < 0) {
+ ALOGW("reject anchor time since it leads to negative media time.");
+ return;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+ mAnchorTimeRealUs = nowUs;
+ mAnchorTimeMediaUs = nowMediaUs;
+ mMaxTimeMediaUs = maxTimeMediaUs;
+}
+
+void MediaClock::updateMaxTimeMedia(int64_t maxTimeMediaUs) {
+ Mutex::Autolock autoLock(mLock);
+ mMaxTimeMediaUs = maxTimeMediaUs;
+}
+
+void MediaClock::pause() {
+ Mutex::Autolock autoLock(mLock);
+ if (mPaused) {
+ return;
+ }
+
+ mPaused = true;
+ if (mAnchorTimeRealUs == -1) {
+ return;
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+ mAnchorTimeMediaUs += nowUs - mAnchorTimeRealUs;
+ if (mAnchorTimeMediaUs < 0) {
+ ALOGW("anchor time should not be negative, set to 0.");
+ mAnchorTimeMediaUs = 0;
+ }
+ mAnchorTimeRealUs = nowUs;
+}
+
+void MediaClock::resume() {
+ Mutex::Autolock autoLock(mLock);
+ if (!mPaused) {
+ return;
+ }
+
+ mPaused = false;
+ if (mAnchorTimeRealUs == -1) {
+ return;
+ }
+
+ mAnchorTimeRealUs = ALooper::GetNowUs();
+}
+
+int64_t MediaClock::getTimeMedia(int64_t realUs, bool allowPastMaxTime) {
+ Mutex::Autolock autoLock(mLock);
+ if (mAnchorTimeRealUs == -1) {
+ return -1ll;
+ }
+
+ if (mPaused) {
+ realUs = mAnchorTimeRealUs;
+ }
+ int64_t currentMediaUs = mAnchorTimeMediaUs + realUs - mAnchorTimeRealUs;
+ if (currentMediaUs > mMaxTimeMediaUs && !allowPastMaxTime) {
+ currentMediaUs = mMaxTimeMediaUs;
+ }
+ if (currentMediaUs < mStartingTimeMediaUs) {
+ currentMediaUs = mStartingTimeMediaUs;
+ }
+ if (currentMediaUs < 0) {
+ currentMediaUs = 0;
+ }
+ return currentMediaUs;
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/MediaClock.h b/media/libmediaplayerservice/nuplayer/MediaClock.h
new file mode 100644
index 0000000..d005993
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/MediaClock.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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 MEDIA_CLOCK_H_
+
+#define MEDIA_CLOCK_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AMessage;
+
+struct MediaClock : public RefBase {
+ MediaClock();
+
+ void setStartingTimeMedia(int64_t startingTimeMediaUs);
+
+ void clearAnchor();
+ // It's highly recommended to use timestamp of just rendered frame as
+ // anchor time, especially in paused state. Such restriction will be
+ // required when dynamic playback rate is supported in the future.
+ void updateAnchor(
+ int64_t anchorTimeMediaUs,
+ int64_t anchorTimeRealUs,
+ int64_t maxTimeMediaUs = INT64_MAX);
+
+ void updateMaxTimeMedia(int64_t maxTimeMediaUs);
+
+ void pause();
+ void resume();
+
+ int64_t getTimeMedia(int64_t realUs, bool allowPastMaxTime = false);
+
+protected:
+ virtual ~MediaClock();
+
+private:
+ Mutex mLock;
+
+ int64_t mAnchorTimeMediaUs;
+ int64_t mAnchorTimeRealUs;
+ int64_t mMaxTimeMediaUs;
+ int64_t mStartingTimeMediaUs;
+
+ bool mPaused;
+
+ DISALLOW_EVIL_CONSTRUCTORS(MediaClock);
+};
+
+} // namespace android
+
+#endif // MEDIA_CLOCK_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e02a2d5..1f55706 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -180,7 +180,9 @@
mFlushingVideo(NONE),
mResumePending(false),
mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
- mStarted(false) {
+ mStarted(false),
+ mPaused(false),
+ mPausedByClient(false) {
clearFlushComplete();
}
@@ -598,6 +600,7 @@
} else {
onStart();
}
+ mPausedByClient = false;
break;
}
@@ -956,16 +959,8 @@
case kWhatPause:
{
- if (mSource != NULL) {
- mSource->pause();
- } else {
- ALOGW("pause called when source is gone or not set");
- }
- if (mRenderer != NULL) {
- mRenderer->pause();
- } else {
- ALOGW("pause called when renderer is gone or not set");
- }
+ onPause();
+ mPausedByClient = true;
break;
}
@@ -988,6 +983,10 @@
}
void NuPlayer::onResume() {
+ if (!mPaused) {
+ return;
+ }
+ mPaused = false;
if (mSource != NULL) {
mSource->resume();
} else {
@@ -1072,6 +1071,23 @@
postScanSources();
}
+void NuPlayer::onPause() {
+ if (mPaused) {
+ return;
+ }
+ mPaused = true;
+ if (mSource != NULL) {
+ mSource->pause();
+ } else {
+ ALOGW("pause called when source is gone or not set");
+ }
+ if (mRenderer != NULL) {
+ mRenderer->pause();
+ } else {
+ ALOGW("pause called when renderer is gone or not set");
+ }
+}
+
bool NuPlayer::audioDecoderStillNeeded() {
// Audio decoder is no longer needed if it's in shut/shutting down status.
return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
@@ -1709,18 +1725,49 @@
break;
}
+ case Source::kWhatPauseOnBufferingStart:
+ {
+ // ignore if not playing
+ if (mStarted && !mPausedByClient) {
+ ALOGI("buffer low, pausing...");
+
+ onPause();
+ }
+ // fall-thru
+ }
+
case Source::kWhatBufferingStart:
{
notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
break;
}
+ case Source::kWhatResumeOnBufferingEnd:
+ {
+ // ignore if not playing
+ if (mStarted && !mPausedByClient) {
+ ALOGI("buffer ready, resuming...");
+
+ onResume();
+ }
+ // fall-thru
+ }
+
case Source::kWhatBufferingEnd:
{
notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
break;
}
+ case Source::kWhatCacheStats:
+ {
+ int32_t kbps;
+ CHECK(msg->findInt32("bandwidth", &kbps));
+
+ notifyListener(MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
+ break;
+ }
+
case Source::kWhatSubtitleData:
{
sp<ABuffer> buffer;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index bb32eac..57eaf74 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -177,6 +177,14 @@
bool mStarted;
+ // Actual pause state, either as requested by client or due to buffering.
+ bool mPaused;
+
+ // Pause state as requested by client. Note that if mPausedByClient is
+ // true, mPaused is always true; if mPausedByClient is false, mPaused could
+ // still become true, when we pause internally due to buffering.
+ bool mPausedByClient;
+
inline const sp<DecoderBase> &getDecoder(bool audio) {
return audio ? mAudioDecoder : mVideoDecoder;
}
@@ -204,6 +212,7 @@
void onStart();
void onResume();
+ void onPause();
bool audioDecoderStillNeeded();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 2abd9d6..5d98d98 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -823,7 +823,7 @@
const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
int32_t oldVal, newVal;
- if (!mOutputFormat->findInt32(keys[i], &oldVal) ||
+ if (!mInputFormat->findInt32(keys[i], &oldVal) ||
!targetFormat->findInt32(keys[i], &newVal) ||
oldVal != newVal) {
return false;
@@ -831,7 +831,7 @@
}
sp<ABuffer> oldBuf, newBuf;
- if (mOutputFormat->findBuffer("csd-0", &oldBuf) &&
+ if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
targetFormat->findBuffer("csd-0", &newBuf)) {
if (oldBuf->size() != newBuf->size()) {
return false;
@@ -843,7 +843,7 @@
}
bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
- if (mOutputFormat == NULL) {
+ if (mInputFormat == NULL) {
return false;
}
@@ -852,7 +852,7 @@
}
AString oldMime, newMime;
- if (!mOutputFormat->findString("mime", &oldMime)
+ if (!mInputFormat->findString("mime", &oldMime)
|| !targetFormat->findString("mime", &newMime)
|| !(oldMime == newMime)) {
return false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index f126b87..abfa4d3 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -662,8 +662,7 @@
mAutoLoop = false;
}
}
- if (mLooping || (mAutoLoop
- && (mAudioSink == NULL || mAudioSink->realtime()))) {
+ if (mLooping || mAutoLoop) {
mPlayer->seekToAsync(0);
if (mAudioSink != NULL) {
// The renderer has stopped the sink at the end in order to play out
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 80b8493..83fc9e9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -20,6 +20,8 @@
#include "NuPlayerRenderer.h"
+#include "MediaClock.h"
+
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -62,22 +64,18 @@
mDrainVideoQueuePending(false),
mAudioQueueGeneration(0),
mVideoQueueGeneration(0),
+ mAudioDrainGeneration(0),
+ mVideoDrainGeneration(0),
mAudioFirstAnchorTimeMediaUs(-1),
mAnchorTimeMediaUs(-1),
- mAnchorTimeRealUs(-1),
mAnchorNumFramesWritten(-1),
- mAnchorMaxMediaUs(-1),
mVideoLateByUs(0ll),
mHasAudio(false),
mHasVideo(false),
- mPauseStartedTimeRealUs(-1),
- mFlushingAudio(false),
- mFlushingVideo(false),
mNotifyCompleteAudio(false),
mNotifyCompleteVideo(false),
mSyncQueues(false),
mPaused(false),
- mPausePositionMediaTimeUs(-1),
mVideoSampleReceived(false),
mVideoRenderingStarted(false),
mVideoRenderingStartGeneration(0),
@@ -88,6 +86,7 @@
mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
mTotalBuffersQueued(0),
mLastAudioBufferDrained(0) {
+ mMediaClock = new MediaClock;
}
NuPlayer::Renderer::~Renderer() {
@@ -103,6 +102,7 @@
const sp<ABuffer> &buffer,
const sp<AMessage> ¬ifyConsumed) {
sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
+ msg->setInt32("queueGeneration", getQueueGeneration(audio));
msg->setInt32("audio", static_cast<int32_t>(audio));
msg->setBuffer("buffer", buffer);
msg->setMessage("notifyConsumed", notifyConsumed);
@@ -113,6 +113,7 @@
CHECK_NE(finalResult, (status_t)OK);
sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
+ msg->setInt32("queueGeneration", getQueueGeneration(audio));
msg->setInt32("audio", static_cast<int32_t>(audio));
msg->setInt32("finalResult", finalResult);
msg->post();
@@ -120,20 +121,21 @@
void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
{
- Mutex::Autolock autoLock(mFlushLock);
+ Mutex::Autolock autoLock(mLock);
if (audio) {
mNotifyCompleteAudio |= notifyComplete;
- if (mFlushingAudio) {
- return;
- }
- mFlushingAudio = true;
+ ++mAudioQueueGeneration;
+ ++mAudioDrainGeneration;
} else {
mNotifyCompleteVideo |= notifyComplete;
- if (mFlushingVideo) {
- return;
- }
- mFlushingVideo = true;
+ ++mVideoQueueGeneration;
+ ++mVideoDrainGeneration;
}
+
+ clearAnchorTime_l();
+ clearAudioFirstAnchorTime_l();
+ mVideoLateByUs = 0;
+ mSyncQueues = false;
}
sp<AMessage> msg = new AMessage(kWhatFlush, id());
@@ -142,17 +144,6 @@
}
void NuPlayer::Renderer::signalTimeDiscontinuity() {
- Mutex::Autolock autoLock(mLock);
- // CHECK(mAudioQueue.empty());
- // CHECK(mVideoQueue.empty());
- setAudioFirstAnchorTime(-1);
- setAnchorTime(-1, -1);
- setVideoLateByUs(0);
- mSyncQueues = false;
-}
-
-void NuPlayer::Renderer::signalAudioSinkChanged() {
- (new AMessage(kWhatAudioSinkChanged, id()))->post();
}
void NuPlayer::Renderer::signalDisableOffloadAudio() {
@@ -177,127 +168,44 @@
msg->post();
}
-// Called on any threads, except renderer's thread.
-status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
- {
- Mutex::Autolock autoLock(mLock);
- int64_t currentPositionUs;
- if (getCurrentPositionIfPaused_l(¤tPositionUs)) {
- *mediaUs = currentPositionUs;
- return OK;
- }
- }
- return getCurrentPositionFromAnchor(mediaUs, ALooper::GetNowUs());
-}
-
-// Called on only renderer's thread.
-status_t NuPlayer::Renderer::getCurrentPositionOnLooper(int64_t *mediaUs) {
- return getCurrentPositionOnLooper(mediaUs, ALooper::GetNowUs());
-}
-
-// Called on only renderer's thread.
-// Since mPaused and mPausePositionMediaTimeUs are changed only on renderer's
-// thread, no need to acquire mLock.
-status_t NuPlayer::Renderer::getCurrentPositionOnLooper(
- int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
- int64_t currentPositionUs;
- if (getCurrentPositionIfPaused_l(¤tPositionUs)) {
- *mediaUs = currentPositionUs;
- return OK;
- }
- return getCurrentPositionFromAnchor(mediaUs, nowUs, allowPastQueuedVideo);
-}
-
-// Called either with mLock acquired or on renderer's thread.
-bool NuPlayer::Renderer::getCurrentPositionIfPaused_l(int64_t *mediaUs) {
- if (!mPaused || mPausePositionMediaTimeUs < 0ll) {
- return false;
- }
- *mediaUs = mPausePositionMediaTimeUs;
- return true;
-}
-
// Called on any threads.
-status_t NuPlayer::Renderer::getCurrentPositionFromAnchor(
- int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
- Mutex::Autolock autoLock(mTimeLock);
- if (!mHasAudio && !mHasVideo) {
+status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
+ int64_t currentTimeUs = mMediaClock->getTimeMedia(ALooper::GetNowUs());
+ if (currentTimeUs == -1) {
return NO_INIT;
}
-
- if (mAnchorTimeMediaUs < 0) {
- return NO_INIT;
- }
-
- int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
-
- if (mPauseStartedTimeRealUs != -1) {
- positionUs -= (nowUs - mPauseStartedTimeRealUs);
- }
-
- // limit position to the last queued media time (for video only stream
- // position will be discrete as we don't know how long each frame lasts)
- if (mAnchorMaxMediaUs >= 0 && !allowPastQueuedVideo) {
- if (positionUs > mAnchorMaxMediaUs) {
- positionUs = mAnchorMaxMediaUs;
- }
- }
-
- if (positionUs < mAudioFirstAnchorTimeMediaUs) {
- positionUs = mAudioFirstAnchorTimeMediaUs;
- }
-
- *mediaUs = (positionUs <= 0) ? 0 : positionUs;
+ *mediaUs = currentTimeUs;
return OK;
}
-void NuPlayer::Renderer::setHasMedia(bool audio) {
- Mutex::Autolock autoLock(mTimeLock);
- if (audio) {
- mHasAudio = true;
- } else {
- mHasVideo = true;
- }
+void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
+ mAudioFirstAnchorTimeMediaUs = -1;
+ mMediaClock->setStartingTimeMedia(-1);
}
-void NuPlayer::Renderer::setAudioFirstAnchorTime(int64_t mediaUs) {
- Mutex::Autolock autoLock(mTimeLock);
- mAudioFirstAnchorTimeMediaUs = mediaUs;
-}
-
-void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs) {
- Mutex::Autolock autoLock(mTimeLock);
+void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
if (mAudioFirstAnchorTimeMediaUs == -1) {
mAudioFirstAnchorTimeMediaUs = mediaUs;
+ mMediaClock->setStartingTimeMedia(mediaUs);
}
}
-void NuPlayer::Renderer::setAnchorTime(
- int64_t mediaUs, int64_t realUs, int64_t numFramesWritten, bool resume) {
- Mutex::Autolock autoLock(mTimeLock);
- mAnchorTimeMediaUs = mediaUs;
- mAnchorTimeRealUs = realUs;
- mAnchorNumFramesWritten = numFramesWritten;
- if (resume) {
- mPauseStartedTimeRealUs = -1;
- }
+void NuPlayer::Renderer::clearAnchorTime_l() {
+ mMediaClock->clearAnchor();
+ mAnchorTimeMediaUs = -1;
+ mAnchorNumFramesWritten = -1;
}
void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
- Mutex::Autolock autoLock(mTimeLock);
+ Mutex::Autolock autoLock(mLock);
mVideoLateByUs = lateUs;
}
int64_t NuPlayer::Renderer::getVideoLateByUs() {
- Mutex::Autolock autoLock(mTimeLock);
+ Mutex::Autolock autoLock(mLock);
return mVideoLateByUs;
}
-void NuPlayer::Renderer::setPauseStartedTimeRealUs(int64_t realUs) {
- Mutex::Autolock autoLock(mTimeLock);
- mPauseStartedTimeRealUs = realUs;
-}
-
status_t NuPlayer::Renderer::openAudioSink(
const sp<AMessage> &format,
bool offloadOnly,
@@ -381,8 +289,8 @@
case kWhatDrainAudioQueue:
{
int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
- if (generation != mAudioQueueGeneration) {
+ CHECK(msg->findInt32("drainGeneration", &generation));
+ if (generation != getDrainGeneration(true /* audio */)) {
break;
}
@@ -404,9 +312,7 @@
// Let's give it more data after about half that time
// has elapsed.
- // kWhatDrainAudioQueue is used for non-offloading mode,
- // and mLock is used only for offloading mode. Therefore,
- // no need to acquire mLock here.
+ Mutex::Autolock autoLock(mLock);
postDrainAudioQueue_l(delayUs / 2);
}
break;
@@ -415,8 +321,8 @@
case kWhatDrainVideoQueue:
{
int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
- if (generation != mVideoQueueGeneration) {
+ CHECK(msg->findInt32("drainGeneration", &generation));
+ if (generation != getDrainGeneration(false /* audio */)) {
break;
}
@@ -431,8 +337,8 @@
case kWhatPostDrainVideoQueue:
{
int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
- if (generation != mVideoQueueGeneration) {
+ CHECK(msg->findInt32("drainGeneration", &generation));
+ if (generation != getDrainGeneration(false /* audio */)) {
break;
}
@@ -459,12 +365,6 @@
break;
}
- case kWhatAudioSinkChanged:
- {
- onAudioSinkChanged();
- break;
- }
-
case kWhatDisableOffloadAudio:
{
onDisableOffloadAudio();
@@ -506,7 +406,7 @@
case kWhatAudioOffloadPauseTimeout:
{
int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
+ CHECK(msg->findInt32("drainGeneration", &generation));
if (generation != mAudioOffloadPauseTimeoutGeneration) {
break;
}
@@ -533,18 +433,18 @@
mDrainAudioQueuePending = true;
sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
- msg->setInt32("generation", mAudioQueueGeneration);
+ msg->setInt32("drainGeneration", mAudioDrainGeneration);
msg->post(delayUs);
}
-void NuPlayer::Renderer::prepareForMediaRenderingStart() {
- mAudioRenderingStartGeneration = mAudioQueueGeneration;
- mVideoRenderingStartGeneration = mVideoQueueGeneration;
+void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
+ mAudioRenderingStartGeneration = mAudioDrainGeneration;
+ mVideoRenderingStartGeneration = mVideoDrainGeneration;
}
-void NuPlayer::Renderer::notifyIfMediaRenderingStarted() {
- if (mVideoRenderingStartGeneration == mVideoQueueGeneration &&
- mAudioRenderingStartGeneration == mAudioQueueGeneration) {
+void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
+ if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
+ mAudioRenderingStartGeneration == mAudioDrainGeneration) {
mVideoRenderingStartGeneration = -1;
mAudioRenderingStartGeneration = -1;
@@ -612,7 +512,7 @@
int64_t mediaTimeUs;
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
- setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
+ setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
}
size_t copy = entry->mBuffer->size() - entry->mOffset;
@@ -632,17 +532,18 @@
entry = NULL;
}
sizeCopied += copy;
- notifyIfMediaRenderingStarted();
+
+ notifyIfMediaRenderingStarted_l();
}
if (mAudioFirstAnchorTimeMediaUs >= 0) {
int64_t nowUs = ALooper::GetNowUs();
- setAnchorTime(mAudioFirstAnchorTimeMediaUs, nowUs - getPlayedOutAudioDurationUs(nowUs));
+ // we don't know how much data we are queueing for offloaded tracks.
+ mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs,
+ nowUs - getPlayedOutAudioDurationUs(nowUs),
+ INT64_MAX);
}
- // we don't know how much data we are queueing for offloaded tracks
- mAnchorMaxMediaUs = -1;
-
if (hasEOS) {
(new AMessage(kWhatStopAudioSink, id()))->post();
}
@@ -727,7 +628,10 @@
size_t copiedFrames = written / mAudioSink->frameSize();
mNumFramesWritten += copiedFrames;
- notifyIfMediaRenderingStarted();
+ {
+ Mutex::Autolock autoLock(mLock);
+ notifyIfMediaRenderingStarted_l();
+ }
if (written != (ssize_t)copy) {
// A short count was received from AudioSink::write()
@@ -750,10 +654,15 @@
break;
}
}
- mAnchorMaxMediaUs =
- mAnchorTimeMediaUs +
- (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
- * 1000LL * mAudioSink->msecsPerFrame());
+ int64_t maxTimeMedia;
+ {
+ Mutex::Autolock autoLock(mLock);
+ maxTimeMedia =
+ mAnchorTimeMediaUs +
+ (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
+ * 1000LL * mAudioSink->msecsPerFrame());
+ }
+ mMediaClock->updateMaxTimeMedia(maxTimeMedia);
return !mAudioQueue.empty();
}
@@ -765,31 +674,35 @@
}
int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
- int64_t currentPositionUs;
- if (getCurrentPositionOnLooper(
- ¤tPositionUs, nowUs, true /* allowPastQueuedVideo */) != OK) {
- // If failed to get current position, e.g. due to audio clock is not ready, then just
- // play out video immediately without delay.
+ int64_t currentPositionUs =
+ mMediaClock->getTimeMedia(nowUs, true /* allowPastMaxTime */);
+ if (currentPositionUs == -1) {
+ // If failed to get current position, e.g. due to audio clock is
+ // not ready, then just play out video immediately without delay.
return nowUs;
}
return (mediaTimeUs - currentPositionUs) + nowUs;
}
void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
+ Mutex::Autolock autoLock(mLock);
// TRICKY: vorbis decoder generates multiple frames with the same
// timestamp, so only update on the first frame with a given timestamp
if (mediaTimeUs == mAnchorTimeMediaUs) {
return;
}
- setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
+ setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
int64_t nowUs = ALooper::GetNowUs();
- setAnchorTime(
- mediaTimeUs, nowUs + getPendingAudioPlayoutDurationUs(nowUs), mNumFramesWritten);
+ mMediaClock->updateAnchor(mediaTimeUs,
+ nowUs + getPendingAudioPlayoutDurationUs(nowUs),
+ mediaTimeUs);
+ mAnchorTimeMediaUs = mediaTimeUs;
}
+// Called without mLock acquired.
void NuPlayer::Renderer::postDrainVideoQueue() {
if (mDrainVideoQueuePending
- || mSyncQueues
+ || getSyncQueues()
|| (mPaused && mVideoSampleReceived)) {
return;
}
@@ -801,7 +714,7 @@
QueueEntry &entry = *mVideoQueue.begin();
sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
- msg->setInt32("generation", mVideoQueueGeneration);
+ msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
if (entry.mBuffer == NULL) {
// EOS doesn't carry a timestamp.
@@ -821,15 +734,19 @@
int64_t mediaTimeUs;
CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
- if (mAnchorTimeMediaUs < 0) {
- setAnchorTime(mediaTimeUs, nowUs);
- mAnchorMaxMediaUs = mediaTimeUs;
- realTimeUs = nowUs;
- } else {
- realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
+ {
+ Mutex::Autolock autoLock(mLock);
+ if (mAnchorTimeMediaUs < 0) {
+ mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
+ mAnchorTimeMediaUs = mediaTimeUs;
+ realTimeUs = nowUs;
+ } else {
+ realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
+ }
}
if (!mHasAudio) {
- mAnchorMaxMediaUs = mediaTimeUs + 100000; // smooth out videos >= 10fps
+ // smooth out videos >= 10fps
+ mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
}
// Heuristics to handle situation when media time changed without a
@@ -910,14 +827,15 @@
} else {
ALOGV("rendering video at media time %.2f secs",
(mFlags & FLAG_REAL_TIME ? realTimeUs :
- (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
+ mMediaClock->getTimeMedia(realTimeUs)) / 1E6);
}
} else {
setVideoLateByUs(0);
if (!mVideoSampleReceived && !mHasAudio) {
// This will ensure that the first frame after a flush won't be used as anchor
// when renderer is in paused state, because resume can happen any time after seek.
- setAnchorTime(-1, -1);
+ Mutex::Autolock autoLock(mLock);
+ clearAnchorTime_l();
}
}
@@ -934,7 +852,8 @@
mVideoRenderingStarted = true;
notifyVideoRenderingStart();
}
- notifyIfMediaRenderingStarted();
+ Mutex::Autolock autoLock(mLock);
+ notifyIfMediaRenderingStarted_l();
}
}
@@ -960,7 +879,15 @@
int32_t audio;
CHECK(msg->findInt32("audio", &audio));
- setHasMedia(audio);
+ if (dropBufferIfStale(audio, msg)) {
+ return;
+ }
+
+ if (audio) {
+ mHasAudio = true;
+ } else {
+ mHasVideo = true;
+ }
if (mHasVideo) {
if (mVideoScheduler == NULL) {
@@ -969,10 +896,6 @@
}
}
- if (dropBufferWhileFlushing(audio, msg)) {
- return;
- }
-
sp<ABuffer> buffer;
CHECK(msg->findBuffer("buffer", &buffer));
@@ -1044,7 +967,9 @@
}
if (!mVideoQueue.empty()) {
+ mLock.unlock();
postDrainVideoQueue();
+ mLock.lock();
}
}
@@ -1052,7 +977,7 @@
int32_t audio;
CHECK(msg->findInt32("audio", &audio));
- if (dropBufferWhileFlushing(audio, msg)) {
+ if (dropBufferIfStale(audio, msg)) {
return;
}
@@ -1071,7 +996,7 @@
mAudioQueue.push_back(entry);
postDrainAudioQueue_l();
} else {
- if (mVideoQueue.empty() && mSyncQueues) {
+ if (mVideoQueue.empty() && getSyncQueues()) {
Mutex::Autolock autoLock(mLock);
syncQueuesDone_l();
}
@@ -1085,31 +1010,25 @@
CHECK(msg->findInt32("audio", &audio));
{
- Mutex::Autolock autoLock(mFlushLock);
+ Mutex::Autolock autoLock(mLock);
if (audio) {
- mFlushingAudio = false;
notifyComplete = mNotifyCompleteAudio;
mNotifyCompleteAudio = false;
} else {
- mFlushingVideo = false;
notifyComplete = mNotifyCompleteVideo;
mNotifyCompleteVideo = false;
}
- }
- // If we're currently syncing the queues, i.e. dropping audio while
- // aligning the first audio/video buffer times and only one of the
- // two queues has data, we may starve that queue by not requesting
- // more buffers from the decoder. If the other source then encounters
- // a discontinuity that leads to flushing, we'll never find the
- // corresponding discontinuity on the other queue.
- // Therefore we'll stop syncing the queues if at least one of them
- // is flushed.
- {
- Mutex::Autolock autoLock(mLock);
- syncQueuesDone_l();
- setPauseStartedTimeRealUs(-1);
- setAnchorTime(-1, -1);
+ // If we're currently syncing the queues, i.e. dropping audio while
+ // aligning the first audio/video buffer times and only one of the
+ // two queues has data, we may starve that queue by not requesting
+ // more buffers from the decoder. If the other source then encounters
+ // a discontinuity that leads to flushing, we'll never find the
+ // corresponding discontinuity on the other queue.
+ // Therefore we'll stop syncing the queues if at least one of them
+ // is flushed.
+ syncQueuesDone_l();
+ clearAnchorTime_l();
}
ALOGV("flushing %s", audio ? "audio" : "video");
@@ -1118,11 +1037,11 @@
Mutex::Autolock autoLock(mLock);
flushQueue(&mAudioQueue);
- ++mAudioQueueGeneration;
- prepareForMediaRenderingStart();
+ ++mAudioDrainGeneration;
+ prepareForMediaRenderingStart_l();
if (offloadingAudio()) {
- setAudioFirstAnchorTime(-1);
+ clearAudioFirstAnchorTime_l();
}
}
@@ -1137,13 +1056,14 @@
flushQueue(&mVideoQueue);
mDrainVideoQueuePending = false;
- ++mVideoQueueGeneration;
if (mVideoScheduler != NULL) {
mVideoScheduler->restart();
}
- prepareForMediaRenderingStart();
+ Mutex::Autolock autoLock(mLock);
+ ++mVideoDrainGeneration;
+ prepareForMediaRenderingStart_l();
}
mVideoSampleReceived = false;
@@ -1173,20 +1093,12 @@
notify->post();
}
-bool NuPlayer::Renderer::dropBufferWhileFlushing(
+bool NuPlayer::Renderer::dropBufferIfStale(
bool audio, const sp<AMessage> &msg) {
- bool flushing = false;
+ int32_t queueGeneration;
+ CHECK(msg->findInt32("queueGeneration", &queueGeneration));
- {
- Mutex::Autolock autoLock(mFlushLock);
- if (audio) {
- flushing = mFlushingAudio;
- } else {
- flushing = mFlushingVideo;
- }
- }
-
- if (!flushing) {
+ if (queueGeneration == getQueueGeneration(audio)) {
return false;
}
@@ -1204,7 +1116,10 @@
}
CHECK(!mDrainAudioQueuePending);
mNumFramesWritten = 0;
- mAnchorNumFramesWritten = -1;
+ {
+ Mutex::Autolock autoLock(mLock);
+ mAnchorNumFramesWritten = -1;
+ }
uint32_t written;
if (mAudioSink->getFramesWritten(&written) == OK) {
mNumFramesWritten = written;
@@ -1214,13 +1129,13 @@
void NuPlayer::Renderer::onDisableOffloadAudio() {
Mutex::Autolock autoLock(mLock);
mFlags &= ~FLAG_OFFLOAD_AUDIO;
- ++mAudioQueueGeneration;
+ ++mAudioDrainGeneration;
}
void NuPlayer::Renderer::onEnableOffloadAudio() {
Mutex::Autolock autoLock(mLock);
mFlags |= FLAG_OFFLOAD_AUDIO;
- ++mAudioQueueGeneration;
+ ++mAudioDrainGeneration;
}
void NuPlayer::Renderer::onPause() {
@@ -1229,23 +1144,13 @@
return;
}
int64_t currentPositionUs;
- if (getCurrentPositionFromAnchor(
- ¤tPositionUs, ALooper::GetNowUs()) == OK) {
- mPausePositionMediaTimeUs = currentPositionUs;
- } else {
- // Set paused position to -1 (unavailabe) if we don't have anchor time
- // This could happen if client does a seekTo() immediately followed by
- // pause(). Renderer will be flushed with anchor time cleared. We don't
- // want to leave stale value in mPausePositionMediaTimeUs.
- mPausePositionMediaTimeUs = -1;
- }
{
Mutex::Autolock autoLock(mLock);
- ++mAudioQueueGeneration;
- ++mVideoQueueGeneration;
- prepareForMediaRenderingStart();
+ ++mAudioDrainGeneration;
+ ++mVideoDrainGeneration;
+ prepareForMediaRenderingStart_l();
mPaused = true;
- setPauseStartedTimeRealUs(ALooper::GetNowUs());
+ mMediaClock->pause();
}
mDrainAudioQueuePending = false;
@@ -1270,17 +1175,14 @@
mAudioSink->start();
}
- Mutex::Autolock autoLock(mLock);
- mPaused = false;
- if (mPauseStartedTimeRealUs != -1) {
- int64_t newAnchorRealUs =
- mAnchorTimeRealUs + ALooper::GetNowUs() - mPauseStartedTimeRealUs;
- setAnchorTime(
- mAnchorTimeMediaUs, newAnchorRealUs, mAnchorNumFramesWritten, true /* resume */);
- }
+ {
+ Mutex::Autolock autoLock(mLock);
+ mPaused = false;
+ mMediaClock->resume();
- if (!mAudioQueue.empty()) {
- postDrainAudioQueue_l();
+ if (!mAudioQueue.empty()) {
+ postDrainAudioQueue_l();
+ }
}
if (!mVideoQueue.empty()) {
@@ -1295,6 +1197,21 @@
mVideoScheduler->init(fps);
}
+int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
+ Mutex::Autolock autoLock(mLock);
+ return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
+}
+
+int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
+ Mutex::Autolock autoLock(mLock);
+ return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
+}
+
+bool NuPlayer::Renderer::getSyncQueues() {
+ Mutex::Autolock autoLock(mLock);
+ return mSyncQueues;
+}
+
// TODO: Remove unnecessary calls to getPlayedOutAudioDurationUs()
// as it acquires locks and may query the audio driver.
//
@@ -1366,7 +1283,7 @@
mAudioOffloadTornDown = true;
int64_t currentPositionUs;
- if (getCurrentPositionOnLooper(¤tPositionUs) != OK) {
+ if (getCurrentPosition(¤tPositionUs) != OK) {
currentPositionUs = 0;
}
@@ -1383,7 +1300,7 @@
void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
if (offloadingAudio()) {
sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, id());
- msg->setInt32("generation", mAudioOffloadPauseTimeoutGeneration);
+ msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
msg->post(kOffloadPauseMaxUs);
}
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 23907c8..b35c86a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -23,6 +23,7 @@
namespace android {
struct ABuffer;
+struct MediaClock;
struct VideoFrameScheduler;
struct NuPlayer::Renderer : public AHandler {
@@ -60,16 +61,8 @@
void setVideoFrameRate(float fps);
- // Following setters and getters are protected by mTimeLock.
status_t getCurrentPosition(int64_t *mediaUs);
- void setHasMedia(bool audio);
- void setAudioFirstAnchorTime(int64_t mediaUs);
- void setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs);
- void setAnchorTime(
- int64_t mediaUs, int64_t realUs, int64_t numFramesWritten = -1, bool resume = false);
- void setVideoLateByUs(int64_t lateUs);
int64_t getVideoLateByUs();
- void setPauseStartedTimeRealUs(int64_t realUs);
status_t openAudioSink(
const sp<AMessage> &format,
@@ -107,7 +100,6 @@
kWhatQueueBuffer = 'queB',
kWhatQueueEOS = 'qEOS',
kWhatFlush = 'flus',
- kWhatAudioSinkChanged = 'auSC',
kWhatPause = 'paus',
kWhatResume = 'resm',
kWhatOpenAudioSink = 'opnA',
@@ -141,26 +133,17 @@
bool mDrainVideoQueuePending;
int32_t mAudioQueueGeneration;
int32_t mVideoQueueGeneration;
+ int32_t mAudioDrainGeneration;
+ int32_t mVideoDrainGeneration;
- Mutex mTimeLock;
- // |mTimeLock| protects the following 7 member vars that are related to time.
- // Note: those members are only written on Renderer thread, so reading on Renderer thread
- // doesn't need to be protected. Otherwise accessing those members must be protected by
- // |mTimeLock|.
- // TODO: move those members to a seperated media clock class.
+ sp<MediaClock> mMediaClock;
int64_t mAudioFirstAnchorTimeMediaUs;
int64_t mAnchorTimeMediaUs;
- int64_t mAnchorTimeRealUs;
int64_t mAnchorNumFramesWritten;
- int64_t mAnchorMaxMediaUs;
int64_t mVideoLateByUs;
bool mHasAudio;
bool mHasVideo;
- int64_t mPauseStartedTimeRealUs;
- Mutex mFlushLock; // protects the following 2 member vars.
- bool mFlushingAudio;
- bool mFlushingVideo;
bool mNotifyCompleteAudio;
bool mNotifyCompleteVideo;
@@ -168,7 +151,6 @@
// modified on only renderer's thread.
bool mPaused;
- int64_t mPausePositionMediaTimeUs;
bool mVideoSampleReceived;
bool mVideoRenderingStarted;
@@ -194,13 +176,6 @@
int32_t mTotalBuffersQueued;
int32_t mLastAudioBufferDrained;
- status_t getCurrentPositionOnLooper(int64_t *mediaUs);
- status_t getCurrentPositionOnLooper(
- int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
- bool getCurrentPositionIfPaused_l(int64_t *mediaUs);
- status_t getCurrentPositionFromAnchor(
- int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
-
size_t fillAudioBuffer(void *buffer, size_t size);
bool onDrainAudioQueue();
@@ -208,14 +183,19 @@
int64_t getPlayedOutAudioDurationUs(int64_t nowUs);
void postDrainAudioQueue_l(int64_t delayUs = 0);
+ void clearAnchorTime_l();
+ void clearAudioFirstAnchorTime_l();
+ void setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs);
+ void setVideoLateByUs(int64_t lateUs);
+
void onNewAudioMediaTime(int64_t mediaTimeUs);
int64_t getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs);
void onDrainVideoQueue();
void postDrainVideoQueue();
- void prepareForMediaRenderingStart();
- void notifyIfMediaRenderingStarted();
+ void prepareForMediaRenderingStart_l();
+ void notifyIfMediaRenderingStarted_l();
void onQueueBuffer(const sp<AMessage> &msg);
void onQueueEOS(const sp<AMessage> &msg);
@@ -226,6 +206,9 @@
void onPause();
void onResume();
void onSetVideoFrameRate(float fps);
+ int32_t getQueueGeneration(bool audio);
+ int32_t getDrainGeneration(bool audio);
+ bool getSyncQueues();
void onAudioOffloadTearDown(AudioOffloadTearDownReason reason);
status_t onOpenAudioSink(
const sp<AMessage> &format,
@@ -242,7 +225,7 @@
void notifyAudioOffloadTearDown();
void flushQueue(List<QueueEntry> *queue);
- bool dropBufferWhileFlushing(bool audio, const sp<AMessage> &msg);
+ bool dropBufferIfStale(bool audio, const sp<AMessage> &msg);
void syncQueuesDone_l();
bool offloadingAudio() const { return (mFlags & FLAG_OFFLOAD_AUDIO) != 0; }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index c81d3b9..5a8beb1 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -48,6 +48,9 @@
kWhatBufferingUpdate,
kWhatBufferingStart,
kWhatBufferingEnd,
+ kWhatPauseOnBufferingStart,
+ kWhatResumeOnBufferingEnd,
+ kWhatCacheStats,
kWhatSubtitleData,
kWhatTimedTextData,
kWhatQueueDecoderShutdown,
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index fa31c44..6a84c11 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1258,8 +1258,8 @@
}
sp<RefBase> obj;
- int32_t haveNativeWindow = msg->findObject("native-window", &obj) &&
- obj != NULL;
+ bool haveNativeWindow = msg->findObject("native-window", &obj)
+ && obj != NULL;
mStoreMetaDataInOutputBuffers = false;
if (video && !encoder) {
inputFormat->setInt32("adaptive-playback", false);
@@ -1333,6 +1333,15 @@
ALOGV("Configuring CPU controlled video playback.");
mTunneled = false;
+ // Explicity reset the sideband handle of the window for
+ // non-tunneled video in case the window was previously used
+ // for a tunneled video playback.
+ err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
+ if (err != OK) {
+ ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
+ return err;
+ }
+
// Always try to enable dynamic output buffers on native surface
err = mOMX->storeMetaDataInBuffers(
mNode, kPortIndexOutput, OMX_TRUE);
@@ -1410,7 +1419,7 @@
if (encoder) {
err = setupVideoEncoder(mime, msg);
} else {
- err = setupVideoDecoder(mime, msg);
+ err = setupVideoDecoder(mime, msg, haveNativeWindow);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
int32_t numChannels, sampleRate;
@@ -2053,7 +2062,8 @@
status_t ACodec::setVideoPortFormatType(
OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE compressionFormat,
- OMX_COLOR_FORMATTYPE colorFormat) {
+ OMX_COLOR_FORMATTYPE colorFormat,
+ bool usingNativeBuffers) {
OMX_VIDEO_PARAM_PORTFORMATTYPE format;
InitOMXParams(&format);
format.nPortIndex = portIndex;
@@ -2073,10 +2083,10 @@
// substitute back flexible color format to codec supported format
OMX_U32 flexibleEquivalent;
- if (compressionFormat == OMX_VIDEO_CodingUnused &&
- isFlexibleColorFormat(
- mOMX, mNode, format.eColorFormat, &flexibleEquivalent) &&
- colorFormat == flexibleEquivalent) {
+ if (compressionFormat == OMX_VIDEO_CodingUnused
+ && isFlexibleColorFormat(
+ mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
+ && colorFormat == flexibleEquivalent) {
ALOGI("[%s] using color format %#x in place of %#x",
mComponentName.c_str(), format.eColorFormat, colorFormat);
colorFormat = format.eColorFormat;
@@ -2120,18 +2130,66 @@
return err;
}
-status_t ACodec::setSupportedOutputFormat() {
- OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+// Set optimal output format. OMX component lists output formats in the order
+// of preference, but this got more complicated since the introduction of flexible
+// YUV formats. We support a legacy behavior for applications that do not use
+// surface output, do not specify an output format, but expect a "usable" standard
+// OMX format. SW readable and standard formats must be flex-YUV.
+//
+// Suggested preference order:
+// - optimal format for texture rendering (mediaplayer behavior)
+// - optimal SW readable & texture renderable format (flex-YUV support)
+// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
+// - legacy "usable" standard formats
+//
+// For legacy support, we prefer a standard format, but will settle for a SW readable
+// flex-YUV format.
+status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
InitOMXParams(&format);
format.nPortIndex = kPortIndexOutput;
- format.nIndex = 0;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoPortFormat,
- &format, sizeof(format));
- CHECK_EQ(err, (status_t)OK);
- CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
+ InitOMXParams(&legacyFormat);
+ // this field will change when we find a suitable legacy format
+ legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
+ for (OMX_U32 index = 0; ; ++index) {
+ format.nIndex = index;
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ if (err != OK) {
+ // no more formats, pick legacy format if found
+ if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
+ memcpy(&format, &legacyFormat, sizeof(format));
+ break;
+ }
+ return err;
+ }
+ if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
+ return OMX_ErrorBadParameter;
+ }
+ if (!getLegacyFlexibleFormat) {
+ break;
+ }
+ // standard formats that were exposed to users before
+ if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+ || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
+ || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+ || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
+ || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
+ break;
+ }
+ // find best legacy non-standard format
+ OMX_U32 flexibleEquivalent;
+ if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
+ && isFlexibleColorFormat(
+ mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
+ &flexibleEquivalent)
+ && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
+ memcpy(&legacyFormat, &format, sizeof(format));
+ }
+ }
return mOMX->setParameter(
mNode, OMX_IndexParamVideoPortFormat,
&format, sizeof(format));
@@ -2183,7 +2241,7 @@
}
status_t ACodec::setupVideoDecoder(
- const char *mime, const sp<AMessage> &msg) {
+ const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
int32_t width, height;
if (!msg->findInt32("width", &width)
|| !msg->findInt32("height", &height)) {
@@ -2209,22 +2267,31 @@
OMX_COLOR_FORMATTYPE colorFormat =
static_cast<OMX_COLOR_FORMATTYPE>(tmp);
err = setVideoPortFormatType(
- kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat);
+ kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
if (err != OK) {
ALOGW("[%s] does not support color format %d",
mComponentName.c_str(), colorFormat);
- err = setSupportedOutputFormat();
+ err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
}
} else {
- err = setSupportedOutputFormat();
+ err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
}
if (err != OK) {
return err;
}
+ int32_t frameRateInt;
+ float frameRateFloat;
+ if (!msg->findFloat("frame-rate", &frameRateFloat)) {
+ if (!msg->findInt32("frame-rate", &frameRateInt)) {
+ frameRateInt = -1;
+ }
+ frameRateFloat = (float)frameRateInt;
+ }
+
err = setVideoFormatOnPort(
- kPortIndexInput, width, height, compressionFormat);
+ kPortIndexInput, width, height, compressionFormat, frameRateFloat);
if (err != OK) {
return err;
@@ -2988,7 +3055,8 @@
status_t ACodec::setVideoFormatOnPort(
OMX_U32 portIndex,
- int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
+ int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
+ float frameRate) {
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
def.nPortIndex = portIndex;
@@ -3016,6 +3084,9 @@
if (portIndex == kPortIndexInput) {
video_def->eCompressionFormat = compressionFormat;
video_def->eColorFormat = OMX_COLOR_FormatUnused;
+ if (frameRate >= 0) {
+ video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
+ }
}
err = mOMX->setParameter(
@@ -3217,7 +3288,7 @@
// static
bool ACodec::isFlexibleColorFormat(
const sp<IOMX> &omx, IOMX::node_id node,
- uint32_t colorFormat, OMX_U32 *flexibleEquivalent) {
+ uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
DescribeColorFormatParams describeParams;
InitOMXParams(&describeParams);
describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
@@ -3226,6 +3297,7 @@
describeParams.nFrameHeight = 128;
describeParams.nStride = 128;
describeParams.nSliceHeight = 128;
+ describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
CHECK(flexibleEquivalent != NULL);
@@ -3283,20 +3355,23 @@
notify->setInt32("slice-height", videoDef->nSliceHeight);
notify->setInt32("color-format", videoDef->eColorFormat);
- DescribeColorFormatParams describeParams;
- InitOMXParams(&describeParams);
- describeParams.eColorFormat = videoDef->eColorFormat;
- describeParams.nFrameWidth = videoDef->nFrameWidth;
- describeParams.nFrameHeight = videoDef->nFrameHeight;
- describeParams.nStride = videoDef->nStride;
- describeParams.nSliceHeight = videoDef->nSliceHeight;
+ if (mNativeWindow == NULL) {
+ DescribeColorFormatParams describeParams;
+ InitOMXParams(&describeParams);
+ describeParams.eColorFormat = videoDef->eColorFormat;
+ describeParams.nFrameWidth = videoDef->nFrameWidth;
+ describeParams.nFrameHeight = videoDef->nFrameHeight;
+ describeParams.nStride = videoDef->nStride;
+ describeParams.nSliceHeight = videoDef->nSliceHeight;
+ describeParams.bUsingNativeBuffers = OMX_FALSE;
- if (describeColorFormat(mOMX, mNode, describeParams)) {
- notify->setBuffer(
- "image-data",
- ABuffer::CreateAsCopy(
- &describeParams.sMediaImage,
- sizeof(describeParams.sMediaImage)));
+ if (describeColorFormat(mOMX, mNode, describeParams)) {
+ notify->setBuffer(
+ "image-data",
+ ABuffer::CreateAsCopy(
+ &describeParams.sMediaImage,
+ sizeof(describeParams.sMediaImage)));
+ }
}
if (portIndex != kPortIndexOutput) {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 007c090..87eef1e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -889,10 +889,7 @@
}
}
if ((mFlags & LOOPING)
- || ((mFlags & AUTO_LOOPING)
- && (mAudioSink == NULL || mAudioSink->realtime()))) {
- // Don't AUTO_LOOP if we're being recorded, since that cannot be
- // turned off and recording would go on indefinitely.
+ || (mFlags & AUTO_LOOPING)) {
seekTo_l(0);
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index dec52f3..8bf7f63 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1144,7 +1144,7 @@
{
*offset += chunk_size;
- if (chunk_data_size < 4) {
+ if (chunk_data_size < 4 || mLastTrack == NULL) {
return ERROR_MALFORMED;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 8fa07b2..c838427 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1716,7 +1716,7 @@
size_t i = 0;
for (;;) {
sp<ABuffer> csd;
- if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
+ if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
break;
}
@@ -2239,7 +2239,7 @@
memcpy(csd->data() + 4, nalStart, nalSize);
mOutputFormat->setBuffer(
- StringPrintf("csd-%u", csdIndex).c_str(), csd);
+ AStringPrintf("csd-%u", csdIndex).c_str(), csd);
++csdIndex;
}
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index bd0a41d..7d7d631 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -354,7 +354,7 @@
Mutex::Autolock autoLock(mLock);
if (n == 0 || mDisconnecting) {
- ALOGI("ERROR_END_OF_STREAM");
+ ALOGI("caching reached eos.");
mNumRetriesLeft = 0;
mFinalStatus = ERROR_END_OF_STREAM;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 69f4989..ea19ab2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -4538,7 +4538,8 @@
OMX_U32 flexibleEquivalent;
if (ACodec::isFlexibleColorFormat(
- omx, node, portFormat.eColorFormat, &flexibleEquivalent)) {
+ omx, node, portFormat.eColorFormat, false /* usingNativeWindow */,
+ &flexibleEquivalent)) {
bool marked = false;
for (size_t i = 0; i < caps->mColorFormats.size(); i++) {
if (caps->mColorFormats.itemAt(i) == flexibleEquivalent) {
diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
index d1fe833..4fd16a1 100644
--- a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
+++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
@@ -245,10 +245,9 @@
Word32 rsqrt(Word32 value, /*!< Operand to square root (0.0 ... 1) */
Word32 accuracy) /*!< Number of valid bits that will be calculated */
{
- UNUSED(accuracy);
-
Word32 root = 0;
Word32 scale;
+ UNUSED(accuracy);
if(value < 0)
return 0;
diff --git a/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp b/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
index 521fe2b..41a9e98 100644
--- a/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
@@ -26,6 +26,7 @@
* SUCH DAMAGE.
*/
+#include <malloc.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
index b783222..90d7c6b 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
@@ -292,8 +292,10 @@
if (video->shortVideoHeader == PV_TRUE)
{
- video->displayWidth = video->width = width;
- video->displayHeight = video->height = height;
+ video->displayWidth = width;
+ video->displayHeight = height;
+ video->width = (width + 15) & -16;
+ video->height = (height + 15) & -16;
video->nMBPerRow =
video->nMBinGOB = video->width / MB_SIZE;
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
index b03ec8c..60c79a6 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -118,6 +118,10 @@
{
/* support SPL0-3 & SSPL0-2 */
if (tmpvar != 0x01 && tmpvar != 0x02 && tmpvar != 0x03 && tmpvar != 0x08 &&
+ /* While not technically supported, try to decode SPL4&SPL5 files as well. */
+ /* We'll fail later if the size is too large. This is to allow playback of */
+ /* some <=CIF files generated by other encoders. */
+ tmpvar != 0x04 && tmpvar != 0x05 &&
tmpvar != 0x10 && tmpvar != 0x11 && tmpvar != 0x12 &&
tmpvar != 0x21 && tmpvar != 0x22 && /* Core Profile Levels */
tmpvar != 0xA1 && tmpvar != 0xA2 && tmpvar != 0xA3 &&
diff --git a/media/libstagefright/codecs/on2/enc/Android.mk b/media/libstagefright/codecs/on2/enc/Android.mk
index e265104..253fa04 100644
--- a/media/libstagefright/codecs/on2/enc/Android.mk
+++ b/media/libstagefright/codecs/on2/enc/Android.mk
@@ -6,7 +6,6 @@
LOCAL_C_INCLUDES := \
$(TOP)/external/libvpx/libvpx \
- $(TOP)/external/openssl/include \
$(TOP)/external/libvpx/libvpx/vpx_codec \
$(TOP)/external/libvpx/libvpx/vpx_ports \
frameworks/av/media/libstagefright/include \
diff --git a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
index 524a3f0..a073dcb 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
@@ -36,6 +36,7 @@
1. Include headers
------------------------------------------------------------------------------*/
#include <stdlib.h>
+#include <string.h>
#include "basetype.h"
#include "h264bsd_container.h"
#include "H264SwDecApi.h"
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 795e8a6..1f46bc9 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -426,19 +426,19 @@
AString tmp;
if (isFourcc(mWhat)) {
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"'%c%c%c%c'",
(char)(mWhat >> 24),
(char)((mWhat >> 16) & 0xff),
(char)((mWhat >> 8) & 0xff),
(char)(mWhat & 0xff));
} else {
- tmp = StringPrintf("0x%08x", mWhat);
+ tmp = AStringPrintf("0x%08x", mWhat);
}
s.append(tmp);
if (mTarget != 0) {
- tmp = StringPrintf(", target = %d", mTarget);
+ tmp = AStringPrintf(", target = %d", mTarget);
s.append(tmp);
}
s.append(") = {\n");
@@ -448,37 +448,37 @@
switch (item.mType) {
case kTypeInt32:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"int32_t %s = %d", item.mName, item.u.int32Value);
break;
case kTypeInt64:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"int64_t %s = %lld", item.mName, item.u.int64Value);
break;
case kTypeSize:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"size_t %s = %d", item.mName, item.u.sizeValue);
break;
case kTypeFloat:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"float %s = %f", item.mName, item.u.floatValue);
break;
case kTypeDouble:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"double %s = %f", item.mName, item.u.doubleValue);
break;
case kTypePointer:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"void *%s = %p", item.mName, item.u.ptrValue);
break;
case kTypeString:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"string %s = \"%s\"",
item.mName,
item.u.stringValue->c_str());
break;
case kTypeObject:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"RefBase *%s = %p", item.mName, item.u.refValue);
break;
case kTypeBuffer:
@@ -486,18 +486,18 @@
sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
- tmp = StringPrintf("Buffer %s = {\n", item.mName);
+ tmp = AStringPrintf("Buffer %s = {\n", item.mName);
hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
appendIndent(&tmp, indent + 2);
tmp.append("}");
} else {
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"Buffer *%s = %p", item.mName, buffer.get());
}
break;
}
case kTypeMessage:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"AMessage %s = %s",
item.mName,
static_cast<AMessage *>(
@@ -505,7 +505,7 @@
indent + strlen(item.mName) + 14).c_str());
break;
case kTypeRect:
- tmp = StringPrintf(
+ tmp = AStringPrintf(
"Rect %s(%d, %d, %d, %d)",
item.mName,
item.u.rectValue.mLeft,
diff --git a/media/libstagefright/foundation/ANetworkSession.cpp b/media/libstagefright/foundation/ANetworkSession.cpp
index 4504c2b..b230400 100644
--- a/media/libstagefright/foundation/ANetworkSession.cpp
+++ b/media/libstagefright/foundation/ANetworkSession.cpp
@@ -187,7 +187,7 @@
CHECK_GE(res, 0);
in_addr_t addr = ntohl(localAddr.sin_addr.s_addr);
- AString localAddrString = StringPrintf(
+ AString localAddrString = AStringPrintf(
"%d.%d.%d.%d",
(addr >> 24),
(addr >> 16) & 0xff,
@@ -195,7 +195,7 @@
addr & 0xff);
addr = ntohl(remoteAddr.sin_addr.s_addr);
- AString remoteAddrString = StringPrintf(
+ AString remoteAddrString = AStringPrintf(
"%d.%d.%d.%d",
(addr >> 24),
(addr >> 16) & 0xff,
@@ -301,7 +301,7 @@
uint32_t ip = ntohl(remoteAddr.sin_addr.s_addr);
notify->setString(
"fromAddr",
- StringPrintf(
+ AStringPrintf(
"%u.%u.%u.%u",
ip >> 24,
(ip >> 16) & 0xff,
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index 9835ca3..b167543 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -366,7 +366,7 @@
return err;
}
-AString StringPrintf(const char *format, ...) {
+AString AStringPrintf(const char *format, ...) {
va_list ap;
va_start(ap, format);
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
index e8d558c..93b7935 100644
--- a/media/libstagefright/httplive/Android.mk
+++ b/media/libstagefright/httplive/Android.mk
@@ -10,8 +10,7 @@
LOCAL_C_INCLUDES:= \
$(TOP)/frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/external/openssl/include
+ $(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Werror
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 190188a..d0f3bc2 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -846,11 +846,11 @@
headers.add(
String8("Range"),
String8(
- StringPrintf(
+ AStringPrintf(
"bytes=%lld-%s",
range_offset,
range_length < 0
- ? "" : StringPrintf("%lld",
+ ? "" : AStringPrintf("%lld",
range_offset + range_length - 1).c_str()).c_str()));
}
status_t err = mHTTPDataSource->connect(url, &headers);
@@ -1508,14 +1508,15 @@
if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
int64_t tmpUs;
- CHECK(meta->findInt64("timeUs", &tmpUs));
- if (startTimeUs < 0 || tmpUs < startTimeUs) {
- startTimeUs = tmpUs;
- }
+ int64_t tmpSegmentUs;
- CHECK(meta->findInt64("segmentStartTimeUs", &tmpUs));
- if (segmentStartTimeUs < 0 || tmpUs < segmentStartTimeUs) {
- segmentStartTimeUs = tmpUs;
+ CHECK(meta->findInt64("timeUs", &tmpUs));
+ CHECK(meta->findInt64("segmentStartTimeUs", &tmpSegmentUs));
+ if (startTimeUs < 0 || tmpSegmentUs < segmentStartTimeUs) {
+ startTimeUs = tmpUs;
+ segmentStartTimeUs = tmpSegmentUs;
+ } else if (tmpSegmentUs == segmentStartTimeUs && tmpUs < startTimeUs) {
+ startTimeUs = tmpUs;
}
int32_t seq;
@@ -1627,6 +1628,12 @@
return;
}
+ if (mSwitchInProgress || mReconfigurationInProgress) {
+ ALOGV("Switch/Reconfig in progress, defer switch down");
+ mSwitchDownMonitor->post(1000000ll);
+ return;
+ }
+
for (size_t i = 0; i < kMaxStreams; ++i) {
int32_t targetDuration;
sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(indexToType(i));
@@ -1657,7 +1664,6 @@
return;
}
- changeConfiguration(-1, mCurBandwidthIndex - 1, false);
}
// Mark switch done when:
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 1526af1..1227600 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -757,6 +757,9 @@
mSeqNumber = firstSeqNumberInPlaylist;
}
} else {
+ // When seeking mSegmentStartTimeUs is unavailable (< 0), we
+ // use mStartTimeUs (client supplied timestamp) to determine both start segment
+ // and relative position inside a segment
mSeqNumber = getSeqNumberForTime(mStartTimeUs);
mStartTimeUs -= getSegmentStartTimeUs(mSeqNumber);
}
@@ -765,6 +768,10 @@
mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist,
lastSeqNumberInPlaylist);
} else {
+ // When adapting or track switching, mSegmentStartTimeUs (relative
+ // to media time 0) is used to determine the start segment; mStartTimeUs (absolute
+ // timestamps coming from the media container) is used to determine the position
+ // inside a segments.
mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs);
if (mAdaptive) {
// avoid double fetch/decode
@@ -976,6 +983,10 @@
if (err == -EAGAIN) {
// starting sequence number too low/high
mTSParser.clear();
+ for (size_t i = 0; i < mPacketSources.size(); i++) {
+ sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
+ packetSource->clear();
+ }
postMonitorQueue();
return;
} else if (err == ERROR_OUT_OF_RANGE) {
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 793d116..e1607bf 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -461,7 +461,7 @@
sdp.append("m=audio ");
}
- sdp.append(StringPrintf("%d", ntohs(mRTPAddr.sin_port)));
+ sdp.append(AStringPrintf("%d", ntohs(mRTPAddr.sin_port)));
sdp.append(
" RTP/AVP " PT_STR "\r\n"
"b=AS 320000\r\n"
@@ -480,7 +480,7 @@
CHECK_EQ(sampleRate, (mMode == AMR_NB) ? 8000 : 16000);
sdp.append(mMode == AMR_NB ? "AMR" : "AMR-WB");
- sdp.append(StringPrintf("/%d/%d", sampleRate, numChannels));
+ sdp.append(AStringPrintf("/%d/%d", sampleRate, numChannels));
} else {
TRESPASS();
}
@@ -543,7 +543,7 @@
CHECK_EQ((unsigned)data[0], 0x67u);
mProfileLevel =
- StringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
+ AStringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
encodeBase64(data, startCodePos, &mSeqParamSet);
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index f25539c..60b3aaf 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -42,7 +42,7 @@
// static
const AString ARTSPConnection::sUserAgent =
- StringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
+ AStringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
: mUIDValid(uidValid),
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index d60dc2f..9fedb71 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -19,10 +19,11 @@
ASessionDescription.cpp \
SDPLoader.cpp \
+LOCAL_SHARED_LIBRARIES += libcrypto
+
LOCAL_C_INCLUDES:= \
$(TOP)/frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/external/openssl/include
+ $(TOP)/frameworks/native/include/media/openmax
LOCAL_MODULE:= libstagefright_rtsp
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 423a420..3bf489b 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -156,7 +156,7 @@
mSessionURL.append("rtsp://");
mSessionURL.append(host);
mSessionURL.append(":");
- mSessionURL.append(StringPrintf("%u", port));
+ mSessionURL.append(AStringPrintf("%u", port));
mSessionURL.append(path);
ALOGV("rewritten session url: '%s'", mSessionURL.c_str());
@@ -508,7 +508,7 @@
mSessionURL.append("rtsp://");
mSessionURL.append(host);
mSessionURL.append(":");
- mSessionURL.append(StringPrintf("%u", port));
+ mSessionURL.append(AStringPrintf("%u", port));
mSessionURL.append(path);
ALOGI("rewritten session url: '%s'", mSessionURL.c_str());
@@ -1238,7 +1238,7 @@
request.append("\r\n");
request.append(
- StringPrintf(
+ AStringPrintf(
"Range: npt=%lld-\r\n", timeUs / 1000000ll));
request.append("\r\n");
diff --git a/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp b/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
index 40e93c7..3a06d61 100644
--- a/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
+++ b/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
@@ -120,26 +120,26 @@
err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
EXPECT_EQ(OK, err);
CheckStartTimeMs(parcel, i * kSecToMsec);
- subtitle = StringPrintf("%d\n\n", i);
+ subtitle = AStringPrintf("%d\n\n", i);
CheckDataEquals(parcel, subtitle.c_str());
}
// read edge cases
err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
EXPECT_EQ(OK, err);
CheckStartTimeMs(parcel, 5500);
- subtitle = StringPrintf("6\n\n");
+ subtitle = AStringPrintf("6\n\n");
CheckDataEquals(parcel, subtitle.c_str());
err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
EXPECT_EQ(OK, err);
CheckStartTimeMs(parcel, 5800);
- subtitle = StringPrintf("7\n\n");
+ subtitle = AStringPrintf("7\n\n");
CheckDataEquals(parcel, subtitle.c_str());
err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
EXPECT_EQ(OK, err);
CheckStartTimeMs(parcel, 6000);
- subtitle = StringPrintf("8\n\n");
+ subtitle = AStringPrintf("8\n\n");
CheckDataEquals(parcel, subtitle.c_str());
err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
@@ -202,21 +202,21 @@
err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
EXPECT_EQ(OK, err);
EXPECT_EQ(5500 * kMsecToUsec, startTimeUs);
- subtitle = StringPrintf("6\n\n");
+ subtitle = AStringPrintf("6\n\n");
CheckDataEquals(parcel, subtitle.c_str());
options.setSeekTo(5800 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
EXPECT_EQ(OK, err);
EXPECT_EQ(5800 * kMsecToUsec, startTimeUs);
- subtitle = StringPrintf("7\n\n");
+ subtitle = AStringPrintf("7\n\n");
CheckDataEquals(parcel, subtitle.c_str());
options.setSeekTo(6000 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
EXPECT_EQ(OK, err);
EXPECT_EQ(6000 * kMsecToUsec, startTimeUs);
- subtitle = StringPrintf("8\n\n");
+ subtitle = AStringPrintf("8\n\n");
CheckDataEquals(parcel, subtitle.c_str());
}
diff --git a/media/libstagefright/wifi-display/VideoFormats.cpp b/media/libstagefright/wifi-display/VideoFormats.cpp
index 04e02c1..2f4af5b 100644
--- a/media/libstagefright/wifi-display/VideoFormats.cpp
+++ b/media/libstagefright/wifi-display/VideoFormats.cpp
@@ -435,7 +435,7 @@
// max-hres (none or 2 byte)
// max-vres (none or 2 byte)
- return StringPrintf(
+ return AStringPrintf(
"%02x 00 %02x %02x %08x %08x %08x 00 0000 0000 00 none none",
forM4Message ? 0x00 : ((mNativeIndex << 3) | mNativeType),
mConfigs[mNativeType][mNativeIndex].profile,
diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
index 50d317a..4c5ad17 100644
--- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp
+++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
@@ -106,7 +106,7 @@
|| !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
for (size_t i = 0;; ++i) {
sp<ABuffer> csd;
- if (!mFormat->findBuffer(StringPrintf("csd-%d", i).c_str(), &csd)) {
+ if (!mFormat->findBuffer(AStringPrintf("csd-%d", i).c_str(), &csd)) {
break;
}
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 0c39ccf..7eb8b73 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -598,7 +598,7 @@
AppendCommonResponse(&request, mNextCSeq);
request.append("Content-Type: text/parameters\r\n");
- request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+ request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
request.append("\r\n");
request.append(body);
@@ -639,26 +639,26 @@
if (mSinkSupportsAudio) {
body.append(
- StringPrintf("wfd_audio_codecs: %s\r\n",
+ AStringPrintf("wfd_audio_codecs: %s\r\n",
(mUsingPCMAudio
? "LPCM 00000002 00" // 2 ch PCM 48kHz
: "AAC 00000001 00"))); // 2 ch AAC 48kHz
}
body.append(
- StringPrintf(
+ AStringPrintf(
"wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n",
mClientInfo.mLocalIP.c_str()));
body.append(
- StringPrintf(
+ AStringPrintf(
"wfd_client_rtp_ports: %s\r\n", mWfdClientRtpPorts.c_str()));
AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
AppendCommonResponse(&request, mNextCSeq);
request.append("Content-Type: text/parameters\r\n");
- request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+ request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
request.append("\r\n");
request.append(body);
@@ -704,7 +704,7 @@
AppendCommonResponse(&request, mNextCSeq);
request.append("Content-Type: text/parameters\r\n");
- request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+ request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
request.append("\r\n");
request.append(body);
@@ -729,7 +729,7 @@
CHECK_EQ(sessionID, mClientSessionID);
request.append(
- StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
+ AStringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
request.append("\r\n"); // Empty body
status_t err =
@@ -1305,7 +1305,7 @@
if (rtpMode == RTPSender::TRANSPORT_TCP_INTERLEAVED) {
response.append(
- StringPrintf(
+ AStringPrintf(
"Transport: RTP/AVP/TCP;interleaved=%d-%d;",
clientRtp, clientRtcp));
} else {
@@ -1318,14 +1318,14 @@
if (clientRtcp >= 0) {
response.append(
- StringPrintf(
+ AStringPrintf(
"Transport: RTP/AVP/%s;unicast;client_port=%d-%d;"
"server_port=%d-%d\r\n",
transportString.c_str(),
clientRtp, clientRtcp, serverRtp, serverRtp + 1));
} else {
response.append(
- StringPrintf(
+ AStringPrintf(
"Transport: RTP/AVP/%s;unicast;client_port=%d;"
"server_port=%d\r\n",
transportString.c_str(),
@@ -1585,15 +1585,15 @@
response->append(buf);
response->append("\r\n");
- response->append(StringPrintf("Server: %s\r\n", sUserAgent.c_str()));
+ response->append(AStringPrintf("Server: %s\r\n", sUserAgent.c_str()));
if (cseq >= 0) {
- response->append(StringPrintf("CSeq: %d\r\n", cseq));
+ response->append(AStringPrintf("CSeq: %d\r\n", cseq));
}
if (playbackSessionID >= 0ll) {
response->append(
- StringPrintf(
+ AStringPrintf(
"Session: %d;timeout=%lld\r\n",
playbackSessionID, kPlaybackSessionTimeoutSecs));
}
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index e4e16f2..07199e3 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -1119,10 +1119,10 @@
MtpResponseCode MtpServer::doDeleteObject() {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- if (mRequest.getParameterCount() < 2)
+ if (mRequest.getParameterCount() < 1)
return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
- MtpObjectFormat format = mRequest.getParameter(2);
+ MtpObjectFormat format;
// FIXME - support deleting all objects if handle is 0xFFFFFFFF
// FIXME - implement deleting objects by format
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 4508fa7..116d0d6 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -75,7 +75,8 @@
// indicate a change in device connection status
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address) = 0;
+ const char *device_address,
+ const char *device_name) = 0;
// retrieve a device connection status
virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address) = 0;
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
index a45dbb3..e9ff8389 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
@@ -28,7 +28,8 @@
status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address)
+ const char *device_address,
+ const char *device_name)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
@@ -46,8 +47,8 @@
ALOGV("setDeviceConnectionState()");
Mutex::Autolock _l(mLock);
- return mAudioPolicyManager->setDeviceConnectionState(device,
- state, device_address);
+ return mAudioPolicyManager->setDeviceConnectionState(device, state,
+ device_address, device_name);
}
audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
index b8846c6..5a91192 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
@@ -33,7 +33,8 @@
status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address)
+ const char *device_address,
+ const char *device_name __unused)
{
if (mpAudioPolicy == NULL) {
return NO_INIT;
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 0349327..5a0c958 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -212,34 +212,32 @@
// ----------------------------------------------------------------------------
status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
- audio_policy_dev_state_t state,
- const char *device_address)
+ audio_policy_dev_state_t state,
+ const char *device_address,
+ const char *device_name)
{
- return setDeviceConnectionStateInt(device, state, device_address);
+ return setDeviceConnectionStateInt(device, state, device_address, device_name);
}
status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
- audio_policy_dev_state_t state,
- const char *device_address)
+ audio_policy_dev_state_t state,
+ const char *device_address,
+ const char *device_name)
{
- String8 address = (device_address == NULL) ? String8("") : String8(device_address);
- // handle legacy remote submix case where the address was not always specified
- if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
- address = String8("0");
- }
-
- ALOGV("setDeviceConnectionState() device: %x, state %d, address %s",
- device, state, address.string());
+ ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s",
+- device, state, device_address, device_name);
// connect/disconnect only 1 device at a time
if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
+ sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address);
+
+ String8 name = String8(device_name != NULL ? device_name : "");
+
// handle output devices
if (audio_is_output_device(device)) {
SortedVector <audio_io_handle_t> outputs;
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
- devDesc->mAddress = address;
ssize_t index = mAvailableOutputDevices.indexOf(devDesc);
// save a copy of the opened output descriptors before any output is opened or closed
@@ -248,7 +246,7 @@
switch (state)
{
// handle output device connection
- case AUDIO_POLICY_DEVICE_STATE_AVAILABLE:
+ case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
if (index >= 0) {
ALOGW("setDeviceConnectionState() device already connected: %x", device);
return INVALID_OPERATION;
@@ -265,13 +263,12 @@
mAvailableOutputDevices.remove(devDesc);
return INVALID_OPERATION;
}
- mAvailableOutputDevices[index]->mId = nextUniqueId();
- mAvailableOutputDevices[index]->mModule = module;
+ mAvailableOutputDevices[index]->attach(module);
} else {
return NO_MEMORY;
}
- if (checkOutputsForDevice(devDesc, state, outputs, address) != NO_ERROR) {
+ if (checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress) != NO_ERROR) {
mAvailableOutputDevices.remove(devDesc);
return INVALID_OPERATION;
}
@@ -280,7 +277,14 @@
"checkOutputsForDevice() returned no outputs but status OK");
ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %zu outputs",
outputs.size());
- break;
+
+
+ // Set connect to HALs
+ AudioParameter param = AudioParameter(devDesc->mAddress);
+ param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
+ mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+
+ } break;
// handle output device disconnection
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
if (index < 0) {
@@ -290,15 +294,15 @@
ALOGV("setDeviceConnectionState() disconnecting output device %x", device);
- // Set Disconnect to HALs
- AudioParameter param = AudioParameter(address);
+ // Send Disconnect to HALs
+ AudioParameter param = AudioParameter(devDesc->mAddress);
param.addInt(String8(AUDIO_PARAMETER_DEVICE_DISCONNECT), device);
mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
// remove device from available output devices
mAvailableOutputDevices.remove(devDesc);
- checkOutputsForDevice(devDesc, state, outputs, address);
+ checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
} break;
default:
@@ -355,8 +359,6 @@
if (audio_is_input_device(device)) {
SortedVector <audio_io_handle_t> inputs;
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
- devDesc->mAddress = address;
ssize_t index = mAvailableInputDevices.indexOf(devDesc);
switch (state)
{
@@ -372,17 +374,22 @@
device);
return INVALID_OPERATION;
}
- if (checkInputsForDevice(device, state, inputs, address) != NO_ERROR) {
+ if (checkInputsForDevice(device, state, inputs, devDesc->mAddress) != NO_ERROR) {
return INVALID_OPERATION;
}
index = mAvailableInputDevices.add(devDesc);
if (index >= 0) {
- mAvailableInputDevices[index]->mId = nextUniqueId();
- mAvailableInputDevices[index]->mModule = module;
+ mAvailableInputDevices[index]->attach(module);
} else {
return NO_MEMORY;
}
+
+ // Set connect to HALs
+ AudioParameter param = AudioParameter(devDesc->mAddress);
+ param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
+ mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+
} break;
// handle input device disconnection
@@ -395,11 +402,11 @@
ALOGV("setDeviceConnectionState() disconnecting input device %x", device);
// Set Disconnect to HALs
- AudioParameter param = AudioParameter(address);
+ AudioParameter param = AudioParameter(devDesc->mAddress);
param.addInt(String8(AUDIO_PARAMETER_DEVICE_DISCONNECT), device);
mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
- checkInputsForDevice(device, state, inputs, address);
+ checkInputsForDevice(device, state, inputs, devDesc->mAddress);
mAvailableInputDevices.remove(devDesc);
} break;
@@ -427,14 +434,7 @@
audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
const char *device_address)
{
- audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
- devDesc->mAddress = (device_address == NULL) ? String8("") : String8(device_address);
- // handle legacy remote submix case where the address was not always specified
- if (deviceDistinguishesOnAddress(device) && (devDesc->mAddress.length() == 0)) {
- devDesc->mAddress = String8("0");
- }
- ssize_t index;
+ sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address);
DeviceVector *deviceVector;
if (audio_is_output_device(device)) {
@@ -446,7 +446,7 @@
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
- index = deviceVector->indexOf(devDesc);
+ ssize_t index = deviceVector->indexOf(devDesc);
if (index >= 0) {
return AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
} else {
@@ -454,6 +454,36 @@
}
}
+sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::getDeviceDescriptor(
+ const audio_devices_t device,
+ const char *device_address)
+{
+ String8 address = (device_address == NULL) ? String8("") : String8(device_address);
+ // handle legacy remote submix case where the address was not always specified
+ if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
+ address = String8("0");
+ }
+
+ for (size_t i = 0; i < mHwModules.size(); i++) {
+ if (mHwModules[i]->mHandle == 0) {
+ continue;
+ }
+ DeviceVector deviceList =
+ mHwModules[i]->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
+ if (!deviceList.isEmpty()) {
+ return deviceList.itemAt(0);
+ }
+ deviceList = mHwModules[i]->mDeclaredDevices.getDevicesFromType(device);
+ if (!deviceList.isEmpty()) {
+ return deviceList.itemAt(0);
+ }
+ }
+
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
+ devDesc->mAddress = address;
+ return devDesc;
+}
+
void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs)
{
bool createTxPatch = false;
@@ -1098,6 +1128,10 @@
if (output != AUDIO_IO_HANDLE_NONE) {
mpClientInterface->closeOutput(output);
}
+ // fall back to mixer output if possible when the direct output could not be open
+ if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) {
+ goto non_direct_output;
+ }
return AUDIO_IO_HANDLE_NONE;
}
outputDesc->mSamplingRate = config.sample_rate;
@@ -1290,7 +1324,8 @@
outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- outputDesc->mPolicyMix->mRegistrationId);
+ outputDesc->mPolicyMix->mRegistrationId,
+ "remote-submix");
}
// force reevaluating accessibility routing when ringtone or alarm starts
@@ -1339,7 +1374,8 @@
outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- outputDesc->mPolicyMix->mRegistrationId);
+ outputDesc->mPolicyMix->mRegistrationId,
+ "remote-submix");
}
outputDesc->mStopTime[stream] = systemTime();
@@ -1640,7 +1676,7 @@
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address);
+ address, "remote-submix");
}
}
}
@@ -1688,7 +1724,7 @@
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address);
+ address, "remote-submix");
}
}
@@ -2145,11 +2181,11 @@
if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string());
+ address.string(), "remote-submix");
} else {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string());
+ address.string(), "remote-submix");
}
}
return NO_ERROR;
@@ -2187,7 +2223,7 @@
{
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string());
+ address.string(), "remote-submix");
}
if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
@@ -2195,7 +2231,7 @@
{
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string());
+ address.string(), "remote-submix");
}
module->removeOutputProfile(address);
module->removeInputProfile(address);
@@ -3010,6 +3046,8 @@
return android_atomic_inc(&mAudioPortGeneration);
}
+int32_t volatile AudioPolicyManager::mNextUniqueId = 1;
+
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
:
#ifdef AUDIO_POLICY_TEST
@@ -3020,7 +3058,7 @@
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
mA2dpSuspended(false),
- mSpeakerDrcEnabled(false), mNextUniqueId(1),
+ mSpeakerDrcEnabled(false),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
@@ -3033,7 +3071,7 @@
mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
}
- mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER);
+ mDefaultOutputDevice = new DeviceDescriptor(String8("Speaker"), AUDIO_DEVICE_OUT_SPEAKER);
if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
ALOGE("could not load audio policy configuration file, setting defaults");
@@ -3116,9 +3154,8 @@
ssize_t index =
mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
// give a valid ID to an attached device once confirmed it is reachable
- if ((index >= 0) && (mAvailableOutputDevices[index]->mId == 0)) {
- mAvailableOutputDevices[index]->mId = nextUniqueId();
- mAvailableOutputDevices[index]->mModule = mHwModules[i];
+ if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
+ mAvailableOutputDevices[index]->attach(mHwModules[i]);
}
}
if (mPrimaryOutput == 0 &&
@@ -3185,9 +3222,8 @@
ssize_t index =
mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
// give a valid ID to an attached device once confirmed it is reachable
- if ((index >= 0) && (mAvailableInputDevices[index]->mId == 0)) {
- mAvailableInputDevices[index]->mId = nextUniqueId();
- mAvailableInputDevices[index]->mModule = mHwModules[i];
+ if (index >= 0 && !mAvailableInputDevices[index]->isAttached()) {
+ mAvailableInputDevices[index]->attach(mHwModules[i]);
}
}
mpClientInterface->closeInput(input);
@@ -3200,7 +3236,7 @@
}
// make sure all attached devices have been allocated a unique ID
for (size_t i = 0; i < mAvailableOutputDevices.size();) {
- if (mAvailableOutputDevices[i]->mId == 0) {
+ if (!mAvailableOutputDevices[i]->isAttached()) {
ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType);
mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
continue;
@@ -3208,7 +3244,7 @@
i++;
}
for (size_t i = 0; i < mAvailableInputDevices.size();) {
- if (mAvailableInputDevices[i]->mId == 0) {
+ if (!mAvailableInputDevices[i]->isAttached()) {
ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType);
mAvailableInputDevices.remove(mAvailableInputDevices[i]);
continue;
@@ -6377,7 +6413,7 @@
profile->mChannelMasks.add(config->channel_mask);
profile->mFormats.add(config->format);
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
devDesc->mAddress = address;
profile->mSupportedDevices.add(devDesc);
@@ -6407,7 +6443,7 @@
profile->mChannelMasks.add(config->channel_mask);
profile->mFormats.add(config->format);
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
devDesc->mAddress = address;
profile->mSupportedDevices.add(devDesc);
@@ -6473,16 +6509,22 @@
AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type,
audio_port_role_t role, const sp<HwModule>& module) :
- mName(name), mType(type), mRole(role), mModule(module), mFlags(0)
+ mName(name), mType(type), mRole(role), mModule(module), mFlags(0), mId(0)
{
mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
}
+void AudioPolicyManager::AudioPort::attach(const sp<HwModule>& module) {
+ mId = AudioPolicyManager::nextUniqueId();
+ mModule = module;
+}
+
void AudioPolicyManager::AudioPort::toAudioPort(struct audio_port *port) const
{
port->role = mRole;
port->type = mType;
+ strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
unsigned int i;
for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) {
if (mSamplingRates[i] != 0) {
@@ -7441,17 +7483,15 @@
// --- DeviceDescriptor implementation
+String8 AudioPolicyManager::DeviceDescriptor::emptyNameStr = String8("");
AudioPolicyManager::DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE,
NULL),
- mDeviceType(type), mAddress(""), mId(0)
+ mDeviceType(type), mAddress("")
{
- if (mGains.size() > 0) {
- mGains[0]->getDefaultConfig(&mGain);
- }
}
bool AudioPolicyManager::DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
@@ -7466,6 +7506,15 @@
mChannelMask == other->mChannelMask);
}
+void AudioPolicyManager::DeviceDescriptor::loadGains(cnode *root)
+{
+ AudioPort::loadGains(root);
+ if (mGains.size() > 0) {
+ mGains[0]->getDefaultConfig(&mGain);
+ }
+}
+
+
void AudioPolicyManager::DeviceVector::refreshTypes()
{
mDeviceTypes = AUDIO_DEVICE_NONE;
@@ -7528,7 +7577,7 @@
uint32_t i = 31 - __builtin_clz(types);
uint32_t type = 1 << i;
types &= ~type;
- add(new DeviceDescriptor(String8(""), type | role_bit));
+ add(new DeviceDescriptor(String8("device_type"), type | role_bit));
}
}
@@ -7542,7 +7591,7 @@
ARRAY_SIZE(sDeviceNameToEnumTable),
devName);
if (type != AUDIO_DEVICE_NONE) {
- sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(""), type);
+ sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(name), type);
if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX ||
type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
dev->mAddress = String8("0");
@@ -7584,8 +7633,7 @@
{
sp<DeviceDescriptor> device;
for (size_t i = 0; i < size(); i++) {
- ALOGV("DeviceVector::getDeviceFromId(%d) itemAt(%zu)->mId %d", id, i, itemAt(i)->mId);
- if (itemAt(i)->mId == id) {
+ if (itemAt(i)->getHandle() == id) {
device = itemAt(i);
break;
}
@@ -7645,13 +7693,17 @@
}
AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-
dstConfig->id = mId;
dstConfig->role = audio_is_output_device(mDeviceType) ?
AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
dstConfig->ext.device.type = mDeviceType;
- dstConfig->ext.device.hw_module = mModule->mHandle;
+
+ //TODO Understand why this test is necessary. i.e. why at boot time does it crash
+ // without the test?
+ // This has been demonstrated to NOT be true (at start up)
+ // ALOG_ASSERT(mModule != NULL);
+ dstConfig->ext.device.hw_module = mModule != NULL ? mModule->mHandle : NULL;
strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
}
@@ -7890,7 +7942,7 @@
ARRAY_SIZE(sDeviceNameToEnumTable),
(char *)node->value);
if (device != AUDIO_DEVICE_NONE) {
- mDefaultOutputDevice = new DeviceDescriptor(String8(""), device);
+ mDefaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
} else {
ALOGW("loadGlobalConfig() default device not specified");
}
@@ -7941,8 +7993,8 @@
{
sp<HwModule> module;
sp<IOProfile> profile;
- sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(String8(""),
- AUDIO_DEVICE_IN_BUILTIN_MIC);
+ sp<DeviceDescriptor> defaultInputDevice =
+ new DeviceDescriptor(String8("builtin-mic"), AUDIO_DEVICE_IN_BUILTIN_MIC);
mAvailableOutputDevices.add(mDefaultOutputDevice);
mAvailableInputDevices.add(defaultInputDevice);
@@ -7975,6 +8027,9 @@
if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
return AUDIO_STREAM_BLUETOOTH_SCO;
}
+ if ((attr->flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
+ return AUDIO_STREAM_TTS;
+ }
// usage to stream type mapping
switch (attr->usage) {
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index 0fa182b..3e3c662 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -73,7 +73,8 @@
// AudioPolicyInterface
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address);
+ const char *device_address,
+ const char *device_name);
virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address);
virtual void setPhoneState(audio_mode_t state);
@@ -252,6 +253,11 @@
audio_port_role_t role, const sp<HwModule>& module);
virtual ~AudioPort() {}
+ audio_port_handle_t getHandle() { return mId; }
+
+ void attach(const sp<HwModule>& module);
+ bool isAttached() { return mId != 0; }
+
virtual void toAudioPort(struct audio_port *port) const;
void importAudioPort(const sp<AudioPort> port);
@@ -264,7 +270,7 @@
audio_gain_mode_t loadGainMode(char *name);
void loadGain(cnode *root, int index);
- void loadGains(cnode *root);
+ virtual void loadGains(cnode *root);
// searches for an exact match
status_t checkExactSamplingRate(uint32_t samplingRate) const;
@@ -301,6 +307,12 @@
sp<HwModule> mModule; // audio HW module exposing this I/O stream
uint32_t mFlags; // attribute flags (e.g primary output,
// direct output...).
+
+ protected:
+ //TODO - clarify the role of mId in this case, both an "attached" indicator
+ // and a unique ID for identifying a port to the (upcoming) selection API,
+ // and its relationship to the mId in AudioOutputDescriptor and AudioInputDescriptor.
+ audio_port_handle_t mId;
};
class AudioPortConfig: public virtual RefBase
@@ -344,17 +356,22 @@
virtual ~DeviceDescriptor() {}
bool equals(const sp<DeviceDescriptor>& other) const;
+
+ // AudioPortConfig
+ virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
- virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
+ // AudioPort
+ virtual void loadGains(cnode *root);
virtual void toAudioPort(struct audio_port *port) const;
status_t dump(int fd, int spaces, int index) const;
audio_devices_t mDeviceType;
String8 mAddress;
- audio_port_handle_t mId;
+
+ static String8 emptyNameStr;
};
class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
@@ -828,7 +845,7 @@
// to boost soft sounds, used to adjust volume curves accordingly
Vector < sp<HwModule> > mHwModules;
- volatile int32_t mNextUniqueId;
+ static volatile int32_t mNextUniqueId;
volatile int32_t mAudioPortGeneration;
DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
@@ -878,7 +895,7 @@
static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
int indexInUi);
static bool isVirtualInputDevice(audio_devices_t device);
- uint32_t nextUniqueId();
+ static uint32_t nextUniqueId();
uint32_t nextAudioPortGeneration();
private:
// updates device caching and output for streams that can influence the
@@ -924,7 +941,10 @@
// Called by setDeviceConnectionState().
status_t setDeviceConnectionStateInt(audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address);
+ const char *device_address,
+ const char *device_name);
+ sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t device,
+ const char *device_address);
};
};
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index b80380e..eb9116d 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -908,8 +908,10 @@
}
removedCommands.clear();
- // Disable wait for status if delay is not 0
- if (delayMs != 0) {
+ // Disable wait for status if delay is not 0.
+ // Except for create audio patch command because the returned patch handle
+ // is needed by audio policy manager
+ if (delayMs != 0 && command->mCommand != CREATE_AUDIO_PATCH) {
command->mWaitStatus = false;
}
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 80284a4..7c2b59d 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -61,7 +61,8 @@
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
- const char *device_address);
+ const char *device_address,
+ const char *device_name);
virtual audio_policy_dev_state_t getDeviceConnectionState(
audio_devices_t device,
const char *device_address);
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index e184d97..de9551d 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -25,6 +25,7 @@
CameraDeviceFactory.cpp \
common/Camera2ClientBase.cpp \
common/CameraDeviceBase.cpp \
+ common/CameraModule.cpp \
common/FrameProcessorBase.cpp \
api1/CameraClient.cpp \
api1/Camera2Client.cpp \
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 1232c32..485b979 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -113,14 +113,17 @@
BnCameraService::onFirstRef();
+ camera_module_t *rawModule;
if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
- (const hw_module_t **)&mModule) < 0) {
+ (const hw_module_t **)&rawModule) < 0) {
ALOGE("Could not load camera HAL module");
mNumberOfCameras = 0;
}
else {
- ALOGI("Loaded \"%s\" camera module", mModule->common.name);
- mNumberOfCameras = mModule->get_number_of_cameras();
+ mModule = new CameraModule(rawModule);
+ const hw_module_t *common = mModule->getRawModule();
+ ALOGI("Loaded \"%s\" camera module", common->name);
+ mNumberOfCameras = mModule->getNumberOfCameras();
if (mNumberOfCameras > MAX_CAMERAS) {
ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
mNumberOfCameras, MAX_CAMERAS);
@@ -130,14 +133,13 @@
setCameraFree(i);
}
- if (mModule->common.module_api_version >=
- CAMERA_MODULE_API_VERSION_2_1) {
- mModule->set_callbacks(this);
+ if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_1) {
+ mModule->setCallbacks(this);
}
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
- if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
+ if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
setUpVendorTags();
}
@@ -152,6 +154,9 @@
}
}
+ if (mModule) {
+ delete mModule;
+ }
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
gCameraService = NULL;
}
@@ -236,7 +241,7 @@
struct camera_info info;
status_t rc = filterGetInfoErrorCode(
- mModule->get_camera_info(cameraId, &info));
+ mModule->getCameraInfo(cameraId, &info));
cameraInfo->facing = info.facing;
cameraInfo->orientation = info.orientation;
return rc;
@@ -347,7 +352,7 @@
int facing;
status_t ret = OK;
- if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
+ if (mModule->getRawModule()->module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
getDeviceVersion(cameraId, &facing) <= CAMERA_DEVICE_API_VERSION_2_1 ) {
/**
* Backwards compatibility mode for old HALs:
@@ -368,7 +373,7 @@
* Normal HAL 2.1+ codepath.
*/
struct camera_info info;
- ret = filterGetInfoErrorCode(mModule->get_camera_info(cameraId, &info));
+ ret = filterGetInfoErrorCode(mModule->getCameraInfo(cameraId, &info));
*cameraInfo = info.static_camera_characteristics;
}
@@ -387,12 +392,12 @@
int CameraService::getDeviceVersion(int cameraId, int* facing) {
struct camera_info info;
- if (mModule->get_camera_info(cameraId, &info) != OK) {
+ if (mModule->getCameraInfo(cameraId, &info) != OK) {
return -1;
}
int deviceVersion;
- if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
+ if (mModule->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
deviceVersion = info.device_version;
} else {
deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
@@ -433,13 +438,13 @@
vendor_tag_ops_t vOps = vendor_tag_ops_t();
// Check if vendor operations have been implemented
- if (mModule->get_vendor_tag_ops == NULL) {
+ if (!mModule->isVendorTagDefined()) {
ALOGI("%s: No vendor tags defined for this device.", __FUNCTION__);
return false;
}
ATRACE_BEGIN("camera3->get_metadata_vendor_tag_ops");
- mModule->get_vendor_tag_ops(&vOps);
+ mModule->getVendorTagOps(&vOps);
ATRACE_END();
// Ensure all vendor operations are present
@@ -789,8 +794,9 @@
/*out*/
sp<ICamera>& device) {
+ int apiVersion = mModule->getRawModule()->module_api_version;
if (halVersion != CAMERA_HAL_API_VERSION_UNSPECIFIED &&
- mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_3) {
+ apiVersion < CAMERA_MODULE_API_VERSION_2_3) {
/*
* Either the HAL version is unspecified in which case this just creates
* a camera client selected by the latest device version, or
@@ -798,7 +804,7 @@
* the open_legacy call
*/
ALOGE("%s: camera HAL module version %x doesn't support connecting to legacy HAL devices!",
- __FUNCTION__, mModule->common.module_api_version);
+ __FUNCTION__, apiVersion);
return INVALID_OPERATION;
}
@@ -1633,14 +1639,11 @@
return NO_ERROR;
}
- result = String8::format("Camera module HAL API version: 0x%x\n",
- mModule->common.hal_api_version);
- result.appendFormat("Camera module API version: 0x%x\n",
- mModule->common.module_api_version);
- result.appendFormat("Camera module name: %s\n",
- mModule->common.name);
- result.appendFormat("Camera module author: %s\n",
- mModule->common.author);
+ const hw_module_t* common = mModule->getRawModule();
+ result = String8::format("Camera module HAL API version: 0x%x\n", common->hal_api_version);
+ result.appendFormat("Camera module API version: 0x%x\n", common->module_api_version);
+ result.appendFormat("Camera module name: %s\n", common->name);
+ result.appendFormat("Camera module author: %s\n", common->author);
result.appendFormat("Number of camera devices: %d\n\n", mNumberOfCameras);
sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();
@@ -1660,7 +1663,7 @@
result = String8::format("Camera %d static information:\n", i);
camera_info info;
- status_t rc = mModule->get_camera_info(i, &info);
+ status_t rc = mModule->getCameraInfo(i, &info);
if (rc != OK) {
result.appendFormat(" Error reading static information!\n");
write(fd, result.string(), result.size());
@@ -1669,8 +1672,7 @@
info.facing == CAMERA_FACING_BACK ? "BACK" : "FRONT");
result.appendFormat(" Orientation: %d\n", info.orientation);
int deviceVersion;
- if (mModule->common.module_api_version <
- CAMERA_MODULE_API_VERSION_2_0) {
+ if (common->module_api_version < CAMERA_MODULE_API_VERSION_2_0) {
deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
} else {
deviceVersion = info.device_version;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 126d8d9..7d0df3a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -37,6 +37,8 @@
#include <camera/ICameraServiceListener.h>
+#include "common/CameraModule.h"
+
/* This needs to be increased if we can have more cameras */
#define MAX_CAMERAS 2
@@ -153,7 +155,7 @@
class BasicClient : public virtual RefBase {
public:
- virtual status_t initialize(camera_module_t *module) = 0;
+ virtual status_t initialize(CameraModule *module) = 0;
virtual void disconnect();
// because we can't virtually inherit IInterface, which breaks
@@ -385,7 +387,7 @@
sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
int mSoundRef; // reference count (release all MediaPlayer when 0)
- camera_module_t *mModule;
+ CameraModule* mModule;
Vector<sp<ICameraServiceListener> >
mListenerList;
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 0ed5586..4ac5166 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -67,7 +67,7 @@
mLegacyMode = legacyMode;
}
-status_t Camera2Client::initialize(camera_module_t *module)
+status_t Camera2Client::initialize(CameraModule *module)
{
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index d68bb29..5a8241f 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -94,7 +94,7 @@
virtual ~Camera2Client();
- status_t initialize(camera_module_t *module);
+ status_t initialize(CameraModule *module);
virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index bbb2fe0..6bea3b6 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -59,7 +59,7 @@
LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
}
-status_t CameraClient::initialize(camera_module_t *module) {
+status_t CameraClient::initialize(CameraModule *module) {
int callingPid = getCallingPid();
status_t res;
@@ -75,7 +75,7 @@
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
mHardware = new CameraHardwareInterface(camera_device_name);
- res = mHardware->initialize(&module->common);
+ res = mHardware->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 63a9d0f..95616b2 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -68,7 +68,7 @@
bool legacyMode = false);
~CameraClient();
- status_t initialize(camera_module_t *module);
+ status_t initialize(CameraModule *module);
status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 6a1ee44..acc092c 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -71,7 +71,7 @@
ALOGI("CameraDeviceClient %d: Opened", cameraId);
}
-status_t CameraDeviceClient::initialize(camera_module_t *module)
+status_t CameraDeviceClient::initialize(CameraModule *module)
{
ATRACE_CALL();
status_t res;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 84e46b7..e687175 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -119,7 +119,7 @@
int servicePid);
virtual ~CameraDeviceClient();
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
index 59e5083..30a89c2 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
@@ -50,7 +50,7 @@
mExclusiveLock = false;
}
-status_t ProCamera2Client::initialize(camera_module_t *module)
+status_t ProCamera2Client::initialize(CameraModule *module)
{
ATRACE_CALL();
status_t res;
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.h b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
index 9d83122..7f5f6ac 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.h
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
@@ -85,7 +85,7 @@
int servicePid);
virtual ~ProCamera2Client();
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 453c8bd..0415d67 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -78,7 +78,7 @@
}
template <typename TClientBase>
-status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
+status_t Camera2ClientBase<TClientBase>::initialize(CameraModule *module) {
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
TClientBase::mCameraId);
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index e09c1b5..eb21d55 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -18,6 +18,7 @@
#define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
#include "common/CameraDeviceBase.h"
+#include "common/CameraModule.h"
#include "camera/CaptureResult.h"
namespace android {
@@ -55,7 +56,7 @@
int servicePid);
virtual ~Camera2ClientBase();
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t dump(int fd, const Vector<String16>& args);
/**
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index d26e20c..06615f6 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -29,6 +29,7 @@
#include "hardware/camera3.h"
#include "camera/CameraMetadata.h"
#include "camera/CaptureResult.h"
+#include "common/CameraModule.h"
namespace android {
@@ -45,7 +46,7 @@
*/
virtual int getId() const = 0;
- virtual status_t initialize(camera_module_t *module) = 0;
+ virtual status_t initialize(CameraModule *module) = 0;
virtual status_t disconnect() = 0;
virtual status_t dump(int fd, const Vector<String16> &args) = 0;
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
new file mode 100644
index 0000000..bbf47e8
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 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_TAG "CameraModule"
+//#define LOG_NDEBUG 0
+
+#include "CameraModule.h"
+
+namespace android {
+
+void CameraModule::deriveCameraCharacteristicsKeys(
+ uint32_t deviceVersion, CameraMetadata &chars) {
+ // HAL1 devices should not reach here
+ if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
+ ALOGV("%s: Cannot derive keys for HAL version < 2.0");
+ return;
+ }
+
+ // Keys added in HAL3.3
+ if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) {
+ Vector<uint8_t> controlModes;
+ uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
+ chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
+ data = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE;
+ chars.update(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &data, /*count*/1);
+ controlModes.push(ANDROID_CONTROL_MODE_OFF);
+ controlModes.push(ANDROID_CONTROL_MODE_AUTO);
+ camera_metadata_entry entry = chars.find(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
+ if (entry.count > 1 || entry.data.u8[0] != ANDROID_CONTROL_SCENE_MODE_DISABLED) {
+ controlModes.push(ANDROID_CONTROL_MODE_USE_SCENE_MODE);
+ }
+ chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
+ }
+ return;
+}
+
+CameraModule::CameraModule(camera_module_t *module) {
+ if (module == NULL) {
+ ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
+ assert(0);
+ }
+
+ mModule = module;
+ for (int i = 0; i < MAX_CAMERAS_PER_MODULE; i++) {
+ mCameraInfoCached[i] = false;
+ }
+}
+
+int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
+ Mutex::Autolock lock(mCameraInfoLock);
+ if (cameraId < 0 || cameraId >= MAX_CAMERAS_PER_MODULE) {
+ ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
+ return -EINVAL;
+ }
+
+ camera_info &wrappedInfo = mCameraInfo[cameraId];
+ if (!mCameraInfoCached[cameraId]) {
+ camera_info rawInfo;
+ int ret = mModule->get_camera_info(cameraId, &rawInfo);
+ if (ret != 0) {
+ return ret;
+ }
+ CameraMetadata &m = mCameraCharacteristics[cameraId];
+ m = rawInfo.static_camera_characteristics;
+ int deviceVersion;
+ int apiVersion = mModule->common.module_api_version;
+ if (apiVersion >= CAMERA_MODULE_API_VERSION_2_0) {
+ deviceVersion = rawInfo.device_version;
+ } else {
+ deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
+ }
+ deriveCameraCharacteristicsKeys(deviceVersion, m);
+ wrappedInfo = rawInfo;
+ wrappedInfo.static_camera_characteristics = m.getAndLock();
+ mCameraInfoCached[cameraId] = true;
+ }
+ *info = wrappedInfo;
+ return 0;
+}
+
+int CameraModule::open(const char* id, struct hw_device_t** device) {
+ return mModule->common.methods->open(&mModule->common, id, device);
+}
+
+int CameraModule::openLegacy(
+ const char* id, uint32_t halVersion, struct hw_device_t** device) {
+ return mModule->open_legacy(&mModule->common, id, halVersion, device);
+}
+
+const hw_module_t* CameraModule::getRawModule() {
+ return &mModule->common;
+}
+
+int CameraModule::getNumberOfCameras() {
+ return mModule->get_number_of_cameras();
+}
+
+int CameraModule::setCallbacks(const camera_module_callbacks_t *callbacks) {
+ return mModule->set_callbacks(callbacks);
+}
+
+bool CameraModule::isVendorTagDefined() {
+ return mModule->get_vendor_tag_ops != NULL;
+}
+
+void CameraModule::getVendorTagOps(vendor_tag_ops_t* ops) {
+ if (mModule->get_vendor_tag_ops) {
+ mModule->get_vendor_tag_ops(ops);
+ }
+}
+
+int CameraModule::setTorchMode(const char* camera_id, bool enable) {
+ return mModule->set_torch_mode(camera_id, enable);
+}
+
+}; // namespace android
+
diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h
new file mode 100644
index 0000000..31b9ae2
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraModule.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
+#define ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
+
+#include <hardware/camera.h>
+#include <camera/CameraMetadata.h>
+#include <utils/Mutex.h>
+
+/* This needs to be increased if we can have more cameras */
+#define MAX_CAMERAS_PER_MODULE 2
+
+
+namespace android {
+/**
+ * A wrapper class for HAL camera module.
+ *
+ * This class wraps camera_module_t returned from HAL to provide a wrapped
+ * get_camera_info implementation which CameraService generates some
+ * camera characteristics keys defined in newer HAL version on an older HAL.
+ */
+class CameraModule {
+public:
+ CameraModule(camera_module_t *module);
+
+ const hw_module_t* getRawModule();
+ int getCameraInfo(int cameraId, struct camera_info *info);
+ int getNumberOfCameras(void);
+ int open(const char* id, struct hw_device_t** device);
+ int openLegacy(const char* id, uint32_t halVersion, struct hw_device_t** device);
+ int setCallbacks(const camera_module_callbacks_t *callbacks);
+ bool isVendorTagDefined();
+ void getVendorTagOps(vendor_tag_ops_t* ops);
+ int setTorchMode(const char* camera_id, bool enable);
+
+private:
+ // Derive camera characteristics keys defined after HAL device version
+ static void deriveCameraCharacteristicsKeys(uint32_t deviceVersion, CameraMetadata &chars);
+ camera_module_t *mModule;
+ CameraMetadata mCameraCharacteristics[MAX_CAMERAS_PER_MODULE];
+ camera_info mCameraInfo[MAX_CAMERAS_PER_MODULE];
+ bool mCameraInfoCached[MAX_CAMERAS_PER_MODULE];
+ Mutex mCameraInfoLock;
+};
+
+} // namespace android
+
+#endif
+
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 1935c2b..9e1cdc9 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -89,24 +89,23 @@
}
}
- status_t initialize(hw_module_t *module)
+ status_t initialize(CameraModule *module)
{
ALOGI("Opening camera %s", mName.string());
- camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module);
camera_info info;
- status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
+ status_t res = module->getCameraInfo(atoi(mName.string()), &info);
if (res != OK) return res;
int rc = OK;
- if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
+ if (module->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
// Open higher version camera device as HAL1.0 device.
- rc = cameraModule->open_legacy(module, mName.string(),
- CAMERA_DEVICE_API_VERSION_1_0,
- (hw_device_t **)&mDevice);
+ rc = module->openLegacy(mName.string(),
+ CAMERA_DEVICE_API_VERSION_1_0,
+ (hw_device_t **)&mDevice);
} else {
- rc = CameraService::filterOpenErrorCode(module->methods->open(
- module, mName.string(), (hw_device_t **)&mDevice));
+ rc = CameraService::filterOpenErrorCode(module->open(
+ mName.string(), (hw_device_t **)&mDevice));
}
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index d1158d6..be66c4d 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -53,7 +53,7 @@
return mId;
}
-status_t Camera2Device::initialize(camera_module_t *module)
+status_t Camera2Device::initialize(CameraModule *module)
{
ATRACE_CALL();
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
@@ -68,8 +68,8 @@
camera2_device_t *device;
- res = CameraService::filterOpenErrorCode(module->common.methods->open(
- &module->common, name, reinterpret_cast<hw_device_t**>(&device)));
+ res = CameraService::filterOpenErrorCode(module->open(
+ name, reinterpret_cast<hw_device_t**>(&device)));
if (res != OK) {
ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
@@ -87,7 +87,7 @@
}
camera_info info;
- res = module->get_camera_info(mId, &info);
+ res = module->getCameraInfo(mId, &info);
if (res != OK ) return res;
if (info.device_version != device->common.version) {
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 4def8ae..1cc5482 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -43,7 +43,7 @@
* CameraDevice interface
*/
virtual int getId() const;
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t disconnect();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual const CameraMetadata& info() const;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index bba3905..9a4e5ac 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -86,7 +86,7 @@
* CameraDeviceBase interface
*/
-status_t Camera3Device::initialize(camera_module_t *module)
+status_t Camera3Device::initialize(CameraModule *module)
{
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
@@ -106,9 +106,8 @@
camera3_device_t *device;
ATRACE_BEGIN("camera3->open");
- res = CameraService::filterOpenErrorCode(module->common.methods->open(
- &module->common, deviceName.string(),
- reinterpret_cast<hw_device_t**>(&device)));
+ res = CameraService::filterOpenErrorCode(module->open(
+ deviceName.string(), reinterpret_cast<hw_device_t**>(&device)));
ATRACE_END();
if (res != OK) {
@@ -127,7 +126,7 @@
}
camera_info info;
- res = CameraService::filterGetInfoErrorCode(module->get_camera_info(
+ res = CameraService::filterGetInfoErrorCode(module->getCameraInfo(
mId, &info));
if (res != OK) return res;
@@ -361,16 +360,15 @@
return BAD_VALUE;
}
maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
+ assert(kMinJpegBufferSize < maxJpegBufferSize);
// Calculate final jpeg buffer size for the given resolution.
float scaleFactor = ((float) (width * height)) /
(maxJpegResolution.width * maxJpegResolution.height);
- ssize_t jpegBufferSize = scaleFactor * maxJpegBufferSize;
- // Bound the buffer size to [MIN_JPEG_BUFFER_SIZE, maxJpegBufferSize].
+ ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
+ kMinJpegBufferSize;
if (jpegBufferSize > maxJpegBufferSize) {
jpegBufferSize = maxJpegBufferSize;
- } else if (jpegBufferSize < kMinJpegBufferSize) {
- jpegBufferSize = kMinJpegBufferSize;
}
return jpegBufferSize;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index ec8dc10..de10cfe 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -73,7 +73,7 @@
virtual int getId() const;
// Transitions to idle state on success.
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t disconnect();
virtual status_t dump(int fd, const Vector<String16> &args);
virtual const CameraMetadata& info() const;