Search in sources :

Example 6 with ParsableBitArray

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

the class DvbParser method paintPixelDataSubBlock.

/**
 * Draws a pixel data sub-block, as defined by ETSI EN 300 743 7.2.5.1, into a canvas.
 */
private static void paintPixelDataSubBlock(byte[] pixelData, int[] clutEntries, int regionDepth, int horizontalAddress, int verticalAddress, @Nullable Paint paint, Canvas canvas) {
    ParsableBitArray data = new ParsableBitArray(pixelData);
    int column = horizontalAddress;
    int line = verticalAddress;
    @Nullable byte[] clutMapTable2To4 = null;
    @Nullable byte[] clutMapTable2To8 = null;
    @Nullable byte[] clutMapTable4To8 = null;
    while (data.bitsLeft() != 0) {
        int dataType = data.readBits(8);
        switch(dataType) {
            case DATA_TYPE_2BP_CODE_STRING:
                @Nullable byte[] clutMapTable2ToX;
                if (regionDepth == REGION_DEPTH_8_BIT) {
                    clutMapTable2ToX = clutMapTable2To8 == null ? defaultMap2To8 : clutMapTable2To8;
                } else if (regionDepth == REGION_DEPTH_4_BIT) {
                    clutMapTable2ToX = clutMapTable2To4 == null ? defaultMap2To4 : clutMapTable2To4;
                } else {
                    clutMapTable2ToX = null;
                }
                column = paint2BitPixelCodeString(data, clutEntries, clutMapTable2ToX, column, line, paint, canvas);
                data.byteAlign();
                break;
            case DATA_TYPE_4BP_CODE_STRING:
                @Nullable byte[] clutMapTable4ToX;
                if (regionDepth == REGION_DEPTH_8_BIT) {
                    clutMapTable4ToX = clutMapTable4To8 == null ? defaultMap4To8 : clutMapTable4To8;
                } else {
                    clutMapTable4ToX = null;
                }
                column = paint4BitPixelCodeString(data, clutEntries, clutMapTable4ToX, column, line, paint, canvas);
                data.byteAlign();
                break;
            case DATA_TYPE_8BP_CODE_STRING:
                column = paint8BitPixelCodeString(data, clutEntries, /* clutMapTable= */
                null, column, line, paint, canvas);
                break;
            case DATA_TYPE_24_TABLE_DATA:
                clutMapTable2To4 = buildClutMapTable(4, 4, data);
                break;
            case DATA_TYPE_28_TABLE_DATA:
                clutMapTable2To8 = buildClutMapTable(4, 8, data);
                break;
            case DATA_TYPE_48_TABLE_DATA:
                clutMapTable4To8 = buildClutMapTable(16, 8, data);
                break;
            case DATA_TYPE_END_LINE:
                column = horizontalAddress;
                line += 2;
                break;
            default:
                // Do nothing.
                break;
        }
    }
}
Also used : Paint(android.graphics.Paint) Nullable(androidx.annotation.Nullable) ParsableBitArray(com.google.android.exoplayer2.util.ParsableBitArray)

Example 7 with ParsableBitArray

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

the class AdtsExtractor method sniff.

@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
    // Skip any ID3 headers.
    ParsableByteArray scratch = new ParsableByteArray(10);
    ParsableBitArray scratchBits = new ParsableBitArray(scratch.data);
    int startPosition = 0;
    while (true) {
        input.peekFully(scratch.data, 0, 10);
        scratch.setPosition(0);
        if (scratch.readUnsignedInt24() != ID3_TAG) {
            break;
        }
        scratch.skipBytes(3);
        int length = scratch.readSynchSafeInt();
        startPosition += 10 + length;
        input.advancePeekPosition(length);
    }
    input.resetPeekPosition();
    input.advancePeekPosition(startPosition);
    // Try to find four or more consecutive AAC audio frames, exceeding the MPEG TS packet size.
    int headerPosition = startPosition;
    int validFramesSize = 0;
    int validFramesCount = 0;
    while (true) {
        input.peekFully(scratch.data, 0, 2);
        scratch.setPosition(0);
        int syncBytes = scratch.readUnsignedShort();
        if ((syncBytes & 0xFFF6) != 0xFFF0) {
            validFramesCount = 0;
            validFramesSize = 0;
            input.resetPeekPosition();
            if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
                return false;
            }
            input.advancePeekPosition(headerPosition);
        } else {
            if (++validFramesCount >= 4 && validFramesSize > 188) {
                return true;
            }
            // Skip the frame.
            input.peekFully(scratch.data, 0, 4);
            scratchBits.setPosition(14);
            int frameSize = scratchBits.readBits(13);
            // Either the stream is malformed OR we're not parsing an ADTS stream.
            if (frameSize <= 6) {
                return false;
            }
            input.advancePeekPosition(frameSize - 6);
            validFramesSize += frameSize;
        }
    }
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ParsableBitArray(com.google.android.exoplayer2.util.ParsableBitArray)

