Add boilerplate code for H.264.

R=mflodman@webrtc.org, niklas.enbom@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6603 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/common_types.h b/webrtc/common_types.h
index 6892a83..193e281 100644
--- a/webrtc/common_types.h
+++ b/webrtc/common_types.h
@@ -587,10 +587,24 @@
   }
 };
 
+// H264 specific.
+struct VideoCodecH264
+{
+    VideoCodecProfile profile;
+    bool           frameDroppingOn;
+    int            keyFrameInterval;
+    // These are NULL/0 if not externally negotiated.
+    const uint8_t* spsData;
+    size_t         spsLen;
+    const uint8_t* ppsData;
+    size_t         ppsLen;
+};
+
 // Video codec types
 enum VideoCodecType
 {
     kVideoCodecVP8,
+    kVideoCodecH264,
     kVideoCodecI420,
     kVideoCodecRED,
     kVideoCodecULPFEC,
@@ -601,6 +615,7 @@
 union VideoCodecUnion
 {
     VideoCodecVP8       VP8;
+    VideoCodecH264      H264;
 };
 
 
diff --git a/webrtc/engine_configurations.h b/webrtc/engine_configurations.h
index be858b8..e9f2309 100644
--- a/webrtc/engine_configurations.h
+++ b/webrtc/engine_configurations.h
@@ -51,6 +51,7 @@
 
 #define VIDEOCODEC_I420
 #define VIDEOCODEC_VP8
+#define VIDEOCODEC_H264
 
 // ============================================================================
 //                                 VoiceEngine
diff --git a/webrtc/modules/interface/module_common_types.h b/webrtc/modules/interface/module_common_types.h
index 2c94707..e37313c 100644
--- a/webrtc/modules/interface/module_common_types.h
+++ b/webrtc/modules/interface/module_common_types.h
@@ -75,14 +75,22 @@
   bool beginningOfPartition;  // True if this packet is the first
                               // in a VP8 partition. Otherwise false
 };
