Search in sources :

Example 6 with EventMessage

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);
}
Also used : EventMessage(androidx.media3.extractor.metadata.emsg.EventMessage) ArrayList(java.util.ArrayList) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Pair(android.util.Pair)

Example 7 with EventMessage

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);
        }
    }
}
Also used : ParsableByteArray(androidx.media3.common.util.ParsableByteArray) EventMessage(androidx.media3.extractor.metadata.emsg.EventMessage) TrackOutput(androidx.media3.extractor.TrackOutput)

Example 8 with EventMessage

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);
}
Also used : EventMessage(androidx.media3.extractor.metadata.emsg.EventMessage) Metadata(androidx.media3.common.Metadata) Test(org.junit.Test)

Example 9 with EventMessage

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();
}
Also used : EventMessage(androidx.media3.extractor.metadata.emsg.EventMessage) Metadata(androidx.media3.common.Metadata) Test(org.junit.Test)

Example 10 with EventMessage

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);
}
Also used : EventMessage(androidx.media3.extractor.metadata.emsg.EventMessage) Metadata(androidx.media3.common.Metadata) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)20 EventMessage (androidx.media3.extractor.metadata.emsg.EventMessage)17 EventStream (androidx.media3.exoplayer.dash.manifest.EventStream)13 Metadata (androidx.media3.common.Metadata)5 ParsableByteArray (androidx.media3.common.util.ParsableByteArray)2 Pair (android.util.Pair)1 TrackOutput (androidx.media3.extractor.TrackOutput)1 TextInformationFrame (androidx.media3.extractor.metadata.id3.TextInformationFrame)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 ArrayList (java.util.ArrayList)1