Java Code Examples for com.google.android.exoplayer2.util.ParsableByteArray#bytesLeft()

The following examples show how to use com.google.android.exoplayer2.util.ParsableByteArray#bytesLeft() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: SsaDecoder.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
/**
 * Parse the {@code [V4+ Styles]} section.
 *
 * <p>When this returns, {@code data.position} will be set to the beginning of the first line that
 * starts with {@code [} (i.e. the title of the next section).
 *
 * @param data A {@link ParsableByteArray} with {@link ParsableByteArray#getPosition()} pointing
 *     at the beginning of of the first line after {@code [V4+ Styles]}.
 */
private static Map<String, SsaStyle> parseStyles(ParsableByteArray data) {
  Map<String, SsaStyle> styles = new LinkedHashMap<>();
  @Nullable SsaStyle.Format formatInfo = null;
  @Nullable String currentLine;
  while ((currentLine = data.readLine()) != null
      && (data.bytesLeft() == 0 || data.peekUnsignedByte() != '[')) {
    if (currentLine.startsWith(FORMAT_LINE_PREFIX)) {
      formatInfo = SsaStyle.Format.fromFormatLine(currentLine);
    } else if (currentLine.startsWith(STYLE_LINE_PREFIX)) {
      if (formatInfo == null) {
        Log.w(TAG, "Skipping 'Style:' line before 'Format:' line: " + currentLine);
        continue;
      }
      @Nullable SsaStyle style = SsaStyle.fromStyleLine(currentLine, formatInfo);
      if (style != null) {
        styles.put(style.name, style);
      }
    }
  }
  return styles;
}
 
Example 2
Source File: Ac3Reader.java    From K-Sonic with MIT License 6 votes vote down vote up
/**
 * Locates the next syncword, advancing the position to the byte that immediately follows it. If a
 * syncword was not located, the position is advanced to the limit.
 *
 * @param pesBuffer The buffer whose position should be advanced.
 * @return Whether a syncword position was found.
 */
private boolean skipToNextSync(ParsableByteArray pesBuffer) {
  while (pesBuffer.bytesLeft() > 0) {
    if (!lastByteWas0B) {
      lastByteWas0B = pesBuffer.readUnsignedByte() == 0x0B;
      continue;
    }
    int secondByte = pesBuffer.readUnsignedByte();
    if (secondByte == 0x77) {
      lastByteWas0B = false;
      return true;
    } else {
      lastByteWas0B = secondByte == 0x0B;
    }
  }
  return false;
}
 
Example 3
Source File: MpegAudioReader.java    From K-Sonic with MIT License 6 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_HEADER:
        findHeader(data);
        break;
      case STATE_READING_HEADER:
        readHeaderRemainder(data);
        break;
      case STATE_READING_FRAME:
        readFrameRemainder(data);
        break;
    }
  }
}
 
Example 4
Source File: AdtsReader.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void consume(ParsableByteArray data) throws ParserException {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SAMPLE:
        findNextSample(data);
        break;
      case STATE_READING_ID3_HEADER:
        if (continueRead(data, id3HeaderBuffer.data, ID3_HEADER_SIZE)) {
          parseId3Header();
        }
        break;
      case STATE_CHECKING_ADTS_HEADER:
        checkAdtsHeader(data);
        break;
      case STATE_READING_ADTS_HEADER:
        int targetLength = hasCrc ? HEADER_SIZE + CRC_SIZE : HEADER_SIZE;
        if (continueRead(data, adtsScratch.data, targetLength)) {
          parseAdtsHeader();
        }
        break;
      case STATE_READING_SAMPLE:
        readSample(data);
        break;
      default:
        throw new IllegalStateException();
    }
  }
}
 
Example 5
Source File: VorbisUtil.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Verifies whether the next bytes in {@code header} are a vorbis header of the given
 * {@code headerType}.
 *
 * @param headerType the type of the header expected.
 * @param header the alleged header bytes.
 * @param quiet if {@code true} no exceptions are thrown. Instead {@code false} is returned.
 * @return the number of bytes read.
 * @throws ParserException thrown if header type or capture pattern is not as expected.
 */