Example 8 with ParsableBitArray

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

the class FlacMetadataReader method readMetadataBlock.

/**
 * Reads one FLAC metadata block.
 *
 * <p>If no exception is thrown, the peek position of {@code input} is aligned with the read
 * position.
 *
 * @param input Input stream to read the metadata block from (header included).
 * @param metadataHolder A holder for the metadata read. If the stream info block (which must be
 *     the first metadata block) is read, the holder contains a new instance representing the
 *     stream info data. If the block read is a Vorbis comment block or a picture block, the
 *     holder contains a copy of the existing stream metadata with the corresponding metadata
 *     added. Otherwise, the metadata in the holder is unchanged.
 * @return Whether the block read is the last metadata block.
 * @throws IllegalArgumentException If the block read is not a stream info block and the metadata
 *     in {@code metadataHolder} is {@code null}. In this case, the read position will be at the
 *     start of a metadata block and there is no guarantee on the peek position.
 * @throws IOException If reading from the input fails. In this case, the read position will be at
 *     the start of a metadata block and there is no guarantee on the peek position.
 */
public static boolean readMetadataBlock(ExtractorInput input, FlacStreamMetadataHolder metadataHolder) throws IOException {
    input.resetPeekPosition();
    ParsableBitArray scratch = new ParsableBitArray(new byte[4]);
    input.peekFully(scratch.data, 0, FlacConstants.METADATA_BLOCK_HEADER_SIZE);
    boolean isLastMetadataBlock = scratch.readBit();
    int type = scratch.readBits(7);
    int length = FlacConstants.METADATA_BLOCK_HEADER_SIZE + scratch.readBits(24);
    if (type == FlacConstants.METADATA_TYPE_STREAM_INFO) {
        metadataHolder.flacStreamMetadata = readStreamInfoBlock(input);
    } else {
        @Nullable FlacStreamMetadata flacStreamMetadata = metadataHolder.flacStreamMetadata;
        if (flacStreamMetadata == null) {
            throw new IllegalArgumentException();
        }
        if (type == FlacConstants.METADATA_TYPE_SEEK_TABLE) {
            FlacStreamMetadata.SeekTable seekTable = readSeekTableMetadataBlock(input, length);
            metadataHolder.flacStreamMetadata = flacStreamMetadata.copyWithSeekTable(seekTable);
        } else if (type == FlacConstants.METADATA_TYPE_VORBIS_COMMENT) {
            List<String> vorbisComments = readVorbisCommentMetadataBlock(input, length);
            metadataHolder.flacStreamMetadata = flacStreamMetadata.copyWithVorbisComments(vorbisComments);
        } else if (type == FlacConstants.METADATA_TYPE_PICTURE) {
            ParsableByteArray pictureBlock = new ParsableByteArray(length);
            input.readFully(pictureBlock.getData(), 0, length);
            pictureBlock.skipBytes(FlacConstants.METADATA_BLOCK_HEADER_SIZE);
            PictureFrame pictureFrame = PictureFrame.fromPictureBlock(pictureBlock);
            metadataHolder.flacStreamMetadata = flacStreamMetadata.copyWithPictureFrames(ImmutableList.of(pictureFrame));
        } else {
            input.skipFully(length);
        }
    }
    return isLastMetadataBlock;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) PictureFrame(com.google.android.exoplayer2.metadata.flac.PictureFrame) Nullable(androidx.annotation.Nullable) ParsableBitArray(com.google.android.exoplayer2.util.ParsableBitArray)

Example 9 with ParsableBitArray

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

the class DtsUtil method getNormalizedFrameHeader.

private static ParsableBitArray getNormalizedFrameHeader(byte[] frameHeader) {
    if (frameHeader[0] == FIRST_BYTE_BE) {
        // The frame is already 16-bit mode, big endian.
        return new ParsableBitArray(frameHeader);
    }
    // Data is not normalized, but we don't want to modify frameHeader.
    frameHeader = Arrays.copyOf(frameHeader, frameHeader.length);
    if (isLittleEndianFrameHeader(frameHeader)) {
        // Change endianness.
        for (int i = 0; i < frameHeader.length - 1; i += 2) {
            byte temp = frameHeader[i];
            frameHeader[i] = frameHeader[i + 1];
            frameHeader[i + 1] = temp;
        }
    }
    ParsableBitArray frameBits = new ParsableBitArray(frameHeader);
    if (frameHeader[0] == (byte) (SYNC_VALUE_14B_BE >> 24)) {
        // Discard the 2 most significant bits of each 16 bit word.
        ParsableBitArray scratchBits = new ParsableBitArray(frameHeader);
        while (scratchBits.bitsLeft() >= 16) {
            scratchBits.skipBits(2);
            frameBits.putInt(scratchBits.readBits(14), 14);
        }
    }
    frameBits.reset(frameHeader);
    return frameBits;
}
Also used : ParsableBitArray(com.google.android.exoplayer2.util.ParsableBitArray)

