Merge "libcameraservice: update for revised HIDL gralloc" into oc-dev
diff --git a/media/libmedia/include/mediaplayer.h b/media/libmedia/include/mediaplayer.h
index 18d69a7..623c374 100644
--- a/media/libmedia/include/mediaplayer.h
+++ b/media/libmedia/include/mediaplayer.h
@@ -133,6 +133,10 @@
MEDIA_INFO_NOT_SEEKABLE = 801,
// New media metadata is available.
MEDIA_INFO_METADATA_UPDATE = 802,
+ // Audio can not be played.
+ MEDIA_INFO_PLAY_AUDIO_ERROR = 804,
+ // Video can not be played.
+ MEDIA_INFO_PLAY_VIDEO_ERROR = 805,
//9xx
MEDIA_INFO_TIMED_TEXT_ERROR = 900,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 2c37aed..d9a5c26 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -197,6 +197,8 @@
mPrepared(false),
mResetting(false),
mSourceStarted(false),
+ mAudioDecoderError(false),
+ mVideoDecoderError(false),
mPaused(false),
mPausedByClient(true),
mPausedForBuffering(false),
@@ -1093,12 +1095,14 @@
ALOGV("%s shutdown completed", audio ? "audio" : "video");
if (audio) {
mAudioDecoder.clear();
+ mAudioDecoderError = false;
++mAudioDecoderGeneration;
CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
mFlushingAudio = SHUT_DOWN;
} else {
mVideoDecoder.clear();
+ mVideoDecoderError = false;
++mVideoDecoderGeneration;
CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
@@ -1153,7 +1157,29 @@
finishFlushIfPossible(); // Should not occur.
break; // Finish anyways.
}
- notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+ if (mSource != nullptr) {
+ if (audio) {
+ if (mVideoDecoderError || mSource->getFormat(false /* audio */) == NULL) {
+ // When both audio and video have error, or this stream has only audio
+ // which has error, notify client of error.
+ notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+ } else {
+ // Only audio track has error. Video track could be still good to play.
+ notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_AUDIO_ERROR, err);
+ }
+ mAudioDecoderError = true;
+ } else {
+ if (mAudioDecoderError || mSource->getFormat(true /* audio */) == NULL) {
+ // When both audio and video have error, or this stream has only video
+ // which has error, notify client of error.
+ notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+ } else {
+ // Only video track has error. Audio track could be still good to play.
+ notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_VIDEO_ERROR, err);
+ }
+ mVideoDecoderError = true;
+ }
+ }
} else {
ALOGV("Unhandled decoder notification %d '%c%c%c%c'.",
what,
@@ -1636,6 +1662,7 @@
if (mAudioDecoder != NULL) {
mAudioDecoder->pause();
mAudioDecoder.clear();
+ mAudioDecoderError = false;
++mAudioDecoderGeneration;
}
if (mFlushingAudio == FLUSHING_DECODER) {
@@ -1773,6 +1800,7 @@
*decoder = new Decoder(notify, mSource, mPID, mUID, mRenderer);
ALOGV("instantiateDecoder audio Decoder");
}
+ mAudioDecoderError = false;
} else {
sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
++mVideoDecoderGeneration;
@@ -1780,6 +1808,7 @@
*decoder = new Decoder(
notify, mSource, mPID, mUID, mRenderer, mSurface, mCCDecoder);
+ mVideoDecoderError = false;
// enable FRC if high-quality AV sync is requested, even if not
// directly queuing to display, as this will even improve textureview
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index d3cb7c1..d542749 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -218,6 +218,8 @@
bool mPrepared;
bool mResetting;
bool mSourceStarted;
+ bool mAudioDecoderError;
+ bool mVideoDecoderError;
// Actual pause state, either as requested by client or due to buffering.
bool mPaused;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index f2cc4f7..72645ab 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -549,6 +549,7 @@
mTimePerFrameUs(-1ll),
mTimePerCaptureUs(-1ll),
mCreateInputBuffersSuspended(false),
+ mLatency(0),
mTunneled(false),
mDescribeColorAspectsIndex((OMX_INDEXTYPE)0),
mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0),
@@ -2281,6 +2282,30 @@
return err;
}
+status_t ACodec::setLatency(uint32_t latency) {
+ OMX_PARAM_U32TYPE config;
+ InitOMXParams(&config);
+ config.nPortIndex = kPortIndexInput;
+ config.nU32 = (OMX_U32)latency;
+ status_t err = mOMXNode->setConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigLatency,
+ &config, sizeof(config));
+ return err;
+}
+
+status_t ACodec::getLatency(uint32_t *latency) {
+ OMX_PARAM_U32TYPE config;
+ InitOMXParams(&config);
+ config.nPortIndex = kPortIndexInput;
+ status_t err = mOMXNode->getConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigLatency,
+ &config, sizeof(config));
+ if (err == OK) {
+ *latency = config.nU32;
+ }
+ return err;
+}
+
status_t ACodec::setPriority(int32_t priority) {
if (priority < 0) {
return BAD_VALUE;
@@ -3798,6 +3823,8 @@
}
}
+ configureEncoderLatency(msg);
+
switch (compressionFormat) {
case OMX_VIDEO_CodingMPEG4:
err = setupMPEG4EncoderParameters(msg);
@@ -4257,7 +4284,7 @@
h264type.nSliceHeaderSpacing = 0;
h264type.bUseHadamard = OMX_TRUE;
h264type.nRefFrames = 2;
- h264type.nBFrames = 1;
+ h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
h264type.nAllowedPictureTypes =
OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB;
@@ -4528,6 +4555,29 @@
OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
}
+void ACodec::configureEncoderLatency(const sp<AMessage> &msg) {
+ if (!mIsEncoder || !mIsVideo) {
+ return;
+ }
+
+ int32_t latency = 0, bitrateMode;
+ if (msg->findInt32("latency", &latency) && latency > 0) {
+ status_t err = setLatency(latency);
+ if (err != OK) {
+ ALOGW("[%s] failed setLatency. Failure is fine since this key is optional",
+ mComponentName.c_str());
+ err = OK;
+ } else {
+ mLatency = latency;
+ }
+ } else if ((!msg->findInt32("bitrate-mode", &bitrateMode) &&
+ bitrateMode == OMX_Video_ControlRateConstant)) {
+ // default the latency to be 1 if latency key is not specified or unsupported and bitrateMode
+ // is CBR.
+ mLatency = 1;
+ }
+}
+
status_t ACodec::setupErrorCorrectionParameters() {
OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
InitOMXParams(&errorCorrectionType);
@@ -4786,6 +4836,10 @@
if (mConfigFormat->contains("hdr-static-info")) {
(void)getHDRStaticInfoForVideoCodec(kPortIndexInput, notify);
}
+ uint32_t latency = 0;
+ if (mIsEncoder && getLatency(&latency) == OK && latency > 0) {
+ notify->setInt32("latency", latency);
+ }
}
break;
@@ -7182,6 +7236,16 @@
}
}
+ int32_t latency = 0;
+ if (params->findInt32("latency", &latency) && latency > 0) {
+ status_t err = setLatency(latency);
+ if (err != OK) {
+ ALOGI("[%s] failed setLatency. Failure is fine since this key is optional",
+ mComponentName.c_str());
+ err = OK;
+ }
+ }
+
status_t err = configureTemporalLayers(params, false /* inConfigure */, mOutputFormat);
if (err != OK) {
err = OK; // ignore failure
diff --git a/media/libstagefright/include/ACodec.h b/media/libstagefright/include/ACodec.h
index c57005d..6c1a5c6 100644
--- a/media/libstagefright/include/ACodec.h
+++ b/media/libstagefright/include/ACodec.h
@@ -296,6 +296,7 @@
int64_t mTimePerFrameUs;
int64_t mTimePerCaptureUs;
bool mCreateInputBuffersSuspended;
+ uint32_t mLatency;
bool mTunneled;
@@ -483,6 +484,8 @@
AudioEncoding encoding = kAudioEncodingPcm16bit);
status_t setPriority(int32_t priority);
+ status_t setLatency(uint32_t latency);
+ status_t getLatency(uint32_t *latency);
status_t setOperatingRate(float rateFloat, bool isVideo);
status_t getIntraRefreshPeriod(uint32_t *intraRefreshPeriod);
status_t setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure);
@@ -505,6 +508,7 @@
status_t configureBitrate(
int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode);
+ void configureEncoderLatency(const sp<AMessage> &msg);
status_t setupErrorCorrectionParameters();
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
new file mode 100644
index 0000000..72917dd
--- /dev/null
+++ b/media/utils/Android.bp
@@ -0,0 +1,41 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+ name: "libmediautils",
+
+ srcs: [
+ "BatteryNotifier.cpp",
+ "ISchedulingPolicyService.cpp",
+ "MemoryLeakTrackUtil.cpp",
+ "ProcessInfo.cpp",
+ "SchedulingPolicyService.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libmemunreachable",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+}
diff --git a/media/utils/Android.mk b/media/utils/Android.mk
deleted file mode 100644
index 21d1b5b..0000000
--- a/media/utils/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- BatteryNotifier.cpp \
- ISchedulingPolicyService.cpp \
- MemoryLeakTrackUtil.cpp \
- ProcessInfo.cpp \
- SchedulingPolicyService.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libcutils \
- liblog \
- libutils \
- libmemunreachable \
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-
-LOCAL_CFLAGS += \
- -Wall \
- -Wextra \
- -Werror \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-LOCAL_MODULE := libmediautils
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 6aaca7e..b2686bf 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -798,16 +798,38 @@
exposureCompensationStep.data.r[0].denominator);
autoExposureLock = false;
- params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK,
- CameraParameters::FALSE);
- params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED,
- CameraParameters::TRUE);
+ autoExposureLockAvailable = false;
+ camera_metadata_ro_entry_t exposureLockAvailable =
+ staticInfo(ANDROID_CONTROL_AE_LOCK_AVAILABLE, 1, 1);
+ if ((0 < exposureLockAvailable.count) &&
+ (ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE ==
+ exposureLockAvailable.data.u8[0])) {
+ params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK,
+ CameraParameters::FALSE);
+ params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED,
+ CameraParameters::TRUE);
+ autoExposureLockAvailable = true;
+ } else {
+ params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED,
+ CameraParameters::FALSE);
+ }
autoWhiteBalanceLock = false;
- params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK,
- CameraParameters::FALSE);
- params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED,
- CameraParameters::TRUE);
+ autoWhiteBalanceLockAvailable = false;
+ camera_metadata_ro_entry_t whitebalanceLockAvailable =
+ staticInfo(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, 1, 1);
+ if ((0 < whitebalanceLockAvailable.count) &&
+ (ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE ==
+ whitebalanceLockAvailable.data.u8[0])) {
+ params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK,
+ CameraParameters::FALSE);
+ params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED,
+ CameraParameters::TRUE);
+ autoWhiteBalanceLockAvailable = true;
+ } else {
+ params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED,
+ CameraParameters::FALSE);
+ }
meteringAreas.add(Parameters::Area(0, 0, 0, 0, 0));
params.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS,
@@ -816,30 +838,37 @@
"(0,0,0,0,0)");
zoom = 0;
- params.set(CameraParameters::KEY_ZOOM, zoom);
- params.set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1);
-
+ zoomAvailable = false;
camera_metadata_ro_entry_t maxDigitalZoom =
staticInfo(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, /*minCount*/1, /*maxCount*/1);
if (!maxDigitalZoom.count) return NO_INIT;
- {
- String8 zoomRatios;
- float zoom = 1.f;
- float zoomIncrement = (maxDigitalZoom.data.f[0] - zoom) /
- (NUM_ZOOM_STEPS-1);
- bool addComma = false;
- for (size_t i=0; i < NUM_ZOOM_STEPS; i++) {
- if (addComma) zoomRatios += ",";
- addComma = true;
- zoomRatios += String8::format("%d", static_cast<int>(zoom * 100));
- zoom += zoomIncrement;
- }
- params.set(CameraParameters::KEY_ZOOM_RATIOS, zoomRatios);
- }
+ if (fabs(maxDigitalZoom.data.f[0] - 1.f) > 0.00001f) {
+ params.set(CameraParameters::KEY_ZOOM, zoom);
+ params.set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1);
- params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
- CameraParameters::TRUE);
+ {
+ String8 zoomRatios;
+ float zoom = 1.f;
+ float zoomIncrement = (maxDigitalZoom.data.f[0] - zoom) /
+ (NUM_ZOOM_STEPS-1);
+ bool addComma = false;
+ for (size_t i=0; i < NUM_ZOOM_STEPS; i++) {
+ if (addComma) zoomRatios += ",";
+ addComma = true;
+ zoomRatios += String8::format("%d", static_cast<int>(zoom * 100));
+ zoom += zoomIncrement;
+ }
+ params.set(CameraParameters::KEY_ZOOM_RATIOS, zoomRatios);
+ }
+
+ params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
+ CameraParameters::TRUE);
+ zoomAvailable = true;
+ } else {
+ params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
+ CameraParameters::FALSE);
+ }
params.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED,
CameraParameters::FALSE);
@@ -1836,13 +1865,25 @@
return BAD_VALUE;
}
- // AUTO_EXPOSURE_LOCK (always supported)
- validatedParams.autoExposureLock = boolFromString(
- newParams.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK));
+ if (autoExposureLockAvailable) {
+ validatedParams.autoExposureLock = boolFromString(
+ newParams.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK));
+ } else if (nullptr !=
+ newParams.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK)){
+ ALOGE("%s: Requested auto exposure lock is not supported",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
- // AUTO_WHITEBALANCE_LOCK (always supported)
- validatedParams.autoWhiteBalanceLock = boolFromString(
- newParams.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK));
+ if (autoWhiteBalanceLockAvailable) {
+ validatedParams.autoWhiteBalanceLock = boolFromString(
+ newParams.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK));
+ } else if (nullptr !=
+ newParams.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK)) {
+ ALOGE("%s: Requested auto whitebalance lock is not supported",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
// METERING_AREAS
size_t maxAeRegions = (size_t)staticInfo(ANDROID_CONTROL_MAX_REGIONS,
@@ -1862,12 +1903,14 @@
}
// ZOOM
- validatedParams.zoom = newParams.getInt(CameraParameters::KEY_ZOOM);
- if (validatedParams.zoom < 0
- || validatedParams.zoom >= (int)NUM_ZOOM_STEPS) {
- ALOGE("%s: Requested zoom level %d is not supported",
- __FUNCTION__, validatedParams.zoom);
- return BAD_VALUE;
+ if (zoomAvailable) {
+ validatedParams.zoom = newParams.getInt(CameraParameters::KEY_ZOOM);
+ if (validatedParams.zoom < 0
+ || validatedParams.zoom >= (int)NUM_ZOOM_STEPS) {
+ ALOGE("%s: Requested zoom level %d is not supported",
+ __FUNCTION__, validatedParams.zoom);
+ return BAD_VALUE;
+ }
}
// VIDEO_SIZE
@@ -1988,10 +2031,12 @@
}
if (res != OK) return res;
- uint8_t reqWbLock = autoWhiteBalanceLock ?
- ANDROID_CONTROL_AWB_LOCK_ON : ANDROID_CONTROL_AWB_LOCK_OFF;
- res = request->update(ANDROID_CONTROL_AWB_LOCK,
- &reqWbLock, 1);
+ if (autoWhiteBalanceLockAvailable) {
+ uint8_t reqWbLock = autoWhiteBalanceLock ?
+ ANDROID_CONTROL_AWB_LOCK_ON : ANDROID_CONTROL_AWB_LOCK_OFF;
+ res = request->update(ANDROID_CONTROL_AWB_LOCK,
+ &reqWbLock, 1);
+ }
res = request->update(ANDROID_CONTROL_EFFECT_MODE,
&effectMode, 1);
@@ -2049,11 +2094,13 @@
&reqAeMode, 1);
if (res != OK) return res;
- uint8_t reqAeLock = autoExposureLock ?
- ANDROID_CONTROL_AE_LOCK_ON : ANDROID_CONTROL_AE_LOCK_OFF;
- res = request->update(ANDROID_CONTROL_AE_LOCK,
- &reqAeLock, 1);
- if (res != OK) return res;
+ if (autoExposureLockAvailable) {
+ uint8_t reqAeLock = autoExposureLock ?
+ ANDROID_CONTROL_AE_LOCK_ON : ANDROID_CONTROL_AE_LOCK_OFF;
+ res = request->update(ANDROID_CONTROL_AE_LOCK,
+ &reqAeLock, 1);
+ if (res != OK) return res;
+ }
res = request->update(ANDROID_CONTROL_AWB_MODE,
&wbMode, 1);
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index c8ecbba..507de75 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -122,7 +122,9 @@
int32_t exposureCompensation;
bool autoExposureLock;
+ bool autoExposureLockAvailable;
bool autoWhiteBalanceLock;
+ bool autoWhiteBalanceLockAvailable;
// 3A region types, for use with ANDROID_CONTROL_MAX_REGIONS
enum region_t {
@@ -135,6 +137,7 @@
Vector<Area> meteringAreas;
int zoom;
+ bool zoomAvailable;
int videoWidth, videoHeight, videoFormat;
android_dataspace videoDataSpace;