Search in sources :

Example 1 with PositionHolder

use of com.google.android.exoplayer2.extractor.PositionHolder in project ExoPlayer by google.

the class PsExtractor method read.

@Override
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException {
    // First peek and check what type of start code is next.
    if (!input.peekFully(psPacketBuffer.data, 0, 4, true)) {
        return RESULT_END_OF_INPUT;
    }
    psPacketBuffer.setPosition(0);
    int nextStartCode = psPacketBuffer.readInt();
    if (nextStartCode == MPEG_PROGRAM_END_CODE) {
        return RESULT_END_OF_INPUT;
    } else if (nextStartCode == PACK_START_CODE) {
        // Now peek the rest of the pack_header.
        input.peekFully(psPacketBuffer.data, 0, 10);
        // We only care about the pack_stuffing_length in here, skip the first 77 bits.
        psPacketBuffer.setPosition(9);
        // Last 3 bits is the length.
        int packStuffingLength = psPacketBuffer.readUnsignedByte() & 0x07;
        // Now skip the stuffing and the pack header.
        input.skipFully(packStuffingLength + 14);
        return RESULT_CONTINUE;
    } else if (nextStartCode == SYSTEM_HEADER_START_CODE) {
        // We just skip all this, but we need to get the length first.
        input.peekFully(psPacketBuffer.data, 0, 2);
        // Length is the next 2 bytes.
        psPacketBuffer.setPosition(0);
        int systemHeaderLength = psPacketBuffer.readUnsignedShort();
        input.skipFully(systemHeaderLength + 6);
        return RESULT_CONTINUE;
    } else if (((nextStartCode & 0xFFFFFF00) >> 8) != PACKET_START_CODE_PREFIX) {
        // Skip bytes until we see a valid start code again.
        input.skipFully(1);
        return RESULT_CONTINUE;
    }
    // We're at the start of a regular PES packet now.
    // Get the stream ID off the last byte of the start code.
    int streamId = nextStartCode & 0xFF;
    // Check to see if we have this one in our map yet, and if not, then add it.
    PesReader payloadReader = psPayloadReaders.get(streamId);
    if (!foundAllTracks) {
        if (payloadReader == null) {
            ElementaryStreamReader elementaryStreamReader = null;
            if (!foundAudioTrack && streamId == PRIVATE_STREAM_1) {
                // Private stream, used for AC3 audio.
                // NOTE: This may need further parsing to determine if its DTS, but that's likely only
                // valid for DVDs.
                elementaryStreamReader = new Ac3Reader();
                foundAudioTrack = true;
            } else if (!foundAudioTrack && (streamId & AUDIO_STREAM_MASK) == AUDIO_STREAM) {
                elementaryStreamReader = new MpegAudioReader();
                foundAudioTrack = true;
            } else if (!foundVideoTrack && (streamId & VIDEO_STREAM_MASK) == VIDEO_STREAM) {
                elementaryStreamReader = new H262Reader();
                foundVideoTrack = true;
            }
            if (elementaryStreamReader != null) {
                TrackIdGenerator idGenerator = new TrackIdGenerator(streamId, MAX_STREAM_ID_PLUS_ONE);
                elementaryStreamReader.createTracks(output, idGenerator);
                payloadReader = new PesReader(elementaryStreamReader, timestampAdjuster);
                psPayloadReaders.put(streamId, payloadReader);
            }
        }
        if ((foundAudioTrack && foundVideoTrack) || input.getPosition() > MAX_SEARCH_LENGTH) {
            foundAllTracks = true;
            output.endTracks();
        }
    }
    // The next 2 bytes are the length. Once we have that we can consume the complete packet.
    input.peekFully(psPacketBuffer.data, 0, 2);
    psPacketBuffer.setPosition(0);
    int payloadLength = psPacketBuffer.readUnsignedShort();
    int pesLength = payloadLength + 6;
    if (payloadReader == null) {
        // Just skip this data.
        input.skipFully(pesLength);
    } else {
        psPacketBuffer.reset(pesLength);
        // Read the whole packet and the header for consumption.
        input.readFully(psPacketBuffer.data, 0, pesLength);
        psPacketBuffer.setPosition(6);
        payloadReader.consume(psPacketBuffer);
        psPacketBuffer.setLimit(psPacketBuffer.capacity());
    }
    return RESULT_CONTINUE;
}
Also used : TrackIdGenerator(com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)

