78 Commits

Author SHA1 Message Date
andrewlewis
174d452bf7 Add missing module registrations
PiperOrigin-RevId: 636506860
2024-05-23 04:50:01 -07:00
Googler
37c2d9957e Fragmented Mp4Muxer: add support to B-frame Muxing
Add composition time offset parameter to TRUN box to
support muxing of videos containing B-frames by FragmentedMp4Muxer.
Update TRUN box version from 0 to 1 in order to manage signed
composition time offset.

PiperOrigin-RevId: 636426397
2024-05-22 23:07:35 -07:00
Googler
55b9c391e8 Box: Implement ctts box
Add ctts box implementation to handle muxing B-frame videos.
Add method convertPresentationTimestampsToCompositionOffset to
provide sample offsets. Return empty ctts box in case of video
does not contain B-frame. Add ctts box to MoovStructure to handle
muxing the video containing B-frames.

PiperOrigin-RevId: 633537106
2024-05-14 04:32:04 -07:00
sheenachhabra
3a3145521b Replace Transformer.Muxer interface with Muxer.Muxer
PiperOrigin-RevId: 633193701
2024-05-13 06:54:19 -07:00
sheenachhabra
10e29be8b6 Allocate correct size for keys and ilst boxes in Mp4Muxer
The keys and ilst boxes in the MP4 muxer were allocated
with a fixed size of 200 bytes. This was not enough to
store the keys and values of large metadata entries, which
could cause the muxer to throw an exception. This CL allocates
the correct size for the keys and ilst boxes based on the size of the metadata entries.

PiperOrigin-RevId: 630331680
2024-05-03 02:47:14 -07:00
sheenachhabra
72013446c4 Update error message to be more specific
PiperOrigin-RevId: 629405290
2024-04-30 07:28:35 -07:00
sheenachhabra
6956d8099a Rename Muxer.addMetadata to addMetadataEntry
This is to make it clear that the method adds a single metadata entry, not a collection of metadata entries.

PiperOrigin-RevId: 629398485
2024-04-30 06:55:50 -07:00
sheenachhabra
bc77cef403 Rollback of 08abc964ab
PiperOrigin-RevId: 629382753
2024-04-30 05:41:45 -07:00
Googler
08abc964ab Box: Implement ctts box
Add ctts box implementation to handle muxing B-frame videos.
Add method convertPresentationTimestampsToCompositionOffset to
provide sample offsets. Return empty ctts box in case of video
does not contain B-frame. Add ctts box to MoovStructure to handle
muxing the video containing B-frames.

PiperOrigin-RevId: 628346257
2024-04-26 02:57:53 -07:00
Googler
430fafded6 Boxes: Update STTS duration calculation.
Update the function convertPresentationTimestampsToDurationsVu
to return a list of duration in decoding order,used in the
creation of STTS boxes.

PiperOrigin-RevId: 627052898
2024-04-22 08:59:06 -07:00
sheenachhabra
03a041c452 Pass BufferInfo in writeSampleData() method in Transformer/Muxer.java
This is to eventually replace Transformer/Muxer.java with Muxer/Muxer.java

PiperOrigin-RevId: 627043808
2024-04-22 08:23:34 -07:00
sheenachhabra
7c7e7ea629 Add API to disable sample copy in Mp4Muxer
PiperOrigin-RevId: 627002635
2024-04-22 05:26:39 -07:00
sheenachhabra
794900bfb8 Update addMetadata method in Transformer/Muxer.java
This is to align the interface with Muxer/Muxer.java and
then finally replace it.

PiperOrigin-RevId: 625283725
2024-04-16 04:40:13 -07:00
sheenachhabra
308c4c4fbf Take fragment duration in Ms instead of Us
PiperOrigin-RevId: 621144165
2024-04-02 05:44:46 -07:00
sheenachhabra
55289b4392 Rename BasicMp4Writer to Mp4Writer
PiperOrigin-RevId: 619560211
2024-03-27 09:44:42 -07:00
sheenachhabra
58e8300ea2 Make isMetadataSupported method public
Moved few other public methods from `Mp4Utils` class into the
corresponding classes which needs them.