+
+struct RTPVideoHeaderH264 {
+  uint8_t nalu_header;
+  bool    single_nalu;
+};
+
 union RTPVideoTypeHeader {
   RTPVideoHeaderVP8 VP8;
+  RTPVideoHeaderH264 H264;
 };
 
 enum RtpVideoCodecTypes {
   kRtpVideoNone,
   kRtpVideoGeneric,
-  kRtpVideoVp8
+  kRtpVideoVp8,
+  kRtpVideoH264
 };
 struct RTPVideoHeader {
   uint16_t width;  // size
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
index db2e4cd..26db8f3 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
@@ -434,6 +434,8 @@
     RtpVideoCodecTypes videoType = kRtpVideoGeneric;
     if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) {
       videoType = kRtpVideoVp8;
+    } else if (ModuleRTPUtility::StringCompare(payloadName, "H264", 4)) {
+      videoType = kRtpVideoH264;
     } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
       videoType = kRtpVideoGeneric;
     } else if (ModuleRTPUtility::StringCompare(payloadName, "ULPFEC", 6)) {
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
index 5bb519f..2615991 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
@@ -113,6 +113,8 @@
       return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
     case kRtpVideoVp8:
       return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
+    case kRtpVideoH264:
+      assert(false);  // Not yet supported.
     case kRtpVideoNone:
       break;
   }
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
index 5d8ae16..e4138ff 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -90,6 +90,8 @@
   RtpVideoCodecTypes videoType = kRtpVideoGeneric;
   if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3)) {
     videoType = kRtpVideoVp8;
+  } else if (ModuleRTPUtility::StringCompare(payloadName, "H264", 4))  {
+    videoType = kRtpVideoH264;
   } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
     videoType = kRtpVideoGeneric;
   } else {
diff --git a/webrtc/modules/video_coding/main/interface/video_coding_defines.h b/webrtc/modules/video_coding/main/interface/video_coding_defines.h
index fab91af..c5f93cb 100644
--- a/webrtc/modules/video_coding/main/interface/video_coding_defines.h
+++ b/webrtc/modules/video_coding/main/interface/video_coding_defines.h
@@ -40,6 +40,7 @@
 #define VCM_ULPFEC_PAYLOAD_TYPE     97
 #define VCM_VP8_PAYLOAD_TYPE       100
 #define VCM_I420_PAYLOAD_TYPE      124
+#define VCM_H264_PAYLOAD_TYPE      127
 
 enum VCMVideoProtection {
   kProtectionNack,                // Both send-side and receive-side
diff --git a/webrtc/modules/video_coding/main/source/codec_database.cc b/webrtc/modules/video_coding/main/source/codec_database.cc
index e7a9d91..7e26bea 100644
--- a/webrtc/modules/video_coding/main/source/codec_database.cc
+++ b/webrtc/modules/video_coding/main/source/codec_database.cc
@@ -102,6 +102,30 @@
       return true;
     }
 #endif
+#ifdef VIDEOCODEC_H264
+    case VCM_H264_IDX: {
+      strncpy(settings->plName, "H264", 5);
+      settings->codecType = kVideoCodecH264;
+      // 96 to 127 dynamic payload types for video codecs.
+      settings->plType = VCM_H264_PAYLOAD_TYPE;
+      settings->startBitrate = 100;
+      settings->minBitrate = VCM_MIN_BITRATE;
+      settings->maxBitrate = 0;
+      settings->maxFramerate = VCM_DEFAULT_FRAME_RATE;
+      settings->width = VCM_DEFAULT_CODEC_WIDTH;
+      settings->height = VCM_DEFAULT_CODEC_HEIGHT;
+      settings->numberOfSimulcastStreams = 0;
+      settings->qpMax = 56;
+      settings->codecSpecific.H264.profile = kProfileBase;
+      settings->codecSpecific.H264.frameDroppingOn = true;
+      settings->codecSpecific.H264.keyFrameInterval = 3000;
+      settings->codecSpecific.H264.spsData = NULL;
+      settings->codecSpecific.H264.spsLen = 0;
+      settings->codecSpecific.H264.ppsData = NULL;
+      settings->codecSpecific.H264.ppsLen = 0;
+      return true;
+    }
+#endif
 #ifdef VIDEOCODEC_I420
     case VCM_I420_IDX: {
       strncpy(settings->plName, "I420", 5);
@@ -316,8 +340,7 @@
     case kVideoCodecVP8:
       if (memcmp(&new_send_codec.codecSpecific.VP8,
                  &send_codec_.codecSpecific.VP8,
-                 sizeof(new_send_codec.codecSpecific.VP8)) !=
-          0) {
+                 sizeof(new_send_codec.codecSpecific.VP8)) != 0) {
         return true;
       }
       break;
@@ -327,6 +350,12 @@
     case kVideoCodecI420:
     case kVideoCodecRED:
     case kVideoCodecULPFEC:
+    case kVideoCodecH264:
+      if (memcmp(&new_send_codec.codecSpecific.H264,
+                 &send_codec_.codecSpecific.H264,
+                 sizeof(new_send_codec.codecSpecific.H264)) != 0) {
+        return true;
+      }
       break;
     // Unknown codec type, reset just to be sure.
     case kVideoCodecUnknown:
@@ -619,6 +648,7 @@
       return new VCMGenericDecoder(*(new I420Decoder));
 #endif
     default:
+      LOG(LS_WARNING) << "No internal decoder of this type exists.";
       return NULL;
   }
 }
diff --git a/webrtc/modules/video_coding/main/source/internal_defines.h b/webrtc/modules/video_coding/main/source/internal_defines.h
index efc6d8d..1128312 100644
--- a/webrtc/modules/video_coding/main/source/internal_defines.h
+++ b/webrtc/modules/video_coding/main/source/internal_defines.h
@@ -39,10 +39,15 @@
 #else
   #define VCM_VP8_IDX VCM_NO_CODEC_IDX
 #endif
-#ifdef VIDEOCODEC_I420
-  #define VCM_I420_IDX VCM_VP8_IDX + 1
+#ifdef VIDEOCODEC_H264
+  #define VCM_H264_IDX VCM_VP8_IDX + 1
 #else
-  #define VCM_I420_IDX VCM_VP8_IDX
+  #define VCM_H264_IDX VCM_VP8_IDX
+#endif
+#ifdef VIDEOCODEC_I420
+  #define VCM_I420_IDX VCM_H264_IDX + 1
+#else
+  #define VCM_I420_IDX VCM_H264_IDX
 #endif
 #define VCM_NUM_VIDEO_CODECS_AVAILABLE VCM_I420_IDX + 1
 
diff --git a/webrtc/test/encoder_settings.cc b/webrtc/test/encoder_settings.cc
index 5193be6..9842d1e 100644
--- a/webrtc/test/encoder_settings.cc
+++ b/webrtc/test/encoder_settings.cc
@@ -59,9 +59,13 @@
 
   codec.plType = encoder_settings.payload_type;
   strcpy(codec.plName, encoder_settings.payload_name.c_str());
