Skip to content

[libmotionphoto] Optimize JPEG motion photo detection and trailer parsing performance. - #6

Merged
DichenZhang1 merged 4 commits into
mainfrom
Development
Oct 2, 2026
Merged

DichenZhang1 merged 4 commits into
mainfrom
Development

Conversation

@DichenZhang1

Copy link
Copy Markdown
Collaborator

Promotes Development (cl/991201939 — PR #4 and PR #5) to main:

  1. Early termination of JPEG scanner at SOS marker:
    XMP metadata precedes the Start of Scan (SOS) marker in JPEG files. When video trailer bounds are extracted directly from XMP metadata, scanning the entire entropy-coded image data (SOS to EOI) is avoided, terminating scanning immediately at SOS.

  2. Parse standard Motion Photo video trailer bounds directly from XMP & separate Legacy MicroVideo into 3P Plugin:
    Inspects standard Motion Photo metadata ((GCamera|Camera):MotionPhoto and Container:Directory Item:Length where Item:Semantic="MotionPhoto" in both attribute and element forms) in JpegContainerSplitter, while moving legacy MicroVideoOffset metadata parsing into the 3P LegacyMicroVideoProvider plugin (DecodeToSemantic -> LegacyMicroVideoMetadata::micro_video_offset and GetVideoInfo).

  3. Expose HandlerOptions in libmotionphoto_api.h and govern is_motion_photo by enabled 3P plugins:
    Exposes HandlerOptions (disable_3p_plugins, enabled_3p_plugins) on ParseMotionPhotoFrom{File,Fd,Memory} and governs out_metadata->is_motion_photo strictly via MetadataEngine::IsMotionPhoto(collection, engine_options).

  4. Eliminate multi-megabyte heap allocation in RawMetadataBlock:
    Retains only a 64-byte prefix in RawMetadataBlock::bytes for signature verification while preserving total_payload_size so full video payloads can be streamed directly from the underlying data source without intermediate RAM allocation.

  5. Lazy on-demand pread DataSource across C++ and JNI APIs:
    Replaces whole-file/whole-fd buffering in ParseMotionPhotoFromFile, ParseMotionPhotoFromFd, ExtractPrimaryImageFromFile, ExtractVideoTrackFromFile, and JNI MetadataEngineJni (parseMetadata and parseMetadataFd) with FdDataSource (reading 64 KB chunks on demand via pread).

DichenZhang1 and others added 4 commits October 2, 2026 01:06
…aths

- Use absl::string_view in GoogleMotionPhotoProvider::Identify and
  LegacyMicroVideoProvider::Identify where absl::StrContains is called,
  fixing compilation against Debian/Ubuntu system libabsl-dev (where
  absl::string_view is absl::debian3::string_view).
- Respect LIBMOTIONPHOTO_USE_SYSTEM_DEPS when resolving absl in
  lib/core/CMakeLists.txt and guard optional absl::log_internal_check_op
  with $<$<TARGET_EXISTS:absl::log_internal_check_op>:...>.
- Avoid installing system abseil in fetchcontent CI jobs so FetchContent
  is properly exercised.
- Update Java API doc check workflow and script paths to lib/java/** and
  harden workflows for Zizmor compliance (explicit permissions, SHA-pinned
  checkout action, and env variable step inputs).
…sing performance.

- Early-terminate JPEG scanner at SOS marker once XMP parses video trailer bounds, avoiding multi-megabyte entropy scan.
- Parse video trailer bounds (Item:Length / MicroVideoOffset) directly from XMP in JpegContainerSplitter.
- Keep only a 64-byte prefix in RawMetadataBlock::bytes while preserving total_payload_size to eliminate 20-120 MB RAM allocations and copies for motion photo video trailers.
- Use lazy FdDataSource (pread in 64 KB chunks on demand over full file range) across C++ (ParseMotionPhotoFromFile/Fd, ExtractPrimaryImageFromFile, ExtractVideoTrackFromFile) and JNI (MetadataEngineJni.parseMetadata and parseMetadataFd).

Tested:
- ./build.sh && ./test.sh (57/57 unit tests pass)
… HandlerOptions in ParseMotionPhoto API (#5)

Syncs the review updates from cl/991201939 onto `Development`:

1. **Standard Motion Photo XMP parsing & Legacy MicroVideo 3P Plugin separation**:
   - Restricts `JpegContainerSplitter::ParseVideoLengthFromXmp` to standard Motion Photo metadata (`(GCamera|Camera):MotionPhoto` and `Container:Directory` `Item:Length` where `Item:Semantic="MotionPhoto"` in both attribute and element forms).
   - Moves legacy `MicroVideoOffset` parsing into `LegacyMicroVideoProvider` (`DecodeToSemantic` -> `LegacyMicroVideoMetadata::micro_video_offset` and `GetVideoInfo`).
   - Uses `total_payload_size` in `LegacyMicroVideoProvider` so full video payloads can be streamed directly from the underlying data source without buffering the video trailer in `RawMetadataBlock::bytes`.

2. **Expose `HandlerOptions` in `libmotionphoto_api.h` and govern `is_motion_photo` by enabled 3P plugins**:
   - Exposes `HandlerOptions` (`disable_3p_plugins`, `enabled_3p_plugins`) on `ParseMotionPhotoFrom{File,Fd,Memory}`.
   - Governs `out_metadata->is_motion_photo` strictly via `MetadataEngine::IsMotionPhoto(collection, engine_options)` so `is_motion_photo` returns `false` when 3P plugins are disabled or only non-matching 3P plugins are enabled, and `true` when all 3P plugins or a matching 3P plugin is enabled.
   - Adds unit tests in `legacy_micro_video_provider_test.cc` and `libmotionphoto_api_test.cc` covering all 4 `HandlerOptions` states.
@DichenZhang1
DichenZhang1 merged commit 9a7da1e into main Oct 2, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant