Build codecs string from SPS data in H.264

Issue:#4555

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=207096569
This commit is contained in:
aquilescanta 2018-08-02 07:30:05 -07:00 committed by Oliver Woodman
parent 03b04ef23c
commit a7e9ebcf68
4 changed files with 72 additions and 10 deletions

View File

@ -21,6 +21,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator;
import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.NalUnitUtil; import com.google.android.exoplayer2.util.NalUnitUtil;
import com.google.android.exoplayer2.util.NalUnitUtil.SpsData; import com.google.android.exoplayer2.util.NalUnitUtil.SpsData;
@ -180,9 +181,23 @@ public final class H264Reader implements ElementaryStreamReader {
initializationData.add(Arrays.copyOf(pps.nalData, pps.nalLength)); initializationData.add(Arrays.copyOf(pps.nalData, pps.nalLength));
NalUnitUtil.SpsData spsData = NalUnitUtil.parseSpsNalUnit(sps.nalData, 3, sps.nalLength); NalUnitUtil.SpsData spsData = NalUnitUtil.parseSpsNalUnit(sps.nalData, 3, sps.nalLength);
NalUnitUtil.PpsData ppsData = NalUnitUtil.parsePpsNalUnit(pps.nalData, 3, pps.nalLength); NalUnitUtil.PpsData ppsData = NalUnitUtil.parsePpsNalUnit(pps.nalData, 3, pps.nalLength);
output.format(Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_H264, null, output.format(
Format.NO_VALUE, Format.NO_VALUE, spsData.width, spsData.height, Format.NO_VALUE, Format.createVideoSampleFormat(
initializationData, Format.NO_VALUE, spsData.pixelWidthAspectRatio, null)); formatId,
MimeTypes.VIDEO_H264,
CodecSpecificDataUtil.buildAvcCodecString(
spsData.profileIdc,
spsData.constraintsFlagsAndReservedZero2Bits,
spsData.levelIdc),
/* bitrate= */ Format.NO_VALUE,
/* maxInputSize= */ Format.NO_VALUE,
spsData.width,
spsData.height,
/* frameRate= */ Format.NO_VALUE,
initializationData,
/* rotationDegrees= */ Format.NO_VALUE,
spsData.pixelWidthAspectRatio,
/* drmInitData= */ null));
hasOutputFormat = true; hasOutputFormat = true;
sampleReader.putSps(spsData); sampleReader.putSps(spsData);
sampleReader.putPps(ppsData); sampleReader.putPps(ppsData);

View File