-  codec.codecType =
-      (encoder_settings.payload_name == "VP8" ? kVideoCodecVP8
-                                              : kVideoCodecGeneric);
+  if (encoder_settings.payload_name == "VP8") {
+    codec.codecType = kVideoCodecVP8;
+  } else if (encoder_settings.payload_name == "H264") {
+    codec.codecType = kVideoCodecH264;
+  } else {
+    codec.codecType = kVideoCodecGeneric;
+  }
 
   if (codec.codecType == kVideoCodecVP8) {
     codec.codecSpecific.VP8.resilience = kResilientStream;
@@ -73,6 +77,12 @@
     codec.codecSpecific.VP8.keyFrameInterval = 3000;
   }
 
+  if (codec.codecType == kVideoCodecH264) {
+    codec.codecSpecific.H264.profile = kProfileBase;
+    codec.codecSpecific.H264.frameDroppingOn = true;
+    codec.codecSpecific.H264.keyFrameInterval = 3000;
+  }
+
   codec.width = 320;
   codec.height = 180;
   codec.startBitrate = codec.minBitrate = codec.maxBitrate = 300;
diff --git a/webrtc/video/loopback.cc b/webrtc/video/loopback.cc
index ea65ebb..276f1d4 100644
--- a/webrtc/video/loopback.cc
+++ b/webrtc/video/loopback.cc
@@ -48,6 +48,9 @@
 
 DEFINE_int32(max_bitrate, 800, "Maximum video bitrate.");
 size_t MaxBitrate() { return static_cast<size_t>(FLAGS_max_bitrate); }
+
+DEFINE_string(codec, "VP8", "Video codec to use.");
+std::string Codec() { return static_cast<std::string>(FLAGS_codec); }
 }  // namespace flags
 
 static const uint32_t kSendSsrc = 0x654321;
@@ -72,10 +75,16 @@
   send_config.rtp.ssrcs.push_back(kSendSsrc);
 
   send_config.local_renderer = local_preview.get();
-
-  scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
+  scoped_ptr<VideoEncoder> encoder;
+  if (flags::Codec() == "VP8") {
+    encoder.reset(VP8Encoder::Create());
+  } else {
+    // Codec not supported.
+    assert(false && "Codec not supported!");
+    return;
+  }
   send_config.encoder_settings.encoder = encoder.get();
-  send_config.encoder_settings.payload_name = "VP8";
+  send_config.encoder_settings.payload_name = flags::Codec();
   send_config.encoder_settings.payload_type = 124;
   std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
   VideoStream* stream = &video_streams[0];
diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
index 188567c..fb1a46f 100644
--- a/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
+++ b/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
@@ -101,6 +101,9 @@
         case webrtc::kVideoCodecI420:
             ViETest::Log("\tcodecType: I420");
             break;
+        case webrtc::kVideoCodecH264:
+            ViETest::Log("\tcodecType: H264");
+            break;
         case webrtc::kVideoCodecRED:
             ViETest::Log("\tcodecType: RED");
             break;
diff --git a/webrtc/video_engine/vie_codec_impl.cc b/webrtc/video_engine/vie_codec_impl.cc
index 3ba56de..050958e 100644
--- a/webrtc/video_engine/vie_codec_impl.cc
+++ b/webrtc/video_engine/vie_codec_impl.cc
@@ -69,6 +69,18 @@
                    << ", qp max "
                    << codec.simulcastStream[idx].qpMax;
     }
+  } else if (codec.codecType == kVideoCodecH264) {
+    LOG(LS_INFO) << "H264 specific settings";
+    LOG(LS_INFO) << "profile: "
+                 <<  codec.codecSpecific.H264.profile
+                 << ", framedropping: "
+                 << codec.codecSpecific.H264.frameDroppingOn
+                 << ", keyFrameInterval: "
+                 << codec.codecSpecific.H264.keyFrameInterval
+                 << ", spslen: "
+                 << codec.codecSpecific.H264.spsLen
+                 << ", ppslen: "
+                 << codec.codecSpecific.H264.ppsLen;
   }
 }
 
@@ -629,7 +641,9 @@
   } else if ((video_codec.codecType == kVideoCodecVP8 &&
               strncmp(video_codec.plName, "VP8", 4) == 0) ||
              (video_codec.codecType == kVideoCodecI420 &&
-              strncmp(video_codec.plName, "I420", 4) == 0)) {
+              strncmp(video_codec.plName, "I420", 4) == 0) ||
+             (video_codec.codecType == kVideoCodecH264 &&
+              strncmp(video_codec.plName, "H264", 4) == 0)) {
     // OK.
   } else if (video_codec.codecType != kVideoCodecGeneric) {
     LOG(LS_ERROR) << "Codec type and name mismatch.";