public static boolean verifyVorbisHeaderCapturePattern(int headerType, ParsableByteArray header,
    boolean quiet)
    throws ParserException {
  if (header.bytesLeft() < 7) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("too short header: " + header.bytesLeft());
    }
  }

  if (header.readUnsignedByte() != headerType) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("expected header type " + Integer.toHexString(headerType));
    }
  }

  if (!(header.readUnsignedByte() == 'v'
      && header.readUnsignedByte() == 'o'
      && header.readUnsignedByte() == 'r'
      && header.readUnsignedByte() == 'b'
      && header.readUnsignedByte() == 'i'
      && header.readUnsignedByte() == 's')) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("expected characters 'vorbis'");
    }
  }
  return true;
}
 
Example 6
Source File: Tx3gDecoder.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private static String readSubtitleText(ParsableByteArray parsableByteArray)
    throws SubtitleDecoderException {
  assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
  int textLength = parsableByteArray.readUnsignedShort();
  if (textLength == 0) {
    return "";
  }
  if (parsableByteArray.bytesLeft() >= SIZE_BOM_UTF16) {
    char firstChar = parsableByteArray.peekChar();
    if (firstChar == BOM_UTF16_BE || firstChar == BOM_UTF16_LE) {
      return parsableByteArray.readString(textLength, Charset.forName(C.UTF16_NAME));
    }
  }
  return parsableByteArray.readString(textLength, Charset.forName(C.UTF8_NAME));
}
 
Example 7
Source File: Id3Reader.java    From K-Sonic with MIT License 5 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  if (!writingSample) {
    return;
  }
  int bytesAvailable = data.bytesLeft();
  if (sampleBytesRead < ID3_HEADER_SIZE) {
    // We're still reading the ID3 header.
    int headerBytesAvailable = Math.min(bytesAvailable, ID3_HEADER_SIZE - sampleBytesRead);
    System.arraycopy(data.data, data.getPosition(), id3Header.data, sampleBytesRead,
        headerBytesAvailable);
    if (sampleBytesRead + headerBytesAvailable == ID3_HEADER_SIZE) {
      // We've finished reading the ID3 header. Extract the sample size.
      id3Header.setPosition(0);
      if ('I' != id3Header.readUnsignedByte() || 'D' != id3Header.readUnsignedByte()
          || '3' != id3Header.readUnsignedByte()) {
        Log.w(TAG, "Discarding invalid ID3 tag");
        writingSample = false;
        return;
      }
      id3Header.skipBytes(3); // version (2) + flags (1)
      sampleSize = ID3_HEADER_SIZE + id3Header.readSynchSafeInt();
    }
  }
  // Write data to the output.
  int bytesToWrite = Math.min(bytesAvailable, sampleSize - sampleBytesRead);
  output.sampleData(data, bytesToWrite);
  sampleBytesRead += bytesToWrite;
}
 
Example 8
Source File: Ac3Reader.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SYNC:
        if (skipToNextSync(data)) {
          state = STATE_READING_HEADER;
          headerScratchBytes.data[0] = 0x0B;
          headerScratchBytes.data[1] = 0x77;
          bytesRead = 2;
        }
        break;
      case STATE_READING_HEADER:
        if (continueRead(data, headerScratchBytes.data, HEADER_SIZE)) {
          parseHeader();
          headerScratchBytes.setPosition(0);
          output.sampleData(headerScratchBytes, HEADER_SIZE);
          state = STATE_READING_SAMPLE;
        }
        break;
      case STATE_READING_SAMPLE:
        int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead);
        output.sampleData(data, bytesToRead);
        bytesRead += bytesToRead;
        if (bytesRead == sampleSize) {
          output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
          timeUs += sampleDurationUs;
          state = STATE_FINDING_SYNC;
        }
        break;
      default:
        break;
    }
  }
}
 
Example 9
Source File: Ac4Reader.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SYNC:
        if (skipToNextSync(data)) {
          state = STATE_READING_HEADER;
          headerScratchBytes.data[0] = (byte) 0xAC;
          headerScratchBytes.data[1] = (byte) (hasCRC ? 0x41 : 0x40);
          bytesRead = 2;
        }
        break;
      case STATE_READING_HEADER:
        if (continueRead(data, headerScratchBytes.data, Ac4Util.HEADER_SIZE_FOR_PARSER)) {
          parseHeader();
          headerScratchBytes.setPosition(0);
          output.sampleData(headerScratchBytes, Ac4Util.HEADER_SIZE_FOR_PARSER);
          state = STATE_READING_SAMPLE;
        }
        break;
      case STATE_READING_SAMPLE:
        int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead);
        output.sampleData(data, bytesToRead);
        bytesRead += bytesToRead;
        if (bytesRead == sampleSize) {
          output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
          timeUs += sampleDurationUs;
          state = STATE_FINDING_SYNC;
        }
        break;
      default:
        break;
    }
  }
}
 
Example 10
Source File: UserDataReader.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
public void consume(long pesTimeUs, ParsableByteArray userDataPayload) {
  if (userDataPayload.bytesLeft() < 9) {
    return;
  }
  int userDataStartCode = userDataPayload.readInt();
  int userDataIdentifier = userDataPayload.readInt();
  int userDataTypeCode = userDataPayload.readUnsignedByte();
  if (userDataStartCode == USER_DATA_START_CODE
      && userDataIdentifier == CeaUtil.USER_DATA_IDENTIFIER_GA94
      && userDataTypeCode == CeaUtil.USER_DATA_TYPE_CODE_MPEG_CC) {
    CeaUtil.consumeCcData(pesTimeUs, userDataPayload, outputs);
  }
}
 
Example 11
Source File: PsDurationReader.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the SCR value read from the next pack in the stream, given the buffer at the pack
 * header start position (just behind the pack start code).
 */
public static long readScrValueFromPack(ParsableByteArray packetBuffer) {
  int originalPosition = packetBuffer.getPosition();
  if (packetBuffer.bytesLeft() < 9) {
    // We require at 9 bytes for pack header to read scr value
    return C.TIME_UNSET;
  }
  byte[] scrBytes = new byte[9];
  packetBuffer.readBytes(scrBytes, /* offset= */ 0, scrBytes.length);
  packetBuffer.setPosition(originalPosition);
  if (!checkMarkerBits(scrBytes)) {
    return C.TIME_UNSET;
  }
  return readScrValueFromPackHeader(scrBytes);
}
 
Example 12
Source File: DtsReader.java    From K-Sonic with MIT License 5 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SYNC:
        if (skipToNextSync(data)) {
          bytesRead = SYNC_VALUE_SIZE;
          state = STATE_READING_HEADER;
        }
        break;
      case STATE_READING_HEADER:
        if (continueRead(data, headerScratchBytes.data, HEADER_SIZE)) {
          parseHeader();
          headerScratchBytes.setPosition(0);
          output.sampleData(headerScratchBytes, HEADER_SIZE);
          state = STATE_READING_SAMPLE;
        }
        break;
      case STATE_READING_SAMPLE:
        int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead);
        output.sampleData(data, bytesToRead);
        bytesRead += bytesToRead;
        if (bytesRead == sampleSize) {
          output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
          timeUs += sampleDurationUs;
          state = STATE_FINDING_SYNC;
        }
        break;
    }
  }
}
 
Example 13
Source File: DtsReader.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SYNC:
        if (skipToNextSync(data)) {
          state = STATE_READING_HEADER;
        }
        break;
      case STATE_READING_HEADER:
        if (continueRead(data, headerScratchBytes.data, HEADER_SIZE)) {
          parseHeader();
          headerScratchBytes.setPosition(0);
          output.sampleData(headerScratchBytes, HEADER_SIZE);
          state = STATE_READING_SAMPLE;
        }
        break;
      case STATE_READING_SAMPLE:
        int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead);
        output.sampleData(data, bytesToRead);
        bytesRead += bytesToRead;
        if (bytesRead == sampleSize) {
          output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
          timeUs += sampleDurationUs;
          state = STATE_FINDING_SYNC;
        }
        break;
    }
  }
}
 
Example 14
Source File: Mp4Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Process an ftyp atom to determine whether the media is QuickTime.
 *
 * @param atomData The ftyp atom data.
 * @return Whether the media is QuickTime.
 */
private static boolean processFtypAtom(ParsableByteArray atomData) {
  atomData.setPosition(Atom.HEADER_SIZE);
  int majorBrand = atomData.readInt();
  if (majorBrand == BRAND_QUICKTIME) {
    return true;
  }
  atomData.skipBytes(4); // minor_version
  while (atomData.bytesLeft() > 0) {
    if (atomData.readInt() == BRAND_QUICKTIME) {
      return true;
    }
  }
  return false;
}
 
Example 15
Source File: H265Reader.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    int offset = data.getPosition();
    int limit = data.limit();
    byte[] dataArray = data.data;

    // Append the data to the buffer.
    totalBytesWritten += data.bytesLeft();
    output.sampleData(data, data.bytesLeft());

    // Scan the appended data, processing NAL units as they are encountered
    while (offset < limit) {
      int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);

      if (nalUnitOffset == limit) {
        // We've scanned to the end of the data without finding the start of another NAL unit.
        nalUnitData(dataArray, offset, limit);
        return;
      }

      // We've seen the start of a NAL unit of the following type.
      int nalUnitType = NalUnitUtil.getH265NalUnitType(dataArray, nalUnitOffset);

      // This is the number of bytes from the current offset to the start of the next NAL unit.
      // It may be negative if the NAL unit started in the previously consumed data.
      int lengthToNalUnit = nalUnitOffset - offset;
      if (lengthToNalUnit > 0) {
        nalUnitData(dataArray, offset, nalUnitOffset);
      }

      int bytesWrittenPastPosition = limit - nalUnitOffset;
      long absolutePosition = totalBytesWritten - bytesWrittenPastPosition;
      // Indicate the end of the previous NAL unit. If the length to the start of the next unit
      // is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes
      // when notifying that the unit has ended.
      endNalUnit(absolutePosition, bytesWrittenPastPosition,
          lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs);
      // Indicate the start of the next NAL unit.
      startNalUnit(absolutePosition, bytesWrittenPastPosition, nalUnitType, pesTimeUs);
      // Continue scanning the data.
      offset = nalUnitOffset + 3;
    }
  }
}
 