Example 2 with PositionHolder

use of com.google.android.exoplayer2.extractor.PositionHolder in project ExoPlayer by google.

the class StreamReader method readPayload.

private int readPayload(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException {
    long position = oggSeeker.read(input);
    if (position >= 0) {
        seekPosition.position = position;
        return Extractor.RESULT_SEEK;
    } else if (position < -1) {
        onSeekEnd(-(position + 2));
    }
    if (!seekMapSet) {
        SeekMap seekMap = oggSeeker.createSeekMap();
        extractorOutput.seekMap(seekMap);
        seekMapSet = true;
    }
    if (lengthOfReadPacket > 0 || oggPacket.populate(input)) {
        lengthOfReadPacket = 0;
        ParsableByteArray payload = oggPacket.getPayload();
        long granulesInPacket = preparePayload(payload);
        if (granulesInPacket >= 0 && currentGranule + granulesInPacket >= targetGranule) {
            // calculate time and send payload data to codec
            long timeUs = convertGranuleToTime(currentGranule);
            trackOutput.sampleData(payload, payload.limit());
            trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, payload.limit(), 0, null);
            targetGranule = -1;
        }
        currentGranule += granulesInPacket;
    } else {
        state = STATE_END_OF_INPUT;
        return Extractor.RESULT_END_OF_INPUT;
    }
    return Extractor.RESULT_CONTINUE;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) SeekMap(com.google.android.exoplayer2.extractor.SeekMap)

Example 3 with PositionHolder

use of com.google.android.exoplayer2.extractor.PositionHolder in project ExoPlayer by google.

the class TsExtractorTest method testCustomInitialSectionReader.

public void testCustomInitialSectionReader() throws Exception {
    CustomTsPayloadReaderFactory factory = new CustomTsPayloadReaderFactory(false, true);
    TsExtractor tsExtractor = new TsExtractor(TsExtractor.MODE_NORMAL, new TimestampAdjuster(0), factory);
    FakeExtractorInput input = new FakeExtractorInput.Builder().setData(TestUtil.getByteArray(getInstrumentation(), "ts/sample_with_sdt.ts")).setSimulateIOErrors(false).setSimulateUnknownLength(false).setSimulatePartialReads(false).build();
    tsExtractor.init(new FakeExtractorOutput());
    PositionHolder seekPositionHolder = new PositionHolder();
    int readResult = Extractor.RESULT_CONTINUE;
    while (readResult != Extractor.RESULT_END_OF_INPUT) {
        readResult = tsExtractor.read(input, seekPositionHolder);
    }
    assertEquals(1, factory.sdtReader.consumedSdts);
}
Also used : FakeExtractorInput(com.google.android.exoplayer2.testutil.FakeExtractorInput) PositionHolder(com.google.android.exoplayer2.extractor.PositionHolder) TimestampAdjuster(com.google.android.exoplayer2.util.TimestampAdjuster) FakeExtractorOutput(com.google.android.exoplayer2.testutil.FakeExtractorOutput)

Example 4 with PositionHolder

use of com.google.android.exoplayer2.extractor.PositionHolder in project ExoPlayer by google.

the class TsExtractorTest method testCustomPesReader.

