Backed out changeset 0d953ca28add (bug 1374774) for bustage at media/libstagefright/binding/H264.cpp(205). 'ptr' not declared. r=backout on a CLOSED TREE

This commit is contained in:
Sebastian Hengst 2017-06-24 00:49:18 +02:00
Родитель f5e3176d23
Коммит 261b25bf86
8 изменённых файлов: 136 добавлений и 138 удалений

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

@ -520,9 +520,9 @@ MP4TrackDemuxer::GetSamples(int32_t aNumSamples)
}
for (const auto& sample : samples->mSamples) {
// Collect telemetry from h264 Annex B SPS.
if (mNeedSPSForTelemetry && mp4_demuxer::H264::HasSPS(sample)) {
if (mNeedSPSForTelemetry && mp4_demuxer::AnnexB::HasSPS(sample)) {
RefPtr<MediaByteBuffer> extradata =
mp4_demuxer::H264::ExtractExtraData(sample);
mp4_demuxer::AnnexB::ExtractExtraData(sample);
mNeedSPSForTelemetry = AccumulateSPSTelemetry(extradata);
}
}

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

@ -939,7 +939,7 @@ ChromiumCDMParent::InitializeVideoDecoder(
mMaxRefFrames =
(aConfig.mCodec() == cdm::VideoDecoderConfig::kCodecH264)
? mp4_demuxer::H264::HasSPS(aInfo.mExtraData)
? mp4_demuxer::AnnexB::HasSPS(aInfo.mExtraData)
? mp4_demuxer::H264::ComputeMaxRefFrames(aInfo.mExtraData)
: 16
: 0;

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

@ -19,7 +19,7 @@ DummyMediaDataDecoder::DummyMediaDataDecoder(UniquePtr<DummyDataCreator>&& aCrea
, mIsH264(MP4Decoder::IsH264(aParams.mConfig.mMimeType))
, mMaxRefFrames(
mIsH264
? mp4_demuxer::H264::HasSPS(aParams.VideoConfig().mExtraData)
? mp4_demuxer::AnnexB::HasSPS(aParams.VideoConfig().mExtraData)
? mp4_demuxer::H264::ComputeMaxRefFrames(aParams.VideoConfig().mExtraData)
: 16
: 0)

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

@ -35,7 +35,7 @@ H264Converter::H264Converter(PlatformDecoderModule* aPDM,
{
CreateDecoder(mOriginalConfig, aParams.mDiagnostics);
if (mDecoder) {
MOZ_ASSERT(mp4_demuxer::H264::HasSPS(mOriginalConfig.mExtraData));
MOZ_ASSERT(mp4_demuxer::AnnexB::HasSPS(mOriginalConfig.mExtraData));
// The video metadata contains out of band SPS/PPS (AVC1) store it.
mOriginalExtraData = mOriginalConfig.mExtraData;
}
@ -240,7 +240,7 @@ nsresult
H264Converter::CreateDecoder(const VideoInfo& aConfig,
DecoderDoctorDiagnostics* aDiagnostics)
{
if (!mp4_demuxer::H264::HasSPS(aConfig.mExtraData)) {
if (!mp4_demuxer::AnnexB::HasSPS(aConfig.mExtraData)) {
// nothing found yet, will try again later
return NS_ERROR_NOT_INITIALIZED;
}
@ -290,10 +290,10 @@ nsresult
H264Converter::CreateDecoderAndInit(MediaRawData* aSample)
{
RefPtr<MediaByteBuffer> extra_data =
mp4_demuxer::H264::ExtractExtraData(aSample);
bool inbandExtradata = mp4_demuxer::H264::HasSPS(extra_data);
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
bool inbandExtradata = mp4_demuxer::AnnexB::HasSPS(extra_data);
if (!inbandExtradata &&
!mp4_demuxer::H264::HasSPS(mCurrentConfig.mExtraData)) {
!mp4_demuxer::AnnexB::HasSPS(mCurrentConfig.mExtraData)) {
return NS_ERROR_NOT_INITIALIZED;
}
@ -393,8 +393,8 @@ nsresult
H264Converter::CheckForSPSChange(MediaRawData* aSample)
{
RefPtr<MediaByteBuffer> extra_data =
mp4_demuxer::H264::ExtractExtraData(aSample);
if (!mp4_demuxer::H264::HasSPS(extra_data)) {
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
MOZ_ASSERT(mCanRecycleDecoder.isSome());
if (!*mCanRecycleDecoder) {
// If the decoder can't be recycled, the out of band extradata will never
@ -406,15 +406,15 @@ H264Converter::CheckForSPSChange(MediaRawData* aSample)
// We now check if the out of band one has changed.
// This scenario can only occur on Android with devices that can recycle a
// decoder.
if (!mp4_demuxer::H264::HasSPS(aSample->mExtraData) ||
mp4_demuxer::H264::CompareExtraData(aSample->mExtraData,
mOriginalExtraData)) {
if (!mp4_demuxer::AnnexB::HasSPS(aSample->mExtraData) ||
mp4_demuxer::AnnexB::CompareExtraData(aSample->mExtraData,
mOriginalExtraData)) {
return NS_OK;
}
extra_data = mOriginalExtraData = aSample->mExtraData;
}
if (mp4_demuxer::H264::CompareExtraData(extra_data,
mCurrentConfig.mExtraData)) {
if (mp4_demuxer::AnnexB::CompareExtraData(extra_data,
mCurrentConfig.mExtraData)) {
return NS_OK;
}

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

@ -271,6 +271,108 @@ AnnexB::ConvertSampleToAVCC(mozilla::MediaRawData* aSample)
return true;
}
already_AddRefed<mozilla::MediaByteBuffer>
AnnexB::ExtractExtraData(const mozilla::MediaRawData* aSample)
{
MOZ_ASSERT(IsAVCC(aSample));
RefPtr<mozilla::MediaByteBuffer> extradata = new mozilla::MediaByteBuffer;
// SPS content
nsTArray<uint8_t> sps;
ByteWriter spsw(sps);
int numSps = 0;
// PPS content
nsTArray<uint8_t> pps;
ByteWriter ppsw(pps);
int numPps = 0;
int nalLenSize = ((*aSample->mExtraData)[4] & 3) + 1;
size_t sampleSize = aSample->Size();
if (aSample->mCrypto.mValid) {
// The content is encrypted, we can only parse the non-encrypted data.
MOZ_ASSERT(aSample->mCrypto.mPlainSizes.Length() > 0);
if (aSample->mCrypto.mPlainSizes.Length() == 0 ||
aSample->mCrypto.mPlainSizes[0] > sampleSize) {
// This is invalid content.
return nullptr;
}
sampleSize = aSample->mCrypto.mPlainSizes[0];
}
ByteReader reader(aSample->Data(), sampleSize);
// Find SPS and PPS NALUs in AVCC data
while (reader.Remaining() > nalLenSize) {
uint32_t nalLen;
switch (nalLenSize) {
case 1: nalLen = reader.ReadU8(); break;
case 2: nalLen = reader.ReadU16(); break;
case 3: nalLen = reader.ReadU24(); break;
case 4: nalLen = reader.ReadU32(); break;
}
uint8_t nalType = reader.PeekU8() & 0x1f;
const uint8_t* p = reader.Read(nalLen);
if (!p) {
return extradata.forget();
}
if (nalType == 0x7) { /* SPS */
numSps++;
if (!spsw.WriteU16(nalLen)
|| !spsw.Write(p, nalLen)) {
return extradata.forget();
}
} else if (nalType == 0x8) { /* PPS */
numPps++;
if (!ppsw.WriteU16(nalLen)
|| !ppsw.Write(p, nalLen)) {
return extradata.forget();
}
}
}
if (numSps && sps.Length() > 5) {
extradata->AppendElement(1); // version
extradata->AppendElement(sps[3]); // profile
extradata->AppendElement(sps[4]); // profile compat
extradata->AppendElement(sps[5]); // level
extradata->AppendElement(0xfc | 3); // nal size - 1
extradata->AppendElement(0xe0 | numSps);
extradata->AppendElements(sps.Elements(), sps.Length());
extradata->AppendElement(numPps);
if (numPps) {
extradata->AppendElements(pps.Elements(), pps.Length());
}
}
return extradata.forget();
}
bool
AnnexB::HasSPS(const mozilla::MediaRawData* aSample)
{
return HasSPS(aSample->mExtraData);
}
bool
AnnexB::HasSPS(const mozilla::MediaByteBuffer* aExtraData)
{
if (!aExtraData) {
return false;
}
ByteReader reader(aExtraData);
const uint8_t* ptr = reader.Read(5);
if (!ptr || !reader.CanRead8()) {
return false;
}
uint8_t numSps = reader.ReadU8() & 0x1f;
return numSps > 0;
}
bool
AnnexB::ConvertSampleTo4BytesAVCC(mozilla::MediaRawData* aSample)
{
@ -322,4 +424,12 @@ AnnexB::IsAnnexB(const mozilla::MediaRawData* aSample)
return header == 0x00000001 || (header >> 8) == 0x000001;
}
bool
AnnexB::CompareExtraData(const mozilla::MediaByteBuffer* aExtraData1,
const mozilla::MediaByteBuffer* aExtraData2)
{
// Very crude comparison.
return aExtraData1 == aExtraData2 || *aExtraData1 == *aExtraData2;
}
} // namespace mp4_demuxer

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

@ -586,7 +586,7 @@ H264::vui_parameters(BitReader& aBr, SPSData& aDest)
H264::DecodeSPSFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
SPSData& aDest)
{
if (!HasSPS(aExtraData)) {
if (!AnnexB::HasSPS(aExtraData)) {
return false;
}
ByteReader reader(aExtraData);
@ -704,117 +704,6 @@ H264::GetFrameType(const mozilla::MediaRawData* aSample)
return FrameType::OTHER;
}
/* static */ already_AddRefed<mozilla::MediaByteBuffer>
H264::ExtractExtraData(const mozilla::MediaRawData* aSample)
{
MOZ_ASSERT(AnnexB::IsAVCC(aSample));
RefPtr<mozilla::MediaByteBuffer> extradata = new mozilla::MediaByteBuffer;
// SPS content
nsTArray<uint8_t> sps;
ByteWriter spsw(sps);
int numSps = 0;
// PPS content
nsTArray<uint8_t> pps;
ByteWriter ppsw(pps);
int numPps = 0;
int nalLenSize = ((*aSample->mExtraData)[4] & 3) + 1;
size_t sampleSize = aSample->Size();
if (aSample->mCrypto.mValid) {
// The content is encrypted, we can only parse the non-encrypted data.
MOZ_ASSERT(aSample->mCrypto.mPlainSizes.Length() > 0);
if (aSample->mCrypto.mPlainSizes.Length() == 0 ||
aSample->mCrypto.mPlainSizes[0] > sampleSize) {
// This is invalid content.
return nullptr;
}
sampleSize = aSample->mCrypto.mPlainSizes[0];
}
ByteReader reader(aSample->Data(), sampleSize);
// Find SPS and PPS NALUs in AVCC data
while (reader.Remaining() > nalLenSize) {
uint32_t nalLen;
switch (nalLenSize) {
case 1: nalLen = reader.ReadU8(); break;
case 2: nalLen = reader.ReadU16(); break;
case 3: nalLen = reader.ReadU24(); break;
case 4: nalLen = reader.ReadU32(); break;
}
uint8_t nalType = reader.PeekU8() & 0x1f;
const uint8_t* p = reader.Read(nalLen);
if (!p) {
return extradata.forget();
}
if (nalType == 0x7) { /* SPS */
numSps++;
if (!spsw.WriteU16(nalLen)
|| !spsw.Write(p, nalLen)) {
return extradata.forget();
}
} else if (nalType == 0x8) { /* PPS */
numPps++;
if (!ppsw.WriteU16(nalLen)
|| !ppsw.Write(p, nalLen)) {
return extradata.forget();
}
}
}
if (numSps && sps.Length() > 5) {
extradata->AppendElement(1); // version
extradata->AppendElement(sps[3]); // profile
extradata->AppendElement(sps[4]); // profile compat
extradata->AppendElement(sps[5]); // level
extradata->AppendElement(0xfc | 3); // nal size - 1
extradata->AppendElement(0xe0 | numSps);
extradata->AppendElements(sps.Elements(), sps.Length());
extradata->AppendElement(numPps);
if (numPps) {
extradata->AppendElements(pps.Elements(), pps.Length());
}
}
return extradata.forget();
}
/* static */ bool
H264::HasSPS(const mozilla::MediaRawData* aSample)
{
return HasSPS(aSample->mExtraData);
}
/* static */ bool
H264::HasSPS(const mozilla::MediaByteBuffer* aExtraData)
{
if (!aExtraData) {
return false;
}
ByteReader reader(aExtraData);
const uint8_t* ptr = reader.Read(5);
if (!ptr || !reader.CanRead8()) {
return false;
}
uint8_t numSps = reader.ReadU8() & 0x1f;
return numSps > 0;
}
/* static */ bool
H264::CompareExtraData(const mozilla::MediaByteBuffer* aExtraData1,
const mozilla::MediaByteBuffer* aExtraData2)
{
// Very crude comparison.
return aExtraData1 == aExtraData2 || *aExtraData1 == *aExtraData2;
}
#undef READUE
#undef READSE

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

@ -29,10 +29,19 @@ public:
// Parse an AVCC extradata and construct the Annex B sample header.
static already_AddRefed<mozilla::MediaByteBuffer> ConvertExtraDataToAnnexB(
const mozilla::MediaByteBuffer* aExtraData);
// Extract SPS and PPS NALs from aSample by looking into each NALs.
// aSample must be in AVCC format.
static already_AddRefed<mozilla::MediaByteBuffer> ExtractExtraData(
const mozilla::MediaRawData* aSample);
static bool HasSPS(const mozilla::MediaRawData* aSample);
static bool HasSPS(const mozilla::MediaByteBuffer* aExtraData);
// Returns true if format is AVCC and sample has valid extradata.
static bool IsAVCC(const mozilla::MediaRawData* aSample);
// Returns true if format is AnnexB.
static bool IsAnnexB(const mozilla::MediaRawData* aSample);
// Return true if both extradata are equal.
static bool CompareExtraData(const mozilla::MediaByteBuffer* aExtraData1,
const mozilla::MediaByteBuffer* aExtraData2);
private:
// AVCC box parser helper.

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

@ -413,16 +413,6 @@ public:
static already_AddRefed<mozilla::MediaByteBuffer> DecodeNALUnit(
const mozilla::MediaByteBuffer* aNAL);
static bool HasSPS(const mozilla::MediaRawData* aSample);
static bool HasSPS(const mozilla::MediaByteBuffer* aExtraData);
// Extract SPS and PPS NALs from aSample by looking into each NALs.
// aSample must be in AVCC format.
static already_AddRefed<mozilla::MediaByteBuffer> ExtractExtraData(
const mozilla::MediaRawData* aSample);
// Return true if both extradata are equal.
static bool CompareExtraData(const mozilla::MediaByteBuffer* aExtraData1,
const mozilla::MediaByteBuffer* aExtraData2);
// Ensure that SPS data makes sense, Return true if SPS data was, and false
// otherwise. If false, then content will be adjusted accordingly.
static bool EnsureSPSIsSane(SPSData& aSPS);