mirror of
https://github.com/androidx/media.git
synced 2025-05-10 00:59:51 +08:00
Get frame rate from mkv. Get frame rate from AvcConfig.
This commit is contained in:
parent
8bed008934
commit
989a97ebbd
@ -38,6 +38,7 @@ public final class NalUnitUtil {
|
||||
public final int width;
|
||||
public final int height;
|
||||
public final float pixelWidthAspectRatio;
|
||||
public final float frameRate;
|
||||
public final boolean separateColorPlaneFlag;
|
||||
public final boolean frameMbsOnlyFlag;
|
||||
public final int frameNumLength;
|
||||
@ -53,6 +54,7 @@ public final class NalUnitUtil {
|
||||
int width,
|
||||
int height,
|
||||
float pixelWidthAspectRatio,
|
||||
float frameRate,
|
||||
boolean separateColorPlaneFlag,
|
||||
boolean frameMbsOnlyFlag,
|
||||
int frameNumLength,
|
||||
@ -66,6 +68,7 @@ public final class NalUnitUtil {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.pixelWidthAspectRatio = pixelWidthAspectRatio;
|
||||
this.frameRate = frameRate;
|
||||
this.separateColorPlaneFlag = separateColorPlaneFlag;
|
||||
this.frameMbsOnlyFlag = frameMbsOnlyFlag;
|
||||
this.frameNumLength = frameNumLength;
|
||||
@ -349,6 +352,7 @@ public final class NalUnitUtil {
|
||||
}
|
||||
|
||||
float pixelWidthHeightRatio = 1;
|
||||
float frameRate = -1;
|
||||
boolean vuiParametersPresentFlag = data.readBit();
|
||||
if (vuiParametersPresentFlag) {
|
||||
boolean aspectRatioInfoPresentFlag = data.readBit();
|
||||
@ -366,6 +370,68 @@ public final class NalUnitUtil {
|
||||
Log.w(TAG, "Unexpected aspect_ratio_idc value: " + aspectRatioIdc);
|
||||
}
|
||||
}
|
||||
// https://www.androidos.net.cn/android/9.0.0_r8/xref/external/mp4parser/isoparser/src/main/java/com/googlecode/mp4parser/h264/model/SeqParameterSet.java
|
||||
boolean overscan_info_present_flag = data.readBit();
|
||||
if (overscan_info_present_flag) {
|
||||
int overscan_appropriate_flagu = data.readBits(1);
|
||||
}
|
||||
boolean video_signal_type_present_flag = data.readBit();
|
||||
if (video_signal_type_present_flag) {
|
||||
int video_format = data.readBits(3);
|
||||
int video_full_range_flag = data.readBits(1);
|
||||
boolean colour_description_present_flag = data.readBit();
|
||||
if (colour_description_present_flag) {
|
||||
int colour_primaries = data.readBits(8);
|
||||
int transfer_characteristics = data.readBits(8);
|
||||
int matrix_coefficients = data.readBits(8);
|
||||
}
|
||||
}
|
||||
boolean chroma_loc_info_present_flag = data.readBit();
|
||||
if (chroma_loc_info_present_flag) {
|
||||
int chroma_sample_loc_type_top_field = data.readUnsignedExpGolombCodedInt();
|
||||
int chroma_sample_loc_type_bottom_field = data.readUnsignedExpGolombCodedInt();
|
||||
} else {
|
||||
boolean timing_info_present_flag = data.readBit();
|
||||
if (timing_info_present_flag) {
|
||||
int num_units_in_tick = data.readBits(32);
|
||||
int time_scale = data.readBits(32);
|
||||
frameRate = (float) time_scale / (float) num_units_in_tick;
|
||||
boolean fixed_frame_rate_flag = data.readBit();
|
||||
if (fixed_frame_rate_flag) {
|
||||
frameRate = frameRate / 2f;
|
||||
} else if (frameRate > 40f) {
|
||||
frameRate = frameRate / 2f;
|
||||
}
|
||||
}
|
||||
boolean nal_hrd_parameters_present_flag = data.readBit();
|
||||
if (nal_hrd_parameters_present_flag)
|
||||
readHRDParameters(data); //nalHRDParams
|
||||
boolean vcl_hrd_parameters_present_flag = data.readBit();
|
||||
if (vcl_hrd_parameters_present_flag)
|
||||
readHRDParameters(data); //vclHRDParams
|
||||
if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
|
||||
boolean low_delay_hrd_flag = data.readBit();
|
||||
}
|
||||
boolean pic_struct_present_flag = data.readBit();
|
||||
boolean bitstream_restriction_flag = data.readBit();
|
||||
if (bitstream_restriction_flag) {/*
|
||||
vuip.bitstreamRestriction = new VUIParameters.BitstreamRestriction();
|
||||
vuip.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = reader
|
||||
.readBool("VUI: motion_vectors_over_pic_boundaries_flag");
|
||||
vuip.bitstreamRestriction.max_bytes_per_pic_denom = reader
|
||||
.readUE("VUI max_bytes_per_pic_denom");
|
||||
vuip.bitstreamRestriction.max_bits_per_mb_denom = reader
|
||||
.readUE("VUI max_bits_per_mb_denom");
|
||||
vuip.bitstreamRestriction.log2_max_mv_length_horizontal = reader
|
||||
.readUE("VUI log2_max_mv_length_horizontal");
|
||||
vuip.bitstreamRestriction.log2_max_mv_length_vertical = reader
|
||||
.readUE("VUI log2_max_mv_length_vertical");
|
||||
vuip.bitstreamRestriction.num_reorder_frames = reader
|
||||
.readUE("VUI num_reorder_frames");
|
||||
vuip.bitstreamRestriction.max_dec_frame_buffering = reader
|
||||
.readUE("VUI max_dec_frame_buffering");*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new SpsData(
|
||||
@ -376,6 +442,7 @@ public final class NalUnitUtil {
|
||||
frameWidth,
|
||||
frameHeight,
|
||||
pixelWidthHeightRatio,
|
||||
frameRate,
|
||||
separateColorPlaneFlag,
|
||||
frameMbsOnlyFlag,
|
||||
frameNumLength,
|
||||
@ -384,6 +451,29 @@ public final class NalUnitUtil {
|
||||
deltaPicOrderAlwaysZeroFlag);
|
||||
}
|
||||
|
||||
private static void readHRDParameters(ParsableNalUnitBitArray data) {
|
||||
// HRDParameters hrd = new HRDParameters();
|
||||
// hrd.cpb_cnt_minus1 = reader.readUE("SPS: cpb_cnt_minus1");
|
||||
int cpb_cnt_minus1 = data.readUnsignedExpGolombCodedInt();
|
||||
// hrd.bit_rate_scale = (int) reader.readNBit(4, "HRD: bit_rate_scale");
|
||||
int bit_rate_scale = data.readBits(4);
|
||||
// hrd.cpb_size_scale = (int) reader.readNBit(4, "HRD: cpb_size_scale");
|
||||
int cpb_size_scale = data.readBits(4);
|
||||
int[] bit_rate_value_minus1 = new int[cpb_cnt_minus1 + 1];
|
||||
int[] cpb_size_value_minus1 = new int[cpb_cnt_minus1 + 1];
|
||||
boolean[] cbr_flag = new boolean[cpb_cnt_minus1 + 1];
|
||||
|
||||
for (int SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; SchedSelIdx++) {
|
||||
bit_rate_value_minus1[SchedSelIdx] = data.readUnsignedExpGolombCodedInt();
|
||||
cpb_size_value_minus1[SchedSelIdx] = data.readUnsignedExpGolombCodedInt();
|
||||
cbr_flag[SchedSelIdx] = data.readBit();
|
||||
}
|
||||
int initial_cpb_removal_delay_length_minus1 = (int) data.readBits(5);
|
||||
int cpb_removal_delay_length_minus1 = data.readBits(5);
|
||||
int dpb_output_delay_length_minus1 = data.readBits(5);
|
||||
int time_offset_length = data.readBits(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a PPS NAL unit using the syntax defined in ITU-T Recommendation H.264 (2013) subsection
|
||||
* 7.3.2.2.
|
||||
|
@ -34,6 +34,7 @@ public final class AvcConfig {
|
||||
public final int width;
|
||||
public final int height;
|
||||
public final float pixelWidthAspectRatio;
|
||||
public final float frameRate;
|
||||
|
||||
/**
|
||||
* Parses AVC configuration data.
|
||||
@ -63,6 +64,7 @@ public final class AvcConfig {
|
||||
int width = Format.NO_VALUE;
|
||||
int height = Format.NO_VALUE;
|
||||
float pixelWidthAspectRatio = 1;
|
||||
float frameRate = -1;
|
||||
if (numSequenceParameterSets > 0) {
|
||||
byte[] sps = initializationData.get(0);
|
||||
SpsData spsData = NalUnitUtil.parseSpsNalUnit(initializationData.get(0),
|
||||
@ -70,21 +72,23 @@ public final class AvcConfig {
|
||||
width = spsData.width;
|
||||
height = spsData.height;
|
||||
pixelWidthAspectRatio = spsData.pixelWidthAspectRatio;
|
||||
frameRate = spsData.frameRate;
|
||||
}
|
||||
return new AvcConfig(initializationData, nalUnitLengthFieldLength, width, height,
|
||||
pixelWidthAspectRatio);
|
||||
pixelWidthAspectRatio, frameRate);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new ParserException("Error parsing AVC config", e);
|
||||
}
|
||||
}
|
||||
|
||||
private AvcConfig(List<byte[]> initializationData, int nalUnitLengthFieldLength,
|
||||
int width, int height, float pixelWidthAspectRatio) {
|
||||
int width, int height, float pixelWidthAspectRatio, float frameRate) {
|
||||
this.initializationData = initializationData;
|
||||
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.pixelWidthAspectRatio = pixelWidthAspectRatio;
|
||||
this.frameRate = frameRate;
|
||||
}
|
||||
|
||||
private static byte[] buildNalUnitForChild(ParsableByteArray data) {
|
||||
|
@ -97,6 +97,7 @@ import com.google.android.exoplayer2.video.AvcConfig;
|
||||
.setHeight(avcConfig.height)
|
||||
.setPixelWidthHeightRatio(avcConfig.pixelWidthAspectRatio)
|
||||
.setInitializationData(avcConfig.initializationData)
|
||||
.setFrameRate(avcConfig.frameRate < 0 ? Format.NO_VALUE : avcConfig.frameRate)
|
||||
.build();
|
||||
output.format(format);
|
||||
hasOutputFormat = true;
|
||||
|
@ -152,6 +152,7 @@ public class MatroskaExtractor implements Extractor {
|
||||
private static final int ID_INFO = 0x1549A966;
|
||||
private static final int ID_TIMECODE_SCALE = 0x2AD7B1;
|
||||
private static final int ID_DURATION = 0x4489;
|
||||
private static final int ID_FRAME_RATE = 0x2383E3;
|
||||
private static final int ID_CLUSTER = 0x1F43B675;
|
||||
private static final int ID_TIME_CODE = 0xE7;
|
||||
private static final int ID_SIMPLE_BLOCK = 0xA3;
|
||||
@ -589,6 +590,7 @@ public class MatroskaExtractor implements Extractor {
|
||||
case ID_BLOCK_ADDITIONAL:
|
||||
return EbmlProcessor.ELEMENT_TYPE_BINARY;
|
||||
case ID_DURATION:
|
||||
case ID_FRAME_RATE:
|
||||
case ID_SAMPLING_FREQUENCY:
|
||||
case ID_PRIMARY_R_CHROMATICITY_X:
|
||||
case ID_PRIMARY_R_CHROMATICITY_Y:
|
||||
@ -828,6 +830,7 @@ public class MatroskaExtractor implements Extractor {
|
||||
break;
|
||||
case ID_DEFAULT_DURATION:
|
||||
currentTrack.defaultSampleDurationNs = (int) value;
|
||||
currentTrack.frameRate = (float) 1E9 / value;
|
||||
break;
|
||||
case ID_MAX_BLOCK_ADDITION_ID:
|
||||
currentTrack.maxBlockAdditionId = (int) value;
|
||||
@ -1008,6 +1011,9 @@ public class MatroskaExtractor implements Extractor {
|
||||
case ID_DURATION:
|
||||
durationTimecode = (long) value;
|
||||
break;
|
||||
case ID_FRAME_RATE:
|
||||
currentTrack.frameRate = (float) value;
|
||||
break;
|
||||
case ID_SAMPLING_FREQUENCY:
|
||||
currentTrack.sampleRate = (int) value;
|
||||
break;
|
||||
@ -1932,6 +1938,7 @@ public class MatroskaExtractor implements Extractor {
|
||||
public int displayWidth = Format.NO_VALUE;
|
||||
public int displayHeight = Format.NO_VALUE;
|
||||
public int displayUnit = DISPLAY_UNIT_PIXELS;
|
||||
public float frameRate = -1;
|
||||
@C.Projection public int projectionType = Format.NO_VALUE;
|
||||
public float projectionPoseYaw = 0f;
|
||||
public float projectionPosePitch = 0f;
|
||||
@ -2009,6 +2016,7 @@ public class MatroskaExtractor implements Extractor {
|
||||
AvcConfig avcConfig = AvcConfig.parse(new ParsableByteArray(codecPrivate));
|
||||
initializationData = avcConfig.initializationData;
|
||||
nalUnitLengthFieldLength = avcConfig.nalUnitLengthFieldLength;
|
||||
frameRate = avcConfig.frameRate;
|
||||
break;
|
||||
case CODEC_ID_H265:
|
||||
mimeType = MimeTypes.VIDEO_H265;
|
||||
@ -2195,6 +2203,7 @@ public class MatroskaExtractor implements Extractor {
|
||||
.setRotationDegrees(rotationDegrees)
|
||||
.setProjectionData(projectionData)
|
||||
.setStereoMode(stereoMode)
|
||||
.setFrameRate(frameRate < 0 ? Format.NO_VALUE : frameRate)
|
||||
.setColorInfo(colorInfo);
|
||||
} else if (MimeTypes.APPLICATION_SUBRIP.equals(mimeType)) {
|
||||
type = C.TRACK_TYPE_TEXT;
|
||||
|
@ -968,6 +968,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
int height = parent.readUnsignedShort();
|
||||
boolean pixelWidthHeightRatioFromPasp = false;
|
||||
float pixelWidthHeightRatio = 1;
|
||||
float frameRate = -1;
|
||||
parent.skipBytes(50);
|
||||
|
||||
int childPosition = parent.getPosition();
|
||||
@ -1014,6 +1015,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
if (!pixelWidthHeightRatioFromPasp) {
|
||||
pixelWidthHeightRatio = avcConfig.pixelWidthAspectRatio;
|
||||
}
|
||||
frameRate = avcConfig.frameRate;
|
||||
} else if (childAtomType == Atom.TYPE_hvcC) {
|
||||
Assertions.checkState(mimeType == null);
|
||||
mimeType = MimeTypes.VIDEO_H265;
|
||||
@ -1094,6 +1096,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
.setStereoMode(stereoMode)
|
||||
.setInitializationData(initializationData)
|
||||
.setDrmInitData(drmInitData)
|
||||
.setFrameRate(frameRate < 0 ? Format.NO_VALUE : frameRate)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -215,6 +215,7 @@ public final class H264Reader implements ElementaryStreamReader {
|
||||
.setHeight(spsData.height)
|
||||
.setPixelWidthHeightRatio(spsData.pixelWidthAspectRatio)
|
||||
.setInitializationData(initializationData)
|
||||
.setFrameRate(spsData.frameRate < 0 ? Format.NO_VALUE : spsData.frameRate)
|
||||
.build());
|
||||
hasOutputFormat = true;
|
||||
sampleReader.putSps(spsData);
|
||||
|
Loading…
x
Reference in New Issue
Block a user