Loading media/module/extractors/mp4/MPEG4Extractor.cpp +18 −6 Original line number Diff line number Diff line Loading @@ -523,11 +523,10 @@ media_status_t MPEG4Extractor::getTrackMetaData( } [this, &track] { int64_t duration; int64_t duration = track->mMdhdDurationUs; int32_t samplerate; // Only for audio track. if (track->elst_needs_processing && mHeaderTimescale != 0 && AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) && if (track->elst_needs_processing && mHeaderTimescale != 0 && duration != 0 && AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) { // Elst has to be processed only the first time this function is called. track->elst_needs_processing = false; Loading Loading @@ -1645,7 +1644,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { (long long) duration, (long long) mLastTrack->timescale); return ERROR_MALFORMED; } AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs); // Store this track's mdhd duration to calculate the padding. mLastTrack->mMdhdDurationUs = (int64_t)durationUs; } else { mLastTrack->mMdhdDurationUs = 0; } uint8_t lang[2]; Loading Loading @@ -3907,17 +3909,18 @@ status_t MPEG4Extractor::parseTrackHeader( } int32_t id; int64_t duration; if (version == 1) { // we can get ctime value from U64_AT(&buffer[4]) // we can get mtime value from U64_AT(&buffer[12]) id = U32_AT(&buffer[20]); // we can get duration value from U64_AT(&buffer[28]) duration = U64_AT(&buffer[28]); } else if (version == 0) { // we can get ctime value from U32_AT(&buffer[4]) // we can get mtime value from U32_AT(&buffer[8]) id = U32_AT(&buffer[12]); // we can get duration value from U32_AT(&buffer[20]) duration = U32_AT(&buffer[20]); } else { return ERROR_UNSUPPORTED; } Loading @@ -3926,6 +3929,15 @@ status_t MPEG4Extractor::parseTrackHeader( return ERROR_MALFORMED; AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_TRACK_ID, id); if (duration != 0 && mHeaderTimescale != 0) { long double durationUs = ((long double)duration * 1000000) / mHeaderTimescale; if (durationUs < 0 || durationUs > INT64_MAX) { ALOGE("cannot represent %lld * 1000000 / %lld in 64 bits", (long long) duration, (long long) mHeaderTimescale); return ERROR_MALFORMED; } AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs); } size_t matrixOffset = dynSize + 16; int32_t a00 = U32_AT(&buffer[matrixOffset]); Loading media/module/extractors/mp4/include/MPEG4Extractor.h +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ private: uint8_t *mTx3gBuffer; size_t mTx3gSize, mTx3gFilled; int64_t mMdhdDurationUs; Track() { next = NULL; Loading services/camera/virtualcamera/Android.bp +1 −8 Original line number Diff line number Diff line Loading @@ -65,14 +65,7 @@ cc_library_static { cc_library_static { name: "libvirtualcamera", srcs: [ "VirtualCameraProvider.cc", "VirtualCameraDevice.cc", "VirtualCameraSession.cc", "VirtualCameraStream.cc", "VirtualCameraService.cc", "VirtualCameraSessionContext.cc", "VirtualCameraTestInstance.cc", "VirtualCameraRenderThread.cc", "*.cc", ], defaults: [ "libvirtualcamera_defaults", Loading services/camera/virtualcamera/VirtualCameraCaptureRequest.h 0 → 100644 +59 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H #define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H #include "VirtualCameraDevice.h" namespace android { namespace companion { namespace virtualcamera { // Struct used to pass request settings in the different part of // the virtual camera system. struct RequestSettings { // JPEG_QUALITY metadata int jpegQuality = VirtualCameraDevice::kDefaultJpegQuality; // JPEG_ORIENTATION metadata int jpegOrientation = VirtualCameraDevice::kDefaultJpegOrientation; // JPEG_THUMBNAIL_SIZE metadata Resolution thumbnailResolution = Resolution(0, 0); // JPEG_THUMBNAIL_QUALITY metadata int thumbnailJpegQuality = VirtualCameraDevice::kDefaultJpegQuality; // ANDROID_CONTROL_AE_TARGET_FPS_RANGE metadata std::optional<FpsRange> fpsRange; // CONTROL_CAPTURE_INTENT metadata camera_metadata_enum_android_control_capture_intent_t captureIntent = VirtualCameraDevice::kDefaultCaptureIntent; // JPEG_GPS_LOCATION metadata std::optional<GpsCoordinates> gpsCoordinates; // CONTROL_AE_PRECAPTURE_TRIGGER metadata std::optional<camera_metadata_enum_android_control_ae_precapture_trigger> aePrecaptureTrigger; }; } // namespace virtualcamera } // namespace companion } // namespace android #endif // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H No newline at end of file services/camera/virtualcamera/VirtualCameraCaptureResult.cc 0 → 100644 +119 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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. */ #include "VirtualCameraCaptureResult.h" #include <cstdint> #include "VirtualCameraCaptureRequest.h" #include "aidl/android/hardware/camera/device/CameraMetadata.h" #include "util/MetadataUtil.h" namespace android { namespace companion { namespace virtualcamera { using ::aidl::android::hardware::camera::device::CameraMetadata; namespace { // See REQUEST_PIPELINE_DEPTH in CaptureResult.java. // This roughly corresponds to frame latency, we set to // documented minimum of 2. static constexpr uint8_t kPipelineDepth = 2; } // namespace CameraMetadata createCaptureResultMetadata( const std::chrono::nanoseconds timestamp, const RequestSettings& requestSettings, const Resolution reportedSensorSize) { // All of the keys used in the response needs to be referenced in // availableResultKeys in CameraCharacteristics (see initCameraCharacteristics // in VirtualCameraDevice.cc). MetadataBuilder builder = MetadataBuilder() .setAberrationCorrectionMode( ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF) .setControlAeAvailableAntibandingModes( {ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF}) .setControlAeAntibandingMode(ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF) .setControlAeExposureCompensation(0) .setControlAeLockAvailable(false) .setControlAeLock(ANDROID_CONTROL_AE_LOCK_OFF) .setControlAeMode(ANDROID_CONTROL_AE_MODE_ON) .setControlAePrecaptureTrigger( // Limited devices are expected to have precapture ae enabled and // respond to cancellation request. Since we don't actuall support // AE at all, let's just respect the cancellation expectation in // case it's requested requestSettings.aePrecaptureTrigger == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL ? ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL : ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE) .setControlAeState(ANDROID_CONTROL_AE_STATE_INACTIVE) .setControlAfMode(ANDROID_CONTROL_AF_MODE_OFF) .setControlAfTrigger(ANDROID_CONTROL_AF_TRIGGER_IDLE) .setControlAfState(ANDROID_CONTROL_AF_STATE_INACTIVE) .setControlAwbMode(ANDROID_CONTROL_AWB_MODE_AUTO) .setControlAwbLock(ANDROID_CONTROL_AWB_LOCK_OFF) .setControlAwbState(ANDROID_CONTROL_AWB_STATE_INACTIVE) .setControlCaptureIntent(requestSettings.captureIntent) .setControlEffectMode(ANDROID_CONTROL_EFFECT_MODE_OFF) .setControlMode(ANDROID_CONTROL_MODE_AUTO) .setControlSceneMode(ANDROID_CONTROL_SCENE_MODE_DISABLED) .setControlVideoStabilizationMode( ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF) .setCropRegion(0, 0, reportedSensorSize.width, reportedSensorSize.height) .setFaceDetectMode(ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) .setFlashState(ANDROID_FLASH_STATE_UNAVAILABLE) .setFlashMode(ANDROID_FLASH_MODE_OFF) .setFocalLength(VirtualCameraDevice::kFocalLength) .setJpegQuality(requestSettings.jpegQuality) .setJpegOrientation(requestSettings.jpegOrientation) .setJpegThumbnailSize(requestSettings.thumbnailResolution.width, requestSettings.thumbnailResolution.height) .setJpegThumbnailQuality(requestSettings.thumbnailJpegQuality) .setLensOpticalStabilizationMode( ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF) .setNoiseReductionMode(ANDROID_NOISE_REDUCTION_MODE_OFF) .setPipelineDepth(kPipelineDepth) .setSensorTimestamp(timestamp) .setStatisticsHotPixelMapMode( ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF) .setStatisticsLensShadingMapMode( ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF) .setStatisticsSceneFlicker(ANDROID_STATISTICS_SCENE_FLICKER_NONE); if (requestSettings.fpsRange.has_value()) { builder.setControlAeTargetFpsRange(requestSettings.fpsRange.value()); } if (requestSettings.gpsCoordinates.has_value()) { const GpsCoordinates& coordinates = requestSettings.gpsCoordinates.value(); builder.setJpegGpsCoordinates(coordinates); } std::unique_ptr<CameraMetadata> metadata = builder.build(); if (metadata == nullptr) { ALOGE("%s: Failed to build capture result metadata", __func__); return CameraMetadata(); } return std::move(*metadata); } } // namespace virtualcamera } // namespace companion } // namespace android No newline at end of file Loading
media/module/extractors/mp4/MPEG4Extractor.cpp +18 −6 Original line number Diff line number Diff line Loading @@ -523,11 +523,10 @@ media_status_t MPEG4Extractor::getTrackMetaData( } [this, &track] { int64_t duration; int64_t duration = track->mMdhdDurationUs; int32_t samplerate; // Only for audio track. if (track->elst_needs_processing && mHeaderTimescale != 0 && AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) && if (track->elst_needs_processing && mHeaderTimescale != 0 && duration != 0 && AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) { // Elst has to be processed only the first time this function is called. track->elst_needs_processing = false; Loading Loading @@ -1645,7 +1644,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { (long long) duration, (long long) mLastTrack->timescale); return ERROR_MALFORMED; } AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs); // Store this track's mdhd duration to calculate the padding. mLastTrack->mMdhdDurationUs = (int64_t)durationUs; } else { mLastTrack->mMdhdDurationUs = 0; } uint8_t lang[2]; Loading Loading @@ -3907,17 +3909,18 @@ status_t MPEG4Extractor::parseTrackHeader( } int32_t id; int64_t duration; if (version == 1) { // we can get ctime value from U64_AT(&buffer[4]) // we can get mtime value from U64_AT(&buffer[12]) id = U32_AT(&buffer[20]); // we can get duration value from U64_AT(&buffer[28]) duration = U64_AT(&buffer[28]); } else if (version == 0) { // we can get ctime value from U32_AT(&buffer[4]) // we can get mtime value from U32_AT(&buffer[8]) id = U32_AT(&buffer[12]); // we can get duration value from U32_AT(&buffer[20]) duration = U32_AT(&buffer[20]); } else { return ERROR_UNSUPPORTED; } Loading @@ -3926,6 +3929,15 @@ status_t MPEG4Extractor::parseTrackHeader( return ERROR_MALFORMED; AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_TRACK_ID, id); if (duration != 0 && mHeaderTimescale != 0) { long double durationUs = ((long double)duration * 1000000) / mHeaderTimescale; if (durationUs < 0 || durationUs > INT64_MAX) { ALOGE("cannot represent %lld * 1000000 / %lld in 64 bits", (long long) duration, (long long) mHeaderTimescale); return ERROR_MALFORMED; } AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs); } size_t matrixOffset = dynSize + 16; int32_t a00 = U32_AT(&buffer[matrixOffset]); Loading
media/module/extractors/mp4/include/MPEG4Extractor.h +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ private: uint8_t *mTx3gBuffer; size_t mTx3gSize, mTx3gFilled; int64_t mMdhdDurationUs; Track() { next = NULL; Loading
services/camera/virtualcamera/Android.bp +1 −8 Original line number Diff line number Diff line Loading @@ -65,14 +65,7 @@ cc_library_static { cc_library_static { name: "libvirtualcamera", srcs: [ "VirtualCameraProvider.cc", "VirtualCameraDevice.cc", "VirtualCameraSession.cc", "VirtualCameraStream.cc", "VirtualCameraService.cc", "VirtualCameraSessionContext.cc", "VirtualCameraTestInstance.cc", "VirtualCameraRenderThread.cc", "*.cc", ], defaults: [ "libvirtualcamera_defaults", Loading
services/camera/virtualcamera/VirtualCameraCaptureRequest.h 0 → 100644 +59 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H #define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H #include "VirtualCameraDevice.h" namespace android { namespace companion { namespace virtualcamera { // Struct used to pass request settings in the different part of // the virtual camera system. struct RequestSettings { // JPEG_QUALITY metadata int jpegQuality = VirtualCameraDevice::kDefaultJpegQuality; // JPEG_ORIENTATION metadata int jpegOrientation = VirtualCameraDevice::kDefaultJpegOrientation; // JPEG_THUMBNAIL_SIZE metadata Resolution thumbnailResolution = Resolution(0, 0); // JPEG_THUMBNAIL_QUALITY metadata int thumbnailJpegQuality = VirtualCameraDevice::kDefaultJpegQuality; // ANDROID_CONTROL_AE_TARGET_FPS_RANGE metadata std::optional<FpsRange> fpsRange; // CONTROL_CAPTURE_INTENT metadata camera_metadata_enum_android_control_capture_intent_t captureIntent = VirtualCameraDevice::kDefaultCaptureIntent; // JPEG_GPS_LOCATION metadata std::optional<GpsCoordinates> gpsCoordinates; // CONTROL_AE_PRECAPTURE_TRIGGER metadata std::optional<camera_metadata_enum_android_control_ae_precapture_trigger> aePrecaptureTrigger; }; } // namespace virtualcamera } // namespace companion } // namespace android #endif // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H No newline at end of file
services/camera/virtualcamera/VirtualCameraCaptureResult.cc 0 → 100644 +119 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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. */ #include "VirtualCameraCaptureResult.h" #include <cstdint> #include "VirtualCameraCaptureRequest.h" #include "aidl/android/hardware/camera/device/CameraMetadata.h" #include "util/MetadataUtil.h" namespace android { namespace companion { namespace virtualcamera { using ::aidl::android::hardware::camera::device::CameraMetadata; namespace { // See REQUEST_PIPELINE_DEPTH in CaptureResult.java. // This roughly corresponds to frame latency, we set to // documented minimum of 2. static constexpr uint8_t kPipelineDepth = 2; } // namespace CameraMetadata createCaptureResultMetadata( const std::chrono::nanoseconds timestamp, const RequestSettings& requestSettings, const Resolution reportedSensorSize) { // All of the keys used in the response needs to be referenced in // availableResultKeys in CameraCharacteristics (see initCameraCharacteristics // in VirtualCameraDevice.cc). MetadataBuilder builder = MetadataBuilder() .setAberrationCorrectionMode( ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF) .setControlAeAvailableAntibandingModes( {ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF}) .setControlAeAntibandingMode(ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF) .setControlAeExposureCompensation(0) .setControlAeLockAvailable(false) .setControlAeLock(ANDROID_CONTROL_AE_LOCK_OFF) .setControlAeMode(ANDROID_CONTROL_AE_MODE_ON) .setControlAePrecaptureTrigger( // Limited devices are expected to have precapture ae enabled and // respond to cancellation request. Since we don't actuall support // AE at all, let's just respect the cancellation expectation in // case it's requested requestSettings.aePrecaptureTrigger == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL ? ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL : ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE) .setControlAeState(ANDROID_CONTROL_AE_STATE_INACTIVE) .setControlAfMode(ANDROID_CONTROL_AF_MODE_OFF) .setControlAfTrigger(ANDROID_CONTROL_AF_TRIGGER_IDLE) .setControlAfState(ANDROID_CONTROL_AF_STATE_INACTIVE) .setControlAwbMode(ANDROID_CONTROL_AWB_MODE_AUTO) .setControlAwbLock(ANDROID_CONTROL_AWB_LOCK_OFF) .setControlAwbState(ANDROID_CONTROL_AWB_STATE_INACTIVE) .setControlCaptureIntent(requestSettings.captureIntent) .setControlEffectMode(ANDROID_CONTROL_EFFECT_MODE_OFF) .setControlMode(ANDROID_CONTROL_MODE_AUTO) .setControlSceneMode(ANDROID_CONTROL_SCENE_MODE_DISABLED) .setControlVideoStabilizationMode( ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF) .setCropRegion(0, 0, reportedSensorSize.width, reportedSensorSize.height) .setFaceDetectMode(ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) .setFlashState(ANDROID_FLASH_STATE_UNAVAILABLE) .setFlashMode(ANDROID_FLASH_MODE_OFF) .setFocalLength(VirtualCameraDevice::kFocalLength) .setJpegQuality(requestSettings.jpegQuality) .setJpegOrientation(requestSettings.jpegOrientation) .setJpegThumbnailSize(requestSettings.thumbnailResolution.width, requestSettings.thumbnailResolution.height) .setJpegThumbnailQuality(requestSettings.thumbnailJpegQuality) .setLensOpticalStabilizationMode( ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF) .setNoiseReductionMode(ANDROID_NOISE_REDUCTION_MODE_OFF) .setPipelineDepth(kPipelineDepth) .setSensorTimestamp(timestamp) .setStatisticsHotPixelMapMode( ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF) .setStatisticsLensShadingMapMode( ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF) .setStatisticsSceneFlicker(ANDROID_STATISTICS_SCENE_FLICKER_NONE); if (requestSettings.fpsRange.has_value()) { builder.setControlAeTargetFpsRange(requestSettings.fpsRange.value()); } if (requestSettings.gpsCoordinates.has_value()) { const GpsCoordinates& coordinates = requestSettings.gpsCoordinates.value(); builder.setJpegGpsCoordinates(coordinates); } std::unique_ptr<CameraMetadata> metadata = builder.build(); if (metadata == nullptr) { ALOGE("%s: Failed to build capture result metadata", __func__); return CameraMetadata(); } return std::move(*metadata); } } // namespace virtualcamera } // namespace companion } // namespace android No newline at end of file