Bug 1300296: P1. Add method to determine if an H264 frame is an I-Frame. r?jesup
We do so by checking the frame data for NAL of type 5 as per ISO IEC 14496-2.
MozReview-Commit-ID: JFeLysrZ6aG
--- a/media/libstagefright/binding/H264.cpp
+++ b/media/libstagefright/binding/H264.cpp
@@ -483,9 +483,46 @@ H264::ComputeMaxRefFrames(const mozilla:
// pts frames ordering. Use a minimum of 4 to ensure proper playback of
// non compliant videos.
maxRefFrames =
std::min(std::max(maxRefFrames, spsdata.max_num_ref_frames + 1), 16u);
}
return maxRefFrames;
}
+/* static */ H264::FrameType
+H264::GetFrameType(const mozilla::MediaRawData* aSample)
+{
+ if (!AnnexB::IsAVCC(aSample)) {
+ // We must have a valid AVCC frame with extradata.
+ return FrameType::INVALID;
+ }
+ MOZ_ASSERT(aSample->Data());
+
+ int nalLenSize = ((*aSample->mExtraData)[4] & 3) + 1;
+
+ ByteReader reader(aSample->Data(), aSample->Size());
+
+ 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;
+ }
+ if (!nalLen) {
+ continue;
+ }
+ const uint8_t* p = reader.Read(nalLen);
+ if (!p) {
+ return FrameType::INVALID;
+ }
+ if ((p[0] & 0x1f) == 5) {
+ // IDR NAL.
+ return FrameType::I_FRAME;
+ }
+ }
+
+ return FrameType::OTHER;
+}
+
} // namespace mp4_demuxer
--- a/media/libstagefright/binding/include/mp4_demuxer/H264.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/H264.h
@@ -345,16 +345,27 @@ public:
// 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);
// 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.
static uint32_t ComputeMaxRefFrames(const mozilla::MediaByteBuffer* aExtraData);
+ enum class FrameType
+ {
+ I_FRAME,
+ OTHER,
+ INVALID,
+ };
+
+ // Returns the frame type. Returns I_FRAME if the sample is an IDR
+ // (Instantaneous Decoding Refresh) Picture.
+ static FrameType GetFrameType(const mozilla::MediaRawData* aSample);
+
private:
static void vui_parameters(BitReader& aBr, SPSData& aDest);
// Read HRD parameters, all data is ignored.
static void hrd_parameters(BitReader& aBr);
};
} // namespace mp4_demuxer