@ -674,6 +674,9 @@ public final class MediaCodecUtil {
AVC_PROFILE_NUMBER_TO_CONST.put(77, CodecProfileLevel.AVCProfileMain); AVC_PROFILE_NUMBER_TO_CONST.put(77, CodecProfileLevel.AVCProfileMain);
AVC_PROFILE_NUMBER_TO_CONST.put(88, CodecProfileLevel.AVCProfileExtended); AVC_PROFILE_NUMBER_TO_CONST.put(88, CodecProfileLevel.AVCProfileExtended);
AVC_PROFILE_NUMBER_TO_CONST.put(100, CodecProfileLevel.AVCProfileHigh); AVC_PROFILE_NUMBER_TO_CONST.put(100, CodecProfileLevel.AVCProfileHigh);
AVC_PROFILE_NUMBER_TO_CONST.put(110, CodecProfileLevel.AVCProfileHigh10);
AVC_PROFILE_NUMBER_TO_CONST.put(122, CodecProfileLevel.AVCProfileHigh422);
AVC_PROFILE_NUMBER_TO_CONST.put(244, CodecProfileLevel.AVCProfileHigh444);
AVC_LEVEL_NUMBER_TO_CONST = new SparseIntArray(); AVC_LEVEL_NUMBER_TO_CONST = new SparseIntArray();
AVC_LEVEL_NUMBER_TO_CONST.put(10, CodecProfileLevel.AVCLevel1); AVC_LEVEL_NUMBER_TO_CONST.put(10, CodecProfileLevel.AVCLevel1);

View File

@ -205,6 +205,21 @@ public final class CodecSpecificDataUtil {
return specificConfig; return specificConfig;
} }
/**
* Builds an RFC 6381 AVC codec string using the provided parameters.
*
* @param profileIdc The encoding profile.
* @param constraintsFlagsAndReservedZero2Bits The constraint flags followed by the reserved zero
* 2 bits, all contained in the least significant byte of the integer.
* @param levelIdc The encoding level.
* @return An RFC 6381 AVC codec string built using the provided parameters.
*/
public static String buildAvcCodecString(
int profileIdc, int constraintsFlagsAndReservedZero2Bits, int levelIdc) {
return String.format(
"avc1.%02X%02X%02X", profileIdc, constraintsFlagsAndReservedZero2Bits, levelIdc);
}
/** /**
* Constructs a NAL unit consisting of the NAL start code followed by the specified data. * Constructs a NAL unit consisting of the NAL start code followed by the specified data.
* *

View File

@ -31,6 +31,9 @@ public final class NalUnitUtil {
*/ */
public static final class SpsData { public static final class SpsData {
public final int profileIdc;
public final int constraintsFlagsAndReservedZero2Bits;
public final int levelIdc;
public final int seqParameterSetId; public final int seqParameterSetId;
public final int width; public final int width;
public final int height; public final int height;
@ -42,9 +45,23 @@ public final class NalUnitUtil {
public final int picOrderCntLsbLength; public final int picOrderCntLsbLength;
public final boolean deltaPicOrderAlwaysZeroFlag; public final boolean deltaPicOrderAlwaysZeroFlag;
public SpsData(int seqParameterSetId, int width, int height, float pixelWidthAspectRatio, public SpsData(
boolean separateColorPlaneFlag, boolean frameMbsOnlyFlag, int frameNumLength, int profileIdc,
int picOrderCountType, int picOrderCntLsbLength, boolean deltaPicOrderAlwaysZeroFlag) { int constraintsFlagsAndReservedZero2Bits,
int levelIdc,
int seqParameterSetId,
int width,
int height,
float pixelWidthAspectRatio,
boolean separateColorPlaneFlag,
boolean frameMbsOnlyFlag,
int frameNumLength,
int picOrderCountType,
int picOrderCntLsbLength,
boolean deltaPicOrderAlwaysZeroFlag) {
this.profileIdc = profileIdc;
this.constraintsFlagsAndReservedZero2Bits = constraintsFlagsAndReservedZero2Bits;
this.levelIdc = levelIdc;
this.seqParameterSetId = seqParameterSetId; this.seqParameterSetId = seqParameterSetId;
this.width = width; this.width = width;
this.height = height; this.height = height;
@ -251,7 +268,8 @@ public final class NalUnitUtil {
ParsableNalUnitBitArray data = new ParsableNalUnitBitArray(nalData, nalOffset, nalLimit); ParsableNalUnitBitArray data = new ParsableNalUnitBitArray(nalData, nalOffset, nalLimit);
data.skipBits(8); // nal_unit data.skipBits(8); // nal_unit
int profileIdc = data.readBits(8); int profileIdc = data.readBits(8);
data.skipBits(16); // constraint bits (6), reserved (2) and level_idc (8) int constraintsFlagsAndReservedZero2Bits = data.readBits(8);
int levelIdc = data.readBits(8);
int seqParameterSetId = data.readUnsignedExpGolombCodedInt(); int seqParameterSetId = data.readUnsignedExpGolombCodedInt();
int chromaFormatIdc = 1; // Default is 4:2:0 int chromaFormatIdc = 1; // Default is 4:2:0
@ -349,9 +367,20 @@ public final class NalUnitUtil {
} }
} }
return new SpsData(seqParameterSetId, frameWidth, frameHeight, pixelWidthHeightRatio, return new SpsData(
separateColorPlaneFlag, frameMbsOnlyFlag, frameNumLength, picOrderCntType, profileIdc,
picOrderCntLsbLength, deltaPicOrderAlwaysZeroFlag); constraintsFlagsAndReservedZero2Bits,
levelIdc,
seqParameterSetId,
frameWidth,
frameHeight,
pixelWidthHeightRatio,
separateColorPlaneFlag,
frameMbsOnlyFlag,
frameNumLength,
picOrderCntType,
picOrderCntLsbLength,
deltaPicOrderAlwaysZeroFlag);
} }
/** /**