LCOV - code coverage report
Current view: top level - media/libstagefright/binding - H264.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 478 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 30 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "mozilla/ArrayUtils.h"
       6             : #include "mozilla/PodOperations.h"
       7             : #include "mp4_demuxer/AnnexB.h"
       8             : #include "mp4_demuxer/BitReader.h"
       9             : #include "mp4_demuxer/ByteReader.h"
      10             : #include "mp4_demuxer/ByteWriter.h"
      11             : #include "mp4_demuxer/H264.h"
      12             : #include <media/stagefright/foundation/ABitReader.h>
      13             : #include <limits>
      14             : #include <cmath>
      15             : 
      16             : #define READSE(var, min, max)                                                  \
      17             :   {                                                                            \
      18             :     int32_t val = br.ReadSE();                                                 \
      19             :     if (val < min || val > max) {                                              \
      20             :       return false;                                                            \
      21             :     }                                                                          \
      22             :     aDest.var = val;                                                           \
      23             :   }
      24             : 
      25             : #define READUE(var, max)                                                       \
      26             :   {                                                                            \
      27             :     uint32_t uval = br.ReadUE();                                               \
      28             :     if (uval > max) {                                                          \
      29             :       return false;                                                            \
      30             :     }                                                                          \
      31             :     aDest.var = uval;                                                          \
      32             :   }
      33             : 
      34             : using namespace mozilla;
      35             : 
      36             : namespace mp4_demuxer {
      37             : 
      38             : // Default scaling lists (per spec).
      39             : // ITU H264:
      40             : // Table 7-2 – Assignment of mnemonic names to scaling list indices and
      41             : // specification of fall-back rule
      42             : static const uint8_t Default_4x4_Intra[16] = {
      43             :     6, 13, 13, 20,
      44             :    20, 20, 28, 28,
      45             :    28, 28, 32, 32,
      46             :    32, 37, 37, 42
      47             : };
      48             : 
      49             : static const uint8_t Default_4x4_Inter[16] = {
      50             :    10, 14, 14, 20,
      51             :    20, 20, 24, 24,
      52             :    24, 24, 27, 27,
      53             :    27, 30, 30, 34
      54             : };
      55             : 
      56             : static const uint8_t Default_8x8_Intra[64] = {
      57             :     6, 10, 10, 13, 11, 13, 16, 16,
      58             :    16, 16, 18, 18, 18, 18, 18, 23,
      59             :    23, 23, 23, 23, 23, 25, 25, 25,
      60             :    25, 25, 25, 25, 27, 27, 27, 27,
      61             :    27, 27, 27, 27, 29, 29, 29, 29,
      62             :    29, 29, 29, 31, 31, 31, 31, 31,
      63             :    31, 33, 33, 33, 33, 33, 36, 36,
      64             :    36, 36, 38, 38, 38, 40, 40, 42
      65             : };
      66             : 
      67             : static const uint8_t Default_8x8_Inter[64] = {
      68             :     9, 13, 13, 15, 13, 15, 17, 17,
      69             :    17, 17, 19, 19, 19, 19, 19, 21,
      70             :    21, 21, 21, 21, 21, 22, 22, 22,
      71             :    22, 22, 22, 22, 24, 24, 24, 24,
      72             :    24, 24, 24, 24, 25, 25, 25, 25,
      73             :    25, 25, 25, 27, 27, 27, 27, 27,
      74             :    27, 28, 28, 28, 28, 28, 30, 30,
      75             :    30, 30, 32, 32, 32, 33, 33, 35
      76             : };
      77             : 
      78             : namespace detail {
      79             : static void
      80           0 : scaling_list(BitReader& aBr, uint8_t* aScalingList, int aSizeOfScalingList,
      81             :              const uint8_t* aDefaultList, const uint8_t* aFallbackList)
      82             : {
      83           0 :   int32_t lastScale = 8;
      84           0 :   int32_t nextScale = 8;
      85             :   int32_t deltaScale;
      86             : 
      87             :   // (pic|seq)_scaling_list_present_flag[i]
      88           0 :   if (!aBr.ReadBit()) {
      89           0 :     if (aFallbackList) {
      90           0 :       memcpy(aScalingList, aFallbackList, aSizeOfScalingList);
      91             :     }
      92           0 :     return;
      93             :   }
      94             : 
      95           0 :   for (int i = 0; i < aSizeOfScalingList; i++) {
      96           0 :     if (nextScale != 0) {
      97           0 :       deltaScale = aBr.ReadSE();
      98           0 :       nextScale = (lastScale + deltaScale + 256) % 256;
      99           0 :       if (!i && !nextScale) {
     100           0 :         memcpy(aScalingList, aDefaultList, aSizeOfScalingList);
     101           0 :         return;
     102             :       }
     103             :     }
     104           0 :     aScalingList[i] = (nextScale == 0) ? lastScale : nextScale;
     105           0 :     lastScale = aScalingList[i];
     106             :   }
     107             : }
     108             : } // namespace detail.
     109             : 
     110             : template <size_t N>
     111             : static void
     112           0 : scaling_list(BitReader& aBr, uint8_t (&aScalingList)[N],
     113             :              const uint8_t (&aDefaultList)[N], const uint8_t (&aFallbackList)[N])
     114             : {
     115           0 :   detail::scaling_list(aBr, aScalingList, N, aDefaultList, aFallbackList);
     116           0 : }
     117             : 
     118             : template <size_t N>
     119             : static void
     120             : scaling_list(BitReader& aBr, uint8_t (&aScalingList)[N], const uint8_t (&aDefaultList)[N])
     121             : {
     122             :   detail::scaling_list(aBr, aScalingList, N, aDefaultList, nullptr);
     123             : }
     124             : 
     125             : static uint32_t
     126           0 : GetBitLength(const mozilla::MediaByteBuffer* aNAL)
     127             : {
     128           0 :   size_t size = aNAL->Length();
     129             : 
     130           0 :   while (size > 0 && aNAL->ElementAt(size - 1) == 0) {
     131           0 :     size--;
     132             :   }
     133             : 
     134           0 :   if (!size) {
     135           0 :     return 0;
     136             :   }
     137             : 
     138           0 :   if (size > UINT32_MAX / 8) {
     139             :     // We can't represent it, we'll use as much as we can.
     140           0 :     return UINT32_MAX;
     141             :   }
     142             : 
     143           0 :   uint8_t v = aNAL->ElementAt(size - 1);
     144           0 :   size *= 8;
     145             : 
     146             :   // Remove the stop bit and following trailing zeros.
     147           0 :   if (v) {
     148             :     // Count the consecutive zero bits (trailing) on the right by binary search.
     149             :     // Adapted from Matt Whitlock algorithm to only bother with 8 bits integers.
     150             :     uint32_t c;
     151           0 :     if (v & 1) {
     152             :       // Special case for odd v (assumed to happen half of the time).
     153           0 :       c = 0;
     154             :     } else {
     155           0 :       c = 1;
     156           0 :       if ((v & 0xf) == 0) {
     157           0 :         v >>= 4;
     158           0 :         c += 4;
     159             :       }
     160           0 :       if ((v & 0x3) == 0) {
     161           0 :         v >>= 2;
     162           0 :         c += 2;
     163             :       }
     164           0 :       c -= v & 0x1;
     165             :     }
     166           0 :     size -= c + 1;
     167             :   }
     168           0 :   return size;
     169             : }
     170             : 
     171           0 : SPSData::SPSData()
     172             : {
     173           0 :   PodZero(this);
     174             :   // Default values when they aren't defined as per ITU-T H.264 (2014/02).
     175           0 :   chroma_format_idc = 1;
     176           0 :   video_format = 5;
     177           0 :   colour_primaries = 2;
     178           0 :   transfer_characteristics = 2;
     179           0 :   sample_ratio = 1.0;
     180           0 :   memset(scaling_matrix4x4, 16, sizeof(scaling_matrix4x4));
     181           0 :   memset(scaling_matrix8x8, 16, sizeof(scaling_matrix8x8));
     182           0 : }
     183             : 
     184             : bool
     185           0 : SPSData::operator==(const SPSData& aOther) const
     186             : {
     187           0 :   return this->valid && aOther.valid &&
     188           0 :     !memcmp(this, &aOther, sizeof(SPSData));
     189             : }
     190             : 
     191             : bool
     192           0 : SPSData::operator!=(const SPSData& aOther) const
     193             : {
     194           0 :   return !(operator==(aOther));
     195             : }
     196             : 
     197             : // SPSNAL and SPSNALIterator do not own their data.
     198           0 : class SPSNAL
     199             : {
     200             : public:
     201           0 :   SPSNAL(const uint8_t* aPtr, size_t aLength)
     202           0 :   {
     203           0 :     MOZ_ASSERT(aPtr);
     204             : 
     205           0 :     if (aLength == 0 || (*aPtr & 0x1f) != H264_NAL_SPS) {
     206           0 :       return;
     207             :     }
     208           0 :     mDecodedNAL = H264::DecodeNALUnit(aPtr, aLength);
     209           0 :     if (mDecodedNAL) {
     210           0 :       mLength = GetBitLength(mDecodedNAL);
     211             :     }
     212             :   }
     213             : 
     214           0 :   SPSNAL() { }
     215             : 
     216             :   bool IsValid() const { return mDecodedNAL; }
     217             : 
     218           0 :   bool operator==(const SPSNAL& aOther) const
     219             :   {
     220           0 :     if (!mDecodedNAL || !aOther.mDecodedNAL) {
     221           0 :       return false;
     222             :     }
     223             : 
     224           0 :     SPSData decodedSPS1;
     225           0 :     SPSData decodedSPS2;
     226           0 :     if (!GetSPSData(decodedSPS1) || !aOther.GetSPSData(decodedSPS2)) {
     227             :       // Couldn't decode one SPS, perform a binary comparison
     228           0 :       if (mLength != aOther.mLength) {
     229           0 :         return false;
     230             :       }
     231           0 :       MOZ_ASSERT(mLength / 8 <= mDecodedNAL->Length());
     232             : 
     233           0 :       if (memcmp(mDecodedNAL->Elements(),
     234           0 :                  aOther.mDecodedNAL->Elements(),
     235           0 :                  mLength / 8)) {
     236           0 :         return false;
     237             :       }
     238             : 
     239           0 :       uint32_t remaining = mLength - (mLength & ~7);
     240             : 
     241           0 :       BitReader b1(mDecodedNAL->Elements() + mLength / 8, remaining);
     242           0 :       BitReader b2(aOther.mDecodedNAL->Elements() + mLength / 8, remaining);
     243           0 :       for (uint32_t i = 0; i < remaining; i++) {
     244           0 :         if (b1.ReadBit() != b2.ReadBit()) {
     245           0 :           return false;
     246             :         }
     247             :       }
     248           0 :       return true;
     249             :     }
     250             : 
     251           0 :     return decodedSPS1 == decodedSPS2;
     252             :   }
     253             : 
     254           0 :   bool operator!=(const SPSNAL& aOther) const
     255             :   {
     256           0 :     return !(operator==(aOther));
     257             :   }
     258             : 
     259           0 :   bool GetSPSData(SPSData& aDest) const
     260             :   {
     261           0 :     return H264::DecodeSPS(mDecodedNAL, aDest);
     262             :   }
     263             : 
     264             : private:
     265             :   RefPtr<mozilla::MediaByteBuffer> mDecodedNAL;
     266             :   uint32_t mLength = 0;
     267             : };
     268             : 
     269           0 : class SPSNALIterator
     270             : {
     271             : public:
     272           0 :   explicit SPSNALIterator(const mozilla::MediaByteBuffer* aExtraData)
     273           0 :     : mExtraDataPtr(aExtraData->Elements())
     274           0 :     , mReader(aExtraData)
     275             :   {
     276           0 :     if (!mReader.Read(5)) {
     277           0 :       return;
     278             :     }
     279             : 
     280           0 :     mNumSPS = mReader.ReadU8() & 0x1f;
     281           0 :     if (mNumSPS == 0) {
     282           0 :       return;
     283             :     }
     284           0 :     mValid = true;
     285             :   }
     286             : 
     287           0 :   SPSNALIterator& operator++()
     288             :   {
     289           0 :     if (mEOS || !mValid) {
     290           0 :       return *this;
     291             :     }
     292           0 :     if (--mNumSPS == 0) {
     293           0 :       mEOS = true;
     294             :     }
     295           0 :     uint16_t length = mReader.ReadU16();
     296           0 :     if (length == 0 || !mReader.Read(length)) {
     297           0 :       mEOS = true;
     298             :     }
     299           0 :     return *this;
     300             :   }
     301             : 
     302           0 :   explicit operator bool() const
     303             :   {
     304           0 :     return mValid && !mEOS;
     305             :   }
     306             : 
     307           0 :   SPSNAL operator*() const
     308             :   {
     309           0 :     MOZ_ASSERT(bool(*this));
     310           0 :     ByteReader reader(mExtraDataPtr + mReader.Offset(), mReader.Remaining());
     311           0 :     uint16_t length = reader.ReadU16();
     312           0 :     const uint8_t* ptr = reader.Read(length);
     313           0 :     if (!ptr) {
     314           0 :       return SPSNAL();
     315             :     }
     316           0 :     return SPSNAL(ptr, length);
     317             :   }
     318             : 
     319             : private:
     320             :   const uint8_t* mExtraDataPtr;
     321             :   ByteReader mReader;
     322             :   bool mValid = false;
     323             :   bool mEOS = false;
     324             :   uint8_t mNumSPS = 0;
     325             : };
     326             : 
     327             : /* static */ already_AddRefed<mozilla::MediaByteBuffer>
     328           0 : H264::DecodeNALUnit(const uint8_t* aNAL, size_t aLength)
     329             : {
     330           0 :   MOZ_ASSERT(aNAL);
     331             : 
     332           0 :   if (aLength < 4) {
     333           0 :     return nullptr;
     334             :   }
     335             : 
     336           0 :   RefPtr<mozilla::MediaByteBuffer> rbsp = new mozilla::MediaByteBuffer;
     337           0 :   ByteReader reader(aNAL, aLength);
     338           0 :   uint8_t nal_unit_type = reader.ReadU8() & 0x1f;
     339           0 :   uint32_t nalUnitHeaderBytes = 1;
     340           0 :   if (nal_unit_type == H264_NAL_PREFIX ||
     341           0 :       nal_unit_type == H264_NAL_SLICE_EXT ||
     342             :       nal_unit_type == H264_NAL_SLICE_EXT_DVC) {
     343           0 :     bool svc_extension_flag = false;
     344           0 :     bool avc_3d_extension_flag = false;
     345           0 :     if (nal_unit_type != H264_NAL_SLICE_EXT_DVC) {
     346           0 :       svc_extension_flag = reader.PeekU8() & 0x80;
     347             :     } else {
     348           0 :       avc_3d_extension_flag = reader.PeekU8() & 0x80;
     349             :     }
     350           0 :     if (svc_extension_flag) {
     351           0 :       nalUnitHeaderBytes += 3;
     352           0 :     } else if (avc_3d_extension_flag) {
     353           0 :       nalUnitHeaderBytes += 2;
     354             :     } else {
     355           0 :       nalUnitHeaderBytes += 3;
     356             :     }
     357             :   }
     358           0 :   if (!reader.Read(nalUnitHeaderBytes - 1)) {
     359           0 :     return nullptr;
     360             :   }
     361           0 :   uint32_t lastbytes = 0xffff;
     362           0 :   while (reader.Remaining()) {
     363           0 :     uint8_t byte = reader.ReadU8();
     364           0 :     if ((lastbytes & 0xffff) == 0 && byte == 0x03) {
     365             :       // reset last two bytes, to detect the 0x000003 sequence again.
     366           0 :       lastbytes = 0xffff;
     367             :     } else {
     368           0 :       rbsp->AppendElement(byte);
     369             :     }
     370           0 :     lastbytes = (lastbytes << 8) | byte;
     371             :   }
     372           0 :   return rbsp.forget();
     373             : }
     374             : 
     375             : static int32_t
     376           0 : ConditionDimension(float aValue)
     377             : {
     378             :   // This will exclude NaNs and too-big values.
     379           0 :   if (aValue > 1.0 && aValue <= INT32_MAX)
     380           0 :     return int32_t(aValue);
     381           0 :   return 0;
     382             : }
     383             : 
     384             : /* static */ bool
     385           0 : H264::DecodeSPS(const mozilla::MediaByteBuffer* aSPS, SPSData& aDest)
     386             : {
     387           0 :   if (!aSPS) {
     388           0 :     return false;
     389             :   }
     390           0 :   BitReader br(aSPS, GetBitLength(aSPS));
     391             : 
     392           0 :   aDest.profile_idc = br.ReadBits(8);
     393           0 :   aDest.constraint_set0_flag = br.ReadBit();
     394           0 :   aDest.constraint_set1_flag = br.ReadBit();
     395           0 :   aDest.constraint_set2_flag = br.ReadBit();
     396           0 :   aDest.constraint_set3_flag = br.ReadBit();
     397           0 :   aDest.constraint_set4_flag = br.ReadBit();
     398           0 :   aDest.constraint_set5_flag = br.ReadBit();
     399           0 :   br.ReadBits(2); // reserved_zero_2bits
     400           0 :   aDest.level_idc = br.ReadBits(8);
     401           0 :   READUE(seq_parameter_set_id, MAX_SPS_COUNT - 1);
     402             : 
     403           0 :   if (aDest.profile_idc == 100 || aDest.profile_idc == 110 ||
     404           0 :       aDest.profile_idc == 122 || aDest.profile_idc == 244 ||
     405           0 :       aDest.profile_idc == 44 || aDest.profile_idc == 83 ||
     406           0 :       aDest.profile_idc == 86 || aDest.profile_idc == 118 ||
     407           0 :       aDest.profile_idc == 128 || aDest.profile_idc == 138 ||
     408           0 :       aDest.profile_idc == 139 || aDest.profile_idc == 134) {
     409           0 :     READUE(chroma_format_idc, 3);
     410           0 :     if (aDest.chroma_format_idc == 3) {
     411           0 :       aDest.separate_colour_plane_flag = br.ReadBit();
     412             :     }
     413           0 :     READUE(bit_depth_luma_minus8, 6);
     414           0 :     READUE(bit_depth_chroma_minus8, 6);
     415           0 :     br.ReadBit();       // qpprime_y_zero_transform_bypass_flag
     416           0 :     aDest.seq_scaling_matrix_present_flag = br.ReadBit();
     417           0 :     if (aDest.seq_scaling_matrix_present_flag) {
     418           0 :       scaling_list(br, aDest.scaling_matrix4x4[0], Default_4x4_Intra,
     419           0 :                    Default_4x4_Intra);
     420           0 :       scaling_list(br, aDest.scaling_matrix4x4[1], Default_4x4_Intra,
     421           0 :                    aDest.scaling_matrix4x4[0]);
     422           0 :       scaling_list(br, aDest.scaling_matrix4x4[2], Default_4x4_Intra,
     423           0 :                    aDest.scaling_matrix4x4[1]);
     424           0 :       scaling_list(br, aDest.scaling_matrix4x4[3], Default_4x4_Inter,
     425           0 :                    Default_4x4_Inter);
     426           0 :       scaling_list(br, aDest.scaling_matrix4x4[4], Default_4x4_Inter,
     427           0 :                    aDest.scaling_matrix4x4[3]);
     428           0 :       scaling_list(br, aDest.scaling_matrix4x4[5], Default_4x4_Inter,
     429           0 :                    aDest.scaling_matrix4x4[4]);
     430             : 
     431           0 :       scaling_list(br, aDest.scaling_matrix8x8[0], Default_8x8_Intra,
     432           0 :                    Default_8x8_Intra);
     433           0 :       scaling_list(br, aDest.scaling_matrix8x8[1], Default_8x8_Inter,
     434           0 :                    Default_8x8_Inter);
     435           0 :       if (aDest.chroma_format_idc == 3) {
     436           0 :         scaling_list(br, aDest.scaling_matrix8x8[2], Default_8x8_Intra,
     437           0 :                      aDest.scaling_matrix8x8[0]);
     438           0 :         scaling_list(br, aDest.scaling_matrix8x8[3], Default_8x8_Inter,
     439           0 :                      aDest.scaling_matrix8x8[1]);
     440           0 :         scaling_list(br, aDest.scaling_matrix8x8[4], Default_8x8_Intra,
     441           0 :                      aDest.scaling_matrix8x8[2]);
     442           0 :         scaling_list(br, aDest.scaling_matrix8x8[5], Default_8x8_Inter,
     443           0 :                      aDest.scaling_matrix8x8[3]);
     444             :       }
     445           0 :     }
     446           0 :   } else if (aDest.profile_idc == 183) {
     447           0 :     aDest.chroma_format_idc = 0;
     448             :   } else {
     449             :     // default value if chroma_format_idc isn't set.
     450           0 :     aDest.chroma_format_idc = 1;
     451             :   }
     452           0 :   READUE(log2_max_frame_num, 12);
     453           0 :   aDest.log2_max_frame_num += 4;
     454           0 :   READUE(pic_order_cnt_type, 2);
     455           0 :   if (aDest.pic_order_cnt_type == 0) {
     456           0 :     READUE(log2_max_pic_order_cnt_lsb, 12);
     457           0 :     aDest.log2_max_pic_order_cnt_lsb += 4;
     458           0 :   } else if (aDest.pic_order_cnt_type == 1) {
     459           0 :     aDest.delta_pic_order_always_zero_flag = br.ReadBit();
     460           0 :     READSE(offset_for_non_ref_pic, -231, 230);
     461           0 :     READSE(offset_for_top_to_bottom_field, -231, 230);
     462           0 :     uint32_t num_ref_frames_in_pic_order_cnt_cycle = br.ReadUE();
     463           0 :     for (uint32_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
     464           0 :       br.ReadSE(); // offset_for_ref_frame[i]
     465             :     }
     466             :   }
     467           0 :   aDest.max_num_ref_frames = br.ReadUE();
     468           0 :   aDest.gaps_in_frame_num_allowed_flag = br.ReadBit();
     469           0 :   aDest.pic_width_in_mbs = br.ReadUE() + 1;
     470           0 :   aDest.pic_height_in_map_units = br.ReadUE() + 1;
     471           0 :   aDest.frame_mbs_only_flag = br.ReadBit();
     472           0 :   if (!aDest.frame_mbs_only_flag) {
     473           0 :     aDest.pic_height_in_map_units *= 2;
     474           0 :     aDest.mb_adaptive_frame_field_flag = br.ReadBit();
     475             :   }
     476           0 :   aDest.direct_8x8_inference_flag = br.ReadBit();
     477           0 :   aDest.frame_cropping_flag = br.ReadBit();
     478           0 :   if (aDest.frame_cropping_flag) {
     479           0 :     aDest.frame_crop_left_offset = br.ReadUE();
     480           0 :     aDest.frame_crop_right_offset = br.ReadUE();
     481           0 :     aDest.frame_crop_top_offset = br.ReadUE();
     482           0 :     aDest.frame_crop_bottom_offset = br.ReadUE();
     483             :   }
     484             : 
     485           0 :   aDest.sample_ratio = 1.0f;
     486           0 :   aDest.vui_parameters_present_flag = br.ReadBit();
     487           0 :   if (aDest.vui_parameters_present_flag) {
     488           0 :     if (!vui_parameters(br, aDest)) {
     489           0 :       return false;
     490             :     }
     491             :   }
     492             : 
     493             :   // Calculate common values.
     494             : 
     495             :   uint8_t ChromaArrayType =
     496           0 :     aDest.separate_colour_plane_flag ? 0 : aDest.chroma_format_idc;
     497             :   // Calculate width.
     498           0 :   uint32_t CropUnitX = 1;
     499           0 :   uint32_t SubWidthC = aDest.chroma_format_idc == 3 ? 1 : 2;
     500           0 :   if (ChromaArrayType != 0) {
     501           0 :     CropUnitX = SubWidthC;
     502             :   }
     503             : 
     504             :   // Calculate Height
     505           0 :   uint32_t CropUnitY = 2 - aDest.frame_mbs_only_flag;
     506           0 :   uint32_t SubHeightC = aDest.chroma_format_idc <= 1 ? 2 : 1;
     507           0 :   if (ChromaArrayType != 0) {
     508           0 :     CropUnitY *= SubHeightC;
     509             :   }
     510             : 
     511           0 :   uint32_t width = aDest.pic_width_in_mbs * 16;
     512           0 :   uint32_t height = aDest.pic_height_in_map_units * 16;
     513           0 :   if (aDest.frame_crop_left_offset <= std::numeric_limits<int32_t>::max() / 4 / CropUnitX &&
     514           0 :       aDest.frame_crop_right_offset <= std::numeric_limits<int32_t>::max() / 4 / CropUnitX &&
     515           0 :       aDest.frame_crop_top_offset <= std::numeric_limits<int32_t>::max() / 4 / CropUnitY &&
     516           0 :       aDest.frame_crop_bottom_offset <= std::numeric_limits<int32_t>::max() / 4 / CropUnitY &&
     517           0 :       (aDest.frame_crop_left_offset + aDest.frame_crop_right_offset) * CropUnitX < width &&
     518           0 :       (aDest.frame_crop_top_offset + aDest.frame_crop_bottom_offset) * CropUnitY < height) {
     519           0 :     aDest.crop_left = aDest.frame_crop_left_offset * CropUnitX;
     520           0 :     aDest.crop_right = aDest.frame_crop_right_offset * CropUnitX;
     521           0 :     aDest.crop_top = aDest.frame_crop_top_offset * CropUnitY;
     522           0 :     aDest.crop_bottom = aDest.frame_crop_bottom_offset * CropUnitY;
     523             :   } else {
     524             :     // Nonsensical value, ignore them.
     525           0 :     aDest.crop_left = aDest.crop_right = aDest.crop_top = aDest.crop_bottom = 0;
     526             :   }
     527             : 
     528           0 :   aDest.pic_width = width - aDest.crop_left - aDest.crop_right;
     529           0 :   aDest.pic_height = height - aDest.crop_top - aDest.crop_bottom;
     530             : 
     531           0 :   aDest.interlaced = !aDest.frame_mbs_only_flag;
     532             : 
     533             :   // Determine display size.
     534           0 :   if (aDest.sample_ratio > 1.0) {
     535             :     // Increase the intrinsic width
     536           0 :     aDest.display_width =
     537           0 :       ConditionDimension(aDest.pic_width * aDest.sample_ratio);
     538           0 :     aDest.display_height = aDest.pic_height;
     539             :   } else {
     540             :     // Increase the intrinsic height
     541           0 :     aDest.display_width = aDest.pic_width;
     542           0 :     aDest.display_height =
     543           0 :       ConditionDimension(aDest.pic_height / aDest.sample_ratio);
     544             :   }
     545             : 
     546           0 :   aDest.valid = true;
     547             : 
     548           0 :   return true;
     549             : }
     550             : 
     551             : /* static */ bool
     552           0 : H264::vui_parameters(BitReader& aBr, SPSData& aDest)
     553             : {
     554           0 :   aDest.aspect_ratio_info_present_flag = aBr.ReadBit();
     555           0 :   if (aDest.aspect_ratio_info_present_flag) {
     556           0 :     aDest.aspect_ratio_idc = aBr.ReadBits(8);
     557           0 :     aDest.sar_width = aDest.sar_height = 0;
     558             : 
     559             :     // From E.2.1 VUI parameters semantics (ITU-T H.264 02/2014)
     560           0 :     switch (aDest.aspect_ratio_idc) {
     561             :       case 0:
     562             :         // Unspecified
     563           0 :         break;
     564             :       case 1:
     565             :         /*
     566             :           1:1
     567             :          7680x4320 16:9 frame without horizontal overscan
     568             :          3840x2160 16:9 frame without horizontal overscan
     569             :          1280x720 16:9 frame without horizontal overscan
     570             :          1920x1080 16:9 frame without horizontal overscan (cropped from 1920x1088)
     571             :          640x480 4:3 frame without horizontal overscan
     572             :          */
     573           0 :         aDest.sample_ratio = 1.0f;
     574           0 :         break;
     575             :       case 2:
     576             :         /*
     577             :           12:11
     578             :          720x576 4:3 frame with horizontal overscan
     579             :          352x288 4:3 frame without horizontal overscan
     580             :          */
     581           0 :         aDest.sample_ratio = 12.0 / 11.0;
     582           0 :         break;
     583             :       case 3:
     584             :         /*
     585             :           10:11
     586             :          720x480 4:3 frame with horizontal overscan
     587             :          352x240 4:3 frame without horizontal overscan
     588             :          */
     589           0 :         aDest.sample_ratio = 10.0 / 11.0;
     590           0 :         break;
     591             :       case 4:
     592             :         /*
     593             :           16:11
     594             :          720x576 16:9 frame with horizontal overscan
     595             :          528x576 4:3 frame without horizontal overscan
     596             :          */
     597           0 :         aDest.sample_ratio = 16.0 / 11.0;
     598           0 :         break;
     599             :       case 5:
     600             :         /*
     601             :           40:33
     602             :          720x480 16:9 frame with horizontal overscan
     603             :          528x480 4:3 frame without horizontal overscan
     604             :          */
     605           0 :         aDest.sample_ratio = 40.0 / 33.0;
     606           0 :         break;
     607             :       case 6:
     608             :         /*
     609             :           24:11
     610             :          352x576 4:3 frame without horizontal overscan
     611             :          480x576 16:9 frame with horizontal overscan
     612             :          */
     613           0 :         aDest.sample_ratio = 24.0 / 11.0;
     614           0 :         break;
     615             :       case 7:
     616             :         /*
     617             :           20:11
     618             :          352x480 4:3 frame without horizontal overscan
     619             :          480x480 16:9 frame with horizontal overscan
     620             :          */
     621           0 :         aDest.sample_ratio = 20.0 / 11.0;
     622           0 :         break;
     623             :       case 8:
     624             :         /*
     625             :           32:11
     626             :          352x576 16:9 frame without horizontal overscan
     627             :          */
     628           0 :         aDest.sample_ratio = 32.0 / 11.0;
     629           0 :         break;
     630             :       case 9:
     631             :         /*
     632             :           80:33
     633             :          352x480 16:9 frame without horizontal overscan
     634             :          */
     635           0 :         aDest.sample_ratio = 80.0 / 33.0;
     636           0 :         break;
     637             :       case 10:
     638             :         /*
     639             :           18:11
     640             :          480x576 4:3 frame with horizontal overscan
     641             :          */
     642           0 :         aDest.sample_ratio = 18.0 / 11.0;
     643           0 :         break;
     644             :       case 11:
     645             :         /*
     646             :           15:11
     647             :          480x480 4:3 frame with horizontal overscan
     648             :          */
     649           0 :         aDest.sample_ratio = 15.0 / 11.0;
     650           0 :         break;
     651             :       case 12:
     652             :         /*
     653             :           64:33
     654             :          528x576 16:9 frame with horizontal overscan
     655             :          */
     656           0 :         aDest.sample_ratio = 64.0 / 33.0;
     657           0 :         break;
     658             :       case 13:
     659             :         /*
     660             :           160:99
     661             :          528x480 16:9 frame without horizontal overscan
     662             :          */
     663           0 :         aDest.sample_ratio = 160.0 / 99.0;
     664           0 :         break;
     665             :       case 14:
     666             :         /*
     667             :           4:3
     668             :          1440x1080 16:9 frame without horizontal overscan
     669             :          */
     670           0 :         aDest.sample_ratio = 4.0 / 3.0;
     671           0 :         break;
     672             :       case 15:
     673             :         /*
     674             :           3:2
     675             :          1280x1080 16:9 frame without horizontal overscan
     676             :          */
     677           0 :         aDest.sample_ratio = 3.2 / 2.0;
     678           0 :         break;
     679             :       case 16:
     680             :         /*
     681             :           2:1
     682             :          960x1080 16:9 frame without horizontal overscan
     683             :          */
     684           0 :         aDest.sample_ratio = 2.0 / 1.0;
     685           0 :         break;
     686             :       case 255:
     687             :         /* Extended_SAR */
     688           0 :         aDest.sar_width = aBr.ReadBits(16);
     689           0 :         aDest.sar_height = aBr.ReadBits(16);
     690           0 :         if (aDest.sar_width && aDest.sar_height) {
     691           0 :           aDest.sample_ratio = float(aDest.sar_width) / float(aDest.sar_height);
     692             :         }
     693           0 :         break;
     694             :       default:
     695           0 :         break;
     696             :     }
     697             :   }
     698             : 
     699           0 :   if (aBr.ReadBit()) { //overscan_info_present_flag
     700           0 :     aDest.overscan_appropriate_flag = aBr.ReadBit();
     701             :   }
     702             : 
     703           0 :   if (aBr.ReadBit()) { // video_signal_type_present_flag
     704           0 :     aDest.video_format = aBr.ReadBits(3);
     705           0 :     aDest.video_full_range_flag = aBr.ReadBit();
     706           0 :     aDest.colour_description_present_flag = aBr.ReadBit();
     707           0 :     if (aDest.colour_description_present_flag) {
     708           0 :       aDest.colour_primaries = aBr.ReadBits(8);
     709           0 :       aDest.transfer_characteristics = aBr.ReadBits(8);
     710           0 :       aDest.matrix_coefficients = aBr.ReadBits(8);
     711             :     }
     712             :   }
     713             : 
     714           0 :   aDest.chroma_loc_info_present_flag = aBr.ReadBit();
     715           0 :   if (aDest.chroma_loc_info_present_flag) {
     716           0 :     BitReader& br = aBr; // so that macro READUE works
     717           0 :     READUE(chroma_sample_loc_type_top_field, 5);
     718           0 :     READUE(chroma_sample_loc_type_bottom_field, 5);
     719             :   }
     720             : 
     721           0 :   bool timing_info_present_flag = aBr.ReadBit();
     722           0 :   if (timing_info_present_flag) {
     723           0 :     aBr.ReadBits(32); // num_units_in_tick
     724           0 :     aBr.ReadBits(32); // time_scale
     725           0 :     aBr.ReadBit(); // fixed_frame_rate_flag
     726             :   }
     727           0 :   return true;
     728             : }
     729             : 
     730             : /* static */ bool
     731           0 : H264::DecodeSPSFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
     732             :                              SPSData& aDest)
     733             : {
     734           0 :   SPSNALIterator it(aExtraData);
     735           0 :   if (!it) {
     736           0 :     return false;
     737             :   }
     738           0 :   return (*it).GetSPSData(aDest);
     739             : }
     740             : 
     741             : /* static */ bool
     742           0 : H264::EnsureSPSIsSane(SPSData& aSPS)
     743             : {
     744           0 :   bool valid = true;
     745             :   static const float default_aspect = 4.0f / 3.0f;
     746           0 :   if (aSPS.sample_ratio <= 0.0f || aSPS.sample_ratio > 6.0f) {
     747           0 :     if (aSPS.pic_width && aSPS.pic_height) {
     748           0 :       aSPS.sample_ratio = (float)aSPS.pic_width / (float)aSPS.pic_height;
     749             :     } else {
     750           0 :       aSPS.sample_ratio = default_aspect;
     751             :     }
     752           0 :     aSPS.display_width = aSPS.pic_width;
     753           0 :     aSPS.display_height = aSPS.pic_height;
     754           0 :     valid = false;
     755             :   }
     756           0 :   if (aSPS.max_num_ref_frames > 16) {
     757           0 :     aSPS.max_num_ref_frames = 16;
     758           0 :     valid = false;
     759             :   }
     760           0 :   return valid;
     761             : }
     762             : 
     763             : /* static */ uint32_t
     764           0 : H264::ComputeMaxRefFrames(const mozilla::MediaByteBuffer* aExtraData)
     765             : {
     766           0 :   uint32_t maxRefFrames = 4;
     767             :   // Retrieve video dimensions from H264 SPS NAL.
     768           0 :   SPSData spsdata;
     769           0 :   if (DecodeSPSFromExtraData(aExtraData, spsdata)) {
     770             :     // max_num_ref_frames determines the size of the sliding window
     771             :     // we need to queue that many frames in order to guarantee proper
     772             :     // pts frames ordering. Use a minimum of 4 to ensure proper playback of
     773             :     // non compliant videos.
     774           0 :     maxRefFrames =
     775           0 :       std::min(std::max(maxRefFrames, spsdata.max_num_ref_frames + 1), 16u);
     776             :   }
     777           0 :   return maxRefFrames;
     778             : }
     779             : 
     780             : /* static */ H264::FrameType
     781           0 : H264::GetFrameType(const mozilla::MediaRawData* aSample)
     782             : {
     783           0 :   if (!AnnexB::IsAVCC(aSample)) {
     784             :     // We must have a valid AVCC frame with extradata.
     785           0 :     return FrameType::INVALID;
     786             :   }
     787           0 :   MOZ_ASSERT(aSample->Data());
     788             : 
     789           0 :   int nalLenSize = ((*aSample->mExtraData)[4] & 3) + 1;
     790             : 
     791           0 :   ByteReader reader(aSample->Data(), aSample->Size());
     792             : 
     793           0 :   while (reader.Remaining() >= nalLenSize) {
     794             :     uint32_t nalLen;
     795           0 :     switch (nalLenSize) {
     796           0 :       case 1: nalLen = reader.ReadU8();  break;
     797           0 :       case 2: nalLen = reader.ReadU16(); break;
     798           0 :       case 3: nalLen = reader.ReadU24(); break;
     799           0 :       case 4: nalLen = reader.ReadU32(); break;
     800             :     }
     801           0 :     if (!nalLen) {
     802           0 :       continue;
     803             :     }
     804           0 :     const uint8_t* p = reader.Read(nalLen);
     805           0 :     if (!p) {
     806           0 :       return FrameType::INVALID;
     807             :     }
     808           0 :     if ((p[0] & 0x1f) == H264_NAL_IDR_SLICE) {
     809             :       // IDR NAL.
     810           0 :       return FrameType::I_FRAME;
     811             :     }
     812             :   }
     813             : 
     814           0 :   return FrameType::OTHER;
     815             : }
     816             : 
     817             : /* static */ already_AddRefed<mozilla::MediaByteBuffer>
     818           0 : H264::ExtractExtraData(const mozilla::MediaRawData* aSample)
     819             : {
     820           0 :   MOZ_ASSERT(AnnexB::IsAVCC(aSample));
     821             : 
     822           0 :   RefPtr<mozilla::MediaByteBuffer> extradata = new mozilla::MediaByteBuffer;
     823             : 
     824             :   // SPS content
     825           0 :   nsTArray<uint8_t> sps;
     826           0 :   ByteWriter spsw(sps);
     827           0 :   int numSps = 0;
     828             :   // PPS content
     829           0 :   nsTArray<uint8_t> pps;
     830           0 :   ByteWriter ppsw(pps);
     831           0 :   int numPps = 0;
     832             : 
     833           0 :   int nalLenSize = ((*aSample->mExtraData)[4] & 3) + 1;
     834             : 
     835           0 :   size_t sampleSize = aSample->Size();
     836           0 :   if (aSample->mCrypto.mValid) {
     837             :     // The content is encrypted, we can only parse the non-encrypted data.
     838           0 :     MOZ_ASSERT(aSample->mCrypto.mPlainSizes.Length() > 0);
     839           0 :     if (aSample->mCrypto.mPlainSizes.Length() == 0 ||
     840           0 :         aSample->mCrypto.mPlainSizes[0] > sampleSize) {
     841             :       // This is invalid content.
     842           0 :       return nullptr;
     843             :     }
     844           0 :     sampleSize = aSample->mCrypto.mPlainSizes[0];
     845             :   }
     846             : 
     847           0 :   ByteReader reader(aSample->Data(), sampleSize);
     848             : 
     849           0 :   nsTArray<SPSData> SPSTable(MAX_SPS_COUNT);
     850           0 :   SPSTable.SetLength(MAX_SPS_COUNT);
     851             :   // If we encounter SPS with the same id but different content, we will stop
     852             :   // attempting to detect duplicates.
     853           0 :   bool checkDuplicate = true;
     854             : 
     855             :   // Find SPS and PPS NALUs in AVCC data
     856           0 :   while (reader.Remaining() > nalLenSize) {
     857             :     uint32_t nalLen;
     858           0 :     switch (nalLenSize) {
     859           0 :       case 1: nalLen = reader.ReadU8();  break;
     860           0 :       case 2: nalLen = reader.ReadU16(); break;
     861           0 :       case 3: nalLen = reader.ReadU24(); break;
     862           0 :       case 4: nalLen = reader.ReadU32(); break;
     863             :     }
     864           0 :     const uint8_t* p = reader.Read(nalLen);
     865           0 :     if (!p) {
     866           0 :       return extradata.forget();
     867             :     }
     868           0 :     uint8_t nalType = *p & 0x1f;
     869             : 
     870           0 :     if (nalType == H264_NAL_SPS) {
     871           0 :       RefPtr<mozilla::MediaByteBuffer> sps = DecodeNALUnit(p, nalLen);
     872           0 :       SPSData data;
     873           0 :       if (!DecodeSPS(sps, data)) {
     874             :         // Invalid SPS, ignore.
     875           0 :         continue;
     876             :       }
     877           0 :       uint8_t spsId = data.seq_parameter_set_id;
     878           0 :       if (checkDuplicate && SPSTable[spsId].valid && SPSTable[spsId] == data) {
     879             :         // Duplicate ignore.
     880           0 :         continue;
     881             :       }
     882           0 :       if (SPSTable[spsId].valid) {
     883             :         // We already have detected a SPS with this Id. Just to be safe we
     884             :         // disable SPS duplicate detection.
     885           0 :         checkDuplicate = false;
     886             :       } else {
     887           0 :         SPSTable[spsId] = data;
     888             :       }
     889           0 :       numSps++;
     890           0 :       if (!spsw.WriteU16(nalLen)
     891           0 :           || !spsw.Write(p, nalLen)) {
     892           0 :         return extradata.forget();
     893             :       }
     894           0 :     } else if (nalType == H264_NAL_PPS) {
     895           0 :       numPps++;
     896           0 :       if (!ppsw.WriteU16(nalLen)
     897           0 :           || !ppsw.Write(p, nalLen)) {
     898           0 :         return extradata.forget();
     899             :       }
     900             :     }
     901             :   }
     902             : 
     903             :   // We ignore PPS data if we didn't find a SPS as we would be unable to
     904             :   // decode it anyway.
     905           0 :   numPps = numSps ? numPps : 0;
     906             : 
     907           0 :   if (numSps && sps.Length() > 5) {
     908           0 :     extradata->AppendElement(1);        // version
     909           0 :     extradata->AppendElement(sps[3]);   // profile
     910           0 :     extradata->AppendElement(sps[4]);   // profile compat
     911           0 :     extradata->AppendElement(sps[5]);   // level
     912           0 :     extradata->AppendElement(0xfc | 3); // nal size - 1
     913           0 :     extradata->AppendElement(0xe0 | numSps);
     914           0 :     extradata->AppendElements(sps.Elements(), sps.Length());
     915           0 :     extradata->AppendElement(numPps);
     916           0 :     if (numPps) {
     917           0 :       extradata->AppendElements(pps.Elements(), pps.Length());
     918             :     }
     919             :   }
     920             : 
     921           0 :   return extradata.forget();
     922             : }
     923             : 
     924             : /* static */ bool
     925           0 : H264::HasSPS(const mozilla::MediaByteBuffer* aExtraData)
     926             : {
     927           0 :   return NumSPS(aExtraData) > 0;
     928             : }
     929             : 
     930             : /* static */ uint8_t
     931           0 : H264::NumSPS(const mozilla::MediaByteBuffer* aExtraData)
     932             : {
     933           0 :   if (!aExtraData) {
     934           0 :     return 0;
     935             :   }
     936             : 
     937           0 :   ByteReader reader(aExtraData);
     938           0 :   const uint8_t* ptr = reader.Read(5);
     939           0 :   if (!ptr || !reader.CanRead8()) {
     940           0 :     return 0;
     941             :   }
     942           0 :   return reader.ReadU8() & 0x1f;
     943             : }
     944             : 
     945             : /* static */ bool
     946           0 : H264::CompareExtraData(const mozilla::MediaByteBuffer* aExtraData1,
     947             :                        const mozilla::MediaByteBuffer* aExtraData2)
     948             : {
     949           0 :   if (aExtraData1 == aExtraData2) {
     950           0 :     return true;
     951             :   }
     952           0 :   uint8_t numSPS = NumSPS(aExtraData1);
     953           0 :   if (numSPS == 0 || numSPS != NumSPS(aExtraData2)) {
     954           0 :     return false;
     955             :   }
     956             : 
     957             :   // We only compare if the SPS are the same as the various H264 decoders can
     958             :   // deal with in-band change of PPS.
     959             : 
     960           0 :   SPSNALIterator it1(aExtraData1);
     961           0 :   SPSNALIterator it2(aExtraData2);
     962             : 
     963           0 :   while (it1 && it2) {
     964           0 :     if (*it1 != *it2) {
     965           0 :       return false;
     966             :     }
     967           0 :     ++it1;
     968           0 :     ++it2;
     969             :   }
     970           0 :   return true;
     971             : }
     972             : 
     973             : #undef READUE
     974             : #undef READSE
     975             : 
     976             : } // namespace mp4_demuxer

Generated by: LCOV version 1.13