|
15 | 15 | */ |
16 | 16 | package com.google.android.exoplayer2.extractor.mp4; |
17 | 17 |
|
| 18 | +import static com.google.android.exoplayer2.audio.Ac3Util.TRUEHD_RECHUNK_SAMPLE_COUNT; |
18 | 19 | import static com.google.android.exoplayer2.extractor.mp4.AtomParsers.parseTraks; |
19 | 20 | import static com.google.android.exoplayer2.extractor.mp4.Sniffer.BRAND_HEIC; |
20 | 21 | import static com.google.android.exoplayer2.extractor.mp4.Sniffer.BRAND_QUICKTIME; |
|
44 | 45 | import com.google.android.exoplayer2.metadata.mp4.MotionPhotoMetadata; |
45 | 46 | import com.google.android.exoplayer2.metadata.mp4.SlowMotionData; |
46 | 47 | import com.google.android.exoplayer2.util.Assertions; |
| 48 | +import com.google.android.exoplayer2.util.Log; |
47 | 49 | import com.google.android.exoplayer2.util.MimeTypes; |
48 | 50 | import com.google.android.exoplayer2.util.NalUnitUtil; |
49 | 51 | import com.google.android.exoplayer2.util.ParsableByteArray; |
@@ -155,6 +157,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { |
155 | 157 | private int sampleBytesRead; |
156 | 158 | private int sampleBytesWritten; |
157 | 159 | private int sampleCurrentNalBytesRemaining; |
| 160 | + private int lastReadSampleSize; |
158 | 161 |
|
159 | 162 | // Extractor outputs. |
160 | 163 | private @MonotonicNonNull ExtractorOutput extractorOutput; |
@@ -506,6 +509,12 @@ private void processMoovAtom(ContainerAtom moov) throws ParserException { |
506 | 509 | // Each sample has up to three bytes of overhead for the start code that replaces its length. |
507 | 510 | // Allow ten source samples per output sample, like the platform extractor. |
508 | 511 | int maxInputSize = trackSampleTable.maximumSize + 3 * 10; |
| 512 | + |
| 513 | + if (track.format.sampleMimeType.equals(MimeTypes.AUDIO_TRUEHD)) { |
| 514 | + // TrueHD collates 16 source samples per output |
| 515 | + maxInputSize = trackSampleTable.maximumSize * TRUEHD_RECHUNK_SAMPLE_COUNT; |
| 516 | + } |
| 517 | + |
509 | 518 | Format.Builder formatBuilder = track.format.buildUpon(); |
510 | 519 | formatBuilder.setMaxInputSize(maxInputSize); |
511 | 520 | if (track.type == C.TRACK_TYPE_VIDEO |
@@ -554,7 +563,7 @@ private void processMoovAtom(ContainerAtom moov) throws ParserException { |
554 | 563 | * @return One of the {@code RESULT_*} flags in {@link Extractor}. |
555 | 564 | * @throws IOException If an error occurs reading from the input. |
556 | 565 | */ |
557 | | - private int readSample(ExtractorInput input, PositionHolder positionHolder) throws IOException { |
| 566 | + private int readSample1(ExtractorInput input, PositionHolder positionHolder) throws IOException { |
558 | 567 | long inputPosition = input.getPosition(); |
559 | 568 | if (sampleTrackIndex == C.INDEX_UNSET) { |
560 | 569 | sampleTrackIndex = getTrackIndexOfNextReadSample(inputPosition); |
@@ -632,20 +641,75 @@ private int readSample(ExtractorInput input, PositionHolder positionHolder) thro |
632 | 641 | sampleCurrentNalBytesRemaining -= writtenBytes; |
633 | 642 | } |
634 | 643 | } |
635 | | - trackOutput.sampleMetadata( |
636 | | - track.sampleTable.timestampsUs[sampleIndex], |
637 | | - track.sampleTable.flags[sampleIndex], |
638 | | - sampleSize, |
639 | | - 0, |
640 | | - null); |
| 644 | + |
641 | 645 | track.sampleIndex++; |
642 | 646 | sampleTrackIndex = C.INDEX_UNSET; |
643 | 647 | sampleBytesRead = 0; |
644 | 648 | sampleBytesWritten = 0; |
645 | 649 | sampleCurrentNalBytesRemaining = 0; |
| 650 | + lastReadSampleSize = sampleSize; |
646 | 651 | return RESULT_CONTINUE; |
647 | 652 | } |
648 | 653 |
|
| 654 | + /** |
| 655 | + * Attempts to extract the next sample or the next 16 samples in case of Dolby TrueHD audio |
| 656 | + * in the current mdat atom for the specified track. |
| 657 | + * |
| 658 | + * <p>Returns {@link #RESULT_SEEK} if the source should be reloaded from the position in {@code |
| 659 | + * positionHolder}. |
| 660 | + * |
| 661 | + * <p>Returns {@link #RESULT_END_OF_INPUT} if no samples are left. Otherwise, returns {@link |
| 662 | + * #RESULT_CONTINUE}. |
| 663 | + * |
| 664 | + * @param input The {@link ExtractorInput} from which to read data. |
| 665 | + * @param positionHolder If {@link #RESULT_SEEK} is returned, this holder is updated to hold the |
| 666 | + * position of the required data. |
| 667 | + * @return One of the {@code RESULT_*} flags in {@link Extractor}. |
| 668 | + * @throws IOException If an error occurs reading from the input. |
| 669 | + */ |
| 670 | + private int readSample(ExtractorInput input, PositionHolder positionHolder) throws IOException { |
| 671 | + long inputPosition = input.getPosition(); |
| 672 | + if (sampleTrackIndex == C.INDEX_UNSET) { |
| 673 | + sampleTrackIndex = getTrackIndexOfNextReadSample(inputPosition); |
| 674 | + if (sampleTrackIndex == C.INDEX_UNSET) { |
| 675 | + return RESULT_END_OF_INPUT; |
| 676 | + } |
| 677 | + } |
| 678 | + |
| 679 | + Mp4Track track = castNonNull(tracks)[sampleTrackIndex]; |
| 680 | + TrackOutput trackOutput = track.trackOutput; |
| 681 | + int sampleIndex = track.sampleIndex; |
| 682 | + int result = readSample1(input, positionHolder); |
| 683 | + |
| 684 | + if (result != RESULT_CONTINUE) { |
| 685 | + return result; |
| 686 | + } |
| 687 | + |
| 688 | + int sampleSize = lastReadSampleSize; |
| 689 | + |
| 690 | + if (MimeTypes.AUDIO_TRUEHD.equals(track.track.format.sampleMimeType)) { |
| 691 | + int untilIdx = sampleIndex + TRUEHD_RECHUNK_SAMPLE_COUNT; |
| 692 | + int lastIdx = track.sampleTable.sizes.length; |
| 693 | + |
| 694 | + untilIdx = min(untilIdx, lastIdx); |
| 695 | + |
| 696 | + while (result == RESULT_CONTINUE && track.sampleIndex < untilIdx) { |
| 697 | + int i = track.sampleIndex; |
| 698 | + result = readSample1(input, positionHolder); |
| 699 | + sampleSize += result == RESULT_CONTINUE ? lastReadSampleSize : 0; |
| 700 | + } |
| 701 | + } |
| 702 | + |
| 703 | + trackOutput.sampleMetadata( |
| 704 | + track.sampleTable.timestampsUs[sampleIndex], |
| 705 | + track.sampleTable.flags[sampleIndex], |
| 706 | + sampleSize, |
| 707 | + 0, |
| 708 | + null); |
| 709 | + |
| 710 | + return result; |
| 711 | + } |
| 712 | + |
649 | 713 | /** |
650 | 714 | * Returns the index of the track that contains the next sample to be read, or {@link |
651 | 715 | * C#INDEX_UNSET} if no samples remain. |
|
0 commit comments