PiperOrigin-RevId: 619535658
2024-03-27 08:16:37 -07:00
sheenachhabra
66547cc331 Remove Mp4Writer interface
Since the public class has already been split into `Mp4Muxer` and
`FragmentedMp4Muxer`, there is no need for having common interface
for internal implementation.

In the follow up CL `BasicMp4Writer` will be renamed to `Mp4Writer`
which is more appropriate and aligns with public class names.

PiperOrigin-RevId: 619486876
2024-03-27 04:28:07 -07:00
sheenachhabra
8eb1390f80 Create FragmentedMp4Muxer class
This CL aims to separate Fragmented MP4 related logic in a separate public class.
Earlier all the logic was in a single class `Mp4Muxer`.

PiperOrigin-RevId: 619206661
2024-03-26 09:02:43 -07:00
sheenachhabra
483d2bb9e7 Add Muxer interface in muxer module
The immediate plan is to replace `Transformer Muxer interface`
with this one.
It was not straight forward to move/change `Transformer Muxer interface`
hence this intermediate step.
The follow up CL will also remove fragmented MP4 related code from
`Mp4Muxer` and move it into `FragmentedMp4Muxer implements Muxer`.

PiperOrigin-RevId: 618789265
2024-03-25 03:40:15 -07:00
sheenachhabra
16aac07bce Add support for processing 3 byte NAL start code in Mp4Muxer
Issue: androidx/media#725

Ideally the test to transmux a `ts` file (having 3 bytes NAL start code)
should go into `Mp4MuxerEndToEndTest`but `Mp4MuxerEndToEndTest` uses `MediaExtractor` and `MediaExtractor` is returning samples with `4 byte NAL start code` which will not exercise the newly added code path.
Hence the test is added in `TransformerWithInAppMuxerEndToEndTest` which
internally uses `media3 extractor` and feeds samples with `3 bytes NAL start code`
only.

PiperOrigin-RevId: 617985866
2024-03-21 15:49:12 -07:00
sheenachhabra
2491dd07e1 Process all samples before writing them to mdat
This refactoring is required to support 3 byte NAL start code, in which
the sample ByteBuffer might change after AnnexB to Avcc conversion.
This would required changes in the corresponding BufferInfo as well.

PiperOrigin-RevId: 617538338
2024-03-20 09:33:10 -07:00
sheenachhabra
3272ad50f3 Skip AnnexB to Avcc conversion for AV1 video format
The AV1 video stream does not contain NAL unit which is a concept
specific to H.264/H.265.
This was not caught before muxer does an in place replacement of
`NAL start code` with `NAL length`. In the absence of `NAL start code`
it was automatically a no-op.

PiperOrigin-RevId: 617193317
2024-03-19 09:18:44 -07:00
sheenachhabra
e14156aa3b Rename test classes having duplicate names
PiperOrigin-RevId: 616887534
2024-03-18 11:16:48 -07:00
sheenachhabra
80247bc32c Remove deprecated methods from Mp4Muxer class
PiperOrigin-RevId: 615736494
2024-03-14 04:59:02 -07:00
sheenachhabra
644d9a3461 Remove usage of deprecated methdods from Mp4Muxer tests
PiperOrigin-RevId: 615392633
2024-03-13 06:31:00 -07:00
sheenachhabra
dfe9fba17d Remove non actionable TODOs from Mp4Muxer code
PiperOrigin-RevId: 615372415
2024-03-13 05:07:34 -07:00
sheenachhabra
aba395ca8b Add Mp4OrientationData class
Mp4Muxer now has a single method to accept different
types of metadata.

PiperOrigin-RevId: 614646331
2024-03-11 06:45:15 -07:00
sheenachhabra
bba45b8b35 Rename DefaultMp4Writer to BasicMp4Writer
PiperOrigin-RevId: 611421036
2024-02-29 04:16:15 -08:00
sheenachhabra
6809c0a642 Change Mp4Writer to an interface
The Mp4Writer does not have any default implementation,
hence it can be an interface rather than an abstract class.

PiperOrigin-RevId: 611110415
2024-02-28 08:28:59 -08:00
sheenachhabra
94e0a27a81 Add unified addMetadata() method in Mp4Muxer
PiperOrigin-RevId: 610710011
2024-02-27 04:34:45 -08:00
sheenachhabra
63a8fff69e Use ByteBuffer.remaining() instead of ByteBuffer.limit() in BoxUtil
PiperOrigin-RevId: 610414628
2024-02-26 08:24:35 -08:00
sheenachhabra
41886434ad Remove duplicate Mp4Location class
PiperOrigin-RevId: 609313551
2024-02-22 03:40:35 -08:00
sheenachhabra
d097fe11d0 Add E2E test for Mp4Muxer to verify overall box structure
There is no super test which covers whole MP4 structure.
In all the E2E test, it verified against `ExtractorOutput` which
would remain same if there are changes in the box structure.

PiperOrigin-RevId: 608310006
2024-02-19 05:31:34 -08:00
ibaker
338aef4830 Fix transformer, effect, muxer and container API dependencies
The public APIs of these modules reference symbols in some of their
dependencies, so these should be API dependencies, not implementation:
> An API dependency is one that contains at least one type that is
> exposed in the library binary interface, often referred to as its ABI
> (Application Binary Interface).

https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_recognizing_dependencies

Transformer also uses symbols from `lib-common`, but these are already
an API dep of `lib-exoplayer` so no need to duplicate that here.

PiperOrigin-RevId: 605660621
2024-02-09 10:05:54 -08:00
sheenachhabra
8a758c2ed7 Replace setModificationTime API with setTimestampData in Mp4Muxer
The new API will take both `creation time` and `modification time`.

Till now, Mp4Muxer wrote `modification time` in both
`creation time` and `modification time` field, which was
incorrect.

PiperOrigin-RevId: 605590623
2024-02-09 04:15:53 -08:00
sheenachhabra
cb7ea09af1 Add regression test of skipping empty track when writing MP4
The implementation of fragmented MP4 caused a regression where muxer
started writing empty tracks even for non fragmented MP4.

PiperOrigin-RevId: 603091348
2024-01-31 10:31:52 -08:00
sheenachhabra
0acf6902e5 Write "stco" box instead of "co64" for fragmented MP4
As per MP4 spec ISO 14496-12: 8.7.5 Chunk Offset Box, Both "stco" and
"co64" can be used to store chunk offsets. While "stco" supports 32-bit
offsets, "co64" supports 64-bit offsets.
In non fragmented MP4, the mdat box can be extremely large, hence muxer
uses "co64" box.
But for fragmented MP4, muxer does not write any data in this chunk offset
box (present in "moov" box) because all sample related info is present in
"moof" box.
Technically, "co64" box should also work in fragmented MP4because
its empty only but QuickTime player fails to play video if "co64"
box is present in fragmented MP4 output file.

Testing: Verified that QuickTime player does not play video when "co64"
box is present but is able to play when "stco" box is present.

#minor-release

PiperOrigin-RevId: 601147046
2024-01-24 09:40:20 -08:00
sheenachhabra
806f90922b Write sample data offset related fields in tfhd and trun box
This fix makes output playable on VLC player.
The output does not play on QuickTime player which is being fixed in
a separate CL.

#minor-release

