mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Trim more than one sample for elst gapless
Allow trimming an arbitrary small number of samples (needing to trim up to two samples actually seems to be common). For larger numbers of samples we do coarse trimming by applying the edit list in the normal path, and don't use gapless playback. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=192736956
This commit is contained in:
parent
0a68d1f09c
commit
387cc2f2bd
2 changed files with 28 additions and 11 deletions
|
|
@ -43,6 +43,8 @@
|
||||||
((#3845)[https://github.com/google/ExoPlayer/issues/3845]).
|
((#3845)[https://github.com/google/ExoPlayer/issues/3845]).
|
||||||
* Handle non-empty end-of-stream buffers, to fix gapless playback of streams
|
* Handle non-empty end-of-stream buffers, to fix gapless playback of streams
|
||||||
with encoder padding when the decoder returns a non-empty final buffer.
|
with encoder padding when the decoder returns a non-empty final buffer.
|
||||||
|
* Allow trimming more than one sample when applying an elst audio edit via
|
||||||
|
gapless playback info.
|
||||||
* Caching:
|
* Caching:
|
||||||
* Add release method to Cache interface.
|
* Add release method to Cache interface.
|
||||||
* Prevent multiple instances of SimpleCache in the same folder.
|
* Prevent multiple instances of SimpleCache in the same folder.
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,12 @@ import java.util.List;
|
||||||
private static final int TYPE_clcp = Util.getIntegerCodeForString("clcp");
|
private static final int TYPE_clcp = Util.getIntegerCodeForString("clcp");
|
||||||
private static final int TYPE_meta = Util.getIntegerCodeForString("meta");
|
private static final int TYPE_meta = Util.getIntegerCodeForString("meta");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The threshold number of samples to trim from the start/end of an audio track when applying an
|
||||||
|
* edit below which gapless info can be used (rather than removing samples from the sample table).
|
||||||
|
*/
|
||||||
|
private static final int MAX_GAPLESS_TRIM_SIZE_SAMPLES = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a trak atom (defined in 14496-12).
|
* Parses a trak atom (defined in 14496-12).
|
||||||
*
|
*
|
||||||
|
|
@ -311,22 +317,18 @@ import java.util.List;
|
||||||
|
|
||||||
// See the BMFF spec (ISO 14496-12) subsection 8.6.6. Edit lists that require prerolling from a
|
// See the BMFF spec (ISO 14496-12) subsection 8.6.6. Edit lists that require prerolling from a
|
||||||
// sync sample after reordering are not supported. Partial audio sample truncation is only
|
// sync sample after reordering are not supported. Partial audio sample truncation is only
|
||||||
// supported in edit lists with one edit that removes less than one sample from the start/end of
|
// supported in edit lists with one edit that removes less than MAX_GAPLESS_TRIM_SIZE_SAMPLES
|
||||||
// the track, for gapless audio playback. This implementation handles simple discarding/delaying
|
// samples from the start/end of the track. This implementation handles simple
|
||||||
// of samples. The extractor may place further restrictions on what edited streams are playable.
|
// discarding/delaying of samples. The extractor may place further restrictions on what edited
|
||||||
|
// streams are playable.
|
||||||
|
|
||||||
if (track.editListDurations.length == 1 && track.type == C.TRACK_TYPE_AUDIO
|
if (track.editListDurations.length == 1
|
||||||
|
&& track.type == C.TRACK_TYPE_AUDIO
|
||||||
&& timestamps.length >= 2) {
|
&& timestamps.length >= 2) {
|
||||||
// Handle the edit by setting gapless playback metadata, if possible. This implementation
|
|
||||||
// assumes that only one "roll" sample is needed, which is the case for AAC, so the start/end
|
|
||||||
// points of the edit must lie within the first/last samples respectively.
|
|
||||||
long editStartTime = track.editListMediaTimes[0];
|
long editStartTime = track.editListMediaTimes[0];
|
||||||
long editEndTime = editStartTime + Util.scaleLargeTimestamp(track.editListDurations[0],
|
long editEndTime = editStartTime + Util.scaleLargeTimestamp(track.editListDurations[0],
|
||||||
track.timescale, track.movieTimescale);
|
track.timescale, track.movieTimescale);
|
||||||
if (timestamps[0] <= editStartTime
|
if (canApplyEditWithGaplessInfo(timestamps, duration, editStartTime, editEndTime)) {
|
||||||
&& editStartTime < timestamps[1]
|
|
||||||
&& timestamps[timestamps.length - 1] < editEndTime
|
|
||||||
&& editEndTime <= duration) {
|
|
||||||
long paddingTimeUnits = duration - editEndTime;
|
long paddingTimeUnits = duration - editEndTime;
|
||||||
long encoderDelay = Util.scaleLargeTimestamp(editStartTime - timestamps[0],
|
long encoderDelay = Util.scaleLargeTimestamp(editStartTime - timestamps[0],
|
||||||
track.format.sampleRate, track.timescale);
|
track.format.sampleRate, track.timescale);
|
||||||
|
|
@ -1180,6 +1182,19 @@ import java.util.List;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns whether it's possible to apply the specified edit using gapless playback info. */
|
||||||
|
private static boolean canApplyEditWithGaplessInfo(
|
||||||
|
long[] timestamps, long duration, long editStartTime, long editEndTime) {
|
||||||
|
int lastIndex = timestamps.length - 1;
|
||||||
|
int latestDelayIndex = Util.constrainValue(MAX_GAPLESS_TRIM_SIZE_SAMPLES, 0, lastIndex);
|
||||||
|
int earliestPaddingIndex =
|
||||||
|
Util.constrainValue(timestamps.length - MAX_GAPLESS_TRIM_SIZE_SAMPLES, 0, lastIndex);
|
||||||
|
return timestamps[0] <= editStartTime
|
||||||
|
&& editStartTime < timestamps[latestDelayIndex]
|
||||||
|
&& timestamps[earliestPaddingIndex] < editEndTime
|
||||||
|
&& editEndTime <= duration;
|
||||||
|
}
|
||||||
|
|
||||||
private AtomParsers() {
|
private AtomParsers() {
|
||||||
// Prevent instantiation.
|
// Prevent instantiation.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue