use of androidx.media3.extractor.metadata.emsg.EventMessage in project media by androidx.
the class DashManifestParser method parseEventStream.
/**
* Parses a single EventStream node in the manifest.
*
* @param xpp The current xml parser.
* @return The {@link EventStream} parsed from this EventStream node.
* @throws XmlPullParserException If there is any error parsing this node.
* @throws IOException If there is any error reading from the underlying input stream.
*/
protected EventStream parseEventStream(XmlPullParser xpp) throws XmlPullParserException, IOException {
String schemeIdUri = parseString(xpp, "schemeIdUri", "");
String value = parseString(xpp, "value", "");
long timescale = parseLong(xpp, "timescale", 1);
List<Pair<Long, EventMessage>> eventMessages = new ArrayList<>();
ByteArrayOutputStream scratchOutputStream = new ByteArrayOutputStream(512);
do {
xpp.next();
if (XmlPullParserUtil.isStartTag(xpp, "Event")) {
Pair<Long, EventMessage> event = parseEvent(xpp, schemeIdUri, value, timescale, scratchOutputStream);
eventMessages.add(event);
} else {
maybeSkipTag(xpp);
}
} while (!XmlPullParserUtil.isEndTag(xpp, "EventStream"));
long[] presentationTimesUs = new long[eventMessages.size()];
EventMessage[] events = new EventMessage[eventMessages.size()];
for (int i = 0; i < eventMessages.size(); i++) {
Pair<Long, EventMessage> event = eventMessages.get(i);
presentationTimesUs[i] = event.first;
events[i] = event.second;
}
return buildEventStream(schemeIdUri, value, timescale, presentationTimesUs, events);
}
use of androidx.media3.extractor.metadata.emsg.EventMessage in project media by androidx.
the class FragmentedMp4Extractor method onEmsgLeafAtomRead.
/**
* Handles an emsg atom (defined in 23009-1).
*/
private void onEmsgLeafAtomRead(ParsableByteArray atom) {
if (emsgTrackOutputs.length == 0) {
return;
}
atom.setPosition(Atom.HEADER_SIZE);
int fullAtom = atom.readInt();
int version = Atom.parseFullAtomVersion(fullAtom);
String schemeIdUri;
String value;
long timescale;
// Only set if version == 0
long presentationTimeDeltaUs = C.TIME_UNSET;
long sampleTimeUs = C.TIME_UNSET;
long durationMs;
long id;
switch(version) {
case 0:
schemeIdUri = checkNotNull(atom.readNullTerminatedString());
value = checkNotNull(atom.readNullTerminatedString());
timescale = atom.readUnsignedInt();
presentationTimeDeltaUs = Util.scaleLargeTimestamp(atom.readUnsignedInt(), C.MICROS_PER_SECOND, timescale);
if (segmentIndexEarliestPresentationTimeUs != C.TIME_UNSET) {
sampleTimeUs = segmentIndexEarliestPresentationTimeUs + presentationTimeDeltaUs;
}
durationMs = Util.scaleLargeTimestamp(atom.readUnsignedInt(), C.MILLIS_PER_SECOND, timescale);
id = atom.readUnsignedInt();
break;
case 1:
timescale = atom.readUnsignedInt();
sampleTimeUs = Util.scaleLargeTimestamp(atom.readUnsignedLongToLong(), C.MICROS_PER_SECOND, timescale);
durationMs = Util.scaleLargeTimestamp(atom.readUnsignedInt(), C.MILLIS_PER_SECOND, timescale);
id = atom.readUnsignedInt();
schemeIdUri = checkNotNull(atom.readNullTerminatedString());
value = checkNotNull(atom.readNullTerminatedString());
break;
default:
Log.w(TAG, "Skipping unsupported emsg version: " + version);
return;
}
byte[] messageData = new byte[atom.bytesLeft()];
atom.readBytes(messageData, /*offset=*/
0, atom.bytesLeft());
EventMessage eventMessage = new EventMessage(schemeIdUri, value, durationMs, id, messageData);
ParsableByteArray encodedEventMessage = new ParsableByteArray(eventMessageEncoder.encode(eventMessage));
int sampleSize = encodedEventMessage.bytesLeft();
// Output the sample data.
for (TrackOutput emsgTrackOutput : emsgTrackOutputs) {
encodedEventMessage.setPosition(0);
emsgTrackOutput.sampleData(encodedEventMessage, sampleSize);
}
// Output the sample metadata.
if (sampleTimeUs == C.TIME_UNSET) {
// We're processing a v0 emsg atom, which contains a presentation time delta, and cannot yet
// calculate its absolute sample timestamp. Defer outputting the metadata until we can.
pendingMetadataSampleInfos.addLast(new MetadataSampleInfo(presentationTimeDeltaUs, /* sampleTimeIsRelative= */
true, sampleSize));
pendingMetadataSampleBytes += sampleSize;
} else if (!pendingMetadataSampleInfos.isEmpty()) {
// We also need to defer outputting metadata if pendingMetadataSampleInfos is non-empty, else
// we will output metadata for samples in the wrong order. See:
// https://github.com/google/ExoPlayer/issues/9996.
pendingMetadataSampleInfos.addLast(new MetadataSampleInfo(sampleTimeUs, /* sampleTimeIsRelative= */
false, sampleSize));
pendingMetadataSampleBytes += sampleSize;
} else {
// We can output the sample metadata immediately.
if (timestampAdjuster != null) {
sampleTimeUs = timestampAdjuster.adjustSampleTimestamp(sampleTimeUs);
}
for (TrackOutput emsgTrackOutput : emsgTrackOutputs) {
emsgTrackOutput.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, /* offset= */
0, null);
}
}
}
use of androidx.media3.extractor.metadata.emsg.EventMessage in project media by androidx.
the class MetadataRendererTest method decodeMetadata.
@Test
public void decodeMetadata() throws Exception {
EventMessage emsg = new EventMessage("urn:test-scheme-id", /* value= */
"", /* durationMs= */
1, /* id= */
0, "Test data".getBytes(UTF_8));
List<Metadata> metadata = runRenderer(eventMessageEncoder.encode(emsg));
assertThat(metadata).hasSize(1);
assertThat(metadata.get(0).length()).isEqualTo(1);
assertThat(metadata.get(0).get(0)).isEqualTo(emsg);
}
use of androidx.media3.extractor.metadata.emsg.EventMessage in project media by androidx.
the class MetadataRendererTest method decodeMetadata_skipsMalformedWrappedMetadata.
@Test
public void decodeMetadata_skipsMalformedWrappedMetadata() throws Exception {
EventMessage emsg = new EventMessage(EventMessage.ID3_SCHEME_ID_AOM, /* value= */
"", /* durationMs= */
1, /* id= */
0, "Not a real ID3 tag".getBytes(ISO_8859_1));
List<Metadata> metadata = runRenderer(eventMessageEncoder.encode(emsg));
assertThat(metadata).isEmpty();
}
use of androidx.media3.extractor.metadata.emsg.EventMessage in project media by androidx.
the class MetadataRendererTest method decodeMetadata_handlesScte35WrappedInEmsg.
@Test
public void decodeMetadata_handlesScte35WrappedInEmsg() throws Exception {
EventMessage emsg = new EventMessage(EventMessage.SCTE35_SCHEME_ID, /* value= */
"", /* durationMs= */
1, /* id= */
0, SCTE35_TIME_SIGNAL_BYTES);
List<Metadata> metadata = runRenderer(eventMessageEncoder.encode(emsg));
assertThat(metadata).hasSize(1);
assertThat(metadata.get(0).length()).isEqualTo(1);
assertThat(metadata.get(0).get(0)).isInstanceOf(TimeSignalCommand.class);
}
Aggregations