Support emsg metadata decoding
Note: End to end emsg support is still non-functional. There's some additional plumbing that still needs to be done. Issue: #2176 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=143775147
This commit is contained in:
parent
9d5c750fe9
commit
f2634d11f5
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.metadata.emsg;
|
||||||
|
|
||||||
|
import android.test.MoreAsserts;
|
||||||
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link EventMessageDecoder}.
|
||||||
|
*/
|
||||||
|
public final class EventMessageDecoderTest extends TestCase {
|
||||||
|
|
||||||
|
public void testDecodeEventMessage() {
|
||||||
|
byte[] rawEmsgBody = new byte[] {
|
||||||
|
117, 114, 110, 58, 116, 101, 115, 116, 0, // scheme_id_uri = "urn:test"
|
||||||
|
49, 50, 51, 0, // value = "123"
|
||||||
|
0, 0, -69, -128, // timescale = 48000
|
||||||
|
0, 0, 0, 0, // presentation_time_delta (ignored) = 0
|
||||||
|
0, 2, 50, -128, // event_duration = 144000
|
||||||
|
0, 15, 67, -45, // id = 1000403
|
||||||
|
0, 1, 2, 3, 4}; // message_data = {0, 1, 2, 3, 4}
|
||||||
|
EventMessageDecoder decoder = new EventMessageDecoder();
|
||||||
|
Metadata metadata = decoder.decode(rawEmsgBody, rawEmsgBody.length);
|
||||||
|
assertEquals(1, metadata.length());
|
||||||
|
EventMessage eventMessage = (EventMessage) metadata.get(0);
|
||||||
|
assertEquals("urn:test", eventMessage.schemeIdUri);
|
||||||
|
assertEquals("123", eventMessage.value);
|
||||||
|
assertEquals(3000, eventMessage.durationMs);
|
||||||
|
assertEquals(1000403, eventMessage.id);
|
||||||
|
MoreAsserts.assertEquals(new byte[] {0, 1, 2, 3, 4}, eventMessage.messageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.metadata.emsg;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link EventMessage}.
|
||||||
|
*/
|
||||||
|
public final class EventMessageTest extends TestCase {
|
||||||
|
|
||||||
|
public void testEventMessageParcelable() {
|
||||||
|
EventMessage eventMessage = new EventMessage("urn:test", "123", 3000, 1000403,
|
||||||
|
new byte[] {0, 1, 2, 3, 4});
|
||||||
|
// Write to parcel.
|
||||||
|
Parcel parcel = Parcel.obtain();
|
||||||
|
eventMessage.writeToParcel(parcel, 0);
|
||||||
|
// Create from parcel.
|
||||||
|
parcel.setDataPosition(0);
|
||||||
|
EventMessage fromParcelEventMessage = EventMessage.CREATOR.createFromParcel(parcel);
|
||||||
|
// Assert equals.
|
||||||
|
assertEquals(eventMessage, fromParcelEventMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -21,9 +21,9 @@ import com.google.android.exoplayer2.metadata.MetadataDecoderException;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link Id3Decoder}
|
* Test for {@link Id3Decoder}.
|
||||||
*/
|
*/
|
||||||
public class Id3DecoderTest extends TestCase {
|
public final class Id3DecoderTest extends TestCase {
|
||||||
|
|
||||||
public void testDecodeTxxxFrame() throws MetadataDecoderException {
|
public void testDecodeTxxxFrame() throws MetadataDecoderException {
|
||||||
byte[] rawId3 = new byte[] {73, 68, 51, 4, 0, 0, 0, 0, 0, 41, 84, 88, 88, 88, 0, 0, 0, 31, 0, 0,
|
byte[] rawId3 = new byte[] {73, 68, 51, 4, 0, 0, 0, 0, 0, 41, 84, 88, 88, 88, 0, 0, 0, 31, 0, 0,
|
||||||
|
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.metadata.emsg;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Event Message (emsg) as defined in ISO 23009-1.
|
||||||
|
*/
|
||||||
|
public final class EventMessage implements Metadata.Entry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message scheme.
|
||||||
|
*/
|
||||||
|
public final String schemeIdUri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value for the event.
|
||||||
|
*/
|
||||||
|
public final String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The duration of the event in milliseconds.
|
||||||
|
*/
|
||||||
|
public final long durationMs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance identifier.
|
||||||
|
*/
|
||||||
|
public final long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The body of the message.
|
||||||
|
*/
|
||||||
|
public final byte[] messageData;
|
||||||
|
|
||||||
|
// Lazily initialized hashcode.
|
||||||
|
private int hashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param schemeIdUri The message scheme.
|
||||||
|
* @param value The value for the event.
|
||||||
|
* @param durationMs The duration of the event in milliseconds.
|
||||||
|
* @param id The instance identifier.
|
||||||
|
* @param messageData The body of the message.
|
||||||
|
*/
|
||||||
|
public EventMessage(String schemeIdUri, String value, long durationMs, long id,
|
||||||
|
byte[] messageData) {
|
||||||
|
this.schemeIdUri = schemeIdUri;
|
||||||
|
this.value = value;
|
||||||
|
this.durationMs = durationMs;
|
||||||
|
this.id = id;
|
||||||
|
this.messageData = messageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ EventMessage(Parcel in) {
|
||||||
|
schemeIdUri = in.readString();
|
||||||
|
value = in.readString();
|
||||||
|
durationMs = in.readLong();
|
||||||
|
id = in.readLong();
|
||||||
|
messageData = in.createByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
if (hashCode == 0) {
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + (schemeIdUri != null ? schemeIdUri.hashCode() : 0);
|
||||||
|
result = 31 * result + (value != null ? value.hashCode() : 0);
|
||||||
|
result = 31 * result + (int) (durationMs ^ (durationMs >>> 32));
|
||||||
|
result = 31 * result + (int) (id ^ (id >>> 32));
|
||||||
|
result = 31 * result + Arrays.hashCode(messageData);
|
||||||
|
hashCode = result;
|
||||||
|
}
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EventMessage other = (EventMessage) obj;
|
||||||
|
return durationMs == other.durationMs && id == other.id
|
||||||
|
&& Util.areEqual(schemeIdUri, other.schemeIdUri) && Util.areEqual(value, other.value)
|
||||||
|
&& Arrays.equals(messageData, other.messageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable implementation.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeString(schemeIdUri);
|
||||||
|
dest.writeString(value);
|
||||||
|
dest.writeLong(durationMs);
|
||||||
|
dest.writeLong(id);
|
||||||
|
dest.writeByteArray(messageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<EventMessage> CREATOR =
|
||||||
|
new Parcelable.Creator<EventMessage>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventMessage createFromParcel(Parcel in) {
|
||||||
|
return new EventMessage(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventMessage[] newArray(int size) {
|
||||||
|
return new EventMessage[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.metadata.emsg;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
|
import com.google.android.exoplayer2.metadata.MetadataDecoder;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes Event Message (emsg) atoms, as defined in ISO 23009-1.
|
||||||
|
* <p>
|
||||||
|
* Atom data should be provided to the decoder without the full atom header (i.e. starting from the
|
||||||
|
* first byte of the scheme_id_uri field).
|
||||||
|
*/
|
||||||
|
public final class EventMessageDecoder implements MetadataDecoder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canDecode(String mimeType) {
|
||||||
|
return MimeTypes.APPLICATION_EMSG.equals(mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Metadata decode(byte[] data, int size) {
|
||||||
|
ParsableByteArray emsgData = new ParsableByteArray(data, size);
|
||||||
|
String schemeIdUri = emsgData.readNullTerminatedString();
|
||||||
|
String value = emsgData.readNullTerminatedString();
|
||||||
|
long timescale = emsgData.readUnsignedInt();
|
||||||
|
emsgData.skipBytes(4); // presentation_time_delta
|
||||||
|
long durationMs = (emsgData.readUnsignedInt() * 1000) / timescale;
|
||||||
|
long id = emsgData.readUnsignedInt();
|
||||||
|
byte[] messageData = Arrays.copyOfRange(data, emsgData.getPosition(), size);
|
||||||
|
return new Metadata(new EventMessage(schemeIdUri, value, durationMs, id, messageData));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -79,6 +79,7 @@ public final class MimeTypes {
|
|||||||
public static final String APPLICATION_PGS = BASE_TYPE_APPLICATION + "/pgs";
|
public static final String APPLICATION_PGS = BASE_TYPE_APPLICATION + "/pgs";
|
||||||
public static final String APPLICATION_SCTE35 = BASE_TYPE_APPLICATION + "/x-scte35";
|
public static final String APPLICATION_SCTE35 = BASE_TYPE_APPLICATION + "/x-scte35";
|
||||||
public static final String APPLICATION_CAMERA_MOTION = BASE_TYPE_APPLICATION + "/x-camera-motion";
|
public static final String APPLICATION_CAMERA_MOTION = BASE_TYPE_APPLICATION + "/x-camera-motion";
|
||||||
|
public static final String APPLICATION_EMSG = BASE_TYPE_APPLICATION + "/x-emsg";
|
||||||
|
|
||||||
private MimeTypes() {}
|
private MimeTypes() {}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user