public void testCustomPesReader() throws Exception {
    CustomTsPayloadReaderFactory factory = new CustomTsPayloadReaderFactory(true, false);
    TsExtractor tsExtractor = new TsExtractor(TsExtractor.MODE_NORMAL, new TimestampAdjuster(0), factory);
    FakeExtractorInput input = new FakeExtractorInput.Builder().setData(TestUtil.getByteArray(getInstrumentation(), "ts/sample.ts")).setSimulateIOErrors(false).setSimulateUnknownLength(false).setSimulatePartialReads(false).build();
    FakeExtractorOutput output = new FakeExtractorOutput();
    tsExtractor.init(output);
    PositionHolder seekPositionHolder = new PositionHolder();
    int readResult = Extractor.RESULT_CONTINUE;
    while (readResult != Extractor.RESULT_END_OF_INPUT) {
        readResult = tsExtractor.read(input, seekPositionHolder);
    }
    CustomEsReader reader = factory.esReader;
    assertEquals(2, reader.packetsRead);
    TrackOutput trackOutput = reader.getTrackOutput();
    assertTrue(trackOutput == output.trackOutputs.get(257));
    assertEquals(Format.createTextSampleFormat("1/257", "mime", null, 0, 0, "und", null, 0), ((FakeTrackOutput) trackOutput).format);
}
Also used : FakeExtractorInput(com.google.android.exoplayer2.testutil.FakeExtractorInput) PositionHolder(com.google.android.exoplayer2.extractor.PositionHolder) TimestampAdjuster(com.google.android.exoplayer2.util.TimestampAdjuster) FakeExtractorOutput(com.google.android.exoplayer2.testutil.FakeExtractorOutput) TrackOutput(com.google.android.exoplayer2.extractor.TrackOutput) FakeTrackOutput(com.google.android.exoplayer2.testutil.FakeTrackOutput)

Example 5 with PositionHolder

use of com.google.android.exoplayer2.extractor.PositionHolder in project ExoPlayer by google.

the class WavExtractor method read.

@Override
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException {
    if (wavHeader == null) {
        wavHeader = WavHeaderReader.peek(input);
        if (wavHeader == null) {
            // Should only happen if the media wasn't sniffed.
            throw new ParserException("Unsupported or unrecognized wav header.");
        }
        Format format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_RAW, null, wavHeader.getBitrate(), MAX_INPUT_SIZE, wavHeader.getNumChannels(), wavHeader.getSampleRateHz(), wavHeader.getEncoding(), null, null, 0, null);
        trackOutput.format(format);
        bytesPerFrame = wavHeader.getBytesPerFrame();
    }
    if (!wavHeader.hasDataBounds()) {
        WavHeaderReader.skipToData(input, wavHeader);
        extractorOutput.seekMap(this);
    }
    int bytesAppended = trackOutput.sampleData(input, MAX_INPUT_SIZE - pendingBytes, true);
    if (bytesAppended != RESULT_END_OF_INPUT) {
        pendingBytes += bytesAppended;
    }
    // Samples must consist of a whole number of frames.
    int pendingFrames = pendingBytes / bytesPerFrame;
    if (pendingFrames > 0) {
        long timeUs = wavHeader.getTimeUs(input.getPosition() - pendingBytes);
        int size = pendingFrames * bytesPerFrame;
        pendingBytes -= size;
        trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, size, pendingBytes, null);
    }
    return bytesAppended == RESULT_END_OF_INPUT ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
Also used : ParserException(com.google.android.exoplayer2.ParserException) Format(com.google.android.exoplayer2.Format)

Aggregations

PositionHolder (com.google.android.exoplayer2.extractor.PositionHolder)3 Format (com.google.android.exoplayer2.Format)2 SeekMap (com.google.android.exoplayer2.extractor.SeekMap)2 TrackOutput (com.google.android.exoplayer2.extractor.TrackOutput)2 FakeExtractorInput (com.google.android.exoplayer2.testutil.FakeExtractorInput)2 FakeExtractorOutput (com.google.android.exoplayer2.testutil.FakeExtractorOutput)2 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)2 TimestampAdjuster (com.google.android.exoplayer2.util.TimestampAdjuster)2 ParserException (com.google.android.exoplayer2.ParserException)1 TrackIdGenerator (com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)1 SimulatedIOException (com.google.android.exoplayer2.testutil.FakeExtractorInput.SimulatedIOException)1 FakeTrackOutput (com.google.android.exoplayer2.testutil.FakeTrackOutput)1 FlacStreamInfo (com.google.android.exoplayer2.util.FlacStreamInfo)1 IOException (java.io.IOException)1