tballison commented on PR #2936:
URL: https://github.com/apache/tika/pull/2936#issuecomment-4934951662

   Feedback from claude:
   
   ```
   The feature is worth having and the byte-slicing is genuinely bounds-safe (I 
traced every offset; no OOB, no infinite loops, entry counts can't run away). 
But three things
     stand out: about half the diff re-implements traversal that 
metadata-extractor already does, there are two real bugs in the edit-list 
logic, and the metadata key shape
     deserves a conversation before it becomes API.
   
     1. Most of the plumbing is redundant (verified, not guessed)
   
     Mp4MetaHandler extends Mp4MediaHandler, whose shouldAcceptContainer 
already accepts minf and stbl, and whose shouldAcceptBox already accepts stsd.
     Mp4MetaHandler.processSampleDescription(SequentialReader) is an empty 
override waiting to be filled in.
   
     I confirmed this by running the stock handler plus a one-line hdlr 
injection against the PR's own fixture:
   
     >>> injecting TracingMetaHandler at hdlr/meta
       MetaHandler.shouldAcceptContainer(minf) = true
       MetaHandler.shouldAcceptContainer(stbl) = true
       MetaHandler.shouldAcceptBox(stsd) = true
       *** Mp4MetaHandler.processSampleDescription CALLED ***
           first 16 bytes of stsd payload: 0000000000000001000000506d656278
           entry type at +12: 'mebx'
   
     So instead of the hdlr hijack that returns this and suppresses 
Mp4MetaHandler entirely, plus the global minf/stbl/stsd acceptance in 
TikaMp4BoxHandler, the PR could return
     a TikaMp4MetaHandler extends Mp4MetaHandler from the hdlr branch (passing 
in emptyEditDuration and the movie timescale) and override 
processSampleDescription. That would:
   
     - keep Mp4MetaDirectory alive rather than silently deleting it from the 
extracted directories,
     - stop TikaMp4BoxHandler from descending into minf/stbl and slurping the 
stsd payload of every track whose handler type isn't soun/vide/hint/text/meta 
(sbtl, clcp, tmcd,
     …), which it now does for no benefit,
     - delete shouldAcceptContainer's minf/stbl cases and shouldAcceptBox's 
stsd case.
   
     Only edts (container) and elst (box) genuinely need adding to 
TikaMp4BoxHandler — I confirmed the stock handler returns false for both.
   
     Separately, processMovieTimescale is dead weight: the base 
processMovieHeader already stores the movie timescale, and 
directory.getLongObject(Mp4Directory.TAG_TIME_SCALE)
     returns 600 on this exact fixture. Ten lines and a field can go.
   
     To be fair about the Mp4MetaDirectory deletion: I checked the tag IDs, and 
Mp4MetaDirectory only ever holds TAG_CREATION_TIME=101, 
TAG_MODIFICATION_TIME=102,
     TAG_LANGUAGE_CODE=104, none of which collide with the 0x01xx tags 
processActualMp4Directory reads. So there's no visible regression today. It's a 
latent one.
   
     2. Two correctness bugs in processEditList
   
     The javadoc says "leading empty edit," but the loop scans every entry and 
takes the first mediaTime == -1 wherever it appears:
   
     - Edit list [(dur=100, mt=0), (dur=740, mt=-1), (dur=1, mt=0)] — the track 
presents media starting at movie time 0, so the start is 0. The code reports 
1233333.
     - Two consecutive leading empty edits [(740, -1), (300, -1), (1, 0)] — the 
true start is 1040 ticks. The code reports 740.
   
     The fix is to only honor entry 0, and to sum consecutive leading -1 
entries. Neither shape appears in Apple's own files, but the code doesn't say 
that and nothing stops a
     fuzzer or a third-party muxer.
   
     Related, and cheaper to fix than to argue about: emptyEditDuration * 
1_000_000L overflows for a version-1 elst with a large segment_duration. A 
emptyEditDuration > 
     Long.MAX_VALUE / 1_000_000 guard costs one line.
   
     Also, resetting emptyEditDuration on tkhd assumes tkhd precedes edts. It's 
mandated, but resetting on the trak container instead (processContainer routes 
through
     processBox("trak", null, …)) is free and order-independent.
   
     3. The design question I'd want settled before merge
   
     <key>.track-start-us attaches a track-level fact to every key name the 
track declares. The PR body confirms this in practice: on the real iPhone Live 
Photo, the
     still-image-time track also declares transform keys, and all of them get a 
.track-start-us sibling.
   
     For still-image-time the statement is meaningful only because that track 
has exactly one one-tick sample, so track-start is the sample's presentation 
time. The code never
     checks the sample count — it filters on "is delayed," which correlates 
with "single sample" in Apple's output but isn't the invariant. Note the JIRA 
description explicitly
     lists stts among the boxes to correlate; the PR doesn't read it. A delayed 
multi-sample mebx track would get <key>.track-start-us on keys whose values are 
timestamped all
     over the track.
   
     Two smaller shape questions:
   
     Namespace. com.apple.quicktime.still-image-time.track-start-us is a 
Tika-invented suffix grafted into Apple's namespace. It reads like a key Apple 
defined. It doesn't
     collide with reserved Tika keys (the suffix makes that impossible), so 
it's not a trust-boundary problem in the TIKA-4769 sense — but it's the kind of 
thing that's hard to
     rename later.
   
     Absence is ambiguous. Suppressing undelayed tracks means "no 
still-image-time.track-start-us" can't distinguish "still is the first frame" 
from "not a Live Photo."
     Emitting 0 for a declared-but-undelayed still-image-time track would be 
unambiguous, at the cost of noise on the other keys — which loops back to the 
per-key question.
   
     4. Test gaps
   
     The fixture is a hand-built .mov whose minf contains only stbl and whose 
stbl contains only stsd. Real QuickTime metadata tracks have gmhd, a 
data-reference hdlr
     (dhlr/alis), and dinf inside minf, plus stts/stsc/stsz/stco inside stbl. 
The test therefore never exercises the traversal as it will actually run — in 
particular that
     inner hdlr, which under the PR's approach now reaches super.processBox and 
gets handler-type-dispatched. It works (I checked: alis falls through), but the 
test wouldn't
     catch it if it stopped working.
   
     Nothing covers: an undelayed meta track producing no key (asserted in the 
PR body, untested), a version-1 elst, a non-leading empty edit, or a video 
track with a leading
     empty edit followed by a meta track without one (the state-leak path).
   
     Nits
   
     - The shouldAcceptContainer comment says timed metadata tracks have 
handler type mdta. They have meta — mdta is the moov/meta/hdlr metadata 
handler. The code's own hdlr
     check disagrees with the comment.
     - readInt64 is defined between boxType and addLocation, far from its only 
caller.
     - tikaMetadata.set(...) here vs tikaMetadata.add(...) on the ilst path — 
two delayed tracks declaring the same key silently overwrite.
     - The fixture change also adds mvhd and a trak to a file that previously 
had neither, so testQuickTimeMetadataKeys now additionally produces 
dcterms:created,
     xmpDM:duration, and xmpDM:audioSampleRate=600 (the last being a 
pre-existing MP4Parser quirk — it maps movie timescale to audio sample rate — 
not this PR's fault).
     Existing assertions still pass; just noting the fixture is no longer inert.
   
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to