Merge "Update the test output path." into jb-mr2-dev
diff --git a/camera/Android.mk b/camera/Android.mk
index e33fb50..fa518ff 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -22,6 +22,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
+ liblog \
libbinder \
libhardware \
libui \
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index d583e65..3844487 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -9,7 +9,7 @@
LOCAL_SHARED_LIBRARIES := \
libstagefright libmedia libutils libbinder libstagefright_foundation \
- libjpeg libgui libcutils
+ libjpeg libgui libcutils liblog
LOCAL_C_INCLUDES:= \
frameworks/av/media/libstagefright \
@@ -187,4 +187,3 @@
LOCAL_MODULE:= muxer
include $(BUILD_EXECUTABLE)
-
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
index 96205a1..dc973da 100644
--- a/drm/drmserver/Android.mk
+++ b/drm/drmserver/Android.mk
@@ -24,6 +24,7 @@
LOCAL_SHARED_LIBRARIES := \
libmedia \
libutils \
+ liblog \
libbinder \
libdl
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index 9e07fe3..49c4f9b 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -25,6 +25,7 @@
LOCAL_SHARED_LIBRARIES := \
libutils \
+ liblog \
libbinder \
libdl
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
index 205b9a5..e251f82 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -36,6 +36,7 @@
libicui18n \
libicuuc \
libutils \
+ liblog \
libdl \
libcrypto \
libssl \
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
index d170d49..cb3a2e2 100644
--- a/drm/libdrmframework/plugins/passthru/Android.mk
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -25,6 +25,7 @@
LOCAL_SHARED_LIBRARIES := \
libutils \
+ liblog \
libdl
diff --git a/drm/mediadrm/plugins/mock/Android.mk b/drm/mediadrm/plugins/mock/Android.mk
index a056cd8..ada23a2 100644
--- a/drm/mediadrm/plugins/mock/Android.mk
+++ b/drm/mediadrm/plugins/mock/Android.mk
@@ -24,7 +24,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)/mediadrm
LOCAL_SHARED_LIBRARIES := \
- libutils
+ libutils liblog
LOCAL_C_INCLUDES += \
$(TOP)/frameworks/av/include \
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 96baf34..5cfe5bc 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -46,6 +46,7 @@
kWhatInputSurfaceCreated = 'isfc',
kWhatSignaledInputEOS = 'seos',
kWhatBuffersAllocated = 'allc',
+ kWhatOMXDied = 'OMXd',
};
ACodec();
@@ -97,6 +98,7 @@
struct ExecutingToIdleState;
struct IdleToLoadedState;
struct FlushingState;
+ struct DeathNotifier;
enum {
kWhatSetup = 'setu',
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index b0c1b34..742bc0e 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -54,6 +54,7 @@
// Convenience methods:
bool getUInt16(off64_t offset, uint16_t *x);
+ bool getUInt24(off64_t offset, uint32_t *x); // 3 byte int, returned as a 32-bit int
bool getUInt32(off64_t offset, uint32_t *x);
bool getUInt64(off64_t offset, uint64_t *x);
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index be08c19..9ab3edc 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -157,6 +157,10 @@
kKeyCryptoKey = 'cryK', // uint8_t[16]
kKeyCryptoIV = 'cryI', // uint8_t[16]
kKeyCryptoMode = 'cryM', // int32_t
+
+ kKeyCryptoDefaultIVSize = 'cryS', // int32_t
+
+ kKeyPssh = 'pssh', // raw data
};
enum {
diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h
index 0833110..5ae6f6b 100644
--- a/include/media/stagefright/NuMediaExtractor.h
+++ b/include/media/stagefright/NuMediaExtractor.h
@@ -55,6 +55,8 @@
size_t countTracks() const;
status_t getTrackFormat(size_t index, sp<AMessage> *format) const;
+ status_t getFileFormat(sp<AMessage> *format) const;
+
status_t selectTrack(size_t index);
status_t unselectTrack(size_t index);
diff --git a/libvideoeditor/lvpp/Android.mk b/libvideoeditor/lvpp/Android.mk
index 778c5ac..2286827 100755
--- a/libvideoeditor/lvpp/Android.mk
+++ b/libvideoeditor/lvpp/Android.mk
@@ -50,6 +50,7 @@
libaudioutils \
libbinder \
libcutils \
+ liblog \
libEGL \
libGLESv2 \
libgui \
diff --git a/libvideoeditor/osal/src/Android.mk b/libvideoeditor/osal/src/Android.mk
index b73b9ae..4f38b0c 100755
--- a/libvideoeditor/osal/src/Android.mk
+++ b/libvideoeditor/osal/src/Android.mk
@@ -41,7 +41,7 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libcutils libutils
+LOCAL_SHARED_LIBRARIES := libcutils libutils liblog
LOCAL_C_INCLUDES += \
$(TOP)/frameworks/av/libvideoeditor/osal/inc \
@@ -64,4 +64,3 @@
-DUSE_STAGEFRIGHT_3GPP_READER
include $(BUILD_SHARED_LIBRARY)
-
diff --git a/libvideoeditor/vss/src/Android.mk b/libvideoeditor/vss/src/Android.mk
index cda7a83..0caa15b 100755
--- a/libvideoeditor/vss/src/Android.mk
+++ b/libvideoeditor/vss/src/Android.mk
@@ -57,6 +57,7 @@
libaudioutils \
libbinder \
libcutils \
+ liblog \
libmedia \
libstagefright \
libstagefright_foundation \
@@ -96,4 +97,3 @@
-DDECODE_GIF_ON_SAVING
include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/common_time/Android.mk b/media/common_time/Android.mk
index 526f17b..632acbc 100644
--- a/media/common_time/Android.mk
+++ b/media/common_time/Android.mk
@@ -16,6 +16,7 @@
utils.cpp
LOCAL_SHARED_LIBRARIES := libbinder \
libhardware \
- libutils
+ libutils \
+ liblog
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk
index 3052ad9..5d0a87c 100644
--- a/media/libeffects/downmix/Android.mk
+++ b/media/libeffects/downmix/Android.mk
@@ -7,7 +7,7 @@
EffectDownmix.c
LOCAL_SHARED_LIBRARIES := \
- libcutils
+ libcutils liblog
LOCAL_MODULE:= libdownmix
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
index 6e69151..60a6ce5 100644
--- a/media/libeffects/factory/Android.mk
+++ b/media/libeffects/factory/Android.mk
@@ -7,7 +7,7 @@
EffectsFactory.c
LOCAL_SHARED_LIBRARIES := \
- libcutils
+ libcutils liblog
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE:= libeffects
diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk
index dfa1711..c344352 100644
--- a/media/libeffects/preprocessing/Android.mk
+++ b/media/libeffects/preprocessing/Android.mk
@@ -21,7 +21,8 @@
LOCAL_SHARED_LIBRARIES := \
libwebrtc_audio_preprocessing \
libspeexresampler \
- libutils
+ libutils \
+ liblog
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index 49cf4fa..e196eb2 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -10,6 +10,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
+ liblog \
libdl
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index fbe71ad..2c0c3a5 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -63,7 +63,7 @@
LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"'
LOCAL_SHARED_LIBRARIES := \
- libui libcutils libutils libbinder libsonivox libicuuc libexpat \
+ libui liblog libcutils libutils libbinder libsonivox libicuuc libexpat \
libcamera_client libstagefright_foundation \
libgui libdl libaudioutils
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 2a6f3c7..d87bc7f 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -27,6 +27,7 @@
libbinder \
libcamera_client \
libcutils \
+ liblog \
libdl \
libgui \
libmedia \
diff --git a/media/libnbaio/Android.mk b/media/libnbaio/Android.mk
index d372d20..5d00d15 100644
--- a/media/libnbaio/Android.mk
+++ b/media/libnbaio/Android.mk
@@ -30,6 +30,7 @@
libbinder \
libcommon_time_client \
libcutils \
- libutils
+ libutils \
+ liblog
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ff72b71..ee49033 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -166,6 +166,24 @@
////////////////////////////////////////////////////////////////////////////////
+struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
+ DeathNotifier(const sp<AMessage> ¬ify)
+ : mNotify(notify) {
+ }
+
+ virtual void binderDied(const wp<IBinder> &) {
+ mNotify->post();
+ }
+
+protected:
+ virtual ~DeathNotifier() {}
+
+private:
+ sp<AMessage> mNotify;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
+};
+
struct ACodec::UninitializedState : public ACodec::BaseState {
UninitializedState(ACodec *codec);
@@ -177,6 +195,8 @@
void onSetup(const sp<AMessage> &msg);
bool onAllocateComponent(const sp<AMessage> &msg);
+ sp<DeathNotifier> mDeathNotifier;
+
DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
};
@@ -1432,14 +1452,6 @@
CHECK_EQ(err, (status_t)OK);
CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
- CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
- || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
- || format.eColorFormat == OMX_COLOR_FormatCbYCrY
- || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
- || format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled);
-
return mOMX->setParameter(
mNode, OMX_IndexParamVideoPortFormat,
&format, sizeof(format));
@@ -2487,6 +2499,13 @@
return true;
}
+ case ACodec::kWhatOMXDied:
+ {
+ ALOGE("OMX/mediaserver died, signalling error!");
+ mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
+ break;
+ }
+
default:
return false;
}
@@ -3035,6 +3054,18 @@
void ACodec::UninitializedState::stateEntered() {
ALOGV("Now uninitialized");
+
+ if (mDeathNotifier != NULL) {
+ mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
+ mDeathNotifier.clear();
+ }
+
+ mCodec->mNativeWindow.clear();
+ mCodec->mNode = NULL;
+ mCodec->mOMX.clear();
+ mCodec->mQuirks = 0;
+ mCodec->mFlags = 0;
+ mCodec->mComponentName.clear();
}
bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
@@ -3106,6 +3137,15 @@
sp<IOMX> omx = client.interface();
+ sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
+
+ mDeathNotifier = new DeathNotifier(notify);
+ if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
+ // This was a local binder, if it dies so do we, we won't care
+ // about any notifications in the afterlife.
+ mDeathNotifier.clear();
+ }
+
Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
AString mime;
@@ -3170,7 +3210,7 @@
return false;
}
- sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
+ notify = new AMessage(kWhatOMXMessage, mCodec->id());
observer->setNotificationMessage(notify);
mCodec->mComponentName = componentName;
@@ -3224,13 +3264,6 @@
if (!keepComponentAllocated) {
CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
- mCodec->mNativeWindow.clear();
- mCodec->mNode = NULL;
- mCodec->mOMX.clear();
- mCodec->mQuirks = 0;
- mCodec->mFlags = 0;
- mCodec->mComponentName.clear();
-
mCodec->changeState(mCodec->mUninitializedState);
}
@@ -3626,7 +3659,6 @@
(status_t)OK);
mCodec->changeState(mCodec->mFlushingState);
-
handled = true;
break;
}
@@ -4141,6 +4173,10 @@
mCodec->mInputEOSResult = OK;
+ if (mCodec->mSkipCutBuffer != NULL) {
+ mCodec->mSkipCutBuffer->clear();
+ }
+
mCodec->changeState(mCodec->mExecutingState);
}
}
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 19b38ee..fc6fd9c 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -58,6 +58,19 @@
return true;
}
+bool DataSource::getUInt24(off64_t offset, uint32_t *x) {
+ *x = 0;
+
+ uint8_t byte[3];
+ if (readAt(offset, byte, 3) != 3) {
+ return false;
+ }
+
+ *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
+
+ return true;
+}
+
bool DataSource::getUInt32(off64_t offset, uint32_t *x) {
*x = 0;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 56fad60..3503aaf 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -78,6 +78,19 @@
int32_t mLastParsedTrackId;
int32_t mTrackId;
+ int32_t mCryptoMode; // passed in from extractor
+ int32_t mDefaultIVSize; // passed in from extractor
+ uint8_t mCryptoKey[16]; // passed in from extractor
+ uint32_t mCurrentAuxInfoType;
+ uint32_t mCurrentAuxInfoTypeParameter;
+ uint32_t mCurrentDefaultSampleInfoSize;
+ uint32_t mCurrentSampleInfoCount;
+ uint32_t mCurrentSampleInfoAllocSize;
+ uint8_t* mCurrentSampleInfoSizes;
+ uint32_t mCurrentSampleInfoOffsetCount;
+ uint32_t mCurrentSampleInfoOffsetsAllocSize;
+ uint64_t* mCurrentSampleInfoOffsets;
+
bool mIsAVC;
size_t mNALLengthSize;
@@ -95,6 +108,8 @@
status_t parseChunk(off64_t *offset);
status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
status_t parseTrackFragmentRun(off64_t offset, off64_t size);
+ status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
+ status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
struct TrackFragmentHeaderInfo {
enum Flags {
@@ -122,6 +137,9 @@
off64_t offset;
size_t size;
uint32_t duration;
+ uint8_t iv[16];
+ Vector<size_t> clearsizes;
+ Vector<size_t> encryptedsizes;
};
Vector<Sample> mCurrentSamples;
@@ -333,6 +351,10 @@
sinf = next;
}
mFirstSINF = NULL;
+
+ for (size_t i = 0; i < mPssh.size(); i++) {
+ delete [] mPssh[i].data;
+ }
}
uint32_t MPEG4Extractor::flags() const {
@@ -353,6 +375,7 @@
size_t MPEG4Extractor::countTracks() {
status_t err;
if ((err = readMetaData()) != OK) {
+ ALOGV("MPEG4Extractor::countTracks: no tracks");
return 0;
}
@@ -363,6 +386,7 @@
track = track->next;
}
+ ALOGV("MPEG4Extractor::countTracks: %d tracks", n);
return n;
}
@@ -461,6 +485,23 @@
}
CHECK_NE(err, (status_t)NO_INIT);
+
+ // copy pssh data into file metadata
+ int psshsize = 0;
+ for (size_t i = 0; i < mPssh.size(); i++) {
+ psshsize += 20 + mPssh[i].datalen;
+ }
+ if (psshsize) {
+ char *buf = (char*)malloc(psshsize);
+ char *ptr = buf;
+ for (size_t i = 0; i < mPssh.size(); i++) {
+ memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
+ memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
+ ptr += (20 + mPssh[i].datalen);
+ }
+ mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
+ free(buf);
+ }
return mInitCheck;
}
@@ -759,6 +800,8 @@
case FOURCC('m', 'f', 'r', 'a'):
case FOURCC('u', 'd', 't', 'a'):
case FOURCC('i', 'l', 's', 't'):
+ case FOURCC('s', 'i', 'n', 'f'):
+ case FOURCC('s', 'c', 'h', 'i'):
{
if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
@@ -846,6 +889,69 @@
break;
}
+ case FOURCC('f', 'r', 'm', 'a'):
+ {
+ int32_t original_fourcc;
+ if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
+ return ERROR_IO;
+ }
+ original_fourcc = ntohl(original_fourcc);
+ ALOGV("read original format: %d", original_fourcc);
+ mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('t', 'e', 'n', 'c'):
+ {
+ if (chunk_size < 32) {
+ return ERROR_MALFORMED;
+ }
+
+ // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
+ // default IV size, 16 bytes default KeyID
+ // (ISO 23001-7)
+ char buf[4];
+ memset(buf, 0, 4);
+ if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
+ return ERROR_IO;
+ }
+ uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
+ if (defaultAlgorithmId > 1) {
+ // only 0 (clear) and 1 (AES-128) are valid
+ return ERROR_MALFORMED;
+ }
+
+ memset(buf, 0, 4);
+ if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
+ return ERROR_IO;
+ }
+ uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
+
+ if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
+ (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
+ // only unencrypted data must have 0 IV size
+ return ERROR_MALFORMED;
+ } else if (defaultIVSize != 0 &&
+ defaultIVSize != 8 &&
+ defaultIVSize != 16) {
+ // only supported sizes are 0, 8 and 16
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t defaultKeyId[16];
+
+ if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
+ return ERROR_IO;
+ }
+
+ mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
+ mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
+ mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
+ *offset += chunk_size;
+ break;
+ }
+
case FOURCC('t', 'k', 'h', 'd'):
{
status_t err;
@@ -857,6 +963,37 @@
break;
}
+ case FOURCC('p', 's', 's', 'h'):
+ {
+ PsshInfo pssh;
+
+ if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
+ return ERROR_IO;
+ }
+
+ uint32_t psshdatalen = 0;
+ if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
+ return ERROR_IO;
+ }
+ pssh.datalen = ntohl(psshdatalen);
+ ALOGV("pssh data size: %d", pssh.datalen);
+ if (pssh.datalen + 20 > chunk_size) {
+ // pssh data length exceeds size of containing box
+ return ERROR_MALFORMED;
+ }
+
+ pssh.data = new uint8_t[pssh.datalen];
+ ALOGV("allocated pssh @ %p", pssh.data);
+ ssize_t requested = (ssize_t) pssh.datalen;
+ if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
+ return ERROR_IO;
+ }
+ mPssh.push_back(pssh);
+
+ *offset += chunk_size;
+ break;
+ }
+
case FOURCC('m', 'd', 'h', 'd'):
{
if (chunk_data_size < 4) {
@@ -970,16 +1107,17 @@
// For 3GPP timed text, there could be multiple tx3g boxes contain
// multiple text display formats. These formats will be used to
// display the timed text.
+ // For encrypted files, there may also be more than one entry.
const char *mime;
CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
- if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
+ strcasecmp(mime, "application/octet-stream")) {
// For now we only support a single type of media per track.
mLastTrack->skipTrack = true;
*offset += chunk_size;
break;
}
}
-
off64_t stop_offset = *offset + chunk_size;
*offset = data_offset + 8;
for (uint32_t i = 0; i < entry_count; ++i) {
@@ -1053,6 +1191,7 @@
}
case FOURCC('m', 'p', '4', 'v'):
+ case FOURCC('e', 'n', 'c', 'v'):
case FOURCC('s', '2', '6', '3'):
case FOURCC('H', '2', '6', '3'):
case FOURCC('h', '2', '6', '3'):
@@ -1075,7 +1214,7 @@
uint16_t width = U16_AT(&buffer[6 + 18]);
uint16_t height = U16_AT(&buffer[6 + 20]);
- // The video sample is not stand-compliant if it has invalid dimension.
+ // The video sample is not standard-compliant if it has invalid dimension.
// Use some default width and height value, and
// let the decoder figure out the actual width and height (and thus
// be prepared for INFO_FOMRAT_CHANGED event).
@@ -1085,7 +1224,10 @@
// printf("*** coding='%s' width=%d height=%d\n",
// chunk, width, height);
- mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+ if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
+ // if the chunk type is encv, we'll get the type from the sinf/frma box later
+ mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+ }
mLastTrack->meta->setInt32(kKeyWidth, width);
mLastTrack->meta->setInt32(kKeyHeight, height);
@@ -1442,6 +1584,7 @@
case FOURCC('m', 'd', 'a', 't'):
{
+ ALOGV("mdat chunk, drm: %d", mIsDrm);
if (!mIsDrm) {
*offset += chunk_size;
break;
@@ -1968,6 +2111,8 @@
return NULL;
}
+ ALOGV("getTrack called, pssh: %d", mPssh.size());
+
return new MPEG4Source(
track->meta, mDataSource, track->timescale, track->sampleTable,
mSidxEntries, mMoofOffset);
@@ -2139,6 +2284,10 @@
mFirstMoofOffset(firstMoofOffset),
mCurrentMoofOffset(firstMoofOffset),
mCurrentTime(0),
+ mCurrentSampleInfoAllocSize(0),
+ mCurrentSampleInfoSizes(NULL),
+ mCurrentSampleInfoOffsetsAllocSize(0),
+ mCurrentSampleInfoOffsets(NULL),
mIsAVC(false),
mNALLengthSize(0),
mStarted(false),
@@ -2146,6 +2295,18 @@
mBuffer(NULL),
mWantsNALFragments(false),
mSrcBuffer(NULL) {
+
+ mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
+ mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
+ uint32_t keytype;
+ const void *key;
+ size_t keysize;
+ if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
+ CHECK(keysize <= 16);
+ memset(mCryptoKey, 0, 16);
+ memcpy(mCryptoKey, key, keysize);
+ }
+
const char *mime;
bool success = mFormat->findCString(kKeyMIMEType, &mime);
CHECK(success);
@@ -2179,6 +2340,8 @@
if (mStarted) {
stop();
}
+ free(mCurrentSampleInfoSizes);
+ free(mCurrentSampleInfoOffsets);
}
status_t MPEG4Source::start(MetaData *params) {
@@ -2274,7 +2437,7 @@
}
}
if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
- // *offset points to then mdat box following this moof
+ // *offset points to the mdat box following this moof
parseChunk(offset); // doesn't actually parse it, just updates offset
mNextMoofOffset = *offset;
}
@@ -2302,6 +2465,31 @@
break;
}
+ case FOURCC('s', 'a', 'i', 'z'): {
+ status_t err;
+ if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
+ return err;
+ }
+ *offset += chunk_size;
+ break;
+ }
+ case FOURCC('s', 'a', 'i', 'o'): {
+ status_t err;
+ if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
+ return err;
+ }
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('m', 'd', 'a', 't'): {
+ // parse DRM info if present
+ ALOGV("MPEG4Source::parseChunk mdat");
+ // if saiz/saoi was previously observed, do something with the sampleinfos
+ *offset += chunk_size;
+ break;
+ }
+
default: {
*offset += chunk_size;
break;
@@ -2310,6 +2498,152 @@
return OK;
}
+status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) {
+ ALOGV("parseSampleAuxiliaryInformationSizes");
+ // 14496-12 8.7.12
+ uint8_t version;
+ if (mDataSource->readAt(
+ offset, &version, sizeof(version))
+ < (ssize_t)sizeof(version)) {
+ return ERROR_IO;
+ }
+
+ if (version != 0) {
+ return ERROR_UNSUPPORTED;
+ }
+ offset++;
+
+ uint32_t flags;
+ if (!mDataSource->getUInt24(offset, &flags)) {
+ return ERROR_IO;
+ }
+ offset += 3;
+
+ if (flags & 1) {
+ uint32_t tmp;
+ if (!mDataSource->getUInt32(offset, &tmp)) {
+ return ERROR_MALFORMED;
+ }
+ mCurrentAuxInfoType = tmp;
+ offset += 4;
+ if (!mDataSource->getUInt32(offset, &tmp)) {
+ return ERROR_MALFORMED;
+ }
+ mCurrentAuxInfoTypeParameter = tmp;
+ offset += 4;
+ }
+
+ uint8_t defsize;
+ if (mDataSource->readAt(offset, &defsize, 1) != 1) {
+ return ERROR_MALFORMED;
+ }
+ mCurrentDefaultSampleInfoSize = defsize;
+ offset++;
+
+ uint32_t smplcnt;
+ if (!mDataSource->getUInt32(offset, &smplcnt)) {
+ return ERROR_MALFORMED;
+ }
+ offset += 4;
+
+ if (smplcnt > mCurrentSampleInfoAllocSize) {
+ mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
+ mCurrentSampleInfoAllocSize = smplcnt;
+ }
+ mCurrentSampleInfoCount = smplcnt;
+
+ mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
+ return OK;
+}
+
+status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) {
+ ALOGV("parseSampleAuxiliaryInformationOffsets");
+ // 14496-12 8.7.13
+ uint8_t version;
+ if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
+ return ERROR_IO;
+ }
+ offset++;
+
+ uint32_t flags;
+ if (!mDataSource->getUInt24(offset, &flags)) {
+ return ERROR_IO;
+ }
+ offset += 3;
+
+ uint32_t entrycount;
+ if (!mDataSource->getUInt32(offset, &entrycount)) {
+ return ERROR_IO;
+ }
+ offset += 4;
+
+ if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
+ mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
+ mCurrentSampleInfoOffsetsAllocSize = entrycount;
+ }
+ mCurrentSampleInfoOffsetCount = entrycount;
+
+ for (size_t i = 0; i < entrycount; i++) {
+ if (version == 0) {
+ uint32_t tmp;
+ if (!mDataSource->getUInt32(offset, &tmp)) {
+ return ERROR_IO;
+ }
+ mCurrentSampleInfoOffsets[i] = tmp;
+ offset += 4;
+ } else {
+ uint64_t tmp;
+ if (!mDataSource->getUInt64(offset, &tmp)) {
+ return ERROR_IO;
+ }
+ mCurrentSampleInfoOffsets[i] = tmp;
+ offset += 8;
+ }
+ }
+
+ // parse clear/encrypted data
+
+ off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
+
+ drmoffset += mCurrentMoofOffset;
+ int ivlength;
+ CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
+ int foo = 1;
+ for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
+ Sample *smpl = &mCurrentSamples.editItemAt(i);
+
+ memset(smpl->iv, 0, 16);
+ if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
+ return ERROR_IO;
+ }
+
+ drmoffset += ivlength;
+
+ uint16_t numsubsamples;
+ if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
+ return ERROR_IO;
+ }
+ drmoffset += 2;
+ for (size_t j = 0; j < numsubsamples; j++) {
+ uint16_t numclear;
+ uint32_t numencrypted;
+ if (!mDataSource->getUInt16(drmoffset, &numclear)) {
+ return ERROR_IO;
+ }
+ drmoffset += 2;
+ if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
+ return ERROR_IO;
+ }
+ drmoffset += 4;
+ smpl->clearsizes.add(numclear);
+ smpl->encryptedsizes.add(numencrypted);
+ }
+ }
+
+
+ return OK;
+}
+
status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
if (size < 8) {
@@ -2317,7 +2651,7 @@
}
uint32_t flags;
- if (!mDataSource->getUInt32(offset, &flags)) {
+ if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
return ERROR_MALFORMED;
}
@@ -2550,8 +2884,8 @@
offset += 4;
}
- ALOGV("adding sample at offset 0x%08llx, size %u, duration %u, "
- " flags 0x%08x",
+ ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, "
+ " flags 0x%08x", i + 1,
dataOffset, sampleSize, sampleDuration,
(flags & kFirstSampleFlagsPresent) && i == 0
? firstSampleFlags : sampleFlags);
@@ -3111,6 +3445,20 @@
mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
}
+ const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
+ if (smpl->encryptedsizes.size()) {
+ // store clear/encrypted lengths in metadata
+ sp<MetaData> bufmeta = mBuffer->meta_data();
+ bufmeta->setData(kKeyPlainSizes, 0,
+ smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
+ bufmeta->setData(kKeyEncryptedSizes, 0,
+ smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
+ bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
+ bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
+ bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
+ bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
+ }
+
++mCurrentSampleIndex;
*out = mBuffer;
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 404fa94..7bc7da2 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -228,6 +228,34 @@
return convertMetaDataToMessage(meta, format);
}
+status_t NuMediaExtractor::getFileFormat(sp<AMessage> *format) const {
+ Mutex::Autolock autoLock(mLock);
+
+ *format = NULL;
+
+ if (mImpl == NULL) {
+ return -EINVAL;
+ }
+
+ sp<MetaData> meta = mImpl->getMetaData();
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+ *format = new AMessage();
+ (*format)->setString("mime", mime);
+
+ uint32_t type;
+ const void *pssh;
+ size_t psshsize;
+ if (meta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
+ sp<ABuffer> buf = new ABuffer(psshsize);
+ memcpy(buf->data(), pssh, psshsize);
+ (*format)->setBuffer("pssh", buf);
+ }
+
+ return OK;
+}
+
status_t NuMediaExtractor::selectTrack(size_t index) {
Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index ff72e0e..1822f07 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -32,7 +32,7 @@
MuxOMX(const sp<IOMX> &remoteOMX);
virtual ~MuxOMX();
- virtual IBinder *onAsBinder() { return NULL; }
+ virtual IBinder *onAsBinder() { return mRemoteOMX->asBinder().get(); }
virtual bool livesLocally(node_id node, pid_t pid);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 22aefcc..6c0779d 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1213,13 +1213,6 @@
CHECK_EQ(err, (status_t)OK);
CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
- CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
- || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
- || format.eColorFormat == OMX_COLOR_FormatCbYCrY
- || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka);
-
int32_t colorFormat;
if (meta->findInt32(kKeyColorFormat, &colorFormat)
&& colorFormat != OMX_COLOR_FormatUnused
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
index 2c6d84c..f26f386 100644
--- a/media/libstagefright/chromium_http/Android.mk
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -22,6 +22,7 @@
libchromium_net \
libutils \
libcutils \
+ liblog \
libstagefright_foundation \
libstagefright \
libdrmframework
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 4dc38a8..ffa64f9 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -20,7 +20,7 @@
LOCAL_STATIC_LIBRARIES := libFraunhoferAAC
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils libcutils
+ libstagefright_omx libstagefright_foundation libutils libcutils liblog
LOCAL_MODULE := libstagefright_soft_aacdec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index a8ab2ac..8ba2afb 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -118,7 +118,7 @@
status = OK;
}
}
- mIsFirst = true;
+ mDecoderHasData = false;
// for streams that contain metadata, use the mobile profile DRC settings unless overridden
// by platform properties:
@@ -327,6 +327,7 @@
notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
return;
}
+
inQueue.erase(inQueue.begin());
info->mOwnedByUs = false;
notifyEmptyBufferDone(header);
@@ -358,7 +359,7 @@
inInfo->mOwnedByUs = false;
notifyEmptyBufferDone(inHeader);
- if (!mIsFirst) {
+ if (mDecoderHasData) {
// flush out the decoder's delayed data by calling DecodeFrame
// one more time, with the AACDEC_FLUSH flag set
INT_PCM *outBuffer =
@@ -370,6 +371,7 @@
outBuffer,
outHeader->nAllocLen,
AACDEC_FLUSH);
+ mDecoderHasData = false;
if (decoderErr != AAC_DEC_OK) {
mSignalledError = true;
@@ -385,9 +387,7 @@
* sizeof(int16_t)
* mStreamInfo->numChannels;
} else {
- // Since we never discarded frames from the start, we won't have
- // to add any padding at the end either.
-
+ // we never submitted any data to the decoder, so there's nothing to flush out
outHeader->nFilledLen = 0;
}
@@ -473,6 +473,7 @@
inBuffer,
inBufferLength,
bytesValid);
+ mDecoderHasData = true;
decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
outBuffer,
@@ -484,45 +485,6 @@
}
}
- /*
- * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
- * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
- * rate system and the sampling rate in the final output is actually
- * doubled compared with the core AAC decoder sampling rate.
- *
- * Explicit signalling is done by explicitly defining SBR audio object
- * type in the bitstream. Implicit signalling is done by embedding
- * SBR content in AAC extension payload specific to SBR, and hence
- * requires an AAC decoder to perform pre-checks on actual audio frames.
- *
- * Thus, we could not say for sure whether a stream is
- * AAC+/eAAC+ until the first data frame is decoded.
- */
- if (mInputBufferCount <= 2) {
- if (mStreamInfo->sampleRate != prevSampleRate ||
- mStreamInfo->numChannels != prevNumChannels) {
- maybeConfigureDownmix();
- ALOGI("Reconfiguring decoder: %d Hz, %d channels",
- mStreamInfo->sampleRate,
- mStreamInfo->numChannels);
-
- // We're going to want to revisit this input buffer, but
- // may have already advanced the offset. Undo that if
- // necessary.
- inHeader->nOffset -= adtsHeaderSize;
- inHeader->nFilledLen += adtsHeaderSize;
-
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
- return;
- }
- } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
- ALOGW("Invalid AAC stream");
- mSignalledError = true;
- notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
- return;
- }
-
size_t numOutBytes =
mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
@@ -544,17 +506,51 @@
// fall through
}
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+
+ /*
+ * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
+ * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
+ * rate system and the sampling rate in the final output is actually
+ * doubled compared with the core AAC decoder sampling rate.
+ *
+ * Explicit signalling is done by explicitly defining SBR audio object
+ * type in the bitstream. Implicit signalling is done by embedding
+ * SBR content in AAC extension payload specific to SBR, and hence
+ * requires an AAC decoder to perform pre-checks on actual audio frames.
+ *
+ * Thus, we could not say for sure whether a stream is
+ * AAC+/eAAC+ until the first data frame is decoded.
+ */
+ if (mInputBufferCount <= 2) {
+ if (mStreamInfo->sampleRate != prevSampleRate ||
+ mStreamInfo->numChannels != prevNumChannels) {
+ maybeConfigureDownmix();
+ ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
+ prevSampleRate, mStreamInfo->sampleRate,
+ prevNumChannels, mStreamInfo->numChannels);
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return;
+ }
+ } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
+ ALOGW("Invalid AAC stream");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ return;
+ }
+
if (decoderErr == AAC_DEC_OK || mNumSamplesOutput > 0) {
// We'll only output data if we successfully decoded it or
// we've previously decoded valid data, in the latter case
// (decode failed) we'll output a silent frame.
- if (mIsFirst) {
- mIsFirst = false;
- // the first decoded frame should be discarded to account
- // for decoder delay
- numOutBytes = 0;
- }
-
outHeader->nFilledLen = numOutBytes;
outHeader->nFlags = 0;
@@ -571,14 +567,6 @@
outHeader = NULL;
}
- if (inHeader->nFilledLen == 0) {
- inInfo->mOwnedByUs = false;
- inQueue.erase(inQueue.begin());
- inInfo = NULL;
- notifyEmptyBufferDone(inHeader);
- inHeader = NULL;
- }
-
if (decoderErr == AAC_DEC_OK) {
++mInputBufferCount;
}
@@ -589,14 +577,21 @@
if (portIndex == 0) {
// Make sure that the next buffer output does not still
// depend on fragments from the last one decoded.
- aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
- mIsFirst = true;
+ // drain all existing data
+ drainDecoder();
}
}
-void SoftAAC2::onReset() {
+void SoftAAC2::drainDecoder() {
+ short buf [2048];
+ aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
+ aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
- mIsFirst = true;
+ mDecoderHasData = false;
+}
+
+void SoftAAC2::onReset() {
+ drainDecoder();
}
void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index 6957ade..2d960ab 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -52,7 +52,7 @@
HANDLE_AACDECODER mAACDecoder;
CStreamInfo *mStreamInfo;
bool mIsADTS;
- bool mIsFirst;
+ bool mDecoderHasData;
size_t mInputBufferCount;
bool mSignalledError;
int64_t mAnchorTimeUs;
@@ -68,6 +68,7 @@
status_t initDecoder();
bool isConfigured() const;
void maybeConfigureDownmix() const;
+ void drainDecoder();
DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2);
};
diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk
index 820734d..057c69b 100644
--- a/media/libstagefright/codecs/aacenc/Android.mk
+++ b/media/libstagefright/codecs/aacenc/Android.mk
@@ -109,7 +109,7 @@
LOCAL_STATIC_LIBRARIES := libFraunhoferAAC
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils
+ libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_aacenc
LOCAL_MODULE_TAGS := optional
@@ -132,7 +132,7 @@
libstagefright_aacenc
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_omx libstagefright_foundation libutils liblog \
libstagefright_enc_common
LOCAL_MODULE := libstagefright_soft_aacenc
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index b48a459..8d6c6f8 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -72,7 +72,7 @@
libstagefright_amrnbdec libstagefright_amrwbdec
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_omx libstagefright_foundation libutils liblog \
libstagefright_amrnb_common
LOCAL_MODULE := libstagefright_soft_amrdec
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk
index 457656a..f4e467a 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.mk
+++ b/media/libstagefright/codecs/amrnb/enc/Android.mk
@@ -92,7 +92,7 @@
libstagefright_amrnbenc
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_omx libstagefright_foundation libutils liblog \
libstagefright_amrnb_common
LOCAL_MODULE := libstagefright_soft_amrnbenc
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
index edfd7b7..c5b8e0c 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -130,7 +130,7 @@
libstagefright_amrwbenc
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_omx libstagefright_foundation libutils liblog \
libstagefright_enc_common
LOCAL_MODULE := libstagefright_soft_amrwbenc
diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk
index cffe469..7d17c2a 100644
--- a/media/libstagefright/codecs/avc/enc/Android.mk
+++ b/media/libstagefright/codecs/avc/enc/Android.mk
@@ -62,6 +62,7 @@
libstagefright_foundation \
libstagefright_omx \
libutils \
+ liblog \
libui
diff --git a/media/libstagefright/codecs/flac/enc/Android.mk b/media/libstagefright/codecs/flac/enc/Android.mk
index 546a357..f01d605 100644
--- a/media/libstagefright/codecs/flac/enc/Android.mk
+++ b/media/libstagefright/codecs/flac/enc/Android.mk
@@ -10,7 +10,7 @@
external/flac/include
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libFLAC \
diff --git a/media/libstagefright/codecs/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk
index 28be646..4c80da6 100644
--- a/media/libstagefright/codecs/g711/dec/Android.mk
+++ b/media/libstagefright/codecs/g711/dec/Android.mk
@@ -9,7 +9,7 @@
frameworks/native/include/media/openmax
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_g711dec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/gsm/dec/Android.mk b/media/libstagefright/codecs/gsm/dec/Android.mk
index 9c0c6ae..71613d2 100644
--- a/media/libstagefright/codecs/gsm/dec/Android.mk
+++ b/media/libstagefright/codecs/gsm/dec/Android.mk
@@ -10,7 +10,7 @@
external/libgsm/inc
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libgsm
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
index a6b1edc..a3d5779 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
@@ -67,7 +67,7 @@
libstagefright_m4vh263dec
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_mpeg4dec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
index 865cc9c..83a2dd2 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
@@ -65,6 +65,7 @@
libstagefright_foundation \
libstagefright_omx \
libutils \
+ liblog \
libui
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index ec8d7ec..135c715 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -70,7 +70,7 @@
$(LOCAL_PATH)/include
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libstagefright_mp3dec
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
index 0082d7c..7f2c46d 100644
--- a/media/libstagefright/codecs/on2/dec/Android.mk
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -15,7 +15,7 @@
libvpx
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_vpxdec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/on2/enc/Android.mk b/media/libstagefright/codecs/on2/enc/Android.mk
index 5d3317c..a92d376 100644
--- a/media/libstagefright/codecs/on2/enc/Android.mk
+++ b/media/libstagefright/codecs/on2/enc/Android.mk
@@ -16,7 +16,7 @@
libvpx
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils \
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog \
LOCAL_MODULE := libstagefright_soft_vpxenc
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/on2/h264dec/Android.mk b/media/libstagefright/codecs/on2/h264dec/Android.mk
index 772fd60..2539f98 100644
--- a/media/libstagefright/codecs/on2/h264dec/Android.mk
+++ b/media/libstagefright/codecs/on2/h264dec/Android.mk
@@ -97,7 +97,7 @@
endif
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils \
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog \
LOCAL_MODULE := libstagefright_soft_h264dec
@@ -124,4 +124,3 @@
LOCAL_MODULE := decoder
include $(BUILD_EXECUTABLE)
-
diff --git a/media/libstagefright/codecs/raw/Android.mk b/media/libstagefright/codecs/raw/Android.mk
index 285c747..fe90a03 100644
--- a/media/libstagefright/codecs/raw/Android.mk
+++ b/media/libstagefright/codecs/raw/Android.mk
@@ -9,7 +9,7 @@
frameworks/native/include/media/openmax
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils
+ libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_rawdec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk
index 395dd6b..2232353 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.mk
+++ b/media/libstagefright/codecs/vorbis/dec/Android.mk
@@ -11,10 +11,9 @@
LOCAL_SHARED_LIBRARIES := \
libvorbisidec libstagefright libstagefright_omx \
- libstagefright_foundation libutils
+ libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_vorbisdec
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index b7577d6..d65e213 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -20,6 +20,7 @@
LOCAL_SHARED_LIBRARIES := \
libbinder \
libutils \
+ liblog
LOCAL_CFLAGS += -Wno-multichar
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index ff35d4a..80a1a3a 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -16,7 +16,7 @@
testid3.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libutils libbinder libstagefright_foundation
+ libstagefright libutils liblog libbinder libstagefright_foundation
LOCAL_STATIC_LIBRARIES := \
libstagefright_id3
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index c68623a..35eff96 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -59,6 +59,11 @@
private:
+ struct PsshInfo {
+ uint8_t uuid[16];
+ uint32_t datalen;
+ uint8_t *data;
+ };
struct Track {
Track *next;
sp<MetaData> meta;
@@ -72,6 +77,8 @@
uint64_t mSidxDuration;
off64_t mMoofOffset;
+ Vector<PsshInfo> mPssh;
+
sp<DataSource> mDataSource;
status_t mInitCheck;
bool mHasVideo;
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 9129f08..a8b4939 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -19,6 +19,7 @@
libbinder \
libmedia \
libutils \
+ liblog \
libui \
libgui \
libcutils \
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 46ff22f..971875f 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -292,15 +292,14 @@
status_t OMXNodeInstance::enableGraphicBuffers(
OMX_U32 portIndex, OMX_BOOL enable) {
Mutex::Autolock autoLock(mLock);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.enableAndroidNativeBuffers");
OMX_INDEXTYPE index;
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"),
- &index);
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
@@ -331,14 +330,12 @@
Mutex::Autolock autoLock(mLock);
OMX_INDEXTYPE index;
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>(
- "OMX.google.android.index.getAndroidNativeBufferUsage"),
- &index);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.getAndroidNativeBufferUsage");
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
@@ -381,7 +378,9 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex %s failed", name);
+ if (enable) {
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
+ }
return StatusFromOMXError(err);
}
@@ -507,13 +506,12 @@
return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
}
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
- &index);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.useAndroidNativeBuffer");
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index 04441ca..1061c39 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -5,7 +5,7 @@
OMXHarness.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright libbinder libmedia libutils libstagefright_foundation
+ libstagefright libbinder libmedia libutils liblog libstagefright_foundation
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/av/media/libstagefright \
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
index 57fff0b..06ce16b 100644
--- a/media/libstagefright/tests/Android.mk
+++ b/media/libstagefright/tests/Android.mk
@@ -26,6 +26,7 @@
libsync \
libui \
libutils \
+ liblog
LOCAL_STATIC_LIBRARIES := \
libgtest \
diff --git a/media/libstagefright/wifi-display/Android.mk b/media/libstagefright/wifi-display/Android.mk
index 1578c21..f99ef60 100644
--- a/media/libstagefright/wifi-display/Android.mk
+++ b/media/libstagefright/wifi-display/Android.mk
@@ -31,6 +31,7 @@
LOCAL_SHARED_LIBRARIES:= \
libbinder \
libcutils \
+ liblog \
libgui \
libmedia \
libstagefright \
@@ -59,6 +60,7 @@
libstagefright_foundation \
libstagefright_wfd \
libutils \
+ liblog \
LOCAL_MODULE:= wfd
@@ -81,6 +83,7 @@
libstagefright_foundation \
libstagefright_wfd \
libutils \
+ liblog \
LOCAL_MODULE:= udptest
@@ -103,6 +106,7 @@
libstagefright_foundation \
libstagefright_wfd \
libutils \
+ liblog \
LOCAL_MODULE:= rtptest
@@ -125,6 +129,7 @@
libstagefright_foundation \
libstagefright_wfd \
libutils \
+ liblog \
LOCAL_MODULE:= nettest
diff --git a/media/libstagefright/yuv/Android.mk b/media/libstagefright/yuv/Android.mk
index a4253f6..b3f7b1b 100644
--- a/media/libstagefright/yuv/Android.mk
+++ b/media/libstagefright/yuv/Android.mk
@@ -6,7 +6,8 @@
YUVCanvas.cpp
LOCAL_SHARED_LIBRARIES := \
- libcutils
+ libcutils \
+ liblog
LOCAL_MODULE:= libstagefright_yuv
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index a485646..1ac647a 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -22,6 +22,7 @@
libmedia \
libmediaplayerservice \
libutils \
+ liblog \
libbinder
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index bee28d4..ac608a1 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -42,6 +42,6 @@
# Needed for <bionic_time.h>
LOCAL_C_INCLUDES := bionic/libc/private
-LOCAL_SHARED_LIBRARIES := libutils libcutils libusbhost libbinder
+LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libusbhost libbinder
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 7806f48..061a079 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -22,7 +22,7 @@
AudioResampler.cpp.arm \
AudioPolicyService.cpp \
ServiceUtilities.cpp \
- AudioResamplerCubic.cpp.arm \
+ AudioResamplerCubic.cpp.arm \
AudioResamplerSinc.cpp.arm
LOCAL_SRC_FILES += StateQueue.cpp
@@ -39,6 +39,7 @@
libcommon_time_client \
libcutils \
libutils \
+ liblog \
libbinder \
libmedia \
libnbaio \
@@ -94,9 +95,10 @@
AudioResamplerSinc.cpp.arm
LOCAL_SHARED_LIBRARIES := \
- libdl \
+ libdl \
libcutils \
- libutils
+ libutils \
+ liblog
LOCAL_MODULE:= test-resample
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 6847bf8..3c84703 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -32,6 +32,7 @@
LOCAL_SHARED_LIBRARIES:= \
libui \
+ liblog \
libutils \
libbinder \
libcutils \
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index f2c8c04..08aef83 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -25,6 +25,18 @@
#define ALOGVV(...) ((void)0)
#endif
+// Convenience macro for transient errors
+#define CLOGE(fmt, ...) ALOGE("Camera %d: %s: " fmt, mId, __FUNCTION__, \
+ ##__VA_ARGS__)
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) setErrorState( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+
#include <utils/Log.h>
#include <utils/Trace.h>
#include <utils/Timers.h>
@@ -69,7 +81,7 @@
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
if (mStatus != STATUS_UNINITIALIZED) {
- ALOGE("%s: Already initialized!", __FUNCTION__);
+ CLOGE("Already initialized!");
return INVALID_OPERATION;
}
@@ -84,21 +96,18 @@
reinterpret_cast<hw_device_t**>(&device));
if (res != OK) {
- ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
- mId, strerror(-res), res);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res);
return res;
}
/** Cross-check device version */
if (device->common.version != CAMERA_DEVICE_API_VERSION_3_0) {
- ALOGE("%s: Could not open camera %d: "
+ SET_ERR_L("Could not open camera: "
"Camera device is not version %x, reports %x instead",
- __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_3_0,
+ CAMERA_DEVICE_API_VERSION_3_0,
device->common.version);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -107,11 +116,10 @@
if (res != OK) return res;
if (info.device_version != device->common.version) {
- ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
- " and device version (%x).", __FUNCTION__,
+ SET_ERR_L("HAL reporting mismatched camera_info version (%x)"
+ " and device version (%x).",
device->common.version, info.device_version);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -119,10 +127,9 @@
res = device->ops->initialize(device, this);
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to initialize HAL device: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ SET_ERR_L("Unable to initialize HAL device: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -135,10 +142,9 @@
if (mVendorTagOps.get_camera_vendor_section_name != NULL) {
res = set_camera_metadata_vendor_tag_ops(&mVendorTagOps);
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to set tag ops: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ SET_ERR_L("Unable to set tag ops: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return res;
}
}
@@ -148,11 +154,10 @@
mRequestThread = new RequestThread(this, device);
res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string());
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to start request queue thread: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ SET_ERR_L("Unable to start request queue thread: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
mRequestThread.clear();
- mStatus = STATUS_ERROR;
return res;
}
@@ -179,12 +184,12 @@
(mStatus == STATUS_ERROR && mRequestThread != NULL)) {
res = mRequestThread->clearRepeatingRequests();
if (res != OK) {
- ALOGE("%s: Can't stop streaming", __FUNCTION__);
+ SET_ERR_L("Can't stop streaming");
return res;
}
res = waitUntilDrainedLocked();
if (res != OK) {
- ALOGE("%s: Timeout waiting for HAL to drain", __FUNCTION__);
+ SET_ERR_L("Timeout waiting for HAL to drain");
return res;
}
}
@@ -225,6 +230,9 @@
mStatus == STATUS_ACTIVE ? "ACTIVE" :
"Unknown";
lines.appendFormat(" Device status: %s\n", status);
+ if (mStatus == STATUS_ERROR) {
+ lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
+ }
lines.appendFormat(" Stream configuration:\n");
if (mInputStream != NULL) {
@@ -251,7 +259,7 @@
ALOGVV("%s: E", __FUNCTION__);
if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
mStatus == STATUS_ERROR)) {
- ALOGE("%s: Access to static info %s!", __FUNCTION__,
+ ALOGW("%s: Access to static info %s!", __FUNCTION__,
mStatus == STATUS_ERROR ?
"when in error state" : "before init");
}
@@ -262,25 +270,27 @@
ATRACE_CALL();
Mutex::Autolock l(mLock);
+ // TODO: take ownership of the request
+
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
sp<CaptureRequest> newRequest = setUpRequestLocked(request);
if (newRequest == NULL) {
- ALOGE("%s: Can't create capture request", __FUNCTION__);
+ CLOGE("Can't create capture request");
return BAD_VALUE;
}
@@ -294,23 +304,23 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
sp<CaptureRequest> newRepeatingRequest = setUpRequestLocked(request);
if (newRepeatingRequest == NULL) {
- ALOGE("%s: Can't create repeating request", __FUNCTION__);
+ CLOGE("Can't create repeating request");
return BAD_VALUE;
}
@@ -328,8 +338,7 @@
if (mStatus == STATUS_IDLE) {
res = configureStreamsLocked();
if (res != OK) {
- ALOGE("%s: Can't set up streams: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Can't set up streams: %s (%d)", strerror(-res), res);
return NULL;
}
}
@@ -344,17 +353,17 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
@@ -363,10 +372,8 @@
status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
ATRACE_CALL();
- (void)requestId; (void)timeout;
- ALOGE("%s: Unimplemented", __FUNCTION__);
- return INVALID_OPERATION;
+ return mRequestThread->waitUntilRequestProcessed(requestId, timeout);
}
status_t Camera3Device::createStream(sp<ANativeWindow> consumer,
@@ -379,10 +386,10 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
// OK
@@ -394,13 +401,12 @@
if (res != OK) {
ALOGE("%s: Can't pause captures to reconfigure streams!",
__FUNCTION__);
- mStatus = STATUS_ERROR;
return res;
}
wasActive = true;
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
assert(mStatus == STATUS_IDLE);
@@ -416,8 +422,7 @@
res = mOutputStreams.add(mNextStreamId, newStream);
if (res < 0) {
- ALOGE("%s: Can't add new stream to set: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
return res;
}
@@ -428,8 +433,8 @@
ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
res = configureStreamsLocked();
if (res != OK) {
- ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
- __FUNCTION__, mNextStreamId, strerror(-res), res);
+ CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
+ mNextStreamId, strerror(-res), res);
return res;
}
mRequestThread->setPaused(false);
@@ -442,7 +447,7 @@
ATRACE_CALL();
(void)outputId; (void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -454,23 +459,23 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized!", __FUNCTION__);
+ CLOGE("Device not initialized!");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d is unknown", __FUNCTION__, id);
+ CLOGE("Stream %d is unknown", id);
return idx;
}
@@ -488,24 +493,24 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d does not exist",
- __FUNCTION__, id);
+ CLOGE("Stream %d does not exist",
+ id);
return BAD_VALUE;
}
@@ -520,7 +525,7 @@
// CameraDevice semantics require device to already be idle before
// deleteStream is called, unlike for createStream.
if (mStatus != STATUS_IDLE) {
- ALOGE("%s: Device not idle", __FUNCTION__);
+ CLOGE("Device not idle");
return INVALID_OPERATION;
}
@@ -531,8 +536,7 @@
} else {
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d does not exist",
- __FUNCTION__, id);
+ CLOGE("Stream %d does not exist", id);
return BAD_VALUE;
}
deletedStream = mOutputStreams.editValueAt(idx);
@@ -542,7 +546,7 @@
// Free up the stream endpoint so that it can be used by some other stream
res = deletedStream->disconnect();
if (res != OK) {
- ALOGE("%s: Can't disconnect deleted stream", __FUNCTION__);
+ SET_ERR_L("Can't disconnect deleted stream %d", id);
// fall through since we want to still list the stream as deleted.
}
mDeletedStreams.add(deletedStream);
@@ -554,7 +558,7 @@
ATRACE_CALL();
(void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -567,24 +571,28 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device is not initialized!", __FUNCTION__);
+ CLOGE("Device is not initialized!");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
const camera_metadata_t *rawRequest;
rawRequest = mHal3Device->ops->construct_default_request_settings(
mHal3Device, templateId);
- if (rawRequest == NULL) return DEAD_OBJECT;
+ if (rawRequest == NULL) {
+ SET_ERR_L("HAL is unable to construct default settings for template %d",
+ templateId);
+ return DEAD_OBJECT;
+ }
*request = rawRequest;
return OK;
@@ -611,35 +619,31 @@
// Need to shut down
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d",mStatus);
return INVALID_OPERATION;
}
if (mRequestThread != NULL) {
res = mRequestThread->waitUntilPaused(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't stop request thread in %f seconds!",
- __FUNCTION__, kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't stop request thread in %f seconds!",
+ kShutdownTimeout/1e9);
return res;
}
}
if (mInputStream != NULL) {
res = mInputStream->waitUntilIdle(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't idle input stream %d in %f seconds!",
- __FUNCTION__, mInputStream->getId(), kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't idle input stream %d in %f seconds!",
+ mInputStream->getId(), kShutdownTimeout/1e9);
return res;
}
}
for (size_t i = 0; i < mOutputStreams.size(); i++) {
res = mOutputStreams.editValueAt(i)->waitUntilIdle(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't idle output stream %d in %f seconds!",
- __FUNCTION__, mOutputStreams.keyAt(i),
- kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't idle output stream %d in %f seconds!",
+ mOutputStreams.keyAt(i), kShutdownTimeout/1e9);
return res;
}
}
@@ -673,8 +677,8 @@
if (res == TIMED_OUT) {
return res;
} else if (res != OK) {
- ALOGE("%s: Camera %d: Error waiting for frame: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ ALOGW("%s: Camera %d: No frame in %lld ns: %s (%d)",
+ __FUNCTION__, mId, timeout, strerror(-res), res);
return res;
}
}
@@ -698,28 +702,62 @@
status_t Camera3Device::triggerAutofocus(uint32_t id) {
ATRACE_CALL();
- (void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
- return INVALID_OPERATION;
+ ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
+ // Mix-in this trigger into the next request and only the next request.
+ RequestTrigger trigger[] = {
+ {
+ ANDROID_CONTROL_AF_TRIGGER,
+ ANDROID_CONTROL_AF_TRIGGER_START
+ },
+ {
+ ANDROID_CONTROL_AF_TRIGGER_ID,
+ static_cast<int32_t>(id)
+ },
+ };
+
+ return mRequestThread->queueTrigger(trigger,
+ sizeof(trigger)/sizeof(trigger[0]));
}
status_t Camera3Device::triggerCancelAutofocus(uint32_t id) {
ATRACE_CALL();
- (void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
- return INVALID_OPERATION;
+ ALOGV("%s: Triggering cancel autofocus, id %d", __FUNCTION__, id);
+ // Mix-in this trigger into the next request and only the next request.
+ RequestTrigger trigger[] = {
+ {
+ ANDROID_CONTROL_AF_TRIGGER,
+ ANDROID_CONTROL_AF_TRIGGER_CANCEL
+ },
+ {
+ ANDROID_CONTROL_AF_TRIGGER_ID,
+ static_cast<int32_t>(id)
+ },
+ };
+ return mRequestThread->queueTrigger(trigger,
+ sizeof(trigger)/sizeof(trigger[0]));
}
status_t Camera3Device::triggerPrecaptureMetering(uint32_t id) {
ATRACE_CALL();
- (void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
- return INVALID_OPERATION;
+ ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
+ // Mix-in this trigger into the next request and only the next request.
+ RequestTrigger trigger[] = {
+ {
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START
+ },
+ {
+ ANDROID_CONTROL_AE_PRECAPTURE_ID,
+ static_cast<int32_t>(id)
+ },
+ };
+ return mRequestThread->queueTrigger(trigger,
+ sizeof(trigger)/sizeof(trigger[0]));
}
status_t Camera3Device::pushReprocessBuffer(int reprocessStreamId,
@@ -727,7 +765,7 @@
ATRACE_CALL();
(void)reprocessStreamId; (void)buffer; (void)listener;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -748,8 +786,8 @@
if (inputStreams.count > 0) {
if (mInputStream == NULL ||
mInputStream->getId() != inputStreams.data.u8[0]) {
- ALOGE("%s: Request references unknown input stream %d",
- __FUNCTION__, inputStreams.data.u8[0]);
+ CLOGE("Request references unknown input stream %d",
+ inputStreams.data.u8[0]);
return NULL;
}
// Lazy completion of stream configuration (allocation/registration)
@@ -757,10 +795,9 @@
if (mInputStream->isConfiguring()) {
res = mInputStream->finishConfiguration(mHal3Device);
if (res != OK) {
- ALOGE("%s: Unable to finish configuring input stream %d:"
+ SET_ERR_L("Unable to finish configuring input stream %d:"
" %s (%d)",
- __FUNCTION__, mInputStream->getId(),
- strerror(-res), res);
+ mInputStream->getId(), strerror(-res), res);
return NULL;
}
}
@@ -772,15 +809,15 @@
camera_metadata_entry_t streams =
newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);
if (streams.count == 0) {
- ALOGE("%s: Zero output streams specified!", __FUNCTION__);
+ CLOGE("Zero output streams specified!");
return NULL;
}
for (size_t i = 0; i < streams.count; i++) {
int idx = mOutputStreams.indexOfKey(streams.data.u8[i]);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Request references unknown stream %d",
- __FUNCTION__, streams.data.u8[i]);
+ CLOGE("Request references unknown stream %d",
+ streams.data.u8[i]);
return NULL;
}
sp<Camera3OutputStream> stream = mOutputStreams.editValueAt(idx);
@@ -790,8 +827,8 @@
if (stream->isConfiguring()) {
res = stream->finishConfiguration(mHal3Device);
if (res != OK) {
- ALOGE("%s: Unable to finish configuring stream %d: %s (%d)",
- __FUNCTION__, stream->getId(), strerror(-res), res);
+ SET_ERR_L("Unable to finish configuring stream %d: %s (%d)",
+ stream->getId(), strerror(-res), res);
return NULL;
}
}
@@ -808,7 +845,7 @@
status_t res;
if (mStatus != STATUS_IDLE) {
- ALOGE("%s: Not idle", __FUNCTION__);
+ CLOGE("Not idle");
return INVALID_OPERATION;
}
@@ -825,9 +862,7 @@
camera3_stream_t *inputStream;
inputStream = mInputStream->startConfiguration();
if (inputStream == NULL) {
- ALOGE("%s: Can't start input stream configuration",
- __FUNCTION__);
- // TODO: Make sure the error flow here is correct
+ SET_ERR_L("Can't start input stream configuration");
return INVALID_OPERATION;
}
streams.add(inputStream);
@@ -837,9 +872,7 @@
camera3_stream_t *outputStream;
outputStream = mOutputStreams.editValueAt(i)->startConfiguration();
if (outputStream == NULL) {
- ALOGE("%s: Can't start output stream configuration",
- __FUNCTION__);
- // TODO: Make sure the error flow here is correct
+ SET_ERR_L("Can't start output stream configuration");
return INVALID_OPERATION;
}
streams.add(outputStream);
@@ -853,8 +886,8 @@
res = mHal3Device->ops->configure_streams(mHal3Device, &config);
if (res != OK) {
- ALOGE("%s: Unable to configure streams with HAL: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
+ strerror(-res), res);
return res;
}
@@ -869,6 +902,38 @@
return OK;
}
+void Camera3Device::setErrorState(const char *fmt, ...) {
+ Mutex::Autolock l(mLock);
+ va_list args;
+ va_start(args, fmt);
+
+ setErrorStateLockedV(fmt, args);
+
+ va_end(args);
+}
+
+void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
+ Mutex::Autolock l(mLock);
+ setErrorStateLockedV(fmt, args);
+}
+
+void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+ setErrorStateLockedV(fmt, args);
+
+ va_end(args);
+}
+
+void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
+ // Only accept the first failure cause
+ if (mStatus == STATUS_ERROR) return;
+
+ mErrorCause = String8::formatV(fmt, args);
+ ALOGE("Camera %d: %s", mId, mErrorCause.string());
+ mStatus = STATUS_ERROR;
+}
/**
* Camera HAL device callback methods
@@ -880,8 +945,7 @@
status_t res;
if (result->result == NULL) {
- // TODO: Report error upstream
- ALOGW("%s: No metadata for frame %d", __FUNCTION__,
+ SET_ERR("No metadata provided by HAL for frame %d",
result->frame_number);
return;
}
@@ -904,13 +968,12 @@
captureResult = result->result;
if (captureResult.update(ANDROID_REQUEST_FRAME_COUNT,
- (int32_t*)&result->frame_number, 1) != OK) {
- ALOGE("%s: Camera %d: Failed to set frame# in metadata (%d)",
- __FUNCTION__, mId, result->frame_number);
- // TODO: Report error upstream
+ (int32_t*)&result->frame_number, 1) != OK) {
+ SET_ERR("Failed to set frame# in metadata (%d)",
+ result->frame_number);
} else {
ALOGVV("%s: Camera %d: Set frame# in metadata (%d)",
- __FUNCTION__, mId, result->frame_number);
+ __FUNCTION__, mId, result->frame_number);
}
// Get timestamp from result metadata
@@ -918,9 +981,8 @@
camera_metadata_entry entry =
captureResult.find(ANDROID_SENSOR_TIMESTAMP);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No timestamp provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
- // TODO: Report error upstream
+ SET_ERR("No timestamp provided by HAL for frame %d!",
+ result->frame_number);
} else {
timestamp = entry.data.i64[0];
}
@@ -929,8 +991,8 @@
entry = captureResult.find(ANDROID_CONTROL_AE_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AE state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AE state provided by HAL for frame %d!",
+ result->frame_number);
} else {
new3aState.aeState =
static_cast<camera_metadata_enum_android_control_ae_state>(
@@ -939,8 +1001,8 @@
entry = captureResult.find(ANDROID_CONTROL_AF_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AF state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AF state provided by HAL for frame %d!",
+ result->frame_number);
} else {
new3aState.afState =
static_cast<camera_metadata_enum_android_control_af_state>(
@@ -949,8 +1011,8 @@
entry = captureResult.find(ANDROID_CONTROL_AWB_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AWB state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AWB state provided by HAL for frame %d!",
+ result->frame_number);
} else {
new3aState.awbState =
static_cast<camera_metadata_enum_android_control_awb_state>(
@@ -959,16 +1021,16 @@
entry = captureResult.find(ANDROID_CONTROL_AF_TRIGGER_ID);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AF trigger ID provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AF trigger ID provided by HAL for frame %d!",
+ result->frame_number);
} else {
afTriggerId = entry.data.i32[0];
}
entry = captureResult.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AE precapture trigger ID provided by HAL"
- " for frame %d!", __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AE precapture trigger ID provided by HAL"
+ " for frame %d!", result->frame_number);
} else {
aeTriggerId = entry.data.i32[0];
}
@@ -987,19 +1049,21 @@
// Note: stream may be deallocated at this point, if this buffer was the
// last reference to it.
if (res != OK) {
- ALOGE("%s: Camera %d: Can't return buffer %d for frame %d to its"
- " stream:%s (%d)", __FUNCTION__, mId, i,
- result->frame_number, strerror(-res), res);
- // TODO: Report error upstream
+ SET_ERR("Can't return buffer %d for frame %d to its stream: "
+ " %s (%d)", i, result->frame_number, strerror(-res), res);
}
}
// Dispatch any 3A change events to listeners
if (listener != NULL) {
if (new3aState.aeState != cur3aState.aeState) {
+ ALOGVV("%s: AE state changed from 0x%x to 0x%x",
+ __FUNCTION__, cur3aState.aeState, new3aState.aeState);
listener->notifyAutoExposure(new3aState.aeState, aeTriggerId);
}
if (new3aState.afState != cur3aState.afState) {
+ ALOGVV("%s: AF state changed from 0x%x to 0x%x",
+ __FUNCTION__, cur3aState.afState, new3aState.afState);
listener->notifyAutoFocus(new3aState.afState, afTriggerId);
}
if (new3aState.awbState != cur3aState.awbState) {
@@ -1018,8 +1082,7 @@
}
if (msg == NULL) {
- ALOGE("%s: Camera %d: HAL sent NULL notify message!",
- __FUNCTION__, mId);
+ SET_ERR_L("HAL sent NULL notify message!");
return;
}
@@ -1042,8 +1105,8 @@
break;
}
default:
- ALOGE("%s: Camera %d: Unknown notify message from HAL: %d",
- __FUNCTION__, mId, msg->type);
+ SET_ERR_L("Unknown notify message from HAL: %d",
+ msg->type);
}
}
@@ -1059,7 +1122,8 @@
mReconfigured(false),
mDoPause(false),
mPaused(true),
- mFrameNumber(0) {
+ mFrameNumber(0),
+ mLatestRequestId(NAME_NOT_FOUND) {
}
void Camera3Device::RequestThread::configurationComplete() {
@@ -1075,6 +1139,57 @@
return OK;
}
+
+status_t Camera3Device::RequestThread::queueTrigger(
+ RequestTrigger trigger[],
+ size_t count) {
+
+ Mutex::Autolock l(mTriggerMutex);
+ status_t ret;
+
+ for (size_t i = 0; i < count; ++i) {
+ ret = queueTriggerLocked(trigger[i]);
+
+ if (ret != OK) {
+ return ret;
+ }
+ }
+
+ return OK;
+}
+
+status_t Camera3Device::RequestThread::queueTriggerLocked(
+ RequestTrigger trigger) {
+
+ uint32_t tag = trigger.metadataTag;
+ ssize_t index = mTriggerMap.indexOfKey(tag);
+
+ switch (trigger.getTagType()) {
+ case TYPE_BYTE:
+ // fall-through
+ case TYPE_INT32:
+ break;
+ default:
+ ALOGE("%s: Type not supported: 0x%x",
+ __FUNCTION__,
+ trigger.getTagType());
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Collect only the latest trigger, since we only have 1 field
+ * in the request settings per trigger tag, and can't send more than 1
+ * trigger per request.
+ */
+ if (index != NAME_NOT_FOUND) {
+ mTriggerMap.editValueAt(index) = trigger;
+ } else {
+ mTriggerMap.add(tag, trigger);
+ }
+
+ return OK;
+}
+
status_t Camera3Device::RequestThread::setRepeatingRequests(
const RequestList &requests) {
Mutex::Autolock l(mRequestLock);
@@ -1108,6 +1223,24 @@
return OK;
}
+status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
+ int32_t requestId, nsecs_t timeout) {
+ Mutex::Autolock l(mLatestRequestMutex);
+ status_t res;
+ while (mLatestRequestId != requestId) {
+ nsecs_t startTime = systemTime();
+
+ res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
+ if (res != OK) return res;
+
+ timeout -= (systemTime() - startTime);
+ }
+
+ return OK;
+}
+
+
+
bool Camera3Device::RequestThread::threadLoop() {
status_t res;
@@ -1125,16 +1258,55 @@
}
// Create request to HAL
-
camera3_capture_request_t request = camera3_capture_request_t();
+ Vector<camera3_stream_buffer_t> outputBuffers;
- if (mPrevRequest != nextRequest) {
+ // Insert any queued triggers (before metadata is locked)
+ int32_t triggerCount;
+ res = insertTriggers(nextRequest);
+ if (res < 0) {
+ SET_ERR("RequestThread: Unable to insert triggers "
+ "(capture request %d, HAL device: %s (%d)",
+ (mFrameNumber+1), strerror(-res), res);
+ cleanUpFailedRequest(request, nextRequest, outputBuffers);
+ return false;
+ }
+ triggerCount = res;
+
+ bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
+
+ // If the request is the same as last, or we had triggers last time
+ if (mPrevRequest != nextRequest || triggersMixedIn) {
+ /**
+ * The request should be presorted so accesses in HAL
+ * are O(logn). Sidenote, sorting a sorted metadata is nop.
+ */
+ nextRequest->mSettings.sort();
request.settings = nextRequest->mSettings.getAndLock();
mPrevRequest = nextRequest;
- } // else leave request.settings NULL to indicate 'reuse latest given'
+ ALOGVV("%s: Request settings are NEW", __FUNCTION__);
+
+ IF_ALOGV() {
+ camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
+ find_camera_metadata_ro_entry(
+ request.settings,
+ ANDROID_CONTROL_AF_TRIGGER,
+ &e
+ );
+ if (e.count > 0) {
+ ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
+ __FUNCTION__,
+ mFrameNumber+1,
+ e.data.u8[0]);
+ }
+ }
+ } else {
+ // leave request.settings NULL to indicate 'reuse latest given'
+ ALOGVV("%s: Request settings are REUSED",
+ __FUNCTION__);
+ }
camera3_stream_buffer_t inputBuffer;
- Vector<camera3_stream_buffer_t> outputBuffers;
// Fill in buffers
@@ -1142,7 +1314,7 @@
request.input_buffer = &inputBuffer;
res = nextRequest->mInputStream->getBuffer(&inputBuffer);
if (res != OK) {
- ALOGE("RequestThread: Can't get input buffer, skipping request:"
+ SET_ERR("RequestThread: Can't get input buffer, skipping request:"
" %s (%d)", strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return true;
@@ -1158,7 +1330,7 @@
res = nextRequest->mOutputStreams.editItemAt(i)->
getBuffer(&outputBuffers.editItemAt(i));
if (res != OK) {
- ALOGE("RequestThread: Can't get output buffer, skipping request:"
+ SET_ERR("RequestThread: Can't get output buffer, skipping request:"
"%s (%d)", strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return true;
@@ -1168,11 +1340,12 @@
request.frame_number = mFrameNumber++;
+
// Submit request and block until ready for next one
res = mHal3Device->ops->process_capture_request(mHal3Device, &request);
if (res != OK) {
- ALOGE("RequestThread: Unable to submit capture request %d to HAL"
+ SET_ERR("RequestThread: Unable to submit capture request %d to HAL"
" device: %s (%d)", request.frame_number, strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return false;
@@ -1181,6 +1354,35 @@
if (request.settings != NULL) {
nextRequest->mSettings.unlock(request.settings);
}
+
+ // Remove any previously queued triggers (after unlock)
+ res = removeTriggers(mPrevRequest);
+ if (res != OK) {
+ SET_ERR("RequestThread: Unable to remove triggers "
+ "(capture request %d, HAL device: %s (%d)",
+ request.frame_number, strerror(-res), res);
+ return false;
+ }
+ mPrevTriggers = triggerCount;
+
+ // Read android.request.id from the request settings metadata
+ // - inform waitUntilRequestProcessed thread of a new request ID
+ {
+ Mutex::Autolock al(mLatestRequestMutex);
+
+ camera_metadata_entry_t requestIdEntry =
+ nextRequest->mSettings.find(ANDROID_REQUEST_ID);
+ if (requestIdEntry.count > 0) {
+ mLatestRequestId = requestIdEntry.data.i32[0];
+ } else {
+ ALOGW("%s: Did not have android.request.id set in the request",
+ __FUNCTION__);
+ mLatestRequestId = NAME_NOT_FOUND;
+ }
+
+ mLatestRequestSignal.signal();
+ }
+
return true;
}
@@ -1201,7 +1403,6 @@
nextRequest->mOutputStreams.editItemAt(i)->returnBuffer(
outputBuffers[i], 0);
}
- // TODO: Report error upstream
}
sp<Camera3Device::CaptureRequest>
@@ -1285,6 +1486,153 @@
return false;
}
+void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent != NULL) {
+ va_list args;
+ va_start(args, fmt);
+
+ parent->setErrorStateV(fmt, args);
+
+ va_end(args);
+ }
+}
+
+status_t Camera3Device::RequestThread::insertTriggers(
+ const sp<CaptureRequest> &request) {
+
+ Mutex::Autolock al(mTriggerMutex);
+
+ CameraMetadata &metadata = request->mSettings;
+ size_t count = mTriggerMap.size();
+
+ for (size_t i = 0; i < count; ++i) {
+ RequestTrigger trigger = mTriggerMap.valueAt(i);
+
+ uint32_t tag = trigger.metadataTag;
+ camera_metadata_entry entry = metadata.find(tag);
+
+ if (entry.count > 0) {
+ /**
+ * Already has an entry for this trigger in the request.
+ * Rewrite it with our requested trigger value.
+ */
+ RequestTrigger oldTrigger = trigger;
+
+ oldTrigger.entryValue = entry.data.u8[0];
+
+ mTriggerReplacedMap.add(tag, oldTrigger);
+ } else {
+ /**
+ * More typical, no trigger entry, so we just add it
+ */
+ mTriggerRemovedMap.add(tag, trigger);
+ }
+
+ status_t res;
+
+ switch (trigger.getTagType()) {
+ case TYPE_BYTE: {
+ uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
+ res = metadata.update(tag,
+ &entryValue,
+ /*count*/1);
+ break;
+ }
+ case TYPE_INT32:
+ res = metadata.update(tag,
+ &trigger.entryValue,
+ /*count*/1);
+ break;
+ default:
+ ALOGE("%s: Type not supported: 0x%x",
+ __FUNCTION__,
+ trigger.getTagType());
+ return INVALID_OPERATION;
+ }
+
+ if (res != OK) {
+ ALOGE("%s: Failed to update request metadata with trigger tag %s"
+ ", value %d", __FUNCTION__, trigger.getTagName(),
+ trigger.entryValue);
+ return res;
+ }
+
+ ALOGV("%s: Mixed in trigger %s, value %d", __FUNCTION__,
+ trigger.getTagName(),
+ trigger.entryValue);
+ }
+
+ mTriggerMap.clear();
+
+ return count;
+}
+
+status_t Camera3Device::RequestThread::removeTriggers(
+ const sp<CaptureRequest> &request) {
+ Mutex::Autolock al(mTriggerMutex);
+
+ CameraMetadata &metadata = request->mSettings;
+
+ /**
+ * Replace all old entries with their old values.
+ */
+ for (size_t i = 0; i < mTriggerReplacedMap.size(); ++i) {
+ RequestTrigger trigger = mTriggerReplacedMap.valueAt(i);
+
+ status_t res;
+
+ uint32_t tag = trigger.metadataTag;
+ switch (trigger.getTagType()) {
+ case TYPE_BYTE: {
+ uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
+ res = metadata.update(tag,
+ &entryValue,
+ /*count*/1);
+ break;
+ }
+ case TYPE_INT32:
+ res = metadata.update(tag,
+ &trigger.entryValue,
+ /*count*/1);
+ break;
+ default:
+ ALOGE("%s: Type not supported: 0x%x",
+ __FUNCTION__,
+ trigger.getTagType());
+ return INVALID_OPERATION;
+ }
+
+ if (res != OK) {
+ ALOGE("%s: Failed to restore request metadata with trigger tag %s"
+ ", trigger value %d", __FUNCTION__,
+ trigger.getTagName(), trigger.entryValue);
+ return res;
+ }
+ }
+ mTriggerReplacedMap.clear();
+
+ /**
+ * Remove all new entries.
+ */
+ for (size_t i = 0; i < mTriggerRemovedMap.size(); ++i) {
+ RequestTrigger trigger = mTriggerRemovedMap.valueAt(i);
+ status_t res = metadata.erase(trigger.metadataTag);
+
+ if (res != OK) {
+ ALOGE("%s: Failed to erase metadata with trigger tag %s"
+ ", trigger value %d", __FUNCTION__,
+ trigger.getTagName(), trigger.entryValue);
+ return res;
+ }
+ }
+ mTriggerRemovedMap.clear();
+
+ return OK;
+}
+
+
+
/**
* Static callback forwarding methods from HAL to instance
*/
diff --git a/services/camera/libcameraservice/Camera3Device.h b/services/camera/libcameraservice/Camera3Device.h
index 8600c6c..2e4a303 100644
--- a/services/camera/libcameraservice/Camera3Device.h
+++ b/services/camera/libcameraservice/Camera3Device.h
@@ -109,7 +109,7 @@
private:
static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec
-
+ struct RequestTrigger;
Mutex mLock;
@@ -128,6 +128,9 @@
STATUS_ACTIVE
} mStatus;
+ // Tracking cause of fatal errors when in STATUS_ERROR
+ String8 mErrorCause;
+
// Mapping of stream IDs to stream instances
typedef KeyedVector<int, sp<camera3::Camera3OutputStream> > StreamSet;
@@ -173,6 +176,33 @@
status_t configureStreamsLocked();
/**
+ * Set device into an error state due to some fatal failure, and set an
+ * error message to indicate why. Only the first call's message will be
+ * used. The message is also sent to the log.
+ */
+ void setErrorState(const char *fmt, ...);
+ void setErrorStateV(const char *fmt, va_list args);
+ void setErrorStateLocked(const char *fmt, ...);
+ void setErrorStateLockedV(const char *fmt, va_list args);
+
+ struct RequestTrigger {
+ // Metadata tag number, e.g. android.control.aePrecaptureTrigger
+ uint32_t metadataTag;
+ // Metadata value, e.g. 'START' or the trigger ID
+ int32_t entryValue;
+
+ // The last part of the fully qualified path, e.g. afTrigger
+ const char *getTagName() const {
+ return get_camera_metadata_tag_name(metadataTag) ?: "NULL";
+ }
+
+ // e.g. TYPE_BYTE, TYPE_INT32, etc.
+ int getTagType() const {
+ return get_camera_metadata_tag_type(metadataTag);
+ }
+ };
+
+ /**
* Thread for managing capture request submission to HAL device.
*/
class RequestThread : public Thread {
@@ -198,6 +228,14 @@
status_t queueRequest(sp<CaptureRequest> request);
/**
+ * Queue a trigger to be dispatched with the next outgoing
+ * process_capture_request. The settings for that request only
+ * will be temporarily rewritten to add the trigger tag/value.
+ * Subsequent requests will not be rewritten (for this tag).
+ */
+ status_t queueTrigger(RequestTrigger trigger[], size_t count);
+
+ /**
* Pause/unpause the capture thread. Doesn't block, so use
* waitUntilPaused to wait until the thread is paused.
*/
@@ -210,11 +248,27 @@
*/
status_t waitUntilPaused(nsecs_t timeout);
+ /**
+ * Wait until thread processes the capture request with settings'
+ * android.request.id == requestId.
+ *
+ * Returns TIMED_OUT in case the thread does not process the request
+ * within the timeout.
+ */
+ status_t waitUntilRequestProcessed(int32_t requestId, nsecs_t timeout);
+
protected:
virtual bool threadLoop();
private:
+ status_t queueTriggerLocked(RequestTrigger trigger);
+ // Mix-in queued triggers into this request
+ int32_t insertTriggers(const sp<CaptureRequest> &request);
+ // Purge the queued triggers from this request,
+ // restoring the old field values for those tags.
+ status_t removeTriggers(const sp<CaptureRequest> &request);
+
static const nsecs_t kRequestTimeout = 50e6; // 50 ms
// Waits for a request, or returns NULL if times out.
@@ -231,6 +285,9 @@
// Pause handling
bool waitIfPaused();
+ // Relay error to parent device object setErrorState
+ void setErrorState(const char *fmt, ...);
+
wp<Camera3Device> mParent;
camera3_device_t *mHal3Device;
@@ -249,8 +306,20 @@
Condition mPausedSignal;
sp<CaptureRequest> mPrevRequest;
+ int32_t mPrevTriggers;
int32_t mFrameNumber;
+
+ Mutex mLatestRequestMutex;
+ Condition mLatestRequestSignal;
+ // android.request.id for latest process_capture_request
+ int32_t mLatestRequestId;
+
+ typedef KeyedVector<uint32_t/*tag*/, RequestTrigger> TriggerMap;
+ Mutex mTriggerMutex;
+ TriggerMap mTriggerMap;
+ TriggerMap mTriggerRemovedMap;
+ TriggerMap mTriggerReplacedMap;
};
sp<RequestThread> mRequestThread;
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index 1880912..ee03329 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -270,6 +270,9 @@
processor->clearZslQueue();
}
+ /**
+ * Fire the jpegCallback in Camera#takePicture(..., jpegCallback)
+ */
if (mCaptureBuffer != 0 && res == OK) {
Camera2Client::SharedCameraCallbacks::Lock
l(client->mSharedCameraCallbacks);
@@ -367,6 +370,8 @@
CaptureSequencer::CaptureState CaptureSequencer::manageStandardStart(
sp<Camera2Client> &client) {
ATRACE_CALL();
+
+ // Get the onFrameAvailable callback when the requestID == mCaptureId
client->registerFrameListener(mCaptureId, mCaptureId + 1,
this);
{
@@ -426,6 +431,13 @@
SharedParameters::Lock l(client->getParameters());
Vector<uint8_t> outputStreams;
+ /**
+ * Set up output streams in the request
+ * - preview
+ * - capture/jpeg
+ * - callback (if preview callbacks enabled)
+ * - recording (if recording enabled)
+ */
outputStreams.push(client->getPreviewStreamId());
outputStreams.push(client->getCaptureStreamId());
@@ -454,6 +466,7 @@
return DONE;
}
+ // Create a capture copy since CameraDeviceBase#capture takes ownership
CameraMetadata captureCopy = mCaptureRequest;
if (captureCopy.entryCount() == 0) {
ALOGE("%s: Camera %d: Unable to copy capture request for HAL device",
@@ -461,7 +474,12 @@
return DONE;
}
+ /**
+ * Clear the streaming request for still-capture pictures
+ * (as opposed to i.e. video snapshots)
+ */
if (l.mParameters.state == Parameters::STILL_CAPTURE) {
+ // API definition of takePicture() - stop preview before taking pic
res = client->stopStream();
if (res != OK) {
ALOGE("%s: Camera %d: Unable to stop preview for still capture: "
@@ -488,6 +506,8 @@
status_t res;
ATRACE_CALL();
Mutex::Autolock l(mInputMutex);
+
+ // Wait for new metadata result (mNewFrame)
while (!mNewFrameReceived) {
res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration);
if (res == TIMED_OUT) {
@@ -495,12 +515,17 @@
break;
}
}
+
+ // Approximation of the shutter being closed
+ // - TODO: use the hal3 exposure callback in Camera3Device instead
if (mNewFrameReceived && !mShutterNotified) {
SharedParameters::Lock l(client->getParameters());
/* warning: this also locks a SharedCameraCallbacks */
shutterNotifyLocked(l.mParameters, client, mMsgType);
mShutterNotified = true;
}
+
+ // Wait until jpeg was captured by JpegProcessor
while (mNewFrameReceived && !mNewCaptureReceived) {
res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration);
if (res == TIMED_OUT) {
@@ -524,7 +549,9 @@
}
if (entry.data.i64[0] != mCaptureTimestamp) {
ALOGW("Mismatched capture timestamps: Metadata frame %lld,"
- " captured buffer %lld", entry.data.i64[0], mCaptureTimestamp);
+ " captured buffer %lld",
+ entry.data.i64[0],
+ mCaptureTimestamp);
}
client->removeFrameListener(mCaptureId, mCaptureId + 1, this);
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.h b/services/camera/libcameraservice/camera2/JpegProcessor.h
index 2283f28..74f4738 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.h
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.h
@@ -44,6 +44,7 @@
JpegProcessor(wp<Camera2Client> client, wp<CaptureSequencer> sequencer);
~JpegProcessor();
+ // CpuConsumer listener implementation
void onFrameAvailable();
status_t updateStream(const Parameters ¶ms);
diff --git a/services/medialog/Android.mk b/services/medialog/Android.mk
index 559b1ed..08006c8 100644
--- a/services/medialog/Android.mk
+++ b/services/medialog/Android.mk
@@ -4,7 +4,7 @@
LOCAL_SRC_FILES := MediaLogService.cpp
-LOCAL_SHARED_LIBRARIES := libmedia libbinder libutils libnbaio
+LOCAL_SHARED_LIBRARIES := libmedia libbinder libutils liblog libnbaio
LOCAL_MODULE:= libmedialogservice