Search in sources :

Example 46 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class SubripDecoder method decode.

@Override
protected SubripSubtitle decode(byte[] bytes, int length) {
    ArrayList<Cue> cues = new ArrayList<>();
    LongArray cueTimesUs = new LongArray();
    ParsableByteArray subripData = new ParsableByteArray(bytes, length);
    String currentLine;
    while ((currentLine = subripData.readLine()) != null) {
        if (currentLine.length() == 0) {
            // Skip blank lines.
            continue;
        }
        // Parse the index line as a sanity check.
        try {
            Integer.parseInt(currentLine);
        } catch (NumberFormatException e) {
            Log.w(TAG, "Skipping invalid index: " + currentLine);
            continue;
        }
        // Read and parse the timing line.
        boolean haveEndTimecode = false;
        currentLine = subripData.readLine();
        Matcher matcher = SUBRIP_TIMING_LINE.matcher(currentLine);
        if (matcher.matches()) {
            cueTimesUs.add(parseTimecode(matcher, 1));
            if (!TextUtils.isEmpty(matcher.group(6))) {
                haveEndTimecode = true;
                cueTimesUs.add(parseTimecode(matcher, 6));
            }
        } else {
            Log.w(TAG, "Skipping invalid timing: " + currentLine);
            continue;
        }
        // Read and parse the text.
        textBuilder.setLength(0);
        while (!TextUtils.isEmpty(currentLine = subripData.readLine())) {
            if (textBuilder.length() > 0) {
                textBuilder.append("<br>");
            }
            textBuilder.append(currentLine.trim());
        }
        Spanned text = Html.fromHtml(textBuilder.toString());
        cues.add(new Cue(text));
        if (haveEndTimecode) {
            cues.add(null);
        }
    }
    Cue[] cuesArray = new Cue[cues.size()];
    cues.toArray(cuesArray);
    long[] cueTimesUsArray = cueTimesUs.toArray();
    return new SubripSubtitle(cuesArray, cueTimesUsArray);
}
Also used : Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) Spanned(android.text.Spanned) LongArray(com.google.android.exoplayer2.util.LongArray) ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) Cue(com.google.android.exoplayer2.text.Cue)

Example 47 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class FfmpegDecoder method decode.

@Override
public FfmpegDecoderException decode(DecoderInputBuffer inputBuffer, SimpleOutputBuffer outputBuffer, boolean reset) {
    if (reset) {
        nativeContext = ffmpegReset(nativeContext, extraData);
        if (nativeContext == 0) {
            return new FfmpegDecoderException("Error resetting (see logcat).");
        }
    }
    ByteBuffer inputData = inputBuffer.data;
    int inputSize = inputData.limit();
    ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, OUTPUT_BUFFER_SIZE);
    int result = ffmpegDecode(nativeContext, inputData, inputSize, outputData, OUTPUT_BUFFER_SIZE);
    if (result < 0) {
        return new FfmpegDecoderException("Error decoding (see logcat). Code: " + result);
    }
    if (!hasOutputFormat) {
        channelCount = ffmpegGetChannelCount(nativeContext);
        sampleRate = ffmpegGetSampleRate(nativeContext);
        if (sampleRate == 0 && "alac".equals(codecName)) {
            // ALAC decoder did not set the sample rate in earlier versions of FFMPEG.
            // See https://trac.ffmpeg.org/ticket/6096
            ParsableByteArray parsableExtraData = new ParsableByteArray(extraData);
            parsableExtraData.setPosition(extraData.length - 4);
            sampleRate = parsableExtraData.readUnsignedIntToInt();
        }
        hasOutputFormat = true;
    }
    outputBuffer.data.position(0);
    outputBuffer.data.limit(result);
    return null;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ByteBuffer(java.nio.ByteBuffer)

Example 48 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class FlacExtractor method read.

