@Override public void consume(ParsableByteArray data, boolean payloadUnitStartIndicator) { // Skip pointer. if (payloadUnitStartIndicator) { int pointerField = data.readUnsignedByte(); data.skip(pointerField); } data.readBytes(patScratch, 3); patScratch.skipBits(12); // table_id (8), section_syntax_indicator (1), '0' (1), reserved (2) int sectionLength = patScratch.readBits(12); // transport_stream_id (16), reserved (2), version_number (5), current_next_indicator (1), // section_number (8), last_section_number (8) data.skip(5); int programCount = (sectionLength - 9) / 4; for (int i = 0; i < programCount; i++) { data.readBytes(patScratch, 4); patScratch.skipBits(19); // program_number (16), reserved (3) int pid = patScratch.readBits(13); tsPayloadReaders.put(pid, new PmtReader()); } // Skip CRC_32. }
@Override public int read(DataSource dataSource) throws IOException { int bytesRead = dataSource.read(tsPacketBuffer.data, tsPacketBytesRead, TS_PACKET_SIZE - tsPacketBytesRead); if (bytesRead == -1) { return -1; } tsPacketBytesRead += bytesRead; if (tsPacketBytesRead < TS_PACKET_SIZE) { // We haven't read the whole packet yet. return bytesRead; } // Reset before reading the packet. tsPacketBytesRead = 0; tsPacketBuffer.setPosition(0); tsPacketBuffer.setLimit(TS_PACKET_SIZE); int syncByte = tsPacketBuffer.readUnsignedByte(); if (syncByte != TS_SYNC_BYTE) { return bytesRead; } tsPacketBuffer.readBytes(tsScratch, 3); tsScratch.skipBits(1); // transport_error_indicator boolean payloadUnitStartIndicator = tsScratch.readBit(); tsScratch.skipBits(1); // transport_priority int pid = tsScratch.readBits(13); tsScratch.skipBits(2); // transport_scrambling_control boolean adaptationFieldExists = tsScratch.readBit(); boolean payloadExists = tsScratch.readBit(); // Last 4 bits of scratch are skipped: continuity_counter // Skip the adaptation field. if (adaptationFieldExists) { int adaptationFieldLength = tsPacketBuffer.readUnsignedByte(); tsPacketBuffer.skip(adaptationFieldLength); } // Read the payload. if (payloadExists) { TsPayloadReader payloadReader = tsPayloadReaders.get(pid); if (payloadReader != null) { payloadReader.consume(tsPacketBuffer, payloadUnitStartIndicator); } } if (!prepared) { prepared = checkPrepared(); } return bytesRead; }
/** * Continues a read from the provided {@code source} into a given {@code target}. It's assumed * that the data should be written into {@code target} starting from an offset of zero. * * @param source The source from which to read. * @param target The target into which data is to be read, or {@code null} to skip. * @param targetLength The target length of the read. * @return Whether the target length has been reached. */ private boolean continueRead(ParsableByteArray source, byte[] target, int targetLength) { int bytesToRead = Math.min(source.bytesLeft(), targetLength - bytesRead); if (bytesToRead <= 0) { return true; } else if (target == null) { source.skip(bytesToRead); } else { source.readBytes(target, bytesRead, bytesToRead); } bytesRead += bytesToRead; return bytesRead == targetLength; }
private static void parseUuid( ParsableByteArray uuid, TrackFragment out, byte[] extendedTypeScratch) throws ParserException { uuid.setPosition(Atom.HEADER_SIZE); uuid.readBytes(extendedTypeScratch, 0, 16); // Currently this parser only supports Microsoft's PIFF SampleEncryptionBox. if (!Arrays.equals(extendedTypeScratch, PIFF_SAMPLE_ENCRYPTION_BOX_EXTENDED_TYPE)) { return; } // Except for the extended type, this box is identical to a SENC box. See "Portable encoding of // audio-video objects: The Protected Interoperable File Format (PIFF), John A. Bocharov et al, // Section 5.3.2.1." parseSenc(uuid, 16, out); }
@Override public void consume(ParsableByteArray data, boolean payloadUnitStartIndicator) { // Skip pointer. if (payloadUnitStartIndicator) { int pointerField = data.readUnsignedByte(); data.skip(pointerField); } data.readBytes(pmtScratch, 3); pmtScratch.skipBits(12); // table_id (8), section_syntax_indicator (1), '0' (1), reserved (2) int sectionLength = pmtScratch.readBits(12); // program_number (16), reserved (2), version_number (5), current_next_indicator (1), // section_number (8), last_section_number (8), reserved (3), PCR_PID (13) // Skip the rest of the PMT header. data.skip(7); data.readBytes(pmtScratch, 2); pmtScratch.skipBits(4); int programInfoLength = pmtScratch.readBits(12); // Skip the descriptors. data.skip(programInfoLength); int entriesSize = sectionLength - 9 /* Size of the rest of the fields before descriptors */ - programInfoLength - 4 /* CRC size */; while (entriesSize > 0) { data.readBytes(pmtScratch, 5); int streamType = pmtScratch.readBits(8); pmtScratch.skipBits(3); // reserved int elementaryPid = pmtScratch.readBits(13); pmtScratch.skipBits(4); // reserved int esInfoLength = pmtScratch.readBits(12); // Skip the descriptors. data.skip(esInfoLength); entriesSize -= esInfoLength + 5; if (sampleQueues.get(streamType) != null) { continue; } ElementaryStreamReader pesPayloadReader = null; switch (streamType) { case TS_STREAM_TYPE_AAC: pesPayloadReader = new AdtsReader(bufferPool); break; case TS_STREAM_TYPE_H264: SeiReader seiReader = new SeiReader(bufferPool); sampleQueues.put(TS_STREAM_TYPE_EIA608, seiReader); pesPayloadReader = new H264Reader(bufferPool, seiReader); break; case TS_STREAM_TYPE_ID3: pesPayloadReader = new Id3Reader(bufferPool); break; } if (pesPayloadReader != null) { sampleQueues.put(streamType, pesPayloadReader); tsPayloadReaders.put(elementaryPid, new PesReader(pesPayloadReader)); } } // Skip CRC_32. }