mirror of
https://github.com/samsonjs/media.git
synced 2026-04-02 10:45:51 +00:00
Don't overwrite MP4 container fps using capture fps
The capture frame rate is currently available both via Format.metadata and decoded in Format.frameRate. As the container Format.frameRate may be useful to apps, only store the capture frame rate in metadata (apps will need to decode it but can now access the container frame rate too). PiperOrigin-RevId: 284165711
This commit is contained in:
parent
781e15ae3e
commit
4ad6d9d85c
8 changed files with 253 additions and 11 deletions
|
|
@ -21,6 +21,8 @@
|
|||
speed ([#5978](https://github.com/google/ExoPlayer/issues/5978)).
|
||||
* Allow `AdtsExtractor` to encounter EoF when calculating average frame size
|
||||
([#6700](https://github.com/google/ExoPlayer/issues/6700)).
|
||||
* In MP4 streams, store the Android capture frame rate only in
|
||||
`Format.metadata`. `Format.frameRate` now stores the calculated frame rate.
|
||||
* Make media session connector dispatch ACTION_SET_CAPTIONING_ENABLED.
|
||||
* Add support for position and overlapping start/end times in SSA/ASS subtitles
|
||||
([#6320](https://github.com/google/ExoPlayer/issues/6320)).
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import com.google.android.exoplayer2.metadata.id3.InternalFrame;
|
|||
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
|
||||
import com.google.android.exoplayer2.util.Log;
|
||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/** Utilities for handling metadata in MP4. */
|
||||
/* package */ final class MetadataUtil {
|
||||
|
|
@ -108,7 +107,6 @@ import java.nio.ByteBuffer;
|
|||
private static final int TYPE_TOP_BYTE_REPLACEMENT = 0xFD; // Truncated value of \uFFFD.
|
||||
|
||||
private static final String MDTA_KEY_ANDROID_CAPTURE_FPS = "com.android.capture.fps";
|
||||
private static final int MDTA_TYPE_INDICATOR_FLOAT = 23;
|
||||
|
||||
private MetadataUtil() {}
|
||||
|
||||
|
|
@ -138,15 +136,8 @@ import java.nio.ByteBuffer;
|
|||
Metadata.Entry entry = mdtaMetadata.get(i);
|
||||
if (entry instanceof MdtaMetadataEntry) {
|
||||
MdtaMetadataEntry mdtaMetadataEntry = (MdtaMetadataEntry) entry;
|
||||
if (MDTA_KEY_ANDROID_CAPTURE_FPS.equals(mdtaMetadataEntry.key)
|
||||
&& mdtaMetadataEntry.typeIndicator == MDTA_TYPE_INDICATOR_FLOAT) {
|
||||
try {
|
||||
float fps = ByteBuffer.wrap(mdtaMetadataEntry.value).asFloatBuffer().get();
|
||||
format = format.copyWithFrameRate(fps);
|
||||
format = format.copyWithMetadata(new Metadata(mdtaMetadataEntry));
|
||||
} catch (NumberFormatException e) {
|
||||
Log.w(TAG, "Ignoring invalid framerate");
|
||||
}
|
||||
if (MDTA_KEY_ANDROID_CAPTURE_FPS.equals(mdtaMetadataEntry.key)) {
|
||||
format = format.copyWithMetadata(new Metadata(mdtaMetadataEntry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
BIN
library/core/src/test/assets/mp4/sample_android_slow_motion.mp4
Normal file
BIN
library/core/src/test/assets/mp4/sample_android_slow_motion.mp4
Normal file
Binary file not shown.
|
|
@ -0,0 +1,61 @@
|
|||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 526000
|
||||
getPosition(0) = [[timeUs=0, position=1161]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
format:
|
||||
bitrate = -1
|
||||
id = 1
|
||||
containerMimeType = null
|
||||
sampleMimeType = video/avc
|
||||
maxInputSize = 34686
|
||||
width = 1280
|
||||
height = 720
|
||||
frameRate = 13.307984
|
||||
rotationDegrees = 0
|
||||
pixelWidthHeightRatio = 1.0
|
||||
channelCount = -1
|
||||
sampleRate = -1
|
||||
pcmEncoding = -1
|
||||
encoderDelay = 0
|
||||
encoderPadding = 0
|
||||
subsampleOffsetUs = 9223372036854775807
|
||||
selectionFlags = 0
|
||||
language = null
|
||||
drmInitData = -
|
||||
metadata = entries=[mdta: key=com.android.capture.fps]
|
||||
initializationData:
|
||||
data = length 22, hash 4CF81805
|
||||
data = length 9, hash FBAFBA1C
|
||||
total output bytes = 42320
|
||||
sample count = 7
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 34656, hash D92B66FF
|
||||
sample 1:
|
||||
time = 325344
|
||||
flags = 0
|
||||
data = length 768, hash D0C3B229
|
||||
sample 2:
|
||||
time = 358677
|
||||
flags = 0
|
||||
data = length 1184, hash C598EFC0
|
||||
sample 3:
|
||||
time = 392011
|
||||
flags = 0
|
||||
data = length 576, hash 667AEC2C
|
||||
sample 4:
|
||||
time = 425344
|
||||
flags = 0
|
||||
data = length 1456, hash 430D1498
|
||||
sample 5:
|
||||
time = 458677
|
||||
flags = 0
|
||||
data = length 1280, hash 12267E0E
|
||||
sample 6:
|
||||
time = 492011
|
||||
flags = 536870912
|
||||
data = length 2400, hash FBCB42C
|
||||
tracksEnded = true
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 526000
|
||||
getPosition(0) = [[timeUs=0, position=1161]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
format:
|
||||
bitrate = -1
|
||||
id = 1
|
||||
containerMimeType = null
|
||||
sampleMimeType = video/avc
|
||||
maxInputSize = 34686
|
||||
width = 1280
|
||||
height = 720
|
||||
frameRate = 13.307984
|
||||
rotationDegrees = 0
|
||||
pixelWidthHeightRatio = 1.0
|
||||
channelCount = -1
|
||||
sampleRate = -1
|
||||
pcmEncoding = -1
|
||||
encoderDelay = 0
|
||||
encoderPadding = 0
|
||||
subsampleOffsetUs = 9223372036854775807
|
||||
selectionFlags = 0
|
||||
language = null
|
||||
drmInitData = -
|
||||
metadata = entries=[mdta: key=com.android.capture.fps]
|
||||
initializationData:
|
||||
data = length 22, hash 4CF81805
|
||||
data = length 9, hash FBAFBA1C
|
||||
total output bytes = 42320
|
||||
sample count = 7
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 34656, hash D92B66FF
|
||||
sample 1:
|
||||
time = 325344
|
||||
flags = 0
|
||||
data = length 768, hash D0C3B229
|
||||
sample 2:
|
||||
time = 358677
|
||||
flags = 0
|
||||
data = length 1184, hash C598EFC0
|
||||
sample 3:
|
||||
time = 392011
|
||||
flags = 0
|
||||
data = length 576, hash 667AEC2C
|
||||
sample 4:
|
||||
time = 425344
|
||||
flags = 0
|
||||
data = length 1456, hash 430D1498
|
||||
sample 5:
|
||||
time = 458677
|
||||
flags = 0
|
||||
data = length 1280, hash 12267E0E
|
||||
sample 6:
|
||||
time = 492011
|
||||
flags = 536870912
|
||||
data = length 2400, hash FBCB42C
|
||||
tracksEnded = true
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 526000
|
||||
getPosition(0) = [[timeUs=0, position=1161]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
format:
|
||||
bitrate = -1
|
||||
id = 1
|
||||
containerMimeType = null
|
||||
sampleMimeType = video/avc
|
||||
maxInputSize = 34686
|
||||
width = 1280
|
||||
height = 720
|
||||
frameRate = 13.307984
|
||||
rotationDegrees = 0
|
||||
pixelWidthHeightRatio = 1.0
|
||||
channelCount = -1
|
||||
sampleRate = -1
|
||||
pcmEncoding = -1
|
||||
encoderDelay = 0
|
||||
encoderPadding = 0
|
||||
subsampleOffsetUs = 9223372036854775807
|
||||
selectionFlags = 0
|
||||
language = null
|
||||
drmInitData = -
|
||||
metadata = entries=[mdta: key=com.android.capture.fps]
|
||||
initializationData:
|
||||
data = length 22, hash 4CF81805
|
||||
data = length 9, hash FBAFBA1C
|
||||
total output bytes = 42320
|
||||
sample count = 7
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 34656, hash D92B66FF
|
||||
sample 1:
|
||||
time = 325344
|
||||
flags = 0
|
||||
data = length 768, hash D0C3B229
|
||||
sample 2:
|
||||
time = 358677
|
||||
flags = 0
|
||||
data = length 1184, hash C598EFC0
|
||||
sample 3:
|
||||
time = 392011
|
||||
flags = 0
|
||||
data = length 576, hash 667AEC2C
|
||||
sample 4:
|
||||
time = 425344
|
||||
flags = 0
|
||||
data = length 1456, hash 430D1498
|
||||
sample 5:
|
||||
time = 458677
|
||||
flags = 0
|
||||
data = length 1280, hash 12267E0E
|
||||
sample 6:
|
||||
time = 492011
|
||||
flags = 536870912
|
||||
data = length 2400, hash FBCB42C
|
||||
tracksEnded = true
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 526000
|
||||
getPosition(0) = [[timeUs=0, position=1161]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
format:
|
||||
bitrate = -1
|
||||
id = 1
|
||||
containerMimeType = null
|
||||
sampleMimeType = video/avc
|
||||
maxInputSize = 34686
|
||||
width = 1280
|
||||
height = 720
|
||||
frameRate = 13.307984
|
||||
rotationDegrees = 0
|
||||
pixelWidthHeightRatio = 1.0
|
||||
channelCount = -1
|
||||
sampleRate = -1
|
||||
pcmEncoding = -1
|
||||
encoderDelay = 0
|
||||
encoderPadding = 0
|
||||
subsampleOffsetUs = 9223372036854775807
|
||||
selectionFlags = 0
|
||||
language = null
|
||||
drmInitData = -
|
||||
metadata = entries=[mdta: key=com.android.capture.fps]
|
||||
initializationData:
|
||||
data = length 22, hash 4CF81805
|
||||
data = length 9, hash FBAFBA1C
|
||||
total output bytes = 42320
|
||||
sample count = 7
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 34656, hash D92B66FF
|
||||
sample 1:
|
||||
time = 325344
|
||||
flags = 0
|
||||
data = length 768, hash D0C3B229
|
||||
sample 2:
|
||||
time = 358677
|
||||
flags = 0
|
||||
data = length 1184, hash C598EFC0
|
||||
sample 3:
|
||||
time = 392011
|
||||
flags = 0
|
||||
data = length 576, hash 667AEC2C
|
||||
sample 4:
|
||||
time = 425344
|
||||
flags = 0
|
||||
data = length 1456, hash 430D1498
|
||||
sample 5:
|
||||
time = 458677
|
||||
flags = 0
|
||||
data = length 1280, hash 12267E0E
|
||||
sample 6:
|
||||
time = 492011
|
||||
flags = 536870912
|
||||
data = length 2400, hash FBCB42C
|
||||
tracksEnded = true
|
||||
|
|
@ -28,4 +28,9 @@ public final class Mp4ExtractorTest {
|
|||
public void testMp4Sample() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(Mp4Extractor::new, "mp4/sample.mp4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMp4SampleWithSlowMotionMetadata() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(Mp4Extractor::new, "mp4/sample_android_slow_motion.mp4");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue