Java Code Examples for com.google.android.exoplayer2.Format#createVideoSampleFormat()

The following examples show how to use com.google.android.exoplayer2.Format#createVideoSampleFormat() . 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: VideoFormatFixture.java    From no-player with Apache License 2.0 5 votes vote down vote up
public Format build() {
    return Format.createVideoSampleFormat(
            id,
            sampleMimeType,
            codecs,
            bitrate,
            maxInputSize,
            width,
            height,
            frameRate,
            initializationData,
            drmInitData
    );
}
 
Example 2
Source File: H262Reader.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Parses the {@link Format} and frame duration from a csd buffer.
 *
 * @param csdBuffer The csd buffer.
 * @param formatId The id for the generated format. May be null.
 * @return A pair consisting of the {@link Format} and the frame duration in microseconds, or
 *     0 if the duration could not be determined.
 */
private static Pair<Format, Long> parseCsdBuffer(CsdBuffer csdBuffer, String formatId) {
  byte[] csdData = Arrays.copyOf(csdBuffer.data, csdBuffer.length);

  int firstByte = csdData[4] & 0xFF;
  int secondByte = csdData[5] & 0xFF;
  int thirdByte = csdData[6] & 0xFF;
  int width = (firstByte << 4) | (secondByte >> 4);
  int height = (secondByte & 0x0F) << 8 | thirdByte;

  float pixelWidthHeightRatio = 1f;
  int aspectRatioCode = (csdData[7] & 0xF0) >> 4;
  switch(aspectRatioCode) {
    case 2:
      pixelWidthHeightRatio = (4 * height) / (float) (3 * width);
      break;
    case 3:
      pixelWidthHeightRatio = (16 * height) / (float) (9 * width);
      break;
    case 4:
      pixelWidthHeightRatio = (121 * height) / (float) (100 * width);
      break;
    default:
      // Do nothing.
      break;
  }

  Format format = Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_MPEG2, null,
      Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE,
      Collections.singletonList(csdData), Format.NO_VALUE, pixelWidthHeightRatio, null);

  long frameDurationUs = 0;
  int frameRateCodeMinusOne = (csdData[7] & 0x0F) - 1;
  if (0 <= frameRateCodeMinusOne && frameRateCodeMinusOne < FRAME_RATE_VALUES.length) {
    double frameRate = FRAME_RATE_VALUES[frameRateCodeMinusOne];
    int sequenceExtensionPosition = csdBuffer.sequenceExtensionPosition;
    int frameRateExtensionN = (csdData[sequenceExtensionPosition + 9] & 0x60) >> 5;
    int frameRateExtensionD = (csdData[sequenceExtensionPosition + 9] & 0x1F);
    if (frameRateExtensionN != frameRateExtensionD) {
      frameRate *= (frameRateExtensionN + 1d) / (frameRateExtensionD + 1);
    }
    frameDurationUs = (long) (C.MICROS_PER_SECOND / frameRate);
  }

  return Pair.create(format, frameDurationUs);
}
 
Example 3
Source File: VideoTagPayloadReader.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
protected boolean 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;
    return false;
  } else if (packetType == AVC_PACKET_TYPE_AVC_NALU && hasOutputFormat) {
    boolean isKeyframe = frameType == VIDEO_FRAME_KEYFRAME;
    if (!hasOutputKeyframe && !isKeyframe) {
      return false;
    }
    // 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, isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0, bytesWritten, 0, null);
    hasOutputKeyframe = true;
    return true;
  } else {
    return false;
  }
}
 
Example 4
Source File: H262Reader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Parses the {@link Format} and frame duration from a csd buffer.
 *
 * @param csdBuffer The csd buffer.
 * @param formatId The id for the generated format. May be null.
 * @return A pair consisting of the {@link Format} and the frame duration in microseconds, or
 *     0 if the duration could not be determined.
 */
private static Pair<Format, Long> parseCsdBuffer(CsdBuffer csdBuffer, String formatId) {
  byte[] csdData = Arrays.copyOf(csdBuffer.data, csdBuffer.length);

  int firstByte = csdData[4] & 0xFF;
  int secondByte = csdData[5] & 0xFF;
  int thirdByte = csdData[6] & 0xFF;
  int width = (firstByte << 4) | (secondByte >> 4);
  int height = (secondByte & 0x0F) << 8 | thirdByte;

  float pixelWidthHeightRatio = 1f;
  int aspectRatioCode = (csdData[7] & 0xF0) >> 4;
  switch(aspectRatioCode) {
    case 2:
      pixelWidthHeightRatio = (4 * height) / (float) (3 * width);
      break;
    case 3:
      pixelWidthHeightRatio = (16 * height) / (float) (9 * width);
      break;
    case 4:
      pixelWidthHeightRatio = (121 * height) / (float) (100 * width);
      break;
    default:
      // Do nothing.
      break;
  }

  Format format = Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_MPEG2, null,
      Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE,
      Collections.singletonList(csdData), Format.NO_VALUE, pixelWidthHeightRatio, null);

  long frameDurationUs = 0;
  int frameRateCodeMinusOne = (csdData[7] & 0x0F) - 1;
  if (0 <= frameRateCodeMinusOne && frameRateCodeMinusOne < FRAME_RATE_VALUES.length) {
    double frameRate = FRAME_RATE_VALUES[frameRateCodeMinusOne];
    int sequenceExtensionPosition = csdBuffer.sequenceExtensionPosition;
    int frameRateExtensionN = (csdData[sequenceExtensionPosition + 9] & 0x60) >> 5;
    int frameRateExtensionD = (csdData[sequenceExtensionPosition + 9] & 0x1F);
    if (frameRateExtensionN != frameRateExtensionD) {
      frameRate *= (frameRateExtensionN + 1d) / (frameRateExtensionD + 1);
    }
    frameDurationUs = (long) (C.MICROS_PER_SECOND / frameRate);
  }

  return Pair.create(format, frameDurationUs);
}
 
Example 5
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 6
Source File: H262Reader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Parses the {@link Format} and frame duration from a csd buffer.
 *
 * @param csdBuffer The csd buffer.
 * @param formatId The id for the generated format. May be null.
 * @return A pair consisting of the {@link Format} and the frame duration in microseconds, or
 *     0 if the duration could not be determined.
 */
private static Pair<Format, Long> parseCsdBuffer(CsdBuffer csdBuffer, String formatId) {
  byte[] csdData = Arrays.copyOf(csdBuffer.data, csdBuffer.length);

  int firstByte = csdData[4] & 0xFF;
  int secondByte = csdData[5] & 0xFF;
  int thirdByte = csdData[6] & 0xFF;
  int width = (firstByte << 4) | (secondByte >> 4);
  int height = (secondByte & 0x0F) << 8 | thirdByte;

  float pixelWidthHeightRatio = 1f;
  int aspectRatioCode = (csdData[7] & 0xF0) >> 4;
  switch(aspectRatioCode) {
    case 2:
      pixelWidthHeightRatio = (4 * height) / (float) (3 * width);
      break;
    case 3:
      pixelWidthHeightRatio = (16 * height) / (float) (9 * width);
      break;
    case 4:
      pixelWidthHeightRatio = (121 * height) / (float) (100 * width);
      break;
    default:
      // Do nothing.
      break;
  }

  Format format = Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_MPEG2, null,
      Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE,
      Collections.singletonList(csdData), Format.NO_VALUE, pixelWidthHeightRatio, null);

  long frameDurationUs = 0;
  int frameRateCodeMinusOne = (csdData[7] & 0x0F) - 1;
  if (0 <= frameRateCodeMinusOne && frameRateCodeMinusOne < FRAME_RATE_VALUES.length) {
    double frameRate = FRAME_RATE_VALUES[frameRateCodeMinusOne];
    int sequenceExtensionPosition = csdBuffer.sequenceExtensionPosition;
    int frameRateExtensionN = (csdData[sequenceExtensionPosition + 9] & 0x60) >> 5;
    int frameRateExtensionD = (csdData[sequenceExtensionPosition + 9] & 0x1F);
    if (frameRateExtensionN != frameRateExtensionD) {
      frameRate *= (frameRateExtensionN + 1d) / (frameRateExtensionD + 1);
    }
    frameDurationUs = (long) (C.MICROS_PER_SECOND / frameRate);
  }

  return Pair.create(format, frameDurationUs);
}
 
Example 7
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 8
Source File: VideoTagPayloadReader.java    From LiveVideoBroadcaster with Apache License 2.0 4 votes vote down vote up
@Override
protected void parsePayload(ParsableByteArray data, long timeUs) throws ParserException {
  int packetType = data.readUnsignedByte();
  int compositionTimeMs = data.readUnsignedInt24();
  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) {
    // 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 9
Source File: H262Reader.java    From K-Sonic with MIT License 4 votes vote down vote up
/**
 * Parses the {@link Format} and frame duration from a csd buffer.
 *
 * @param csdBuffer The csd buffer.
 * @param formatId The id for the generated format. May be null.
 * @return A pair consisting of the {@link Format} and the frame duration in microseconds, or
 *     0 if the duration could not be determined.
 */
private static Pair<Format, Long> parseCsdBuffer(CsdBuffer csdBuffer, String formatId) {
  byte[] csdData = Arrays.copyOf(csdBuffer.data, csdBuffer.length);

  int firstByte = csdData[4] & 0xFF;
  int secondByte = csdData[5] & 0xFF;
  int thirdByte = csdData[6] & 0xFF;
  int width = (firstByte << 4) | (secondByte >> 4);
  int height = (secondByte & 0x0F) << 8 | thirdByte;

  float pixelWidthHeightRatio = 1f;
  int aspectRatioCode = (csdData[7] & 0xF0) >> 4;
  switch(aspectRatioCode) {
    case 2:
      pixelWidthHeightRatio = (4 * height) / (float) (3 * width);
      break;
    case 3:
      pixelWidthHeightRatio = (16 * height) / (float) (9 * width);
      break;
    case 4:
      pixelWidthHeightRatio = (121 * height) / (float) (100 * width);
      break;
    default:
      // Do nothing.
      break;
  }

  Format format = Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_MPEG2, null,
      Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE,
      Collections.singletonList(csdData), Format.NO_VALUE, pixelWidthHeightRatio, null);

  long frameDurationUs = 0;
  int frameRateCodeMinusOne = (csdData[7] & 0x0F) - 1;
  if (0 <= frameRateCodeMinusOne && frameRateCodeMinusOne < FRAME_RATE_VALUES.length) {
    double frameRate = FRAME_RATE_VALUES[frameRateCodeMinusOne];
    int sequenceExtensionPosition = csdBuffer.sequenceExtensionPosition;
    int frameRateExtensionN = (csdData[sequenceExtensionPosition + 9] & 0x60) >> 5;
    int frameRateExtensionD = (csdData[sequenceExtensionPosition + 9] & 0x1F);
    if (frameRateExtensionN != frameRateExtensionD) {
      frameRate *= (frameRateExtensionN + 1d) / (frameRateExtensionD + 1);
    }
    frameDurationUs = (long) (C.MICROS_PER_SECOND / frameRate);
  }

  return Pair.create(format, frameDurationUs);
}
 
Example 10
Source File: VideoTagPayloadReader.java    From K-Sonic with MIT License 4 votes vote down vote up
@Override
protected void parsePayload(ParsableByteArray data, long timeUs) throws ParserException {
  int packetType = data.readUnsignedByte();
  int compositionTimeMs = data.readUnsignedInt24();
  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) {
    // 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 11
Source File: H262Reader.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Parses the {@link Format} and frame duration from a csd buffer.
 *
 * @param csdBuffer The csd buffer.
 * @param formatId The id for the generated format. May be null.
 * @return A pair consisting of the {@link Format} and the frame duration in microseconds, or
 *     0 if the duration could not be determined.
 */
private static Pair<Format, Long> parseCsdBuffer(CsdBuffer csdBuffer, String formatId) {
  byte[] csdData = Arrays.copyOf(csdBuffer.data, csdBuffer.length);

  int firstByte = csdData[4] & 0xFF;
  int secondByte = csdData[5] & 0xFF;
  int thirdByte = csdData[6] & 0xFF;
  int width = (firstByte << 4) | (secondByte >> 4);
  int height = (secondByte & 0x0F) << 8 | thirdByte;

  float pixelWidthHeightRatio = 1f;
  int aspectRatioCode = (csdData[7] & 0xF0) >> 4;
  switch(aspectRatioCode) {
    case 2:
      pixelWidthHeightRatio = (4 * height) / (float) (3 * width);
      break;
    case 3:
      pixelWidthHeightRatio = (16 * height) / (float) (9 * width);
      break;
    case 4:
      pixelWidthHeightRatio = (121 * height) / (float) (100 * width);
      break;
    default:
      // Do nothing.
      break;
  }

  Format format = Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_MPEG2, null,
      Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE,
      Collections.singletonList(csdData), Format.NO_VALUE, pixelWidthHeightRatio, null);

  long frameDurationUs = 0;
  int frameRateCodeMinusOne = (csdData[7] & 0x0F) - 1;
  if (0 <= frameRateCodeMinusOne && frameRateCodeMinusOne < FRAME_RATE_VALUES.length) {
    double frameRate = FRAME_RATE_VALUES[frameRateCodeMinusOne];
    int sequenceExtensionPosition = csdBuffer.sequenceExtensionPosition;
    int frameRateExtensionN = (csdData[sequenceExtensionPosition + 9] & 0x60) >> 5;
    int frameRateExtensionD = (csdData[sequenceExtensionPosition + 9] & 0x1F);
    if (frameRateExtensionN != frameRateExtensionD) {
      frameRate *= (frameRateExtensionN + 1d) / (frameRateExtensionD + 1);
    }
    frameDurationUs = (long) (C.MICROS_PER_SECOND / frameRate);
  }

  return Pair.create(format, frameDurationUs);
}
 
