[AitDecoder] Move to ParsableBitArray

This commit is contained in:
Pierre-Hugues Husson 2020-02-18 15:00:26 +01:00
parent 28c5043dc1
commit 98de7c460b

View File

@ -3,16 +3,20 @@ package com.google.android.exoplayer2.metadata.dvbsi;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataDecoder; import com.google.android.exoplayer2.metadata.MetadataDecoder;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer; import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.util.ParsableBitArray;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.TimestampAdjuster; import com.google.android.exoplayer2.util.TimestampAdjuster;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
// Unless mentioned explicitly, every references here are to
// https://www.etsi.org/deliver/etsi_ts/102800_102899/102809/01.01.01_60/ts_102809v010101p.pdf
public class AitDecoder implements MetadataDecoder { public class AitDecoder implements MetadataDecoder {
// Specification of AIT can be found in 5.3.4 of TS 102 809 v1.1.1 // Specification of AIT can be found in 5.3.4 of TS 102 809 v1.1.1
// https://www.etsi.org/deliver/etsi_ts/102800_102899/102809/01.01.01_60/ts_102809v010101p.pdf
private final static int DESCRIPTOR_TRANSPORT_PROTOCOL = 0x02; private final static int DESCRIPTOR_TRANSPORT_PROTOCOL = 0x02;
private final static int DESCRIPTOR_SIMPLE_APPLICATION_LOCATION = 0x15; private final static int DESCRIPTOR_SIMPLE_APPLICATION_LOCATION = 0x15;
@ -21,10 +25,10 @@ public class AitDecoder implements MetadataDecoder {
private TimestampAdjuster timestampAdjuster; private TimestampAdjuster timestampAdjuster;
private final ParsableByteArray sectionData; private final ParsableBitArray sectionData;
public AitDecoder() { public AitDecoder() {
sectionData = new ParsableByteArray(); sectionData = new ParsableBitArray();
} }
@Override @Override
@ -40,8 +44,7 @@ public class AitDecoder implements MetadataDecoder {
int size = buffer.limit(); int size = buffer.limit();
sectionData.reset(data, size); sectionData.reset(data, size);
int tableId = sectionData.peekUnsignedByte(); int tableId = sectionData.data[0];
//Only this table is allowed in AIT streams //Only this table is allowed in AIT streams
if (tableId == 0x74) { if (tableId == 0x74) {
return parseAit(sectionData); return parseAit(sectionData);
@ -50,80 +53,92 @@ public class AitDecoder implements MetadataDecoder {
return new Metadata(); return new Metadata();
} }
private Metadata parseAit(ParsableByteArray sectionData) { private Metadata parseAit(ParsableBitArray sectionData) {
int tmp; //tableId
sectionData.skipBits(8);
int tableId = sectionData.readUnsignedByte(); //section_syntax_indication | reserved_future_use | reserved
sectionData.skipBits(4);
int sectionLength = sectionData.readBits(12);
int endOfSection = sectionData.getBytePosition() + sectionLength - 4 /* Ignore leading CRC */;
tmp = sectionData.readUnsignedShort(); // test_application_flag | application_type
int endOfSection = sectionData.getPosition() + (tmp & 4095) - 4 /* Ignore leading CRC */; sectionData.skipBits(16);
tmp = sectionData.readUnsignedShort(); // reserved | version_number | current_next_indicator
int applicationType = tmp & 0x7fff; sectionData.skipBits(8);
tmp = sectionData.readUnsignedByte(); // section_number
int versionNumber = (tmp & 0x3e) >> 1; sectionData.skipBits(8);
boolean current = (tmp & 1) == 1; // last_section_number
sectionData.skipBits(8);
int section_number = sectionData.readUnsignedByte(); // reserved_future_use
int last_section_number = sectionData.readUnsignedByte(); sectionData.skipBits(4);
int commonDescriptorsLength = sectionData.readBits(12);
tmp = sectionData.readUnsignedShort();
int commonDescriptorsLength = tmp & 4095;
//Since we currently only keep url and control code, which are unique per application, //Since we currently only keep url and control code, which are unique per application,
//there is no useful information in common descriptor. //there is no useful information in common descriptor.
sectionData.skipBytes(commonDescriptorsLength); sectionData.skipBytes(commonDescriptorsLength);
tmp = sectionData.readUnsignedShort(); // reserved_future_use | application_loop_length
int appLoopLength = tmp & 4095; sectionData.skipBits(16);
ArrayList<Ait> aits = new ArrayList<>(); ArrayList<Ait> aits = new ArrayList<>();
while(sectionData.getPosition() < endOfSection) { while(sectionData.getBytePosition() < endOfSection) {
// Values that will be stored in Ait() // Values that will be stored in Ait()
String aitUrlBase = null; String aitUrlBase = null;
String aitUrlExtension = null; String aitUrlExtension = null;
int aitControlCode = -1; int aitControlCode = -1;
long application_identifier = sectionData.readUnsignedInt24() << 24L; // application_identifier
application_identifier |= sectionData.readUnsignedInt24(); sectionData.skipBits(48);
int controlCode = sectionData.readUnsignedByte(); int controlCode = sectionData.readBits(8);
aitControlCode = controlCode; aitControlCode = controlCode;
tmp = sectionData.readUnsignedShort(); // reserved_future_use
int sectionLength = tmp & 4095; sectionData.skipBits(4);
int positionOfNextSection = sectionData.getPosition() + sectionLength;
while(sectionData.getPosition() < positionOfNextSection) { int applicationDescriptorsLoopLength = sectionData.readBits(12);
int type = sectionData.readUnsignedByte(); int positionOfNextSection = sectionData.getBytePosition() + applicationDescriptorsLoopLength;
int l = sectionData.readUnsignedByte(); while(sectionData.getBytePosition() < positionOfNextSection) {
int positionOfNextSection2 = sectionData.getPosition() + l; int type = sectionData.readBits(8);
int l = sectionData.readBits(8);
int positionOfNextSection2 = sectionData.getBytePosition() + l;
if(type == DESCRIPTOR_TRANSPORT_PROTOCOL) { if(type == DESCRIPTOR_TRANSPORT_PROTOCOL) {
int protocolId = sectionData.readUnsignedShort(); // See section 5.3.6
int label = sectionData.readUnsignedByte(); int protocolId = sectionData.readBits(16);
// label
sectionData.skipBits(8);
if(protocolId == TRANSPORT_PROTOCOL_HTTP) { if(protocolId == TRANSPORT_PROTOCOL_HTTP) {
while (sectionData.getPosition() < positionOfNextSection2) { while (sectionData.getBytePosition() < positionOfNextSection2) {
int urlBaseLength = sectionData.readUnsignedByte(); int urlBaseLength = sectionData.readBits(8);
String urlBase = sectionData.readString(urlBaseLength); byte[] urlBaseByteArray = new byte[urlBaseLength];
int extensionCount = sectionData.readUnsignedByte(); sectionData.readBytes(urlBaseByteArray, 0, urlBaseLength);
String urlBase = new String(urlBaseByteArray, Charset.forName("ASCII"));
int extensionCount = sectionData.readBits(8);
aitUrlBase = urlBase; aitUrlBase = urlBase;
for (int i = 0; i < extensionCount; i++) { for (int i = 0; i < extensionCount; i++) {
int len = sectionData.readUnsignedByte(); int len = sectionData.readBits(8);
sectionData.skipBytes(len); sectionData.skipBytes(len);
} }
} }
} }
} else if(type == DESCRIPTOR_SIMPLE_APPLICATION_LOCATION) { } else if(type == DESCRIPTOR_SIMPLE_APPLICATION_LOCATION) {
String url = sectionData.readString(l); byte[] urlByteArray = new byte[l];
sectionData.readBytes(urlByteArray, 0, l);
String url = new String(urlByteArray, Charset.forName("ASCII"));
aitUrlExtension = url; aitUrlExtension = url;
} }
sectionData.setPosition(positionOfNextSection2); sectionData.setPosition(positionOfNextSection2*8);
} }
sectionData.setPosition(positionOfNextSection); sectionData.setPosition(positionOfNextSection*8);
if(aitControlCode != -1 && aitUrlBase != null && aitUrlExtension != null) { if(aitControlCode != -1 && aitUrlBase != null && aitUrlExtension != null) {
aits.add(new Ait(aitControlCode, aitUrlBase + aitUrlExtension)); aits.add(new Ait(aitControlCode, aitUrlBase + aitUrlExtension));