mirror of
https://github.com/samsonjs/media.git
synced 2026-04-06 11:25:46 +00:00
Unwrap SCTE-35 messages in emsg boxes
PiperOrigin-RevId: 263768428
This commit is contained in:
parent
424f991079
commit
14f77cb8b1
2 changed files with 62 additions and 6 deletions
|
|
@ -35,13 +35,21 @@ public final class EventMessage implements Metadata.Entry {
|
|||
@VisibleForTesting
|
||||
public static final String ID3_SCHEME_ID = "https://developer.apple.com/streaming/emsg-id3";
|
||||
|
||||
/**
|
||||
* scheme_id_uri from section 7.3.2 of <a
|
||||
* href="https://www.scte.org/SCTEDocs/Standards/ANSI_SCTE%20214-3%202015.pdf">SCTE 214-3
|
||||
* 2015</a>.
|
||||
*/
|
||||
@VisibleForTesting public static final String SCTE35_SCHEME_ID = "urn:scte:scte35:2014:bin";
|
||||
|
||||
private static final Format ID3_FORMAT =
|
||||
Format.createSampleFormat(
|
||||
/* id= */ null, MimeTypes.APPLICATION_ID3, Format.OFFSET_SAMPLE_RELATIVE);
|
||||
private static final Format SCTE35_FORMAT =
|
||||
Format.createSampleFormat(
|
||||
/* id= */ null, MimeTypes.APPLICATION_SCTE35, Format.OFFSET_SAMPLE_RELATIVE);
|
||||
|
||||
/**
|
||||
* The message scheme.
|
||||
*/
|
||||
/** The message scheme. */
|
||||
public final String schemeIdUri;
|
||||
|
||||
/**
|
||||
|
|
@ -94,13 +102,20 @@ public final class EventMessage implements Metadata.Entry {
|
|||
@Override
|
||||
@Nullable
|
||||
public Format getWrappedMetadataFormat() {
|
||||
return ID3_SCHEME_ID.equals(schemeIdUri) ? ID3_FORMAT : null;
|
||||
switch (schemeIdUri) {
|
||||
case ID3_SCHEME_ID:
|
||||
return ID3_FORMAT;
|
||||
case SCTE35_SCHEME_ID:
|
||||
return SCTE35_FORMAT;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public byte[] getWrappedMetadataBytes() {
|
||||
return ID3_SCHEME_ID.equals(schemeIdUri) ? messageData : null;
|
||||
return getWrappedMetadataFormat() != null ? messageData : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.google.android.exoplayer2.Format;
|
|||
import com.google.android.exoplayer2.metadata.emsg.EventMessage;
|
||||
import com.google.android.exoplayer2.metadata.emsg.EventMessageEncoder;
|
||||
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
|
||||
import com.google.android.exoplayer2.metadata.scte35.TimeSignalCommand;
|
||||
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
|
|
@ -40,6 +41,28 @@ import org.junit.runner.RunWith;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
public class MetadataRendererTest {
|
||||
|
||||
private static final byte[] SCTE35_TIME_SIGNAL_BYTES =
|
||||
TestUtil.joinByteArrays(
|
||||
TestUtil.createByteArray(
|
||||
0, // table_id.
|
||||
0x80, // section_syntax_indicator, private_indicator, reserved, section_length(4).
|
||||
0x14, // section_length(8).
|
||||
0x00, // protocol_version.
|
||||
0x00), // encrypted_packet, encryption_algorithm, pts_adjustment(1).
|
||||
TestUtil.createByteArray(0x00, 0x00, 0x00, 0x00), // pts_adjustment(32).
|
||||
TestUtil.createByteArray(
|
||||
0x00, // cw_index.
|
||||
0x00, // tier(8).
|
||||
0x00, // tier(4), splice_command_length(4).
|
||||
0x05, // splice_command_length(8).
|
||||
0x06, // splice_command_type = time_signal.
|
||||
// Start of splice_time().
|
||||
0x80), // time_specified_flag, reserved, pts_time(1).
|
||||
TestUtil.createByteArray(
|
||||
0x52, 0x03, 0x02, 0x8f), // pts_time(32). PTS for a second after playback position.
|
||||
TestUtil.createByteArray(
|
||||
0x00, 0x00, 0x00, 0x00)); // CRC_32 (ignored, check happens at extraction).
|
||||
|
||||
private static final Format EMSG_FORMAT =
|
||||
Format.createSampleFormat(null, MimeTypes.APPLICATION_EMSG, Format.OFFSET_SAMPLE_RELATIVE);
|
||||
|
||||
|
|
@ -70,7 +93,7 @@ public class MetadataRendererTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void decodeMetadata_handlesWrappedMetadata() throws Exception {
|
||||
public void decodeMetadata_handlesId3WrappedInEmsg() throws Exception {
|
||||
EventMessage emsg =
|
||||
new EventMessage(
|
||||
EventMessage.ID3_SCHEME_ID,
|
||||
|
|
@ -88,6 +111,24 @@ public class MetadataRendererTest {
|
|||
assertThat(metadata.get(0).get(0)).isEqualTo(expectedId3Frame);
|
||||
}
|
||||
|
||||
@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(EMSG_FORMAT, eventMessageEncoder.encode(emsg));
|
||||
|
||||
assertThat(metadata).hasSize(1);
|
||||
assertThat(metadata.get(0).length()).isEqualTo(1);
|
||||
assertThat(metadata.get(0).get(0)).isInstanceOf(TimeSignalCommand.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decodeMetadata_skipsMalformedWrappedMetadata() throws Exception {
|
||||
EventMessage emsg =
|
||||
|
|
|
|||
Loading…
Reference in a new issue