PiperOrigin-RevId: 601118813
2024-01-24 07:52:02 -08:00
sheenachhabra
4c1581a175 Process all tracks before writing fragment in fragmented MP4
Earlier implementation processed each track (pending sample's buffer info)
individually when writing their corresponding "traf" box in a fragment.
The change involves processing all tracks before start writing "traf" boxes.

#minor-release

PiperOrigin-RevId: 600811093
2024-01-23 09:20:52 -08:00
sheenachhabra
94bf9fa81d Do not write empty track (with no samples) in a non fragmented MP4
PiperOrigin-RevId: 600453680
2024-01-22 07:44:55 -08:00
sheenachhabra
36e99f5264 Remove unnecessary passing around of class variable
PiperOrigin-RevId: 599507570
2024-01-18 08:01:33 -08:00
sheenachhabra
666685bd85 Use 4 Byte size field in fMP4 mdat boxes
Since mdat box can be huge so there is a provision to use 64 bit size field.
In case of fragmented MP4, individual fragments should not have large mdat box
so a 32 bit size field should be sufficient.

PiperOrigin-RevId: 599219041
2024-01-17 10:36:47 -08:00
andrewlewis
0513a28169 Remove initialization in declaration
PiperOrigin-RevId: 598835989
2024-01-16 07:35:18 -08:00
sheenachhabra
3ecf8732ba Add comments for skipping input files in Mp4Muxer tests
PiperOrigin-RevId: 595356012
2024-01-03 03:50:46 -08:00
sheenachhabra
5149cc60ac Skip Mp4Muxer tests for unwanted input files
PiperOrigin-RevId: 594478028
2023-12-29 11:10:26 -08:00
sheenachhabra
27ae6d974e Allow creating fragmented MP4 file via InAppMuxer
PiperOrigin-RevId: 594431665
2023-12-29 04:15:01 -08:00
sheenachhabra
e0257f403f Implement fragmented MP4 (fMP4) in the Mp4Muxer
Changes includes;
1. Public API to enable fMP4 and to pass fragment duration.
2. Added `FragmentedMp4Writer`.
3. Added logic to create fragments based on given fragment duration.
4. Write "moov" box only once in the beginning.
3. Add all the required boxes for current implementation.
4. Unit tests for all the new boxes.
5. E2E test for generating fMP4.

Note: The output file is un seek-able with this first implementation.
PiperOrigin-RevId: 594426486
2023-12-29 03:39:38 -08:00
sheenachhabra
1609928242 Throw exception when B-frames are written to Mp4Muxer
Mp4Muxer does not support out of order B-frames. Currently it
silently writes out of order B-frames, producing an invalid file (with
negative sample durations).

Although `Mp4Extractor` is somehow able to process this invalid file and
`Exoplayer` is able to play it but that is unexpected.

The `sample.mp4` test file contains B frames. Other test files does not
contain `H264 video + AAC audio` format hence created a new test file by
running `sample.mp4` via `Transformer` after applying some effects.

PiperOrigin-RevId: 594016144
2023-12-27 08:32:36 -08:00
sheenachhabra
60c8273521 Split Mp4Writer into an abstract class and DefaultMp4Writer
With fMP4 implementation there will be two writers `DefaultMp4Writer`
and `FragmentedMp4Writer`.

Changes includes:
1. Make Mp4Writer as an abstract class and keep only common functionality
into it.
2. Create a DefaultMp4Writer which contains existing logic to write MP4.
3. The fMP4 logic needs to access `pending sample buffer info` at various
places, so did refactoring to split List<Pair<BufferInfo, ByteBuffer>>
into two separate lists.

PiperOrigin-RevId: 592861398
2023-12-21 08:02:01 -08:00
sheenachhabra
0b88e09a82 Improve durationsVuForStts method implementation
Issues with the current implementation
1. The implementation is unnecessarily complicated and can be
easily simplified.To make all the tracks start from the same time,
its only the first sample that require some timestamp adjustments
but the current implementation shifts all the timestamps. Since method
calculates the `sample duration`, shifting all the timestamps has no effect
as such.
2. The implementation always forced first sample to start at 0. But when we
want to use same method for `Fragmented MP4` then it will look inaccurate
as we will call this method for different `fragments` and each `fragment`
will not start from 0 presentation time. Although the output will be same
since this method returns `duration` and not the `timestamps`.
3. As per previous implementation if there is just one sample then
its duration is made equals to its presentation time, which looks incorrect.
With new changes, if a single sample is passed then its duration will always
be 0 irrespective of specified last sample duration behaviour.

PiperOrigin-RevId: 592826612
2023-12-21 04:45:43 -08:00