Merge "Handle malformed raw AAC/AMR writer better" into jb-mr1-dev
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 8e7861e..ac88d1f 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -349,7 +349,10 @@
size_t len = strlen(argv[1]);
if ((!usemp4 && len >= 3 && !strcasecmp(".ts", &argv[1][len - 3])) ||
- (usemp4 && len >= 4 && !strcasecmp(".mp4", &argv[1][len - 4]))) {
+ (usemp4 && len >= 4 &&
+ (!strcasecmp(".mp4", &argv[1][len - 4])
+ || !strcasecmp(".3gp", &argv[1][len- 4])
+ || !strcasecmp(".3g2", &argv[1][len- 4])))) {
int fd = open(argv[1], O_RDONLY);
if (fd < 0) {
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
index 299116d..bb97abc 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
@@ -1314,34 +1314,3 @@
}
return status;
}
-
-FwdLockConv_Status_t FwdLockConv_ConvertFile(const char *pInputFilename,
- const char *pOutputFilename,
- off64_t *pErrorPos) {
- FwdLockConv_Status_t status;
- if (pErrorPos != NULL) {
- *pErrorPos = INVALID_OFFSET;
- }
- if (pInputFilename == NULL || pOutputFilename == NULL) {
- status = FwdLockConv_Status_InvalidArgument;
- } else {
- int inputFileDesc = open(pInputFilename, O_RDONLY);
- if (inputFileDesc < 0) {
- status = FwdLockConv_Status_FileNotFound;
- } else {
- int outputFileDesc = open(pOutputFilename, O_CREAT | O_TRUNC | O_WRONLY,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (outputFileDesc < 0) {
- status = FwdLockConv_Status_FileCreationFailed;
- } else {
- status = FwdLockConv_ConvertOpenFile(inputFileDesc, read, outputFileDesc, write,
- lseek64, pErrorPos);
- if (close(outputFileDesc) == 0 && status != FwdLockConv_Status_OK) {
- remove(pOutputFilename);
- }
- }
- (void)close(inputFileDesc);
- }
- }
- return status;
-}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h
index e20c0c3..6449d89 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h
@@ -245,36 +245,6 @@
FwdLockConv_LSeekFunc_t *fpLSeekFunc,
off64_t *pErrorPos);
-/**
- * Converts an OMA DRM v1 Forward Lock file to the internal Forward Lock file format in pull mode.
- *
- * @param[in] pInputFilename A reference to the input filename.
- * @param[in] pOutputFilename A reference to the output filename.
- * @param[out] pErrorPos
- * The file position where the error occurred, in the case of a syntax error. May be NULL.
- *
- * @return A status code.
- * @retval FwdLockConv_Status_OK
- * @retval FwdLockConv_Status_InvalidArgument
- * @retval FwdLockConv_Status_OutOfMemory
- * @retval FwdLockConv_Status_FileNotFound
- * @retval FwdLockConv_Status_FileCreationFailed
- * @retval FwdLockConv_Status_FileReadError
- * @retval FwdLockConv_Status_FileWriteError
- * @retval FwdLockConv_Status_FileSeekError
- * @retval FwdLockConv_Status_SyntaxError
- * @retval FwdLockConv_Status_UnsupportedFileFormat
- * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding
- * @retval FwdLockConv_Status_RandomNumberGenerationFailed
- * @retval FwdLockConv_Status_KeyEncryptionFailed
- * @retval FwdLockConv_Status_DataEncryptionFailed
- * @retval FwdLockConv_Status_IntegrityProtectionFailed
- * @retval FwdLockConv_Status_TooManySessions
- */
-FwdLockConv_Status_t FwdLockConv_ConvertFile(const char *pInputFilename,
- const char *pOutputFilename,
- off64_t *pErrorPos);
-
#ifdef __cplusplus
}
#endif
diff --git a/media/libmediaplayerservice/nuplayer/mp4/Parser.cpp b/media/libmediaplayerservice/nuplayer/mp4/Parser.cpp
index b9fe819..7938fa4 100644
--- a/media/libmediaplayerservice/nuplayer/mp4/Parser.cpp
+++ b/media/libmediaplayerservice/nuplayer/mp4/Parser.cpp
@@ -271,6 +271,19 @@
mBuffer->setRange(0, mBuffer->size());
size_t maxBytesToRead = mBuffer->capacity() - mBuffer->size();
+
+ if (maxBytesToRead < needed) {
+ ALOGI("resizing buffer.");
+
+ sp<ABuffer> newBuffer =
+ new ABuffer((mBuffer->size() + needed + 1023) & ~1023);
+ memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
+ newBuffer->setRange(0, mBuffer->size());
+
+ mBuffer = newBuffer;
+ maxBytesToRead = mBuffer->capacity() - mBuffer->size();
+ }
+
CHECK_GE(maxBytesToRead, needed);
ssize_t n = mSource->readAt(
@@ -1023,6 +1036,11 @@
case FOURCC('m', 'p', '4', 'v'):
format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
break;
+ case FOURCC('s', '2', '6', '3'):
+ case FOURCC('h', '2', '6', '3'):
+ case FOURCC('H', '2', '6', '3'):
+ format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
+ break;
default:
format->setString("mime", "application/octet-stream");
break;
@@ -1062,11 +1080,13 @@
case FOURCC('m', 'p', '4', 'a'):
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
break;
+
case FOURCC('s', 'a', 'm', 'r'):
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
format->setInt32("channel-count", 1);
format->setInt32("sample-rate", 8000);
break;
+
case FOURCC('s', 'a', 'w', 'b'):
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
format->setInt32("channel-count", 1);
diff --git a/media/libmediaplayerservice/nuplayer/mp4/TrackFragment.cpp b/media/libmediaplayerservice/nuplayer/mp4/TrackFragment.cpp
index 12e71db..a4c31ea 100644
--- a/media/libmediaplayerservice/nuplayer/mp4/TrackFragment.cpp
+++ b/media/libmediaplayerservice/nuplayer/mp4/TrackFragment.cpp
@@ -24,6 +24,7 @@
#include <media/stagefright/Utils.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
namespace android {
@@ -79,6 +80,7 @@
Parser::StaticTrackFragment::StaticTrackFragment()
: mSampleIndex(0),
mSampleCount(0),
+ mChunkIndex(0),
mSampleToChunkIndex(-1),
mSampleToChunkRemaining(0),
mPrevChunkIndex(0xffffffff),
@@ -149,37 +151,31 @@
mSampleInfo.mSampleDescIndex =
U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 8);
- uint32_t chunkIndex =
- U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex);
-
- CHECK_GE(chunkIndex, 1);
- --chunkIndex;
-
- if (chunkIndex != mPrevChunkIndex) {
- mPrevChunkIndex = chunkIndex;
+ if (mChunkIndex != mPrevChunkIndex) {
+ mPrevChunkIndex = mChunkIndex;
if (mChunkOffsets != NULL) {
uint32_t entryCount = U32_AT(mChunkOffsets->data() + 4);
- if (chunkIndex >= entryCount) {
+ if (mChunkIndex >= entryCount) {
mSampleIndex = mSampleCount;
return;
}
mNextSampleOffset =
- U32_AT(mChunkOffsets->data() + 8 + 4 * chunkIndex);
+ U32_AT(mChunkOffsets->data() + 8 + 4 * mChunkIndex);
} else {
CHECK(mChunkOffsets64 != NULL);
uint32_t entryCount = U32_AT(mChunkOffsets64->data() + 4);
- if (chunkIndex >= entryCount) {
+ if (mChunkIndex >= entryCount) {
mSampleIndex = mSampleCount;
return;
}
mNextSampleOffset =
- U64_AT(mChunkOffsets64->data() + 8 + 8 * chunkIndex);
+ U64_AT(mChunkOffsets64->data() + 8 + 8 * mChunkIndex);
}
}
@@ -194,14 +190,25 @@
++mSampleIndex;
if (--mSampleToChunkRemaining == 0) {
+ ++mChunkIndex;
+
uint32_t entryCount = U32_AT(mSampleToChunk->data() + 4);
- if ((uint32_t)(mSampleToChunkIndex + 1) == entryCount) {
- mSampleIndex = mSampleCount; // EOS.
- return;
+ // If this is the last entry in the sample to chunk table, we will
+ // stay on this entry.
+ if ((uint32_t)(mSampleToChunkIndex + 1) < entryCount) {
+ uint32_t nextChunkIndex =
+ U32_AT(mSampleToChunk->data() + 8 + 12 * (mSampleToChunkIndex + 1));
+
+ CHECK_GE(nextChunkIndex, 1u);
+ --nextChunkIndex;
+
+ if (mChunkIndex >= nextChunkIndex) {
+ CHECK_EQ(mChunkIndex, nextChunkIndex);
+ ++mSampleToChunkIndex;
+ }
}
- ++mSampleToChunkIndex;
mSampleToChunkRemaining =
U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4);
}
@@ -216,46 +223,13 @@
ptr[3] = x & 0xff;
}
-void Parser::StaticTrackFragment::fixSampleToChunkTableIfNecessary() {
- if (mSampleToChunk == NULL) {
- return;
- }
- uint32_t entryCount = U32_AT(mSampleToChunk->data() + 4);
- uint32_t totalSamples = 0;
- for (uint32_t i = 0; i < entryCount; ++i) {
- totalSamples += U32_AT(mSampleToChunk->data() + 8 + 12 * i + 4);
- }
-
- if (totalSamples < mSampleCount) {
- // Some samples are not accounted for in the sample-to-chunk
- // data. Fabricate an extra chunk adjacent to the last one
- // in the table with the same sample desription index.
-
- ALOGW("Faking an extra sample-to-chunk entry for %d samples.",
- mSampleCount - totalSamples);
-
- uint32_t lastChunkIndex =
- U32_AT(mSampleToChunk->data() + 8 + 12 * (entryCount - 1));
-
- uint32_t lastSampleDescriptionIndex =
- U32_AT(mSampleToChunk->data() + 8 + 12 * (entryCount - 1) + 8);
-
- uint8_t *ptr = mSampleToChunk->data() + 8 + 12 * entryCount;
-
- setU32At(ptr, lastChunkIndex + 1);
- setU32At(ptr + 4, mSampleCount - totalSamples);
- setU32At(ptr + 8, lastSampleDescriptionIndex);
- setU32At(mSampleToChunk->data() + 4, entryCount + 1);
- }
-}
-
status_t Parser::StaticTrackFragment::signalCompletion() {
- fixSampleToChunkTableIfNecessary();
-
mSampleToChunkIndex = 0;
- mSampleToChunkRemaining = (mSampleToChunk == NULL) ? 0 :
- U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4);
+ mSampleToChunkRemaining =
+ (mSampleToChunk == NULL)
+ ? 0
+ : U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4);
updateSampleInfo();
@@ -339,7 +313,7 @@
return ERROR_MALFORMED;
}
- parser->copyBuffer(&mSampleToChunk, offset, size, 12 /* extra */);
+ parser->copyBuffer(&mSampleToChunk, offset, size);
return OK;
}
diff --git a/media/libmediaplayerservice/nuplayer/mp4/TrackFragment.h b/media/libmediaplayerservice/nuplayer/mp4/TrackFragment.h
index e5945ac..1498aad 100644
--- a/media/libmediaplayerservice/nuplayer/mp4/TrackFragment.h
+++ b/media/libmediaplayerservice/nuplayer/mp4/TrackFragment.h
@@ -96,6 +96,7 @@
private:
size_t mSampleIndex;
size_t mSampleCount;
+ uint32_t mChunkIndex;
SampleInfo mSampleInfo;
@@ -112,7 +113,6 @@
uint64_t mNextSampleOffset;
void updateSampleInfo();
- void fixSampleToChunkTableIfNecessary();
DISALLOW_EVIL_CONSTRUCTORS(StaticTrackFragment);
};
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index cd74e6d..9c2fbcb 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -88,6 +88,8 @@
return NO_INIT;
}
+ res = mDevice->setNotifyCallback(this);
+
res = buildDefaultParameters();
if (res != OK) {
ALOGE("%s: Camera %d: unable to build defaults: %s (%d)",
@@ -846,6 +848,15 @@
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
+ int triggerId;
+ {
+ LockedParameters::Key k(mParameters);
+ k.mParameters.currentAfTriggerId = ++k.mParameters.afTriggerCounter;
+ triggerId = k.mParameters.currentAfTriggerId;
+ }
+
+ mDevice->triggerAutofocus(triggerId);
+
return OK;
}
@@ -855,6 +866,14 @@
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
+ int triggerId;
+ {
+ LockedParameters::Key k(mParameters);
+ triggerId = ++k.mParameters.afTriggerCounter;
+ }
+
+ mDevice->triggerCancelAutofocus(triggerId);
+
return OK;
}
@@ -1453,6 +1472,9 @@
k.mParameters.sceneMode = sceneMode;
k.mParameters.flashMode = flashMode;
+ if (focusMode != k.mParameters.focusMode) {
+ k.mParameters.currentAfTriggerId = -1;
+ }
k.mParameters.focusMode = focusMode;
k.mParameters.focusingAreas = focusingAreas;
@@ -1625,7 +1647,9 @@
}
status_t Camera2Client::commandEnableFocusMoveMsgL(bool enable) {
- ALOGE("%s: Unimplemented!", __FUNCTION__);
+ LockedParameters::Key k(mParameters);
+ k.mParameters.enableFocusMoveMessages = enable;
+
return OK;
}
@@ -1678,6 +1702,101 @@
void Camera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
ALOGV("%s: Autofocus state now %d, last trigger %d",
__FUNCTION__, newState, triggerId);
+ bool sendCompletedMessage = false;
+ bool sendMovingMessage = false;
+
+ bool success = false;
+ bool afInMotion = false;
+ {
+ LockedParameters::Key k(mParameters);
+ switch (k.mParameters.focusMode) {
+ case Parameters::FOCUS_MODE_AUTO:
+ case Parameters::FOCUS_MODE_MACRO:
+ // Don't send notifications upstream if they're not for the current AF
+ // trigger. For example, if cancel was called in between, or if we
+ // already sent a notification about this AF call.
+ if (triggerId != k.mParameters.currentAfTriggerId) break;
+ switch (newState) {
+ case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+ success = true;
+ // no break
+ case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+ sendCompletedMessage = true;
+ k.mParameters.currentAfTriggerId = -1;
+ break;
+ case ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN:
+ // Just starting focusing, ignore
+ break;
+ case ANDROID_CONTROL_AF_STATE_INACTIVE:
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
+ default:
+ // Unexpected in AUTO/MACRO mode
+ ALOGE("%s: Unexpected AF state transition in AUTO/MACRO mode: %d",
+ __FUNCTION__, newState);
+ break;
+ }
+ break;
+ case Parameters::FOCUS_MODE_CONTINUOUS_VIDEO:
+ case Parameters::FOCUS_MODE_CONTINUOUS_PICTURE:
+ switch (newState) {
+ case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+ success = true;
+ // no break
+ case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+ // Don't send notifications upstream if they're not for
+ // the current AF trigger. For example, if cancel was
+ // called in between, or if we already sent a
+ // notification about this AF call.
+ // Send both a 'AF done' callback and a 'AF move' callback
+ if (triggerId != k.mParameters.currentAfTriggerId) break;
+ sendCompletedMessage = true;
+ afInMotion = false;
+ if (k.mParameters.enableFocusMoveMessages &&
+ k.mParameters.afInMotion) {
+ sendMovingMessage = true;
+ }
+ k.mParameters.currentAfTriggerId = -1;
+ break;
+ case ANDROID_CONTROL_AF_STATE_INACTIVE:
+ // Cancel was called, or we switched state; care if
+ // currently moving
+ afInMotion = false;
+ if (k.mParameters.enableFocusMoveMessages &&
+ k.mParameters.afInMotion) {
+ sendMovingMessage = true;
+ }
+ break;
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
+ // Start passive scan, inform upstream
+ afInMotion = true;
+ // no break
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
+ // Stop passive scan, inform upstream
+ if (k.mParameters.enableFocusMoveMessages) {
+ sendMovingMessage = true;
+ }
+ break;
+ }
+ k.mParameters.afInMotion = afInMotion;
+ break;
+ case Parameters::FOCUS_MODE_EDOF:
+ case Parameters::FOCUS_MODE_INFINITY:
+ case Parameters::FOCUS_MODE_FIXED:
+ default:
+ if (newState != ANDROID_CONTROL_AF_STATE_INACTIVE) {
+ ALOGE("%s: Unexpected AF state change %d (ID %d) in focus mode %d",
+ __FUNCTION__, newState, triggerId, k.mParameters.focusMode);
+ }
+ }
+ }
+ if (sendMovingMessage) {
+ mCameraClient->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
+ afInMotion ? 1 : 0, 0);
+ }
+ if (sendCompletedMessage) {
+ mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, success ? 1 : 0, 0);
+ }
}
void Camera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
@@ -2394,9 +2513,7 @@
k.mParameters.focusMode = Parameters::FOCUS_MODE_AUTO;
params.set(CameraParameters::KEY_FOCUS_MODE,
CameraParameters::FOCUS_MODE_AUTO);
- String8 supportedFocusModes(CameraParameters::FOCUS_MODE_FIXED);
- supportedFocusModes = supportedFocusModes + "," +
- CameraParameters::FOCUS_MODE_INFINITY;
+ String8 supportedFocusModes(CameraParameters::FOCUS_MODE_INFINITY);
bool addComma = true;
for (size_t i=0; i < availableAfModes.count; i++) {
@@ -2573,6 +2690,8 @@
k.mParameters.storeMetadataInBuffers = true;
k.mParameters.playShutterSound = true;
+ k.mParameters.afTriggerCounter = 0;
+ k.mParameters.currentAfTriggerId = -1;
k.mParameters.paramsFlattened = params.flatten();
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index 8c10d6b..dffd4ab 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -200,6 +200,11 @@
// listed in Camera.Parameters
bool storeMetadataInBuffers;
bool playShutterSound;
+ bool enableFocusMoveMessages;
+
+ int afTriggerCounter;
+ int currentAfTriggerId;
+ bool afInMotion;
};
class LockedParameters {
@@ -313,9 +318,6 @@
camera_metadata_t *mRecordingRequest;
sp<Camera2Heap> mRecordingHeap;
- // TODO: This needs to be queried from somewhere, or the BufferQueue needs
- // to be passed all the way to stagefright. Right now, set to a large number
- // to avoid starvation of the video encoders.
static const size_t kDefaultRecordingHeapCount = 8;
size_t mRecordingHeapCount;
size_t mRecordingHeapHead, mRecordingHeapFree;
@@ -325,6 +327,10 @@
status_t updateRecordingRequest(const Parameters ¶ms);
status_t updateRecordingStream(const Parameters ¶ms);
+ /** Notification-related members */
+
+ bool mAfInMotion;
+
/** Camera2Device instance wrapping HAL2 entry */
sp<Camera2Device> mDevice;
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 6eca7c0..7c97e1e 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -127,7 +127,8 @@
}
}
- result.appendFormat(" Camera2Device[%d] dump (detail level %d):\n", mId);
+ result.appendFormat(" Camera2Device[%d] dump (detail level %d):\n",
+ mId, detailLevel);
if (detailLevel > 0) {
result = " Request queue contents:\n";
@@ -339,6 +340,42 @@
}
}
+status_t Camera2Device::triggerAutofocus(uint32_t id) {
+ status_t res;
+ ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
+ res = mDevice->ops->trigger_action(mDevice,
+ CAMERA2_TRIGGER_AUTOFOCUS, id, 0);
+ if (res != OK) {
+ ALOGE("%s: Error triggering autofocus (id %d)",
+ __FUNCTION__, id);
+ }
+ return res;
+}
+
+status_t Camera2Device::triggerCancelAutofocus(uint32_t id) {
+ status_t res;
+ ALOGV("%s: Canceling autofocus, id %d", __FUNCTION__, id);
+ res = mDevice->ops->trigger_action(mDevice,
+ CAMERA2_TRIGGER_CANCEL_AUTOFOCUS, id, 0);
+ if (res != OK) {
+ ALOGE("%s: Error canceling autofocus (id %d)",
+ __FUNCTION__, id);
+ }
+ return res;
+}
+
+status_t Camera2Device::triggerPrecaptureMetering(uint32_t id) {
+ status_t res;
+ ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
+ res = mDevice->ops->trigger_action(mDevice,
+ CAMERA2_TRIGGER_PRECAPTURE_METERING, id, 0);
+ if (res != OK) {
+ ALOGE("%s: Error triggering precapture metering (id %d)",
+ __FUNCTION__, id);
+ }
+ return res;
+}
+
/**
* Camera2Device::NotificationListener
*/
@@ -982,11 +1019,13 @@
if (err != OK) {
ALOGE("%s: Error queueing buffer to native window: %s (%d)",
__FUNCTION__, strerror(-err), err);
+ return err;
}
+
stream->mActiveBuffers--;
stream->mFrameCount++;
stream->mLastTimestamp = timestamp;
- return err;
+ return OK;
}
int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
@@ -999,10 +1038,18 @@
ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
return INVALID_OPERATION;
}
- stream->mActiveBuffers--;
+
ANativeWindow *a = toANW(w);
- return a->cancelBuffer(a,
+ int err = a->cancelBuffer(a,
container_of(buffer, ANativeWindowBuffer, handle), -1);
+ if (err != OK) {
+ ALOGE("%s: Error canceling buffer to native window: %s (%d)",
+ __FUNCTION__, strerror(-err), err);
+ return err;
+ }
+
+ stream->mActiveBuffers--;
+ return OK;
}
int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h
index 91a3fbd..9be370f 100644
--- a/services/camera/libcameraservice/Camera2Device.h
+++ b/services/camera/libcameraservice/Camera2Device.h
@@ -123,6 +123,27 @@
*/
status_t setNotifyCallback(NotificationListener *listener);
+ /**
+ * Trigger auto-focus. The latest ID used in a trigger autofocus or cancel
+ * autofocus call will be returned by the HAL in all subsequent AF
+ * notifications.
+ */
+ status_t triggerAutofocus(uint32_t id);
+
+ /**
+ * Cancel auto-focus. The latest ID used in a trigger autofocus/cancel
+ * autofocus call will be returned by the HAL in all subsequent AF
+ * notifications.
+ */
+ status_t triggerCancelAutofocus(uint32_t id);
+
+ /**
+ * Trigger pre-capture metering. The latest ID used in a trigger pre-capture
+ * call will be returned by the HAL in all subsequent AE and AWB
+ * notifications.
+ */
+ status_t triggerPrecaptureMetering(uint32_t id);
+
private:
const int mId;