зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1374774: P7. Add SPSNAL and SPSNALIterator classes. r=gerald
We will use them to simplify the parsing of the extradata. MozReview-Commit-ID: 5M5uGXAkkFb --HG-- extra : rebase_source : bbd641203eb8bdcccb667d1a4e259c1a0462b11e
This commit is contained in:
Родитель
66b67006ed
Коммит
1a62966642
|
@ -188,17 +188,146 @@ SPSData::operator==(const SPSData& aOther) const
|
|||
!memcmp(this, &aOther, sizeof(SPSData));
|
||||
}
|
||||
|
||||
bool
|
||||
SPSData::operator!=(const SPSData& aOther) const
|
||||
{
|
||||
return !(operator==(aOther));
|
||||
}
|
||||
|
||||
// SPSNAL and SPSNALIterator do not own their data.
|
||||
class SPSNAL
|
||||
{
|
||||
public:
|
||||
SPSNAL(const uint8_t* aPtr, size_t aLength)
|
||||
{
|
||||
MOZ_ASSERT(aPtr);
|
||||
|
||||
if (aLength == 0 || (*aPtr & 0x1f) != H264_NAL_SPS) {
|
||||
return;
|
||||
}
|
||||
mDecodedNAL = H264::DecodeNALUnit(aPtr, aLength);
|
||||
if (mDecodedNAL) {
|
||||
mLength = GetBitLength(mDecodedNAL);
|
||||
}
|
||||
}
|
||||
|
||||
SPSNAL() { }
|
||||
|
||||
bool IsValid() const { return mDecodedNAL; }
|
||||
|
||||
bool operator==(const SPSNAL& aOther) const
|
||||
{
|
||||
if (!mDecodedNAL || !aOther.mDecodedNAL) {
|
||||
return false;
|
||||
}
|
||||
if (mLength != aOther.mLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mLength / 8 <= mDecodedNAL->Length());
|
||||
|
||||
if (memcmp(mDecodedNAL->Elements(),
|
||||
aOther.mDecodedNAL->Elements(),
|
||||
mLength / 8)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t remaining = mLength - (mLength & ~7);
|
||||
|
||||
BitReader b1(mDecodedNAL->Elements() + mLength / 8, remaining);
|
||||
BitReader b2(aOther.mDecodedNAL->Elements() + mLength / 8, remaining);
|
||||
for (uint32_t i = 0; i < remaining; i++) {
|
||||
if (b1.ReadBit() != b2.ReadBit()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const SPSNAL& aOther) const
|
||||
{
|
||||
return !(operator==(aOther));
|
||||
}
|
||||
|
||||
bool GetSPSData(SPSData& aDest)
|
||||
{
|
||||
return H264::DecodeSPS(mDecodedNAL, aDest);
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<mozilla::MediaByteBuffer> mDecodedNAL;
|
||||
uint32_t mLength = 0;
|
||||
};
|
||||
|
||||
class SPSNALIterator
|
||||
{
|
||||
public:
|
||||
explicit SPSNALIterator(const mozilla::MediaByteBuffer* aExtraData)
|
||||
: mExtraDataPtr(aExtraData->Elements())
|
||||
, mReader(aExtraData)
|
||||
{
|
||||
if (!mReader.Read(5)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mNumSPS = mReader.ReadU8() & 0x1f;
|
||||
if (mNumSPS == 0) {
|
||||
return;
|
||||
}
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
SPSNALIterator& operator++()
|
||||
{
|
||||
if (mEOS || !mValid) {
|
||||
return *this;
|
||||
}
|
||||
if (--mNumSPS == 0) {
|
||||
mEOS = true;
|
||||
}
|
||||
uint16_t length = mReader.ReadU16();
|
||||
if (length == 0 || !mReader.Read(length)) {
|
||||
mEOS = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return mValid && !mEOS;
|
||||
}
|
||||
|
||||
SPSNAL operator*() const
|
||||
{
|
||||
MOZ_ASSERT(bool(*this));
|
||||
ByteReader reader(mExtraDataPtr + mReader.Offset(), mReader.Remaining());
|
||||
uint16_t length = reader.ReadU16();
|
||||
const uint8_t* ptr = reader.Read(length);
|
||||
if (!ptr) {
|
||||
return SPSNAL();
|
||||
}
|
||||
return SPSNAL(ptr, length);
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t* mExtraDataPtr;
|
||||
ByteReader mReader;
|
||||
bool mValid = false;
|
||||
bool mEOS = false;
|
||||
uint8_t mNumSPS = 0;
|
||||
};
|
||||
|
||||
/* static */ already_AddRefed<mozilla::MediaByteBuffer>
|
||||
H264::DecodeNALUnit(const mozilla::MediaByteBuffer* aNAL)
|
||||
H264::DecodeNALUnit(const uint8_t* aNAL, size_t aLength)
|
||||
{
|
||||
MOZ_ASSERT(aNAL);
|
||||
|
||||
if (aNAL->Length() < 4) {
|
||||
if (aLength < 4) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> rbsp = new mozilla::MediaByteBuffer;
|
||||
ByteReader reader(aNAL);
|
||||
ByteReader reader(aNAL, aLength);
|
||||
uint8_t nal_unit_type = reader.ReadU8() & 0x1f;
|
||||
uint32_t nalUnitHeaderBytes = 1;
|
||||
if (nal_unit_type == H264_NAL_PREFIX ||
|
||||
|
@ -628,10 +757,7 @@ H264::DecodeSPSFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
|
|||
return false;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> rawNAL = new mozilla::MediaByteBuffer;
|
||||
rawNAL->AppendElements(ptr, length);
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> sps = DecodeNALUnit(rawNAL);
|
||||
RefPtr<mozilla::MediaByteBuffer> sps = DecodeNALUnit(ptr, length);
|
||||
|
||||
if (!sps) {
|
||||
return false;
|
||||
|
@ -770,9 +896,7 @@ H264::ExtractExtraData(const mozilla::MediaRawData* aSample)
|
|||
uint8_t nalType = *p & 0x1f;
|
||||
|
||||
if (nalType == H264_NAL_SPS) {
|
||||
RefPtr<mozilla::MediaByteBuffer> rawNAL = new mozilla::MediaByteBuffer;
|
||||
rawNAL->AppendElements(p, nalLen);
|
||||
RefPtr<mozilla::MediaByteBuffer> sps = DecodeNALUnit(rawNAL);
|
||||
RefPtr<mozilla::MediaByteBuffer> sps = DecodeNALUnit(p, nalLen);
|
||||
SPSData data;
|
||||
if (!DecodeSPS(sps, data)) {
|
||||
// Invalid SPS, ignore.
|
||||
|
|
|
@ -39,6 +39,7 @@ class BitReader;
|
|||
struct SPSData
|
||||
{
|
||||
bool operator==(const SPSData& aOther) const;
|
||||
bool operator!=(const SPSData& aOther) const;
|
||||
|
||||
bool valid;
|
||||
|
||||
|
@ -410,13 +411,6 @@ struct SPSData
|
|||
class H264
|
||||
{
|
||||
public:
|
||||
/* Extract RAW BYTE SEQUENCE PAYLOAD from NAL content.
|
||||
Returns nullptr if invalid content.
|
||||
This is compliant to ITU H.264 7.3.1 Syntax in tabular form NAL unit syntax
|
||||
*/
|
||||
static already_AddRefed<mozilla::MediaByteBuffer> DecodeNALUnit(
|
||||
const mozilla::MediaByteBuffer* aNAL);
|
||||
|
||||
/* Check if out of band extradata contains a SPS NAL */
|
||||
static bool HasSPS(const mozilla::MediaByteBuffer* aExtraData);
|
||||
// Extract SPS and PPS NALs from aSample by looking into each NALs.
|
||||
|
@ -451,6 +445,13 @@ public:
|
|||
static FrameType GetFrameType(const mozilla::MediaRawData* aSample);
|
||||
|
||||
private:
|
||||
friend class SPSNAL;
|
||||
/* Extract RAW BYTE SEQUENCE PAYLOAD from NAL content.
|
||||
Returns nullptr if invalid content.
|
||||
This is compliant to ITU H.264 7.3.1 Syntax in tabular form NAL unit syntax
|
||||
*/
|
||||
static already_AddRefed<mozilla::MediaByteBuffer> DecodeNALUnit(
|
||||
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(BitReader& aBr, SPSData& aDest);
|
||||
|
|
Загрузка…
Ссылка в новой задаче