@Override
public int read(final ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException {
    decoderJni.setData(input);
    if (!metadataParsed) {
        final FlacStreamInfo streamInfo;
        try {
            streamInfo = decoderJni.decodeMetadata();
            if (streamInfo == null) {
                throw new IOException("Metadata decoding failed");
            }
        } catch (IOException e) {
            decoderJni.reset(0);
            input.setRetryPosition(0, e);
            // never executes
            throw e;
        }
        metadataParsed = true;
        extractorOutput.seekMap(new SeekMap() {

            final boolean isSeekable = decoderJni.getSeekPosition(0) != -1;

            final long durationUs = streamInfo.durationUs();

            @Override
            public boolean isSeekable() {
                return isSeekable;
            }

            @Override
            public long getPosition(long timeUs) {
                return isSeekable ? decoderJni.getSeekPosition(timeUs) : 0;
            }

            @Override
            public long getDurationUs() {
                return durationUs;
            }
        });
        Format mediaFormat = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_RAW, null, streamInfo.bitRate(), Format.NO_VALUE, streamInfo.channels, streamInfo.sampleRate, C.ENCODING_PCM_16BIT, null, null, 0, null);
        trackOutput.format(mediaFormat);
        outputBuffer = new ParsableByteArray(streamInfo.maxDecodedFrameSize());
        outputByteBuffer = ByteBuffer.wrap(outputBuffer.data);
    }
    outputBuffer.reset();
    long lastDecodePosition = decoderJni.getDecodePosition();
    int size;
    try {
        size = decoderJni.decodeSample(outputByteBuffer);
    } catch (IOException e) {
        if (lastDecodePosition >= 0) {
            decoderJni.reset(lastDecodePosition);
            input.setRetryPosition(lastDecodePosition, e);
        }
        throw e;
    }
    if (size <= 0) {
        return RESULT_END_OF_INPUT;
    }
    trackOutput.sampleData(outputBuffer, size);
    trackOutput.sampleMetadata(decoderJni.getLastSampleTimestamp(), C.BUFFER_FLAG_KEY_FRAME, size, 0, null);
    return decoderJni.isEndOfData() ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) Format(com.google.android.exoplayer2.Format) FlacStreamInfo(com.google.android.exoplayer2.util.FlacStreamInfo) IOException(java.io.IOException) SeekMap(com.google.android.exoplayer2.extractor.SeekMap)

Example 49 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class AtomParsers method parseVideoSampleEntry.

private static void parseVideoSampleEntry(ParsableByteArray parent, int atomType, int position, int size, int trackId, int rotationDegrees, DrmInitData drmInitData, StsdData out, int entryIndex) throws ParserException {
    parent.setPosition(position + Atom.HEADER_SIZE);
    parent.skipBytes(24);
    int width = parent.readUnsignedShort();
    int height = parent.readUnsignedShort();
    boolean pixelWidthHeightRatioFromPasp = false;
    float pixelWidthHeightRatio = 1;
    parent.skipBytes(50);
    int childPosition = parent.getPosition();
    if (atomType == Atom.TYPE_encv) {
        atomType = parseSampleEntryEncryptionData(parent, position, size, out, entryIndex);
        parent.setPosition(childPosition);
    }
    List<byte[]> initializationData = null;
    String mimeType = null;
    byte[] projectionData = null;
    @C.StereoMode int stereoMode = Format.NO_VALUE;
    while (childPosition - position < size) {
        parent.setPosition(childPosition);
        int childStartPosition = parent.getPosition();
        int childAtomSize = parent.readInt();
        if (childAtomSize == 0 && parent.getPosition() - position == size) {
            // Handle optional terminating four zero bytes in MOV files.
            break;
        }
        Assertions.checkArgument(childAtomSize > 0, "childAtomSize should be positive");
        int childAtomType = parent.readInt();
        if (childAtomType == Atom.TYPE_avcC) {
            Assertions.checkState(mimeType == null);
            mimeType = MimeTypes.VIDEO_H264;
            parent.setPosition(childStartPosition + Atom.HEADER_SIZE);
            AvcConfig avcConfig = AvcConfig.parse(parent);
            initializationData = avcConfig.initializationData;
            out.nalUnitLengthFieldLength = avcConfig.nalUnitLengthFieldLength;
            if (!pixelWidthHeightRatioFromPasp) {
                pixelWidthHeightRatio = avcConfig.pixelWidthAspectRatio;
            }
        } else if (childAtomType == Atom.TYPE_hvcC) {
            Assertions.checkState(mimeType == null);
            mimeType = MimeTypes.VIDEO_H265;
            parent.setPosition(childStartPosition + Atom.HEADER_SIZE);
            HevcConfig hevcConfig = HevcConfig.parse(parent);
            initializationData = hevcConfig.initializationData;
            out.nalUnitLengthFieldLength = hevcConfig.nalUnitLengthFieldLength;
        } else if (childAtomType == Atom.TYPE_vpcC) {
            Assertions.checkState(mimeType == null);
            mimeType = (atomType == Atom.TYPE_vp08) ? MimeTypes.VIDEO_VP8 : MimeTypes.VIDEO_VP9;
        } else if (childAtomType == Atom.TYPE_d263) {
            Assertions.checkState(mimeType == null);
            mimeType = MimeTypes.VIDEO_H263;
        } else if (childAtomType == Atom.TYPE_esds) {
            Assertions.checkState(mimeType == null);
            Pair<String, byte[]> mimeTypeAndInitializationData = parseEsdsFromParent(parent, childStartPosition);
            mimeType = mimeTypeAndInitializationData.first;
            initializationData = Collections.singletonList(mimeTypeAndInitializationData.second);
        } else if (childAtomType == Atom.TYPE_pasp) {
            pixelWidthHeightRatio = parsePaspFromParent(parent, childStartPosition);
            pixelWidthHeightRatioFromPasp = true;
        } else if (childAtomType == Atom.TYPE_sv3d) {
            projectionData = parseProjFromParent(parent, childStartPosition, childAtomSize);
        } else if (childAtomType == Atom.TYPE_st3d) {
            int version = parent.readUnsignedByte();
            // Flags.
            parent.skipBytes(3);
            if (version == 0) {
                int layout = parent.readUnsignedByte();
                switch(layout) {
                    case 0:
                        stereoMode = C.STEREO_MODE_MONO;
                        break;
                    case 1:
                        stereoMode = C.STEREO_MODE_TOP_BOTTOM;
                        break;
                    case 2:
                        stereoMode = C.STEREO_MODE_LEFT_RIGHT;
                        break;
                    case 3:
                        stereoMode = C.STEREO_MODE_STEREO_MESH;
                        break;
                    default:
                        break;
                }
            }
        }
        childPosition += childAtomSize;
    }
    // If the media type was not recognized, ignore the track.
    if (mimeType == null) {
        return;
    }
    out.format = Format.createVideoSampleFormat(Integer.toString(trackId), mimeType, null, Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE, initializationData, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode, drmInitData);
}
Also used : HevcConfig(com.google.android.exoplayer2.video.HevcConfig) AvcConfig(com.google.android.exoplayer2.video.AvcConfig)