Example 16
Source File: PsBinarySearchSeeker.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Skips the buffer position to the position after the end of the current PS pack in the buffer,
 * given the byte position right after the {@link PsExtractor#PACK_START_CODE} of the pack in
 * the buffer. If the pack ends after the end of the buffer, skips to the end of the buffer.
 */
private static void skipToEndOfCurrentPack(ParsableByteArray packetBuffer) {
  int limit = packetBuffer.limit();

  if (packetBuffer.bytesLeft() < 10) {
    // We require at least 9 bytes for pack header to read SCR value + 1 byte for pack_stuffing
    // length.
    packetBuffer.setPosition(limit);
    return;
  }
  packetBuffer.skipBytes(9);

  int packStuffingLength = packetBuffer.readUnsignedByte() & 0x07;
  if (packetBuffer.bytesLeft() < packStuffingLength) {
    packetBuffer.setPosition(limit);
    return;
  }
  packetBuffer.skipBytes(packStuffingLength);

  if (packetBuffer.bytesLeft() < 4) {
    packetBuffer.setPosition(limit);
    return;
  }

  int nextStartCode = peekIntAtPosition(packetBuffer.data, packetBuffer.getPosition());
  if (nextStartCode == PsExtractor.SYSTEM_HEADER_START_CODE) {
    packetBuffer.skipBytes(4);
    int systemHeaderLength = packetBuffer.readUnsignedShort();
    if (packetBuffer.bytesLeft() < systemHeaderLength) {
      packetBuffer.setPosition(limit);
      return;
    }
    packetBuffer.skipBytes(systemHeaderLength);
  }

  // Find the position of the next PACK_START_CODE or MPEG_PROGRAM_END_CODE, which is right
  // after the end position of this pack.
  // If we couldn't find these codes within the buffer, return the buffer limit, or return
  // the first position which PES packets pattern does not match (some malformed packets).
  while (packetBuffer.bytesLeft() >= 4) {
    nextStartCode = peekIntAtPosition(packetBuffer.data, packetBuffer.getPosition());
    if (nextStartCode == PsExtractor.PACK_START_CODE
        || nextStartCode == PsExtractor.MPEG_PROGRAM_END_CODE) {
      break;
    }
    if (nextStartCode >>> 8 != PsExtractor.PACKET_START_CODE_PREFIX) {
      break;
    }
    packetBuffer.skipBytes(4);

    if (packetBuffer.bytesLeft() < 2) {
      // 2 bytes for PES_packet length.
      packetBuffer.setPosition(limit);
      return;
    }
    int pesPacketLength = packetBuffer.readUnsignedShort();
    packetBuffer.setPosition(
        Math.min(packetBuffer.limit(), packetBuffer.getPosition() + pesPacketLength));
  }
}
 
Example 17
Source File: SectionReader.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
public void consume(ParsableByteArray data, @Flags int flags) {
  boolean payloadUnitStartIndicator = (flags & FLAG_PAYLOAD_UNIT_START_INDICATOR) != 0;
  int payloadStartPosition = C.POSITION_UNSET;
  if (payloadUnitStartIndicator) {
    int payloadStartOffset = data.readUnsignedByte();
    payloadStartPosition = data.getPosition() + payloadStartOffset;
  }

  if (waitingForPayloadStart) {
    if (!payloadUnitStartIndicator) {
      return;
    }
    waitingForPayloadStart = false;
    data.setPosition(payloadStartPosition);
    bytesRead = 0;
  }

  while (data.bytesLeft() > 0) {
    if (bytesRead < SECTION_HEADER_LENGTH) {
      // Note: see ISO/IEC 13818-1, section 2.4.4.3 for detailed information on the format of
      // the header.
      if (bytesRead == 0) {
        int tableId = data.readUnsignedByte();
        data.setPosition(data.getPosition() - 1);
        if (tableId == 0xFF /* forbidden value */) {
          // No more sections in this ts packet.
          waitingForPayloadStart = true;
          return;
        }
      }
      int headerBytesToRead = Math.min(data.bytesLeft(), SECTION_HEADER_LENGTH - bytesRead);
      data.readBytes(sectionData.data, bytesRead, headerBytesToRead);
      bytesRead += headerBytesToRead;
      if (bytesRead == SECTION_HEADER_LENGTH) {
        sectionData.reset(SECTION_HEADER_LENGTH);
        sectionData.skipBytes(1); // Skip table id (8).
        int secondHeaderByte = sectionData.readUnsignedByte();
        int thirdHeaderByte = sectionData.readUnsignedByte();
        sectionSyntaxIndicator = (secondHeaderByte & 0x80) != 0;
        totalSectionLength =
            (((secondHeaderByte & 0x0F) << 8) | thirdHeaderByte) + SECTION_HEADER_LENGTH;
        if (sectionData.capacity() < totalSectionLength) {
          // Ensure there is enough space to keep the whole section.
          byte[] bytes = sectionData.data;
          sectionData.reset(
              Math.min(MAX_SECTION_LENGTH, Math.max(totalSectionLength, bytes.length * 2)));
          System.arraycopy(bytes, 0, sectionData.data, 0, SECTION_HEADER_LENGTH);
        }
      }
    } else {
      // Reading the body.
      int bodyBytesToRead = Math.min(data.bytesLeft(), totalSectionLength - bytesRead);
      data.readBytes(sectionData.data, bytesRead, bodyBytesToRead);
      bytesRead += bodyBytesToRead;
      if (bytesRead == totalSectionLength) {
        if (sectionSyntaxIndicator) {
          // This section has common syntax as defined in ISO/IEC 13818-1, section 2.4.4.11.
          if (Util.crc32(sectionData.data, 0, totalSectionLength, 0xFFFFFFFF) != 0) {
            // The CRC is invalid so discard the section.
            waitingForPayloadStart = true;
            return;
          }
          sectionData.reset(totalSectionLength - 4); // Exclude the CRC_32 field.
        } else {
          // This is a private section with private defined syntax.
          sectionData.reset(totalSectionLength);
        }
        reader.consume(sectionData);
        bytesRead = 0;
      }
    }
  }
}
 
Example 18
Source File: H264Reader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  int offset = data.getPosition();
  int limit = data.limit();
  byte[] dataArray = data.data;

  // Append the data to the buffer.
  totalBytesWritten += data.bytesLeft();
  output.sampleData(data, data.bytesLeft());

  // Scan the appended data, processing NAL units as they are encountered
  while (true) {
    int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);

    if (nalUnitOffset == limit) {
      // We've scanned to the end of the data without finding the start of another NAL unit.
      nalUnitData(dataArray, offset, limit);
      return;
    }

    // We've seen the start of a NAL unit of the following type.
    int nalUnitType = NalUnitUtil.getNalUnitType(dataArray, nalUnitOffset);

    // This is the number of bytes from the current offset to the start of the next NAL unit.
    // It may be negative if the NAL unit started in the previously consumed data.
    int lengthToNalUnit = nalUnitOffset - offset;
    if (lengthToNalUnit > 0) {
      nalUnitData(dataArray, offset, nalUnitOffset);
    }
    int bytesWrittenPastPosition = limit - nalUnitOffset;
    long absolutePosition = totalBytesWritten - bytesWrittenPastPosition;
    // Indicate the end of the previous NAL unit. If the length to the start of the next unit
    // is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes
    // when notifying that the unit has ended.
    endNalUnit(absolutePosition, bytesWrittenPastPosition,
        lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs);
    // Indicate the start of the next NAL unit.
    startNalUnit(absolutePosition, nalUnitType, pesTimeUs);
    // Continue scanning the data.
    offset = nalUnitOffset + 3;
  }
}
 
