Search in sources :

Example 26 with ParsableByteArray

use of androidx.media3.common.util.ParsableByteArray in project media by androidx.

the class StreamReader method readPayload.

@RequiresNonNull({ "trackOutput", "oggSeeker", "extractorOutput" })
private int readPayload(ExtractorInput input, PositionHolder seekPosition) throws IOException {
    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 = checkStateNotNull(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(androidx.media3.common.util.ParsableByteArray) SeekMap(androidx.media3.extractor.SeekMap) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 27 with ParsableByteArray

use of androidx.media3.common.util.ParsableByteArray in project media by androidx.

the class SefReader method readSdrs.

private void readSdrs(ExtractorInput input, PositionHolder seekPosition) throws IOException {
    long streamLength = input.getLength();
    int sdrsLength = tailLength - TAIL_HEADER_LENGTH - TAIL_FOOTER_LENGTH;
    ParsableByteArray scratch = new ParsableByteArray(/* limit= */
    sdrsLength);
    input.readFully(scratch.getData(), /* offset= */
    0, /* length= */
    sdrsLength);
    for (int i = 0; i < sdrsLength / LENGTH_OF_ONE_SDR; i++) {
        // SDR data sub info flag and reserved bits (2).
        scratch.skipBytes(2);
        @DataType int dataType = scratch.readLittleEndianShort();
        switch(dataType) {
            case TYPE_SLOW_MOTION_DATA:
            case TYPE_SUPER_SLOW_MOTION_DATA:
            case TYPE_SUPER_SLOW_MOTION_BGM:
            case TYPE_SUPER_SLOW_MOTION_EDIT_DATA:
            case TYPE_SUPER_SLOW_DEFLICKERING_ON:
                // The read int is the distance from the tail info to the start of the metadata.
                // Calculated as an offset from the start by working backwards.
                long startOffset = streamLength - tailLength - scratch.readLittleEndianInt();
                int size = scratch.readLittleEndianInt();
                dataReferences.add(new DataReference(dataType, startOffset, size));
                break;
            default:
                // startPosition (4), size (4).
                scratch.skipBytes(8);
        }
    }
    if (dataReferences.isEmpty()) {
        seekPosition.position = 0;
        return;
    }
    readerState = STATE_READING_SEF_DATA;
    seekPosition.position = dataReferences.get(0).startOffset;
}
Also used : ParsableByteArray(androidx.media3.common.util.ParsableByteArray)

Example 28 with ParsableByteArray

use of androidx.media3.common.util.ParsableByteArray in project media by androidx.

the class VorbisReader method readHeaders.

@Override
@EnsuresNonNullIf(expression = "#3.format", result = false)
protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData) throws IOException {
    if (vorbisSetup != null) {
        checkNotNull(setupData.format);
        return false;
    }
    vorbisSetup = readSetupHeaders(packet);
    if (vorbisSetup == null) {
        return true;
    }
    VorbisSetup vorbisSetup = this.vorbisSetup;
    VorbisUtil.VorbisIdHeader idHeader = vorbisSetup.idHeader;
    ArrayList<byte[]> codecInitializationData = new ArrayList<>();
    codecInitializationData.add(idHeader.data);
    codecInitializationData.add(vorbisSetup.setupHeaderData);
    @Nullable Metadata metadata = VorbisUtil.parseVorbisComments(ImmutableList.copyOf(vorbisSetup.commentHeader.comments));
    setupData.format = new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_VORBIS).setAverageBitrate(idHeader.bitrateNominal).setPeakBitrate(idHeader.bitrateMaximum).setChannelCount(idHeader.channels).setSampleRate(idHeader.sampleRate).setInitializationData(codecInitializationData).setMetadata(metadata).build();
    return true;
}
Also used : Format(androidx.media3.common.Format) ArrayList(java.util.ArrayList) Metadata(androidx.media3.common.Metadata) Nullable(androidx.annotation.Nullable) VorbisUtil(androidx.media3.extractor.VorbisUtil) EnsuresNonNullIf(org.checkerframework.checker.nullness.qual.EnsuresNonNullIf)

Example 29 with ParsableByteArray

use of androidx.media3.common.util.ParsableByteArray in project media by androidx.

the class Id3Decoder method decode.

/**
 * Decodes ID3 tags.
 *
 * @param data The bytes to decode ID3 tags from.
 * @param size Amount of bytes in {@code data} to read.
 * @return A {@link Metadata} object containing the decoded ID3 tags, or null if the data could
 *     not be decoded.
 */
@Nullable
public Metadata decode(byte[] data, int size) {
    List<Id3Frame> id3Frames = new ArrayList<>();
    ParsableByteArray id3Data = new ParsableByteArray(data, size);
    @Nullable Id3Header id3Header = decodeHeader(id3Data);
    if (id3Header == null) {
        return null;
    }
    int startPosition = id3Data.getPosition();
    int frameHeaderSize = id3Header.majorVersion == 2 ? 6 : 10;
    int framesSize = id3Header.framesSize;
    if (id3Header.isUnsynchronized) {
        framesSize = removeUnsynchronization(id3Data, id3Header.framesSize);
    }
    id3Data.setLimit(startPosition + framesSize);
    boolean unsignedIntFrameSizeHack = false;
    if (!validateFrames(id3Data, id3Header.majorVersion, frameHeaderSize, false)) {
        if (id3Header.majorVersion == 4 && validateFrames(id3Data, 4, frameHeaderSize, true)) {
            unsignedIntFrameSizeHack = true;
        } else {
            Log.w(TAG, "Failed to validate ID3 tag with majorVersion=" + id3Header.majorVersion);
            return null;
        }
    }
    while (id3Data.bytesLeft() >= frameHeaderSize) {
        @Nullable Id3Frame frame = decodeFrame(id3Header.majorVersion, id3Data, unsignedIntFrameSizeHack, frameHeaderSize, framePredicate);
        if (frame != null) {
            id3Frames.add(frame);
        }
    }
    return new Metadata(id3Frames);
}
Also used : ParsableByteArray(androidx.media3.common.util.ParsableByteArray) ArrayList(java.util.ArrayList) Metadata(androidx.media3.common.Metadata) Nullable(androidx.annotation.Nullable) Nullable(androidx.annotation.Nullable)