Example 50 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class AtomParsers method parseIlst.

private static Metadata parseIlst(ParsableByteArray ilst, int limit) {
    ilst.skipBytes(Atom.HEADER_SIZE);
    ArrayList<Metadata.Entry> entries = new ArrayList<>();
    while (ilst.getPosition() < limit) {
        Metadata.Entry entry = MetadataUtil.parseIlstElement(ilst);
        if (entry != null) {
            entries.add(entry);
        }
    }
    return entries.isEmpty() ? null : new Metadata(entries);
}
Also used : ArrayList(java.util.ArrayList) Metadata(com.google.android.exoplayer2.metadata.Metadata)

Aggregations

ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)48 ParserException (com.google.android.exoplayer2.ParserException)11 Format (com.google.android.exoplayer2.Format)6 ArrayList (java.util.ArrayList)4 SeekMap (com.google.android.exoplayer2.extractor.SeekMap)3 Metadata (com.google.android.exoplayer2.metadata.Metadata)3 TrackOutput (com.google.android.exoplayer2.extractor.TrackOutput)2 ContainerAtom (com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom)2 FlacStreamInfo (com.google.android.exoplayer2.util.FlacStreamInfo)2 AvcConfig (com.google.android.exoplayer2.video.AvcConfig)2 ByteBuffer (java.nio.ByteBuffer)2 Matcher (java.util.regex.Matcher)2 Spanned (android.text.Spanned)1 ChunkIndex (com.google.android.exoplayer2.extractor.ChunkIndex)1 MpegAudioHeader (com.google.android.exoplayer2.extractor.MpegAudioHeader)1 LeafAtom (com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom)1 TrackIdGenerator (com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)1 CommentFrame (com.google.android.exoplayer2.metadata.id3.CommentFrame)1 TextInformationFrame (com.google.android.exoplayer2.metadata.id3.TextInformationFrame)1 FakeExtractorOutput (com.google.android.exoplayer2.testutil.FakeExtractorOutput)1