Merge "mediaplayer: Add MediaClock component and use it in NuPlayerRenderer."
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/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/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 8509d55..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);
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/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/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/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 8642ad5..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);
@@ -1419,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;
@@ -2062,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;
@@ -2082,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;
@@ -2129,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));
@@ -2192,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)) {
@@ -2218,14 +2267,14 @@
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) {
@@ -3239,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;
@@ -3248,6 +3297,7 @@
describeParams.nFrameHeight = 128;
describeParams.nStride = 128;
describeParams.nSliceHeight = 128;
+ describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
CHECK(flexibleEquivalent != NULL);
@@ -3305,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/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/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/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index d3f25a1..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;
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 0630a5b..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
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/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/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index a58d60c..7f27659 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -242,7 +242,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;
@@ -274,7 +274,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) {
@@ -375,6 +382,12 @@
} 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
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 53e6fa9..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;
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;