Example 30 with ParsableByteArray

use of androidx.media3.common.util.ParsableByteArray in project media by androidx.

the class DefaultTsPayloadReaderFactory method getClosedCaptionFormats.

/**
 * If {@link #FLAG_OVERRIDE_CAPTION_DESCRIPTORS} is set, returns a {@link List<Format>} of {@link
 * #closedCaptionFormats}. If unset, parses the PMT descriptor information and returns a {@link
 * List<Format>} for the declared formats, or {@link #closedCaptionFormats} if the descriptor is
 * not present.
 *
 * @param esInfo The {@link EsInfo} passed to {@link #createPayloadReader(int, EsInfo)}.
 * @return A {@link List<Format>} containing list of closed caption formats.
 */
private List<Format> getClosedCaptionFormats(EsInfo esInfo) {
    if (isSet(FLAG_OVERRIDE_CAPTION_DESCRIPTORS)) {
        return closedCaptionFormats;
    }
    ParsableByteArray scratchDescriptorData = new ParsableByteArray(esInfo.descriptorBytes);
    List<Format> closedCaptionFormats = this.closedCaptionFormats;
    while (scratchDescriptorData.bytesLeft() > 0) {
        int descriptorTag = scratchDescriptorData.readUnsignedByte();
        int descriptorLength = scratchDescriptorData.readUnsignedByte();
        int nextDescriptorPosition = scratchDescriptorData.getPosition() + descriptorLength;
        if (descriptorTag == DESCRIPTOR_TAG_CAPTION_SERVICE) {
            // Note: see ATSC A/65 for detailed information about the caption service descriptor.
            closedCaptionFormats = new ArrayList<>();
            int numberOfServices = scratchDescriptorData.readUnsignedByte() & 0x1F;
            for (int i = 0; i < numberOfServices; i++) {
                String language = scratchDescriptorData.readString(3);
                int captionTypeByte = scratchDescriptorData.readUnsignedByte();
                boolean isDigital = (captionTypeByte & 0x80) != 0;
                String mimeType;
                int accessibilityChannel;
                if (isDigital) {
                    mimeType = MimeTypes.APPLICATION_CEA708;
                    accessibilityChannel = captionTypeByte & 0x3F;
                } else {
                    mimeType = MimeTypes.APPLICATION_CEA608;
                    accessibilityChannel = 1;
                }
                // easy_reader(1), wide_aspect_ratio(1), reserved(6).
                byte flags = (byte) scratchDescriptorData.readUnsignedByte();
                // Skip reserved (8).
                scratchDescriptorData.skipBytes(1);
                @Nullable List<byte[]> initializationData = null;
                // The wide_aspect_ratio flag only has meaning for CEA-708.
                if (isDigital) {
                    boolean isWideAspectRatio = (flags & 0x40) != 0;
                    initializationData = CodecSpecificDataUtil.buildCea708InitializationData(isWideAspectRatio);
                }
                closedCaptionFormats.add(new Format.Builder().setSampleMimeType(mimeType).setLanguage(language).setAccessibilityChannel(accessibilityChannel).setInitializationData(initializationData).build());
            }
        } else {
        // Unknown descriptor. Ignore.
        }
        scratchDescriptorData.setPosition(nextDescriptorPosition);
    }
    return closedCaptionFormats;
}
Also used : ParsableByteArray(androidx.media3.common.util.ParsableByteArray) Format(androidx.media3.common.Format) Nullable(androidx.annotation.Nullable)

Aggregations

ParsableByteArray (androidx.media3.common.util.ParsableByteArray)96 Test (org.junit.Test)38 Nullable (androidx.annotation.Nullable)34 Format (androidx.media3.common.Format)9 ArrayList (java.util.ArrayList)9 Metadata (androidx.media3.common.Metadata)7 FakeExtractorInput (androidx.media3.test.utils.FakeExtractorInput)7 SeekPoint (androidx.media3.extractor.SeekPoint)5 Cue (androidx.media3.common.text.Cue)4 SampleNumberHolder (androidx.media3.extractor.FlacFrameReader.SampleNumberHolder)4 FlacStreamMetadataHolder (androidx.media3.extractor.FlacMetadataReader.FlacStreamMetadataHolder)4 ByteBuffer (java.nio.ByteBuffer)4 RequiresNonNull (org.checkerframework.checker.nullness.qual.RequiresNonNull)4 ParsableBitArray (androidx.media3.common.util.ParsableBitArray)3 Mesh (androidx.media3.exoplayer.video.spherical.Projection.Mesh)3 SubMesh (androidx.media3.exoplayer.video.spherical.Projection.SubMesh)3 TrackOutput (androidx.media3.extractor.TrackOutput)3 SmtaMetadataEntry (androidx.media3.extractor.metadata.mp4.SmtaMetadataEntry)3 LeafAtom (androidx.media3.extractor.mp4.Atom.LeafAtom)3 EnsuresNonNullIf (org.checkerframework.checker.nullness.qual.EnsuresNonNullIf)3