Record H264 NALU type in the h264 header.

BUG=
R=niklas.enbom@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/48999004

Cr-Commit-Position: refs/heads/master@{#9072}
diff --git a/webrtc/modules/interface/module_common_types.h b/webrtc/modules/interface/module_common_types.h
index dc86176..825d7e6 100644
--- a/webrtc/modules/interface/module_common_types.h
+++ b/webrtc/modules/interface/module_common_types.h
@@ -61,9 +61,25 @@
                               // in a VP8 partition. Otherwise false
 };
 
+// The packetization types that we support: single, aggregated, and fragmented.
+enum H264PacketizationTypes {
+  kH264SingleNalu,  // This packet contains a single NAL unit.
+  kH264StapA,       // This packet contains STAP-A (single time
+                    // aggregation) packets. If this packet has an
+                    // associated NAL unit type, it'll be for the
+                    // first such aggregated packet.
+  kH264FuA,         // This packet contains a FU-A (fragmentation
+                    // unit) packet, meaning it is a part of a frame
+                    // that was too large to fit into a single packet.
+};
+
 struct RTPVideoHeaderH264 {
-  bool stap_a;
-  bool single_nalu;
+  uint8_t nalu_type;  // The NAL unit type. If this is a header for a
+                      // fragmented packet, it's the NAL unit type of
+                      // the original data. If this is the header for an
+                      // aggregated packet, it's the NAL unit type of
+                      // the first NAL unit in the packet.
+  H264PacketizationTypes packetization_type;
 };
 
 union RTPVideoTypeHeader {
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc
index 6568c38..e297b7c 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc
@@ -46,14 +46,15 @@
   parsed_payload->type.Video.isFirstPacket = true;
   RTPVideoHeaderH264* h264_header =
       &parsed_payload->type.Video.codecHeader.H264;
-  h264_header->single_nalu = true;
-  h264_header->stap_a = false;
 
   uint8_t nal_type = payload_data[0] & kTypeMask;
   if (nal_type == kStapA) {
     nal_type = payload_data[3] & kTypeMask;
-    h264_header->stap_a = true;
+    h264_header->packetization_type = kH264StapA;
+  } else {
+    h264_header->packetization_type = kH264SingleNalu;
   }
+  h264_header->nalu_type = nal_type;
 
   switch (nal_type) {
     case kSps:
@@ -95,8 +96,8 @@
   parsed_payload->type.Video.isFirstPacket = first_fragment;
   RTPVideoHeaderH264* h264_header =
       &parsed_payload->type.Video.codecHeader.H264;
-  h264_header->single_nalu = false;
-  h264_header->stap_a = false;
+  h264_header->packetization_type = kH264FuA;
+  h264_header->nalu_type = original_nal_type;
 }
 }  // namespace
 
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
index caae400..5ccd853 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
@@ -207,9 +207,9 @@
 TEST(RtpPacketizerH264Test, TestStapA) {
   const size_t kFrameSize =
       kMaxPayloadSize - 3 * kLengthFieldLength - kNalHeaderSize;
-  uint8_t frame[kFrameSize] = {0x07, 0xFF,  // F=0, NRI=0, Type=7.
-                               0x08, 0xFF,  // F=0, NRI=0, Type=8.
-                               0x05};       // F=0, NRI=0, Type=5.
+  uint8_t frame[kFrameSize] = {0x07, 0xFF,  // F=0, NRI=0, Type=7 (SPS).
+                               0x08, 0xFF,  // F=0, NRI=0, Type=8 (PPS).
+                               0x05};       // F=0, NRI=0, Type=5 (IDR).
   const size_t kPayloadOffset = 5;
   for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i)
     frame[i + kPayloadOffset] = i;
@@ -398,7 +398,7 @@
 };
 
 TEST_F(RtpDepacketizerH264Test, TestSingleNalu) {
-  uint8_t packet[2] = {0x05, 0xFF};  // F=0, NRI=0, Type=5.
+  uint8_t packet[2] = {0x05, 0xFF};  // F=0, NRI=0, Type=5 (IDR).
   RtpDepacketizer::ParsedPayload payload;
 
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
@@ -406,15 +406,17 @@
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kRtpVideoH264, payload.type.Video.codec);
   EXPECT_TRUE(payload.type.Video.isFirstPacket);
-  EXPECT_TRUE(payload.type.Video.codecHeader.H264.single_nalu);
-  EXPECT_FALSE(payload.type.Video.codecHeader.H264.stap_a);
+  EXPECT_EQ(kH264SingleNalu,
+            payload.type.Video.codecHeader.H264.packetization_type);
+  EXPECT_EQ(kIdr, payload.type.Video.codecHeader.H264.nalu_type);
 }
 
 TEST_F(RtpDepacketizerH264Test, TestStapAKey) {
   uint8_t packet[16] = {kStapA,  // F=0, NRI=0, Type=24.
                         // Length, nal header, payload.
-                        0,      0x02, kIdr, 0xFF, 0,    0x03, kIdr, 0xFF,
-                        0x00,   0,    0x04, kIdr, 0xFF, 0x00, 0x11};
+                        0, 0x02, kSps, 0xFF,
+                        0, 0x03, kPps, 0xFF, 0x00,
+                        0, 0x04, kIdr, 0xFF, 0x00, 0x11};
   RtpDepacketizer::ParsedPayload payload;
 
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
@@ -422,8 +424,9 @@
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kRtpVideoH264, payload.type.Video.codec);
   EXPECT_TRUE(payload.type.Video.isFirstPacket);
