diff options
19 files changed, 202 insertions, 102 deletions
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index 15c99a5..2fcfc62 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -266,6 +266,7 @@ private: status_t setupMPEG4EncoderParameters(const sp<AMessage> &msg); status_t setupH263EncoderParameters(const sp<AMessage> &msg); status_t setupAVCEncoderParameters(const sp<AMessage> &msg); + status_t setupVPXEncoderParameters(const sp<AMessage> &msg); status_t verifySupportForProfileAndLevel(int32_t profile, int32_t level); diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h index 6b7a63c..34213be 100644 --- a/include/media/stagefright/CameraSourceTimeLapse.h +++ b/include/media/stagefright/CameraSourceTimeLapse.h @@ -41,7 +41,8 @@ public: Size videoSize, int32_t videoFrameRate, const sp<IGraphicBufferProducer>& surface, - int64_t timeBetweenTimeLapseFrameCaptureUs); + int64_t timeBetweenTimeLapseFrameCaptureUs, + bool storeMetaDataInVideoBuffers = true); virtual ~CameraSourceTimeLapse(); @@ -116,7 +117,8 @@ private: Size videoSize, int32_t videoFrameRate, const sp<IGraphicBufferProducer>& surface, - int64_t timeBetweenTimeLapseFrameCaptureUs); + int64_t timeBetweenTimeLapseFrameCaptureUs, + bool storeMetaDataInVideoBuffers = true); // Wrapper over CameraSource::signalBufferReturned() to implement quick stop. // It only handles the case when mLastReadBufferCopy is signalled. Otherwise diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 0e828f7..78dad19 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -70,8 +70,9 @@ StagefrightRecorder::StagefrightRecorder() mOutputFd(-1), mAudioSource(AUDIO_SOURCE_CNT), mVideoSource(VIDEO_SOURCE_LIST_END), - mStarted(false), mSurfaceMediaSource(NULL), - mCaptureTimeLapse(false) { + mCaptureTimeLapse(false), + mStarted(false), + mSurfaceMediaSource(NULL) { ALOGV("Constructor"); reset(); @@ -1089,7 +1090,22 @@ void StagefrightRecorder::clipVideoFrameWidth() { } } -status_t StagefrightRecorder::checkVideoEncoderCapabilities() { +status_t StagefrightRecorder::checkVideoEncoderCapabilities( + bool *supportsCameraSourceMetaDataMode) { + /* hardware codecs must support camera source meta data mode */ + Vector<CodecCapabilities> codecs; + OMXClient client; + CHECK_EQ(client.connect(), (status_t)OK); + QueryCodecs( + client.interface(), + (mVideoEncoder == VIDEO_ENCODER_H263 ? MEDIA_MIMETYPE_VIDEO_H263 : + mVideoEncoder == VIDEO_ENCODER_MPEG_4_SP ? MEDIA_MIMETYPE_VIDEO_MPEG4 : + mVideoEncoder == VIDEO_ENCODER_H264 ? MEDIA_MIMETYPE_VIDEO_AVC : ""), + false /* decoder */, true /* hwCodec */, &codecs); + *supportsCameraSourceMetaDataMode = codecs.size() > 0; + ALOGV("encoder %s camera source meta-data mode", + *supportsCameraSourceMetaDataMode ? "supports" : "DOES NOT SUPPORT"); + if (!mCaptureTimeLapse) { // Dont clip for time lapse capture as encoder will have enough // time to encode because of slow capture rate of time lapse. @@ -1307,7 +1323,9 @@ status_t StagefrightRecorder::setupSurfaceMediaSource() { status_t StagefrightRecorder::setupCameraSource( sp<CameraSource> *cameraSource) { status_t err = OK; - if ((err = checkVideoEncoderCapabilities()) != OK) { + bool encoderSupportsCameraSourceMetaDataMode; + if ((err = checkVideoEncoderCapabilities( + &encoderSupportsCameraSourceMetaDataMode)) != OK) { return err; } Size videoSize; @@ -1323,13 +1341,14 @@ status_t StagefrightRecorder::setupCameraSource( mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera( mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, videoSize, mFrameRate, mPreviewSurface, - mTimeBetweenTimeLapseFrameCaptureUs); + mTimeBetweenTimeLapseFrameCaptureUs, + encoderSupportsCameraSourceMetaDataMode); *cameraSource = mCameraSourceTimeLapse; } else { *cameraSource = CameraSource::CreateFromCamera( mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, videoSize, mFrameRate, - mPreviewSurface, true /*storeMetaDataInVideoBuffers*/); + mPreviewSurface, encoderSupportsCameraSourceMetaDataMode); } mCamera.clear(); mCameraProxy.clear(); diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index ce85957..bc43488 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -134,7 +134,8 @@ private: status_t startRTPRecording(); status_t startMPEG2TSRecording(); sp<MediaSource> createAudioSource(); - status_t checkVideoEncoderCapabilities(); + status_t checkVideoEncoderCapabilities( + bool *supportsCameraSourceMetaDataMode); status_t checkAudioEncoderCapabilities(); // Generic MediaSource set-up. Returns the appropriate // source (CameraSource or SurfaceMediaSource) diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index e7b5caf..6d2191d 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -1962,6 +1962,11 @@ status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { err = setupAVCEncoderParameters(msg); break; + case OMX_VIDEO_CodingVP8: + case OMX_VIDEO_CodingVP9: + err = setupVPXEncoderParameters(msg); + break; + default: break; } @@ -2293,6 +2298,17 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { return configureBitrate(bitrate, bitrateMode); } +status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { + int32_t bitrate; + if (!msg->findInt32("bitrate", &bitrate)) { + return INVALID_OPERATION; + } + + OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); + + return configureBitrate(bitrate, bitrateMode); +} + status_t ACodec::verifySupportForProfileAndLevel( int32_t profile, int32_t level) { OMX_VIDEO_PARAM_PROFILELEVELTYPE params; diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index e1f6563..3f64b66 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -1202,8 +1202,7 @@ void AwesomePlayer::initRenderer_l() { setVideoScalingMode_l(mVideoScalingMode); if (USE_SURFACE_ALLOC && !strncmp(component, "OMX.", 4) - && strncmp(component, "OMX.google.", 11) - && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) { + && strncmp(component, "OMX.google.", 11)) { // Hardware decoders avoid the CPU color conversion by decoding // directly to ANativeBuffers, so we must use a renderer that // just pushes those buffers to the ANativeWindow. @@ -1932,7 +1931,7 @@ void AwesomePlayer::onVideoEvent() { ++mStats.mNumVideoFramesDropped; } - postVideoEvent_l(); + postVideoEvent_l(0); return; } } @@ -1972,6 +1971,41 @@ void AwesomePlayer::onVideoEvent() { return; } + /* get next frame time */ + if (wasSeeking == NO_SEEK) { + MediaSource::ReadOptions options; + for (;;) { + status_t err = mVideoSource->read(&mVideoBuffer, &options); + if (err != OK) { + // deal with any errors next time + CHECK(mVideoBuffer == NULL); + postVideoEvent_l(0); + return; + } + + if (mVideoBuffer->range_length() != 0) { + break; + } + + // Some decoders, notably the PV AVC software decoder + // return spurious empty buffers that we just want to ignore. + + mVideoBuffer->release(); + mVideoBuffer = NULL; + } + + { + Mutex::Autolock autoLock(mStatsLock); + ++mStats.mNumVideoFramesDecoded; + } + + int64_t nextTimeUs; + CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs)); + int64_t delayUs = nextTimeUs - ts->getRealTimeUs() + mTimeSourceDeltaUs; + postVideoEvent_l(delayUs > 10000 ? 10000 : delayUs < 0 ? 0 : delayUs); + return; + } + postVideoEvent_l(); } diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp index 20214e8..5772316 100644 --- a/media/libstagefright/CameraSourceTimeLapse.cpp +++ b/media/libstagefright/CameraSourceTimeLapse.cpp @@ -41,13 +41,15 @@ CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera( Size videoSize, int32_t videoFrameRate, const sp<IGraphicBufferProducer>& surface, - int64_t timeBetweenFrameCaptureUs) { + int64_t timeBetweenFrameCaptureUs, + bool storeMetaDataInVideoBuffers) { CameraSourceTimeLapse *source = new CameraSourceTimeLapse(camera, proxy, cameraId, clientName, clientUid, videoSize, videoFrameRate, surface, - timeBetweenFrameCaptureUs); + timeBetweenFrameCaptureUs, + storeMetaDataInVideoBuffers); if (source != NULL) { if (source->initCheck() != OK) { @@ -67,9 +69,11 @@ CameraSourceTimeLapse::CameraSourceTimeLapse( Size videoSize, int32_t videoFrameRate, const sp<IGraphicBufferProducer>& surface, - int64_t timeBetweenFrameCaptureUs) + int64_t timeBetweenFrameCaptureUs, + bool storeMetaDataInVideoBuffers) : CameraSource(camera, proxy, cameraId, clientName, clientUid, - videoSize, videoFrameRate, surface, true), + videoSize, videoFrameRate, surface, + storeMetaDataInVideoBuffers), mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate), mLastTimeLapseFrameRealTimestampUs(0), mSkipCurrentFrame(false) { diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index cbc169b..8368b39 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -1370,6 +1370,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return err; } + const char *mime; + CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); + if (max_size != 0) { // Assume that a given buffer only contains at most 10 chunks, // each chunk originally prefixed with a 2 byte length will @@ -1379,19 +1382,27 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { } else { // No size was specified. Pick a conservatively large size. int32_t width, height; - if (mLastTrack->meta->findInt32(kKeyWidth, &width) && - mLastTrack->meta->findInt32(kKeyHeight, &height)) { - mLastTrack->meta->setInt32(kKeyMaxInputSize, width * height * 3 / 2); - } else { + if (!mLastTrack->meta->findInt32(kKeyWidth, &width) || + !mLastTrack->meta->findInt32(kKeyHeight, &height)) { ALOGE("No width or height, assuming worst case 1080p"); - mLastTrack->meta->setInt32(kKeyMaxInputSize, 3110400); + width = 1920; + height = 1080; } + + if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { + // AVC requires compression ratio of at least 2, and uses + // macroblocks + max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192; + } else { + // For all other formats there is no minimum compression + // ratio. Use compression ratio of 1. + max_size = width * height * 3 / 2; + } + mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size); } *offset += chunk_size; // Calculate average frame rate. - const char *mime; - CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); if (!strncasecmp("video/", mime, 6)) { size_t nSamples = mLastTrack->sampleTable->countSamples(); int64_t durationUs; diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 063ab49..625922f 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -361,12 +361,7 @@ sp<MediaSource> OMXCodec::Create( observer->setCodec(codec); err = codec->configureCodec(meta); - if (err == OK) { - if (!strcmp("OMX.Nvidia.mpeg2v.decode", componentName)) { - codec->mFlags |= kOnlySubmitOneInputBufferAtOneTime; - } - return codec; } @@ -1359,8 +1354,7 @@ OMXCodec::OMXCodec( mLeftOverBuffer(NULL), mPaused(false), mNativeWindow( - (!strncmp(componentName, "OMX.google.", 11) - || !strcmp(componentName, "OMX.Nvidia.mpeg2v.decode")) + (!strncmp(componentName, "OMX.google.", 11)) ? NULL : nativeWindow) { mPortStatus[kPortIndexInput] = ENABLED; mPortStatus[kPortIndexOutput] = ENABLED; diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index f87b9da..cb57a2f 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp @@ -1199,7 +1199,10 @@ status_t ATSParser::parseTS(ABitReader *br) { unsigned sync_byte = br->getBits(8); CHECK_EQ(sync_byte, 0x47u); - MY_LOGV("transport_error_indicator = %u", br->getBits(1)); + if (br->getBits(1)) { // transport_error_indicator + // silently ignore. + return OK; + } unsigned payload_unit_start_indicator = br->getBits(1); ALOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator); diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index a7c5317..b8970ad 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -156,7 +156,7 @@ void GraphicBufferSource::omxIdle() { if (mExecuting) { // We are only interested in the transition from executing->idle, // not loaded->idle. - mEndOfStream = mEndOfStreamSent = true; + mExecuting = false; } } @@ -206,7 +206,9 @@ void GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) { void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { Mutex::Autolock autoLock(mMutex); - CHECK(mExecuting); // could this happen if app stop()s early? + if (!mExecuting) { + return; + } int cbi = findMatchingCodecBuffer_l(header); if (cbi < 0) { diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 6987dbd..e6d3a4d 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -3994,23 +3994,6 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr sp<Track> l = mLatestActiveTrack.promote(); bool last = l.get() == track; - if (mPreviousTrack != NULL) { - if (track != mPreviousTrack) { - // Flush any data still being written from last track - mBytesRemaining = 0; - if (mPausedBytesRemaining) { - // Last track was paused so we also need to flush saved - // mixbuffer state and invalidate track so that it will - // re-submit that unwritten data when it is next resumed - mPausedBytesRemaining = 0; - // Invalidate is a bit drastic - would be more efficient - // to have a flag to tell client that some of the - // previously written data was lost - mPreviousTrack->invalidate(); - } - } - } - mPreviousTrack = track; if (track->isPausing()) { track->setPaused(); if (last) { @@ -4058,6 +4041,30 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr } if (last) { + if (mPreviousTrack != NULL) { + if (track != mPreviousTrack) { + // Flush any data still being written from last track + mBytesRemaining = 0; + if (mPausedBytesRemaining) { + // Last track was paused so we also need to flush saved + // mixbuffer state and invalidate track so that it will + // re-submit that unwritten data when it is next resumed + mPausedBytesRemaining = 0; + // Invalidate is a bit drastic - would be more efficient + // to have a flag to tell client that some of the + // previously written data was lost + mPreviousTrack->invalidate(); + } + // flush data already sent to the DSP if changing audio session as audio + // comes from a different source. Also invalidate previous track to force a + // seek when resuming. + if (mPreviousTrack->sessionId() != track->sessionId()) { + mPreviousTrack->invalidate(); + mFlushPending = true; + } + } + } + mPreviousTrack = track; // reset retry count track->mRetryCount = kMaxTrackRetriesOffload; mActiveTrack = t; @@ -4076,14 +4083,18 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr track->mState = TrackBase::STOPPING_2; // so presentation completes after drain // do not drain if no data was ever sent to HAL (mStandby == true) if (last && !mStandby) { - sleepTime = 0; - standbyTime = systemTime() + standbyDelay; - mixerStatus = MIXER_DRAIN_TRACK; - mDrainSequence += 2; + // do not modify drain sequence if we are already draining. This happens + // when resuming from pause after drain. + if ((mDrainSequence & 1) == 0) { + sleepTime = 0; + standbyTime = systemTime() + standbyDelay; + mixerStatus = MIXER_DRAIN_TRACK; + mDrainSequence += 2; + } if (mHwPaused) { // It is possible to move from PAUSED to STOPPING_1 without // a resume so we must ensure hardware is running - mOutput->stream->resume(mOutput->stream); + doHwResume = true; mHwPaused = false; } } diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index 1e425ba..08af566 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -183,8 +183,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { // still have to do something sane for them // NOTE: Not scaled like FPS range values are. - previewFps = fpsFromRange(previewFpsRange[0], previewFpsRange[1]); - lastSetPreviewFps = previewFps; + int previewFps = fpsFromRange(previewFpsRange[0], previewFpsRange[1]); params.set(CameraParameters::KEY_PREVIEW_FRAME_RATE, previewFps); @@ -1134,13 +1133,22 @@ status_t Parameters::set(const String8& paramString) { // PREVIEW_FPS_RANGE bool fpsRangeChanged = false; + int32_t lastSetFpsRange[2]; + + params.getPreviewFpsRange(&lastSetFpsRange[0], &lastSetFpsRange[1]); + lastSetFpsRange[0] /= kFpsToApiScale; + lastSetFpsRange[1] /= kFpsToApiScale; + newParams.getPreviewFpsRange(&validatedParams.previewFpsRange[0], &validatedParams.previewFpsRange[1]); validatedParams.previewFpsRange[0] /= kFpsToApiScale; validatedParams.previewFpsRange[1] /= kFpsToApiScale; - if (validatedParams.previewFpsRange[0] != previewFpsRange[0] || - validatedParams.previewFpsRange[1] != previewFpsRange[1]) { + // Compare the FPS range value from the last set() to the current set() + // to determine if the client has changed it + if (validatedParams.previewFpsRange[0] != lastSetFpsRange[0] || + validatedParams.previewFpsRange[1] != lastSetFpsRange[1]) { + fpsRangeChanged = true; camera_metadata_ro_entry_t availablePreviewFpsRanges = staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2); @@ -1158,16 +1166,6 @@ status_t Parameters::set(const String8& paramString) { validatedParams.previewFpsRange[1]); return BAD_VALUE; } - validatedParams.previewFps = - fpsFromRange(validatedParams.previewFpsRange[0], - validatedParams.previewFpsRange[1]); - - // Update our last-seen single preview FPS, needed for disambiguating - // when the application is intending to use the deprecated single-FPS - // setting vs. the range FPS setting - validatedParams.lastSetPreviewFps = newParams.getPreviewFrameRate(); - - newParams.setPreviewFrameRate(validatedParams.previewFps); } // PREVIEW_FORMAT @@ -1205,12 +1203,11 @@ status_t Parameters::set(const String8& paramString) { // PREVIEW_FRAME_RATE Deprecated, only use if the preview fps range is // unchanged this time. The single-value FPS is the same as the minimum of // the range. To detect whether the application has changed the value of - // previewFps, compare against their last-set preview FPS instead of the - // single FPS we may have synthesized from a range FPS set. + // previewFps, compare against their last-set preview FPS. if (!fpsRangeChanged) { - validatedParams.previewFps = newParams.getPreviewFrameRate(); - if (validatedParams.previewFps != lastSetPreviewFps || - recordingHintChanged) { + int previewFps = newParams.getPreviewFrameRate(); + int lastSetPreviewFps = params.getPreviewFrameRate(); + if (previewFps != lastSetPreviewFps || recordingHintChanged) { camera_metadata_ro_entry_t availableFrameRates = staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); /** @@ -1223,8 +1220,8 @@ status_t Parameters::set(const String8& paramString) { * Either way, in case of multiple ranges, break the tie by * selecting the smaller range. */ - int targetFps = validatedParams.previewFps; - // all ranges which have targetFps + + // all ranges which have previewFps Vector<Range> candidateRanges; for (i = 0; i < availableFrameRates.count; i+=2) { Range r = { @@ -1232,13 +1229,13 @@ status_t Parameters::set(const String8& paramString) { availableFrameRates.data.i32[i+1] }; - if (r.min <= targetFps && targetFps <= r.max) { + if (r.min <= previewFps && previewFps <= r.max) { candidateRanges.push(r); } } if (candidateRanges.isEmpty()) { ALOGE("%s: Requested preview frame rate %d is not supported", - __FUNCTION__, validatedParams.previewFps); + __FUNCTION__, previewFps); return BAD_VALUE; } // most applicable range with targetFps @@ -1277,14 +1274,6 @@ status_t Parameters::set(const String8& paramString) { validatedParams.previewFpsRange[1], validatedParams.recordingHint); } - newParams.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, - String8::format("%d,%d", - validatedParams.previewFpsRange[0] * kFpsToApiScale, - validatedParams.previewFpsRange[1] * kFpsToApiScale)); - // Update our last-seen single preview FPS, needed for disambiguating - // when the application is intending to use the deprecated single-FPS - // setting vs. the range FPS setting - validatedParams.lastSetPreviewFps = validatedParams.previewFps; } // PICTURE_SIZE diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h index 93ab113..32dbd42 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.h +++ b/services/camera/libcameraservice/api1/client2/Parameters.h @@ -46,8 +46,6 @@ struct Parameters { int previewWidth, previewHeight; int32_t previewFpsRange[2]; - int lastSetPreviewFps; // the last single FPS value seen in a set call - int previewFps; // deprecated, here only for tracking changes int previewFormat; int previewTransform; // set by CAMERA_CMD_SET_DISPLAY_ORIENTATION diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index 72126c1..1cdf8dc 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -81,7 +81,8 @@ status_t CameraDeviceClient::initialize(camera_module_t *module) mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID, FRAME_PROCESSOR_LISTENER_MAX_ID, - /*listener*/this); + /*listener*/this, + /*quirkSendPartials*/true); return OK; } diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp index b2c9b33..f2064fb 100644 --- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp +++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp @@ -37,11 +37,11 @@ FrameProcessorBase::~FrameProcessorBase() { } status_t FrameProcessorBase::registerListener(int32_t minId, - int32_t maxId, wp<FilteredListener> listener) { + int32_t maxId, wp<FilteredListener> listener, bool quirkSendPartials) { Mutex::Autolock l(mInputMutex); ALOGV("%s: Registering listener for frame id range %d - %d", __FUNCTION__, minId, maxId); - RangeListener rListener = { minId, maxId, listener }; + RangeListener rListener = { minId, maxId, listener, quirkSendPartials }; mRangeListeners.push_back(rListener); return OK; } @@ -145,13 +145,14 @@ status_t FrameProcessorBase::processListeners(const CameraMetadata &frame, ATRACE_CALL(); camera_metadata_ro_entry_t entry; - // Quirks: Don't deliver partial results to listeners + // Quirks: Don't deliver partial results to listeners that don't want them + bool quirkIsPartial = false; entry = frame.find(ANDROID_QUIRKS_PARTIAL_RESULT); if (entry.count != 0 && entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { ALOGV("%s: Camera %d: Not forwarding partial result to listeners", __FUNCTION__, device->getId()); - return OK; + quirkIsPartial = true; } entry = frame.find(ANDROID_REQUEST_ID); @@ -169,7 +170,8 @@ status_t FrameProcessorBase::processListeners(const CameraMetadata &frame, List<RangeListener>::iterator item = mRangeListeners.begin(); while (item != mRangeListeners.end()) { if (requestId >= item->minId && - requestId < item->maxId) { + requestId < item->maxId && + (!quirkIsPartial || item->quirkSendPartials) ) { sp<FilteredListener> listener = item->listener.promote(); if (listener == 0) { item = mRangeListeners.erase(item); diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.h b/services/camera/libcameraservice/common/FrameProcessorBase.h index 4d80ebf..89b608a 100644 --- a/services/camera/libcameraservice/common/FrameProcessorBase.h +++ b/services/camera/libcameraservice/common/FrameProcessorBase.h @@ -44,9 +44,11 @@ class FrameProcessorBase: public Thread { }; // Register a listener for a range of IDs [minId, maxId). Multiple listeners - // can be listening to the same range + // can be listening to the same range. + // QUIRK: sendPartials controls whether partial results will be sent. status_t registerListener(int32_t minId, int32_t maxId, - wp<FilteredListener> listener); + wp<FilteredListener> listener, + bool quirkSendPartials = true); status_t removeListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener); @@ -64,6 +66,7 @@ class FrameProcessorBase: public Thread { int32_t minId; int32_t maxId; wp<FilteredListener> listener; + bool quirkSendPartials; }; List<RangeListener> mRangeListeners; diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index cb72e0e..3dbc1b0 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -1405,7 +1405,8 @@ status_t Camera3Device::registerInFlight(int32_t frameNumber, * Check if all 3A fields are ready, and send off a partial 3A-only result * to the output frame queue */ -bool Camera3Device::processPartial3AQuirk(int32_t frameNumber, +bool Camera3Device::processPartial3AQuirk( + int32_t frameNumber, int32_t requestId, const CameraMetadata& partial) { // Check if all 3A states are present @@ -1452,10 +1453,10 @@ bool Camera3Device::processPartial3AQuirk(int32_t frameNumber, if (!gotAllStates) return false; - ALOGVV("%s: Camera %d: Frame %d: AF mode %d, AWB mode %d, " + ALOGVV("%s: Camera %d: Frame %d, Request ID %d: AF mode %d, AWB mode %d, " "AF state %d, AE state %d, AWB state %d, " "AF trigger %d, AE precapture trigger %d", - __FUNCTION__, mId, frameNumber, + __FUNCTION__, mId, frameNumber, requestId, afMode, awbMode, afState, aeState, awbState, afTriggerId, aeTriggerId); @@ -1463,9 +1464,10 @@ bool Camera3Device::processPartial3AQuirk(int32_t frameNumber, // Got all states, so construct a minimal result to send // In addition to the above fields, this means adding in // android.request.frameCount + // android.request.requestId // android.quirks.partialResult - const size_t kMinimal3AResultEntries = 7; + const size_t kMinimal3AResultEntries = 10; Mutex::Autolock l(mOutputLock); @@ -1479,6 +1481,11 @@ bool Camera3Device::processPartial3AQuirk(int32_t frameNumber, return false; } + if (!insert3AResult(min3AResult, ANDROID_REQUEST_ID, + &requestId, frameNumber)) { + return false; + } + static const uint8_t partialResult = ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL; if (!insert3AResult(min3AResult, ANDROID_QUIRKS_PARTIAL_RESULT, &partialResult, frameNumber)) { @@ -1615,7 +1622,8 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { if (!request.partialResultQuirk.haveSent3A) { request.partialResultQuirk.haveSent3A = processPartial3AQuirk(frameNumber, - request.partialResultQuirk.collectedResult); + request.requestId, + request.partialResultQuirk.collectedResult); } } } diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 4a24a88..468f641 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -491,7 +491,8 @@ class Camera3Device : * and if so, queue up 3A-only result to the client. Returns true if 3A * is sent. */ - bool processPartial3AQuirk(int32_t frameNumber, const CameraMetadata& partial); + bool processPartial3AQuirk(int32_t frameNumber, int32_t requestId, + const CameraMetadata& partial); // Helpers for reading and writing 3A metadata into to/from partial results template<typename T> |