Example 19
Source File: VideoTagPayloadReader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
@Override
protected void parsePayload(ParsableByteArray data, long timeUs) throws ParserException {
  int packetType = data.readUnsignedByte();
  int compositionTimeMs = data.readInt24();

  timeUs += compositionTimeMs * 1000L;
  // Parse avc sequence header in case this was not done before.
  if (packetType == AVC_PACKET_TYPE_SEQUENCE_HEADER && !hasOutputFormat) {
    ParsableByteArray videoSequence = new ParsableByteArray(new byte[data.bytesLeft()]);
    data.readBytes(videoSequence.data, 0, data.bytesLeft());
    AvcConfig avcConfig = AvcConfig.parse(videoSequence);
    nalUnitLengthFieldLength = avcConfig.nalUnitLengthFieldLength;
    // Construct and output the format.
    Format format = Format.createVideoSampleFormat(null, MimeTypes.VIDEO_H264, null,
        Format.NO_VALUE, Format.NO_VALUE, avcConfig.width, avcConfig.height, Format.NO_VALUE,
        avcConfig.initializationData, Format.NO_VALUE, avcConfig.pixelWidthAspectRatio, null);
    output.format(format);
    hasOutputFormat = true;
  } else if (packetType == AVC_PACKET_TYPE_AVC_NALU && hasOutputFormat) {
    // TODO: Deduplicate with Mp4Extractor.
    // Zero the top three bytes of the array that we'll use to decode nal unit lengths, in case
    // they're only 1 or 2 bytes long.
    byte[] nalLengthData = nalLength.data;
    nalLengthData[0] = 0;
    nalLengthData[1] = 0;
    nalLengthData[2] = 0;
    int nalUnitLengthFieldLengthDiff = 4 - nalUnitLengthFieldLength;
    // NAL units are length delimited, but the decoder requires start code delimited units.
    // Loop until we've written the sample to the track output, replacing length delimiters with
    // start codes as we encounter them.
    int bytesWritten = 0;
    int bytesToWrite;
    while (data.bytesLeft() > 0) {
      // Read the NAL length so that we know where we find the next one.
      data.readBytes(nalLength.data, nalUnitLengthFieldLengthDiff, nalUnitLengthFieldLength);
      nalLength.setPosition(0);
      bytesToWrite = nalLength.readUnsignedIntToInt();

      // Write a start code for the current NAL unit.
      nalStartCode.setPosition(0);
      output.sampleData(nalStartCode, 4);
      bytesWritten += 4;

      // Write the payload of the NAL unit.
      output.sampleData(data, bytesToWrite);
      bytesWritten += bytesToWrite;
    }
    output.sampleMetadata(timeUs, frameType == VIDEO_FRAME_KEYFRAME ? C.BUFFER_FLAG_KEY_FRAME : 0,
        bytesWritten, 0, null);
  }
}
 
Example 20
Source File: H265Reader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    int offset = data.getPosition();
    int limit = data.limit();
    byte[] dataArray = data.data;

    // Append the data to the buffer.
    totalBytesWritten += data.bytesLeft();
    output.sampleData(data, data.bytesLeft());

    // Scan the appended data, processing NAL units as they are encountered
    while (offset < limit) {
      int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);

      if (nalUnitOffset == limit) {
        // We've scanned to the end of the data without finding the start of another NAL unit.
        nalUnitData(dataArray, offset, limit);
        return;
      }

      // We've seen the start of a NAL unit of the following type.
      int nalUnitType = NalUnitUtil.getH265NalUnitType(dataArray, nalUnitOffset);

      // This is the number of bytes from the current offset to the start of the next NAL unit.
      // It may be negative if the NAL unit started in the previously consumed data.
      int lengthToNalUnit = nalUnitOffset - offset;
      if (lengthToNalUnit > 0) {
        nalUnitData(dataArray, offset, nalUnitOffset);
      }

      int bytesWrittenPastPosition = limit - nalUnitOffset;
      long absolutePosition = totalBytesWritten - bytesWrittenPastPosition;
      // Indicate the end of the previous NAL unit. If the length to the start of the next unit
      // is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes
      // when notifying that the unit has ended.
      endNalUnit(absolutePosition, bytesWrittenPastPosition,
          lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs);
      // Indicate the start of the next NAL unit.
      startNalUnit(absolutePosition, bytesWrittenPastPosition, nalUnitType, pesTimeUs);
      // Continue scanning the data.
      offset = nalUnitOffset + 3;
    }
  }
}