-  EXPECT_TRUE(payload.type.Video.codecHeader.H264.single_nalu);
-  EXPECT_TRUE(payload.type.Video.codecHeader.H264.stap_a);
+  EXPECT_EQ(kH264StapA, payload.type.Video.codecHeader.H264.packetization_type);
+  // NALU type for aggregated packets is the type of the first packet only.
+  EXPECT_EQ(kSps, payload.type.Video.codecHeader.H264.nalu_type);
 }
 
 TEST_F(RtpDepacketizerH264Test, TestStapADelta) {
@@ -438,8 +441,9 @@
   EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
   EXPECT_EQ(kRtpVideoH264, payload.type.Video.codec);
   EXPECT_TRUE(payload.type.Video.isFirstPacket);
-  EXPECT_TRUE(payload.type.Video.codecHeader.H264.single_nalu);
-  EXPECT_TRUE(payload.type.Video.codecHeader.H264.stap_a);
+  EXPECT_EQ(kH264StapA, payload.type.Video.codecHeader.H264.packetization_type);
+  // NALU type for aggregated packets is the type of the first packet only.
+  EXPECT_EQ(kSlice, payload.type.Video.codecHeader.H264.nalu_type);
 }
 
 TEST_F(RtpDepacketizerH264Test, TestFuA) {
@@ -473,8 +477,8 @@
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kRtpVideoH264, payload.type.Video.codec);
   EXPECT_TRUE(payload.type.Video.isFirstPacket);
-  EXPECT_FALSE(payload.type.Video.codecHeader.H264.single_nalu);
-  EXPECT_FALSE(payload.type.Video.codecHeader.H264.stap_a);
+  EXPECT_EQ(kH264FuA, payload.type.Video.codecHeader.H264.packetization_type);
+  EXPECT_EQ(kIdr, payload.type.Video.codecHeader.H264.nalu_type);
 
   // Following packets will be 2 bytes shorter since they will only be appended
   // onto the first packet.
@@ -484,8 +488,8 @@
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kRtpVideoH264, payload.type.Video.codec);
   EXPECT_FALSE(payload.type.Video.isFirstPacket);
-  EXPECT_FALSE(payload.type.Video.codecHeader.H264.single_nalu);
-  EXPECT_FALSE(payload.type.Video.codecHeader.H264.stap_a);
+  EXPECT_EQ(kH264FuA, payload.type.Video.codecHeader.H264.packetization_type);
+  EXPECT_EQ(kIdr, payload.type.Video.codecHeader.H264.nalu_type);
 
   payload = RtpDepacketizer::ParsedPayload();
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet3, sizeof(packet3)));
@@ -493,7 +497,7 @@
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kRtpVideoH264, payload.type.Video.codec);
   EXPECT_FALSE(payload.type.Video.isFirstPacket);
-  EXPECT_FALSE(payload.type.Video.codecHeader.H264.single_nalu);
-  EXPECT_FALSE(payload.type.Video.codecHeader.H264.stap_a);
+  EXPECT_EQ(kH264FuA, payload.type.Video.codecHeader.H264.packetization_type);
+  EXPECT_EQ(kIdr, payload.type.Video.codecHeader.H264.nalu_type);
 }
 }  // namespace webrtc
diff --git a/webrtc/modules/video_coding/main/source/packet.cc b/webrtc/modules/video_coding/main/source/packet.cc
index fb815c4..c9eb482 100644
--- a/webrtc/modules/video_coding/main/source/packet.cc
+++ b/webrtc/modules/video_coding/main/source/packet.cc
@@ -123,7 +123,7 @@
       if (isFirstPacket)
         insertStartCode = true;
 
-      if (videoHeader.codecHeader.H264.single_nalu) {
+      if (isFirstPacket && markerBit) {
         completeNALU = kNaluComplete;
       } else if (isFirstPacket) {
         completeNALU = kNaluStart;
diff --git a/webrtc/modules/video_coding/main/source/session_info.cc b/webrtc/modules/video_coding/main/source/session_info.cc
index 361c0a1..8eba432 100644
--- a/webrtc/modules/video_coding/main/source/session_info.cc
+++ b/webrtc/modules/video_coding/main/source/session_info.cc
@@ -136,7 +136,8 @@
   const size_t kH264NALHeaderLengthInBytes = 1;
   const size_t kLengthFieldLength = 2;
   if (packet.codecSpecificHeader.codec == kRtpVideoH264 &&
-      packet.codecSpecificHeader.codecHeader.H264.stap_a) {
+      packet.codecSpecificHeader.codecHeader.H264.packetization_type ==
+          kH264StapA) {
     size_t required_length = 0;
     const uint8_t* nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
     while (nalu_ptr < packet_buffer + packet.sizeBytes) {