Bug 1570337 - p2: extend and expose H.264 utility functions. r=jya

Some existing functions that manipulates H.264 bitstream already cover
most of the efforts for converting Android encoder output. With some minor
changes, they can be called by the encoder to avoid code duplications.

Differential Revision: https://phabricator.services.mozilla.com/D43686

--HG--
extra : moz-landing-system : lando
This commit is contained in:
John Lin 2019-08-31 00:21:07 +00:00
Родитель 04a8aad2d9
Коммит c0c0d0e714
4 изменённых файлов: 47 добавлений и 22 удалений

Просмотреть файл

@ -255,7 +255,8 @@ static Result<mozilla::Ok, nsresult> ParseNALUnits(ByteWriter<BigEndian>& aBw,
return Ok();
}
bool AnnexB::ConvertSampleToAVCC(mozilla::MediaRawData* aSample) {
bool AnnexB::ConvertSampleToAVCC(mozilla::MediaRawData* aSample,
const RefPtr<MediaByteBuffer>& aAVCCHeader) {
if (IsAVCC(aSample)) {
return ConvertSampleTo4BytesAVCC(aSample).isOk();
}
@ -275,8 +276,14 @@ bool AnnexB::ConvertSampleToAVCC(mozilla::MediaRawData* aSample) {
if (!samplewriter->Replace(nalu.Elements(), nalu.Length())) {
return false;
}
if (aAVCCHeader) {
aSample->mExtraData = aAVCCHeader;
return true;
}
// Create the AVCC header.
RefPtr<mozilla::MediaByteBuffer> extradata = new mozilla::MediaByteBuffer;
auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
static const uint8_t kFakeExtraData[] = {
1 /* version */,
0x64 /* profile (High) */,
@ -289,7 +296,7 @@ bool AnnexB::ConvertSampleToAVCC(mozilla::MediaRawData* aSample) {
if (!extradata->AppendElements(kFakeExtraData, ArrayLength(kFakeExtraData))) {
return false;
}
aSample->mExtraData = extradata;
aSample->mExtraData = std::move(extradata);
return true;
}

Просмотреть файл

@ -34,7 +34,9 @@ class AnnexB {
mozilla::MediaRawData* aSample, bool aAddSPS = true);
// Convert a sample from Annex B to AVCC.
// an AVCC extradata must not be set.
static bool ConvertSampleToAVCC(mozilla::MediaRawData* aSample);
static bool ConvertSampleToAVCC(
mozilla::MediaRawData* aSample,
const RefPtr<mozilla::MediaByteBuffer>& aAVCCHeader = nullptr);
static mozilla::Result<mozilla::Ok, nsresult> ConvertSampleTo4BytesAVCC(
mozilla::MediaRawData* aSample);

Просмотреть файл

@ -1305,29 +1305,40 @@ bool H264::DecodeRecoverySEI(const mozilla::MediaByteBuffer* aSEI,
RefPtr<MediaByteBuffer> encodedSPS =
EncodeNALUnit(sps->Elements(), sps->Length());
extraData->Clear();
extraData->AppendElement(1);
extraData->AppendElement(aProfile);
extraData->AppendElement(aConstraints);
extraData->AppendElement(aLevel);
extraData->AppendElement(3); // nalLENSize-1
extraData->AppendElement(1); // numPPS
uint8_t c[2];
mozilla::BigEndian::writeUint16(&c[0], encodedSPS->Length() + 1);
extraData->AppendElements(c, 2);
extraData->AppendElement((0x00 << 7) | (0x3 << 5) | H264_NAL_SPS);
extraData->AppendElements(*encodedSPS);
const uint8_t PPS[] = {0xeb, 0xef, 0x20};
extraData->AppendElement(1); // numPPS
mozilla::BigEndian::writeUint16(&c[0], sizeof(PPS) + 1);
extraData->AppendElements(c, 2);
extraData->AppendElement((0x00 << 7) | (0x3 << 5) | H264_NAL_PPS);
extraData->AppendElements(PPS, sizeof(PPS));
WriteExtraData(
extraData, aProfile, aConstraints, aLevel,
MakeSpan<const uint8_t>(encodedSPS->Elements(), encodedSPS->Length()),
MakeSpan<const uint8_t>(PPS, sizeof(PPS)));
return extraData.forget();
}
void H264::WriteExtraData(MediaByteBuffer* aDestExtraData,
const uint8_t aProfile, const uint8_t aConstraints,
const uint8_t aLevel, const Span<const uint8_t> aSPS,
const Span<const uint8_t> aPPS) {
aDestExtraData->AppendElement(1);
aDestExtraData->AppendElement(aProfile);
aDestExtraData->AppendElement(aConstraints);
aDestExtraData->AppendElement(aLevel);
aDestExtraData->AppendElement(3); // nalLENSize-1
aDestExtraData->AppendElement(1); // numPPS
uint8_t c[2];
mozilla::BigEndian::writeUint16(&c[0], aSPS.Length() + 1);
aDestExtraData->AppendElements(c, 2);
aDestExtraData->AppendElement((0x00 << 7) | (0x3 << 5) | H264_NAL_SPS);
aDestExtraData->AppendElements(aSPS.Elements(), aSPS.Length());
aDestExtraData->AppendElement(1); // numPPS
mozilla::BigEndian::writeUint16(&c[0], aPPS.Length() + 1);
aDestExtraData->AppendElements(c, 2);
aDestExtraData->AppendElement((0x00 << 7) | (0x3 << 5) | H264_NAL_PPS);
aDestExtraData->AppendElements(aPPS.Elements(), aPPS.Length());
}
#undef READUE
#undef READSE

Просмотреть файл

@ -469,6 +469,8 @@ class H264 {
static bool DecodeSPSFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
SPSData& aDest);
/* Decode SPS NAL RBSP and fill SPSData structure */
static bool DecodeSPS(const mozilla::MediaByteBuffer* aSPS, SPSData& aDest);
// If the given aExtraData is valid, return the aExtraData.max_num_ref_frames
// clamped to be in the range of [4, 16]; otherwise return 4.
@ -489,6 +491,11 @@ class H264 {
static already_AddRefed<mozilla::MediaByteBuffer> CreateExtraData(
uint8_t aProfile, uint8_t aConstraints, uint8_t aLevel,
const gfx::IntSize& aSize);
static void WriteExtraData(mozilla::MediaByteBuffer* aDestExtraData,
const uint8_t aProfile, const uint8_t aConstraints,
const uint8_t aLevel,
const Span<const uint8_t> aSPS,
const Span<const uint8_t> aPPS);
private:
friend class SPSNAL;
@ -500,8 +507,6 @@ class H264 {
const uint8_t* aNAL, size_t aLength);
static already_AddRefed<mozilla::MediaByteBuffer> EncodeNALUnit(
const uint8_t* aNAL, size_t aLength);
/* Decode SPS NAL RBSP and fill SPSData structure */
static bool DecodeSPS(const mozilla::MediaByteBuffer* aSPS, SPSData& aDest);
static bool vui_parameters(mozilla::BitReader& aBr, SPSData& aDest);
// Read HRD parameters, all data is ignored.
static void hrd_parameters(mozilla::BitReader& aBr);