Example 12
Source File: VideoTagPayloadReader.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
@Override
protected boolean 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;
    return false;
  } else if (packetType == AVC_PACKET_TYPE_AVC_NALU && hasOutputFormat) {
    boolean isKeyframe = frameType == VIDEO_FRAME_KEYFRAME;
    if (!hasOutputKeyframe && !isKeyframe) {
      return false;
    }
    // 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, isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0, bytesWritten, 0, null);
    hasOutputKeyframe = true;
    return true;
  } else {
    return false;
  }
}
 
Example 13
Source File: H262Reader.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Parses the {@link Format} and frame duration from a csd buffer.
 *
 * @param csdBuffer The csd buffer.
 * @param formatId The id for the generated format. May be null.
 * @return A pair consisting of the {@link Format} and the frame duration in microseconds, or
 *     0 if the duration could not be determined.
 */
private static Pair<Format, Long> parseCsdBuffer(CsdBuffer csdBuffer, String formatId) {
  byte[] csdData = Arrays.copyOf(csdBuffer.data, csdBuffer.length);

  int firstByte = csdData[4] & 0xFF;
  int secondByte = csdData[5] & 0xFF;
  int thirdByte = csdData[6] & 0xFF;
  int width = (firstByte << 4) | (secondByte >> 4);
  int height = (secondByte & 0x0F) << 8 | thirdByte;

  float pixelWidthHeightRatio = 1f;
  int aspectRatioCode = (csdData[7] & 0xF0) >> 4;
  switch(aspectRatioCode) {
    case 2:
      pixelWidthHeightRatio = (4 * height) / (float) (3 * width);
      break;
    case 3:
      pixelWidthHeightRatio = (16 * height) / (float) (9 * width);
      break;
    case 4:
      pixelWidthHeightRatio = (121 * height) / (float) (100 * width);
      break;
    default:
      // Do nothing.
      break;
  }

  Format format = Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_MPEG2, null,
      Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE,
      Collections.singletonList(csdData), Format.NO_VALUE, pixelWidthHeightRatio, null);

  long frameDurationUs = 0;
  int frameRateCodeMinusOne = (csdData[7] & 0x0F) - 1;
  if (0 <= frameRateCodeMinusOne && frameRateCodeMinusOne < FRAME_RATE_VALUES.length) {
    double frameRate = FRAME_RATE_VALUES[frameRateCodeMinusOne];
    int sequenceExtensionPosition = csdBuffer.sequenceExtensionPosition;
    int frameRateExtensionN = (csdData[sequenceExtensionPosition + 9] & 0x60) >> 5;
    int frameRateExtensionD = (csdData[sequenceExtensionPosition + 9] & 0x1F);
    if (frameRateExtensionN != frameRateExtensionD) {
      frameRate *= (frameRateExtensionN + 1d) / (frameRateExtensionD + 1);
    }
    frameDurationUs = (long) (C.MICROS_PER_SECOND / frameRate);
  }

  return Pair.create(format, frameDurationUs);
}
 
Example 14
Source File: VideoTagPayloadReader.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
@Override
protected boolean 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;
    return false;
  } else if (packetType == AVC_PACKET_TYPE_AVC_NALU && hasOutputFormat) {
    boolean isKeyframe = frameType == VIDEO_FRAME_KEYFRAME;
    if (!hasOutputKeyframe && !isKeyframe) {
      return false;
    }
    // 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, isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0, bytesWritten, 0, null);
    hasOutputKeyframe = true;
    return true;
  } else {
    return false;
  }
}