Example 10 with ParsableBitArray

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

the class AppInfoTableDecoder method parseAit.

@Nullable
private static Metadata parseAit(ParsableBitArray sectionData) {
    // tableId, section_syntax_indication, reserved_future_use, reserved
    sectionData.skipBits(12);
    int sectionLength = sectionData.readBits(12);
    int endOfSection = sectionData.getBytePosition() + sectionLength - 4;
    // test_application_flag, application_type, reserved, version_number, current_next_indicator,
    // section_number, last_section_number, reserved_future_use
    sectionData.skipBits(44);
    int commonDescriptorsLength = sectionData.readBits(12);
    // Since we currently only keep URL and control code, which are unique per application,
    // there is no useful information in common descriptor.
    sectionData.skipBytes(commonDescriptorsLength);
    // reserved_future_use, application_loop_length
    sectionData.skipBits(16);
    ArrayList<AppInfoTable> appInfoTables = new ArrayList<>();
    while (sectionData.getBytePosition() < endOfSection) {
        @Nullable String urlBase = null;
        @Nullable String urlExtension = null;
        // application_identifier
        sectionData.skipBits(48);
        int controlCode = sectionData.readBits(8);
        // reserved_future_use
        sectionData.skipBits(4);
        int applicationDescriptorsLoopLength = sectionData.readBits(12);
        int positionOfNextApplication = sectionData.getBytePosition() + applicationDescriptorsLoopLength;
        while (sectionData.getBytePosition() < positionOfNextApplication) {
            int descriptorTag = sectionData.readBits(8);
            int descriptorLength = sectionData.readBits(8);
            int positionOfNextDescriptor = sectionData.getBytePosition() + descriptorLength;
            if (descriptorTag == DESCRIPTOR_TRANSPORT_PROTOCOL) {
                // See section 5.3.6.
                int protocolId = sectionData.readBits(16);
                // label
                sectionData.skipBits(8);
                if (protocolId == TRANSPORT_PROTOCOL_HTTP) {
                    // See section 5.3.6.2.
                    while (sectionData.getBytePosition() < positionOfNextDescriptor) {
                        int urlBaseLength = sectionData.readBits(8);
                        urlBase = sectionData.readBytesAsString(urlBaseLength, Charsets.US_ASCII);
                        int extensionCount = sectionData.readBits(8);
                        for (int urlExtensionIndex = 0; urlExtensionIndex < extensionCount; urlExtensionIndex++) {
                            int urlExtensionLength = sectionData.readBits(8);
                            sectionData.skipBytes(urlExtensionLength);
                        }
                    }
                }
            } else if (descriptorTag == DESCRIPTOR_SIMPLE_APPLICATION_LOCATION) {
                // See section 5.3.7.
                urlExtension = sectionData.readBytesAsString(descriptorLength, Charsets.US_ASCII);
            }
            sectionData.setPosition(positionOfNextDescriptor * 8);
        }
        sectionData.setPosition(positionOfNextApplication * 8);
        if (urlBase != null && urlExtension != null) {
            appInfoTables.add(new AppInfoTable(controlCode, urlBase + urlExtension));
        }
    }
    return appInfoTables.isEmpty() ? null : new Metadata(appInfoTables);
}
Also used : ArrayList(java.util.ArrayList) Metadata(com.google.android.exoplayer2.metadata.Metadata) Nullable(androidx.annotation.Nullable) Nullable(androidx.annotation.Nullable)

Aggregations

ParsableBitArray (com.google.android.exoplayer2.util.ParsableBitArray)9 Nullable (androidx.annotation.Nullable)5 Paint (android.graphics.Paint)2 Format (com.google.android.exoplayer2.Format)2 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)2 ArrayList (java.util.ArrayList)2 Metadata (com.google.android.exoplayer2.metadata.Metadata)1 PictureFrame (com.google.android.exoplayer2.metadata.flac.PictureFrame)1 Cue (com.google.android.exoplayer2.text.Cue)1 Mesh (com.google.android.exoplayer2.video.spherical.Projection.Mesh)1 SubMesh (com.google.android.exoplayer2.video.spherical.Projection.SubMesh)1 ImmutableList (com.google.common.collect.ImmutableList)1 List (java.util.List)1 RequiresNonNull (org.checkerframework.checker.nullness.qual.RequiresNonNull)1