Bug 985254: H264 RTP packetization imported from upstream patchset #10 r=jesup
authorRandell Jesup <rjesup@jesup.org>
Sat, 24 May 2014 18:28:00 -0400
changeset 204066 e88a722da07ec2c30240bd0f6475327686614124
parent 204065 4947f68a3c0da1fc4023fc890dba4649ab255a15
child 204067 5246ba3954b76a779c44a00695ddccc4913245fc
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs985254, 13399004
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 985254: H264 RTP packetization imported from upstream patchset #10 r=jesup https://webrtc-codereview.appspot.com/13399004/
media/webrtc/trunk/webrtc/build/common.gypi
media/webrtc/trunk/webrtc/common_types.h
media/webrtc/trunk/webrtc/modules/interface/module_common_types.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h
media/webrtc/trunk/webrtc/modules/video_coding/codecs/h264/include/h264.h
media/webrtc/trunk/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h
media/webrtc/trunk/webrtc/modules/video_coding/main/source/codec_database.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/source/encoded_frame.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/source/internal_defines.h
media/webrtc/trunk/webrtc/modules/video_coding/main/source/packet.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/source/session_info.cc
media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc
--- a/media/webrtc/trunk/webrtc/build/common.gypi
+++ b/media/webrtc/trunk/webrtc/build/common.gypi
@@ -39,31 +39,33 @@
       'build_with_chromium%': '<(build_with_chromium)',
       'build_with_libjingle%': '<(build_with_libjingle)',
       'webrtc_root%': '<(webrtc_root)',
       'apk_tests_path%': '<(apk_tests_path)',
       'import_isolate_path%': '<(import_isolate_path)',
       'modules_java_gyp_path%': '<(modules_java_gyp_path)',
 
       'webrtc_vp8_dir%': '<(webrtc_root)/modules/video_coding/codecs/vp8',
+      'webrtc_h264_dir%': '<(webrtc_root)/modules/video_coding/codecs/h264',
       'rbe_components_path%': '<(webrtc_root)/modules/remote_bitrate_estimator',
       'include_g711%': 1,
       'include_g722%': 1,
       'include_ilbc%': 1,
       'include_opus%': 1,
       'include_isac%': 1,
       'include_pcm16b%': 1,
     },
     'build_with_chromium%': '<(build_with_chromium)',
     'build_with_libjingle%': '<(build_with_libjingle)',
     'webrtc_root%': '<(webrtc_root)',
     'apk_tests_path%': '<(apk_tests_path)',
     'import_isolate_path%': '<(import_isolate_path)',
     'modules_java_gyp_path%': '<(modules_java_gyp_path)',
     'webrtc_vp8_dir%': '<(webrtc_vp8_dir)',
+    'webrtc_h264_dir%': '<(webrtc_h264_dir)',
 
     'include_g711%': '<(include_g711)',
     'include_g722%': '<(include_g722)',
     'include_ilbc%': '<(include_ilbc)',
     'include_opus%': '<(include_opus)',
     'include_isac%': '<(include_isac)',
     'include_pcm16b%': '<(include_pcm16b)',
 
--- a/media/webrtc/trunk/webrtc/common_types.h
+++ b/media/webrtc/trunk/webrtc/common_types.h
@@ -506,19 +506,19 @@ struct VideoCodecVP8
 };
 
 // Unknown specific
 struct VideoCodecGeneric
 {
 };
 
 // Video codec types
-enum VideoCodecType
-{
+enum VideoCodecType {
     kVideoCodecVP8,
+    kVideoCodecH264,
     kVideoCodecI420,
     kVideoCodecRED,
     kVideoCodecULPFEC,
     kVideoCodecGeneric,
     kVideoCodecUnknown
 };
 
 union VideoCodecUnion
--- a/media/webrtc/trunk/webrtc/modules/interface/module_common_types.h
+++ b/media/webrtc/trunk/webrtc/modules/interface/module_common_types.h
@@ -84,27 +84,36 @@ struct RTPVideoHeaderVP8
     int8_t   temporalIdx;    // Temporal layer index, or kNoTemporalIdx.
     bool           layerSync;      // This frame is a layer sync frame.
                                    // Disabled if temporalIdx == kNoTemporalIdx.
     int            keyIdx;         // 5 bits; kNoKeyIdx means not used.
     int            partitionId;    // VP8 partition ID
     bool           beginningOfPartition;  // True if this packet is the first
                                           // in a VP8 partition. Otherwise false
 };
+
+struct RTPVideoHeaderH264 {
+  unsigned char nalu_header;
+  bool          single_nalu;
+};
+
 union RTPVideoTypeHeader
 {
     RTPVideoHeaderVP8       VP8;
+    RTPVideoHeaderH264 H264;
 };
 
 enum RtpVideoCodecTypes
 {
     kRtpVideoNone,
     kRtpVideoGeneric,
-    kRtpVideoVp8
+    kRtpVideoVp8,
+    kRtpVideoH264,
 };
+
 struct RTPVideoHeader
 {
     uint16_t          width;                  // size
     uint16_t          height;
 
     bool                    isFirstPacket;   // first packet in frame
     uint8_t           simulcastIdx;    // Index if the simulcast encoder creating
                                              // this frame, 0 if not using simulcast.
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc
@@ -0,0 +1,101 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string.h>  // memcpy
+
+#include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+RtpFormatH264::RtpFormatH264(const uint8_t* payload_data,
+                             uint32_t payload_size,
+                             int max_payload_len)
+    : payload_data_(payload_data),
+      payload_size_(static_cast<int>(payload_size)),
+      max_payload_len_(static_cast<int>(max_payload_len)),
+      fragments_(0),
+      fragment_size_(0),
+      next_fragment_(-1) {
+  if (payload_size_ <= max_payload_len_) {
+    fragments_ = 0;
+  } else {
+    fragment_size_ = max_payload_len_ - kH264FUAHeaderLengthInBytes;
+    fragments_ = (payload_size_ - kH264NALHeaderLengthInBytes) / fragment_size_;
+    if (fragments_ * fragment_size_ !=
+        (payload_size_ - kH264NALHeaderLengthInBytes)) {
+      ++fragments_;
+    }
+    next_fragment_ = 0;
+  }
+}
+
+RtpFormatH264::~RtpFormatH264() {
+}
+
+int RtpFormatH264::NextPacket(uint8_t* buffer,
+                              int* bytes_to_send,
+                              bool* last_packet) {
+  if (next_fragment_ == fragments_) {
+    *bytes_to_send = 0;
+    *last_packet   = true;
+    return -1;
+  }
+
+  if (payload_size_ <= max_payload_len_) {
+    // single NAL_UNIT
+    *bytes_to_send = payload_size_;
+    *last_packet   = false;
+    memcpy(buffer, payload_data_, payload_size_);
+    WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
+                 "RtpFormatH264(single NALU with type:%d, payload_size:%d",
+                 payload_data_[0] & 0x1F, payload_size_);
+    return 0;
+  } else {
+    unsigned char header = payload_data_[0];
+    unsigned char type   = header & 0x1F;
+    unsigned char fu_indicator = (header & 0xE0) | kH264FUANALUType;
+    unsigned char fu_header = 0;
+    bool first_fragment = (next_fragment_ == 0);
+    bool last_fragment = (next_fragment_ == (fragments_ -1));
+
+    // S | E | R | 5 bit type.
+    fu_header |= (first_fragment ? 128 : 0);  // S bit
+    fu_header |= (last_fragment ? 64 :0);  // E bit
+    fu_header |= type;
+    buffer[0] = fu_indicator;
+    buffer[1] = fu_header;
+
+    if (last_fragment) {
+      // last fragment
+      *bytes_to_send = payload_size_ -
+                       kH264NALHeaderLengthInBytes -
+                       next_fragment_ * fragment_size_ +
+                       kH264FUAHeaderLengthInBytes;
+      *last_packet   = true;
+      memcpy(buffer + kH264FUAHeaderLengthInBytes,
+             payload_data_ + kH264NALHeaderLengthInBytes +
+                next_fragment_ * fragment_size_,
+             *bytes_to_send - kH264FUAHeaderLengthInBytes);
+      // We do not send original NALU header
+    } else {
+      *bytes_to_send = fragment_size_ + kH264FUAHeaderLengthInBytes;
+      *last_packet   = false;
+      memcpy(buffer + kH264FUAHeaderLengthInBytes,
+             payload_data_ + kH264NALHeaderLengthInBytes +
+                 next_fragment_ * fragment_size_,
+             fragment_size_);  // We do not send original NALU header
+    }
+    next_fragment_++;
+    return 1;
+  }
+}
+
+}  // namespace webrtc
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h
@@ -0,0 +1,81 @@
+ /*
+  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+  *
+  *  Use of this source code is governed by a BSD-style license
+  *  that can be found in the LICENSE file in the root of the source
+  *  tree. An additional intellectual property rights grant can be found
+  *  in the file PATENTS.  All contributing project authors may
+  *  be found in the AUTHORS file in the root of the source tree.
+  */
+
+ /*
+  * This file contains the declaration of the H264 packetizer class.
+  * A packetizer object is created for each encoded video frame. The
+  * constructor is called with the payload data and size,
+  * together with the fragmentation information and a packetizer mode
+  * of choice. Alternatively, if no fragmentation info is available, the
+  * second constructor can be used with only payload data and size; in that
+  * case the mode kEqualSize is used.
+  *
+  * After creating the packetizer, the method NextPacket is called
+  * repeatedly to get all packets for the frame. The method returns
+  * false as long as there are more packets left to fetch.
+  */
+
+#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H264_H_
+#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H264_H_
+
+#include "webrtc/modules/interface/module_common_types.h"
+#include "webrtc/system_wrappers/interface/constructor_magic.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+// Packetizer for H264.
+class RtpFormatH264 {
+ public:
+  enum {
+    kH264NALHeaderLengthInBytes = 1,
+    kH264FUAHeaderLengthInBytes = 2,
+    kH264FUANALUType            = 28,
+    kH264NALU_SPS               = 7,
+    kH264NALU_PPS               = 8,
+    kH264NALU_IDR               = 5
+  };
+
+  // Initialize with payload from encoder.
+  // The payload_data must be exactly one encoded H264 frame.
+  RtpFormatH264(const uint8_t* payload_data,
+                uint32_t payload_size,
+                int max_payload_len);
+
+  ~RtpFormatH264();
+
+  // Get the next payload with H264 payload header.
+  // max_payload_len limits the sum length of payload and H264 payload header.
+  // buffer is a pointer to where the output will be written.
+  // bytes_to_send is an output variable that will contain number of bytes
+  // written to buffer. Parameter last_packet is true for the last packet of
+  // the frame, false otherwise (i.e., call the function again to get the
+  // next packet).
+  // Returns 0 on success for single NAL_UNIT
+  // Returns 1 on success for fragmentation
+  // return -1 on error.
+  int NextPacket(uint8_t* buffer,
+                 int* bytes_to_send,
+                 bool* last_packet);
+
+ private:
+  const uint8_t* payload_data_;
+  const int payload_size_;
+  const int max_payload_len_;
+  int   fragments_;
+  int   fragment_size_;
+  int   next_fragment_;
+
+  DISALLOW_COPY_AND_ASSIGN(RtpFormatH264);
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H264_H_
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
@@ -443,16 +443,18 @@ class RTPPayloadVideoStrategy : public R
       const char payloadName[RTP_PAYLOAD_NAME_SIZE],
       const int8_t payloadType,
       const uint32_t frequency,
       const uint8_t channels,
       const uint32_t rate) const OVERRIDE {
     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)) {
       videoType = kRtpVideoNone;
     } else {
       videoType = kRtpVideoGeneric;
     }
     ModuleRTPUtility::Payload* payload = new ModuleRTPUtility::Payload;
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
@@ -10,16 +10,17 @@
 
 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h"
 
 #include <assert.h>
 #include <string.h>
 
 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 #include "webrtc/system_wrappers/interface/trace_event.h"
 
 namespace webrtc {
 
 RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy(
@@ -119,16 +120,18 @@ int32_t RTPReceiverVideo::ParseVideoCode
                rtp_header->header.timestamp);
 
   switch (rtp_header->type.Video.codec) {
     case kRtpVideoGeneric:
       rtp_header->type.Video.isFirstPacket = is_first_packet;
       return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
     case kRtpVideoVp8:
       return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
+    case kRtpVideoH264:
+      return ReceiveH264Codec(rtp_header, payload_data, payload_data_length);
     case kRtpVideoNone:
       break;
   }
   return -1;
 }
 
 int32_t RTPReceiverVideo::BuildRTPheader(
     const WebRtcRTPHeader* rtp_header,
@@ -215,16 +218,86 @@ int32_t RTPReceiverVideo::ReceiveVp8Code
   if (data_callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data,
                                             parsed_packet.info.VP8.dataLength,
                                             rtp_header) != 0) {
     return -1;
   }
   return 0;
 }
 
+int32_t RTPReceiverVideo::ReceiveH264Codec(WebRtcRTPHeader* rtp_header,
+                                          const uint8_t* payload_data,
+                                          uint16_t payload_data_length) {
+  // real payload
+  uint8_t* payload;
+  uint16_t payload_length;
+  unsigned char nal_type = payload_data[0] & 0x1F;
+
+  // Note: This code handles only FU-A and single NALU mode packets.
+  if (nal_type == RtpFormatH264::kH264FUANALUType) {
+    // Fragmentation
+    unsigned char fnri = payload_data[0] & 0xE0;
+    unsigned char original_nal_type = payload_data[1] & 0x1F;
+    bool first_fragment = (payload_data[1] & 0x80) >> 7;
+    //bool last_fragment = (payload_data[1] & 0x40) >> 6;
+
+    unsigned char original_nal_header = fnri | original_nal_type;
+    if (first_fragment) {
+      payload = const_cast<uint8_t*> (payload_data) +
+          RtpFormatH264::kH264NALHeaderLengthInBytes;
+      payload[0] = original_nal_header;
+      payload_length = payload_data_length -
+          RtpFormatH264::kH264NALHeaderLengthInBytes;
+    } else {
+      payload = const_cast<uint8_t*> (payload_data)  +
+          RtpFormatH264::kH264FUAHeaderLengthInBytes;
+      payload_length = payload_data_length -
+          RtpFormatH264::kH264FUAHeaderLengthInBytes;
+    }
+
+    // WebRtcRTPHeader
+    if (original_nal_type == RtpFormatH264::kH264NALU_IDR) {
+      rtp_header->frameType = kVideoFrameKey;
+    } else {
+      rtp_header->frameType = kVideoFrameDelta;
+    }
+    rtp_header->type.Video.codec    = kRtpVideoH264;
+    rtp_header->type.Video.isFirstPacket = first_fragment;
+    RTPVideoHeaderH264* h264_header = &rtp_header->type.Video.codecHeader.H264;
+    h264_header->nalu_header        = original_nal_header;
+    h264_header->single_nalu        = false;
+  } else {
+    // single NALU
+    payload = const_cast<uint8_t*> (payload_data);
+    payload_length = payload_data_length;
+
+    rtp_header->type.Video.codec    = kRtpVideoH264;
+    rtp_header->type.Video.isFirstPacket = true; // First packet
+    RTPVideoHeaderH264* h264_header = &rtp_header->type.Video.codecHeader.H264;
+    h264_header->nalu_header        = payload_data[0];
+    h264_header->single_nalu        = true;
+
+    // WebRtcRTPHeader
+    if (nal_type == RtpFormatH264::kH264NALU_SPS ||
+        nal_type == RtpFormatH264::kH264NALU_PPS) {
+      rtp_header->frameType = kVideoFrameKey;
+      rtp_header->type.Video.isFirstPacket = false;
+    } else {
+      rtp_header->frameType = kVideoFrameDelta;
+    }
+  }
+
+  if (data_callback_->OnReceivedPayloadData(payload,
+                                            payload_length,
+                                            rtp_header) != 0) {
+    return -1;
+  }
+  return 0;
+}
+
 int32_t RTPReceiverVideo::ReceiveGenericCodec(
     WebRtcRTPHeader* rtp_header,
     const uint8_t* payload_data,
     uint16_t payload_data_length) {
   uint8_t generic_header = *payload_data++;
   --payload_data_length;
 
   rtp_header->frameType =
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h
@@ -64,16 +64,20 @@ class RTPReceiverVideo : public RTPRecei
   int32_t ReceiveGenericCodec(WebRtcRTPHeader* rtp_header,
                               const uint8_t* payload_data,
                               uint16_t payload_data_length);
 
   int32_t ReceiveVp8Codec(WebRtcRTPHeader* rtp_header,
                           const uint8_t* payload_data,
                           uint16_t payload_data_length);
 
+  int32_t ReceiveH264Codec(WebRtcRTPHeader* rtp_header,
+                          const uint8_t* payload_data,
+                          uint16_t payload_data_length);
+
   int32_t BuildRTPheader(const WebRtcRTPHeader* rtp_header,
                          uint8_t* data_buffer) const;
 
  private:
   int32_t ParseVideoCodecSpecific(
       WebRtcRTPHeader* rtp_header,
       const uint8_t* payload_data,
       uint16_t payload_data_length,
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi
@@ -86,16 +86,18 @@
         'rtp_payload_registry.cc',
         'rtp_receiver_strategy.cc',
         'rtp_receiver_strategy.h',
         'rtp_receiver_video.cc',
         'rtp_receiver_video.h',
         'rtp_sender_video.cc',
         'rtp_sender_video.h',
         'video_codec_information.h',
+        'rtp_format_h264.cc',
+        'rtp_format_h264.h',
         'rtp_format_vp8.cc',
         'rtp_format_vp8.h',
         'rtp_format_video_generic.h',
         'vp8_partition_aggregator.cc',
         'vp8_partition_aggregator.h',
         # Mocks
         '../mocks/mock_rtp_rtcp.h',
         'mock/mock_rtp_payload_strategy.h',
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -11,16 +11,17 @@
 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
 
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 #include "webrtc/system_wrappers/interface/trace_event.h"
 
 namespace webrtc {
 enum { REDForFECHeaderLength = 1 };
@@ -87,16 +88,18 @@ int32_t RTPSenderVideo::RegisterVideoPay
     const int8_t payloadType,
     const uint32_t maxBitRate,
     ModuleRTPUtility::Payload*& payload) {
   CriticalSectionScoped cs(_sendVideoCritsect);
 
   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 {
     videoType = kRtpVideoGeneric;
   }
   payload = new ModuleRTPUtility::Payload;
   payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
   strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
@@ -275,63 +278,70 @@ RTPSenderVideo::SendVideo(const RtpVideo
                           const FrameType frameType,
                           const int8_t payloadType,
                           const uint32_t captureTimeStamp,
                           int64_t capture_time_ms,
                           const uint8_t* payloadData,
                           const uint32_t payloadSize,
                           const RTPFragmentationHeader* fragmentation,
                           VideoCodecInformation* codecInfo,
-                          const RTPVideoTypeHeader* rtpTypeHdr)
-{
-    if( payloadSize == 0)
-    {
-        return -1;
-    }
+                          const RTPVideoTypeHeader* rtpTypeHdr) {
+  if( payloadSize == 0) {
+      return -1;
+  }
 
-    if (frameType == kVideoFrameKey) {
-      producer_fec_.SetFecParameters(&key_fec_params_,
-                                     _numberFirstPartition);
-    } else {
-      producer_fec_.SetFecParameters(&delta_fec_params_,
-                                     _numberFirstPartition);
-    }
+  if (frameType == kVideoFrameKey) {
+    producer_fec_.SetFecParameters(&key_fec_params_,
+                                   _numberFirstPartition);
+  } else {
+    producer_fec_.SetFecParameters(&delta_fec_params_,
+                                   _numberFirstPartition);
+  }
 
-    // Default setting for number of first partition packets:
-    // Will be extracted in SendVP8 for VP8 codec; other codecs use 0
-    _numberFirstPartition = 0;
+  // Default setting for number of first partition packets:
+  // Will be extracted in SendVP8 for VP8 codec; other codecs use 0
+  _numberFirstPartition = 0;
 
-    int32_t retVal = -1;
-    switch(videoType)
-    {
-    case kRtpVideoGeneric:
-        retVal = SendGeneric(frameType, payloadType, captureTimeStamp,
-                             capture_time_ms, payloadData, payloadSize);
-        break;
-    case kRtpVideoVp8:
-        retVal = SendVP8(frameType,
-                         payloadType,
-                         captureTimeStamp,
-                         capture_time_ms,
-                         payloadData,
-                         payloadSize,
-                         fragmentation,
-                         rtpTypeHdr);
-        break;
-    default:
-        assert(false);
-        break;
-    }
-    if(retVal <= 0)
-    {
-        return retVal;
-    }
-    WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "%s(timestamp:%u)",
-                 __FUNCTION__, captureTimeStamp);
-    return 0;
+  int32_t retVal = -1;
+  switch(videoType) {
+  case kRtpVideoGeneric:
+    retVal = SendGeneric(frameType, payloadType, captureTimeStamp,
+                         capture_time_ms, payloadData, payloadSize);
+      break;
+  case kRtpVideoVp8:
+    retVal = SendVP8(frameType,
+                     payloadType,
+                     captureTimeStamp,
+                     capture_time_ms,
+                     payloadData,
+                     payloadSize,
+                     fragmentation,
+                     rtpTypeHdr);
+    break;
+  case kRtpVideoH264:
+    retVal = SendH264(frameType,
+                      payloadType,
+                      captureTimeStamp,
+                      capture_time_ms,
+                      payloadData,
+                      payloadSize,
+                      fragmentation,
+                      rtpTypeHdr);
+    break;
+  default:
+    assert(false);
+    break;
+  }
+
+  if(retVal <= 0) {
+    return retVal;
+  }
+  WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "%s(timestamp:%u)",
+               __FUNCTION__, captureTimeStamp);
+  return 0;
 }
 
 int32_t RTPSenderVideo::SendGeneric(const FrameType frame_type,
                                     const int8_t payload_type,
                                     const uint32_t capture_timestamp,
                                     int64_t capture_time_ms,
                                     const uint8_t* payload,
                                     uint32_t size) {
@@ -476,16 +486,62 @@ RTPSenderVideo::SendVP8(const FrameType 
                        " %d", _rtpSender.SequenceNumber());
         }
     }
     TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms,
                            "timestamp", _rtpSender.Timestamp());
     return 0;
 }
 
+int32_t RTPSenderVideo::SendH264(const FrameType frameType,
+                                 const int8_t payloadType,
+                                 const uint32_t captureTimeStamp,
+                                 int64_t capture_time_ms,
+                                 const uint8_t* payloadData,
+                                 const uint32_t payloadSize,
+                                 const RTPFragmentationHeader* fragmentation,
+                                 const RTPVideoTypeHeader* rtpTypeHdr) {
+  const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
+  int32_t payloadBytesToSend = payloadSize;
+  const uint8_t* data = payloadData;
+  uint16_t maxPayloadLengthH264 = _rtpSender.MaxDataPayloadLength();
+
+  RtpFormatH264 packetizer(data, payloadBytesToSend, maxPayloadLengthH264);
+
+  StorageType storage = kAllowRetransmission;
+  bool protect = (frameType == kVideoFrameKey);
+  bool last = false;
+
+  while (!last) {
+    // Write H264 Payload
+    uint8_t dataBuffer[IP_PACKET_SIZE] = {0};
+    int payloadBytesInPacket = 0;
+    int ret_val = packetizer.NextPacket(&dataBuffer[rtpHeaderLength],
+                                        &payloadBytesInPacket, &last);
+    if (ret_val < 0) {
+        return -1;
+    }
+
+    // Write RTP header.
+    // Set marker bit true if this is the last packet in frame.
+    _rtpSender.BuildRTPheader(dataBuffer, payloadType, last,
+                              captureTimeStamp, capture_time_ms);
+    if (-1 == SendVideoPacket(dataBuffer, payloadBytesInPacket,
+                              rtpHeaderLength, captureTimeStamp,
+                              capture_time_ms, storage, protect)) {
+    }
+
+    if (ret_val == 0) {
+      // single NAL unit
+      last = true;
+    }
+  }
+  return 0;
+}
+
 void RTPSenderVideo::ProcessBitrate() {
   _videoBitrate.Process();
   _fecOverheadRate.Process();
 }
 
 uint32_t RTPSenderVideo::VideoBitrateSent() const {
   return _videoBitrate.BitrateLast();
 }
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h
@@ -106,16 +106,25 @@ private:
                     const int8_t payloadType,
                     const uint32_t captureTimeStamp,
                     int64_t capture_time_ms,
                     const uint8_t* payloadData,
                     const uint32_t payloadSize,
                     const RTPFragmentationHeader* fragmentation,
                     const RTPVideoTypeHeader* rtpTypeHdr);
 
+    int32_t SendH264(const FrameType frameType,
+                    const int8_t payloadType,
+                    const uint32_t captureTimeStamp,
+                    int64_t capture_time_ms,
+                    const uint8_t* payloadData,
+                    const uint32_t payloadSize,
+                    const RTPFragmentationHeader* fragmentation,
+                    const RTPVideoTypeHeader* rtpTypeHdr);
+
 private:
     int32_t             _id;
     RTPSenderInterface&        _rtpSender;
 
     CriticalSectionWrapper*   _sendVideoCritsect;
     RtpVideoCodecTypes  _videoType;
     VideoCodecInformation*  _videoCodecInformation;
     uint32_t            _maxBitrate;
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/codecs/h264/include/h264.h
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_H_
+#define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_H_
+
+#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
+
+namespace webrtc {
+
+class H264Encoder : public VideoEncoder {
+ public:
+  static H264Encoder* Create();
+
+  virtual ~H264Encoder() {}
+};  // H264Encoder
+
+class H264Decoder : public VideoDecoder {
+ public:
+  static H264Decoder* Create();
+
+  virtual ~H264Decoder() {}
+};  // H264Decoder
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_H_
--- a/media/webrtc/trunk/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h
@@ -42,20 +42,25 @@ struct CodecSpecificInfoVP8
     int              tl0PicIdx;         // Negative value to skip tl0PicIdx
     int8_t     keyIdx;            // negative value to skip keyIdx
 };
 
 struct CodecSpecificInfoGeneric {
   uint8_t simulcast_idx;
 };
 
-union CodecSpecificInfoUnion
-{
+struct CodecSpecificInfoH264 {
+  unsigned char nalu_header;
+  bool          single_nalu;
+};
+
+union CodecSpecificInfoUnion {
     CodecSpecificInfoGeneric   generic;
     CodecSpecificInfoVP8       VP8;
+    CodecSpecificInfoH264      H264;
 };
 
 // Note: if any pointers are added to this struct or its sub-structs, it
 // must be fitted with a copy-constructor. This is because it is copied
 // in the copy-constructor of VCMEncodedFrame.
 struct CodecSpecificInfo
 {
     VideoCodecType   codecType;
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/codec_database.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/codec_database.cc
@@ -344,16 +344,17 @@ bool VCMCodecDataBase::RequiresEncoderRe
           0) {
         return true;
       }
       break;
     // Known codecs without payload-specifics
     case kVideoCodecI420:
     case kVideoCodecRED:
     case kVideoCodecULPFEC:
+    case kVideoCodecH264:
       break;
     // Unknown codec type, reset just to be sure.
     case kVideoCodecUnknown:
       return true;
   }
 
   if (new_send_codec.numberOfSimulcastStreams > 0) {
     for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams;
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/encoded_frame.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/encoded_frame.cc
@@ -95,59 +95,59 @@ void VCMEncodedFrame::Reset()
     _missingFrame = false;
     _length = 0;
     _codecSpecificInfo.codecType = kVideoCodecUnknown;
     _codec = kVideoCodecUnknown;
 }
 
 void VCMEncodedFrame::CopyCodecSpecific(const RTPVideoHeader* header)
 {
-    if (header)
-    {
-        switch (header->codec)
-        {
-            case kRtpVideoVp8:
-            {
-                if (_codecSpecificInfo.codecType != kVideoCodecVP8)
-                {
-                    // This is the first packet for this frame.
-                    _codecSpecificInfo.codecSpecific.VP8.pictureId = -1;
-                    _codecSpecificInfo.codecSpecific.VP8.temporalIdx = 0;
-                    _codecSpecificInfo.codecSpecific.VP8.layerSync = false;
-                    _codecSpecificInfo.codecSpecific.VP8.keyIdx = -1;
-                    _codecSpecificInfo.codecType = kVideoCodecVP8;
-                }
-                _codecSpecificInfo.codecSpecific.VP8.nonReference =
-                    header->codecHeader.VP8.nonReference;
-                if (header->codecHeader.VP8.pictureId != kNoPictureId)
-                {
-                    _codecSpecificInfo.codecSpecific.VP8.pictureId =
-                        header->codecHeader.VP8.pictureId;
-                }
-                if (header->codecHeader.VP8.temporalIdx != kNoTemporalIdx)
-                {
-                    _codecSpecificInfo.codecSpecific.VP8.temporalIdx =
-                        header->codecHeader.VP8.temporalIdx;
-                    _codecSpecificInfo.codecSpecific.VP8.layerSync =
-                        header->codecHeader.VP8.layerSync;
-                }
-                if (header->codecHeader.VP8.keyIdx != kNoKeyIdx)
-                {
-                    _codecSpecificInfo.codecSpecific.VP8.keyIdx =
-                        header->codecHeader.VP8.keyIdx;
-                }
-                break;
-            }
-            default:
-            {
-                _codecSpecificInfo.codecType = kVideoCodecUnknown;
-                break;
-            }
-        }
+    if (header) {
+      switch (header->codec) {
+        case kRtpVideoVp8: {
+          if (_codecSpecificInfo.codecType != kVideoCodecVP8) {
+            // This is the first packet for this frame.
+            _codecSpecificInfo.codecSpecific.VP8.pictureId = -1;
+            _codecSpecificInfo.codecSpecific.VP8.temporalIdx = 0;
+            _codecSpecificInfo.codecSpecific.VP8.layerSync = false;
+            _codecSpecificInfo.codecSpecific.VP8.keyIdx = -1;
+            _codecSpecificInfo.codecType = kVideoCodecVP8;
+          }
+          _codecSpecificInfo.codecSpecific.VP8.nonReference =
+              header->codecHeader.VP8.nonReference;
+          if (header->codecHeader.VP8.pictureId != kNoPictureId) {
+            _codecSpecificInfo.codecSpecific.VP8.pictureId =
+                header->codecHeader.VP8.pictureId;
+          }
+          if (header->codecHeader.VP8.temporalIdx != kNoTemporalIdx) {
+            _codecSpecificInfo.codecSpecific.VP8.temporalIdx =
+                header->codecHeader.VP8.temporalIdx;
+            _codecSpecificInfo.codecSpecific.VP8.layerSync =
+                header->codecHeader.VP8.layerSync;
+          }
+          if (header->codecHeader.VP8.keyIdx != kNoKeyIdx) {
+            _codecSpecificInfo.codecSpecific.VP8.keyIdx =
+                header->codecHeader.VP8.keyIdx;
+          }
+          break;
+      }
+      case kRtpVideoH264: {
+        _codecSpecificInfo.codecSpecific.H264.nalu_header =
+            header->codecHeader.H264.nalu_header;
+        _codecSpecificInfo.codecSpecific.H264.single_nalu =
+            header->codecHeader.H264.single_nalu;
+        _codecSpecificInfo.codecType = kVideoCodecH264;
+        break;
+      }
+      default: {
+        _codecSpecificInfo.codecType = kVideoCodecUnknown;
+        break;
+      }
     }
+  }
 }
 
 const RTPFragmentationHeader* VCMEncodedFrame::FragmentationHeader() const {
   return &_fragmentation;
 }
 
 int32_t
 VCMEncodedFrame::VerifyAndAllocate(const uint32_t minimumSize)
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/internal_defines.h
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/internal_defines.h
@@ -35,19 +35,19 @@ inline uint32_t MaskWord64ToUWord32(int6
 // Helper macros for creating the static codec list
 #define VCM_NO_CODEC_IDX -1
 #ifdef VIDEOCODEC_VP8
   #define VCM_VP8_IDX VCM_NO_CODEC_IDX + 1
 #else
   #define VCM_VP8_IDX VCM_NO_CODEC_IDX
 #endif
 #ifdef VIDEOCODEC_I420
-  #define VCM_I420_IDX VCM_VP8_IDX + 1
+  #define VCM_I420_IDX VIDEOCODEC_VP8 + 1
 #else
-  #define VCM_I420_IDX VCM_VP8_IDX
+  #define VCM_I420_IDX VIDEOCODEC_VP8
 #endif
 #define VCM_NUM_VIDEO_CODECS_AVAILABLE VCM_I420_IDX + 1
 
 #define VCM_NO_RECEIVER_ID 0
 
 inline int32_t VCMId(const int32_t vcmId, const int32_t receiverId = 0)
 {
     return static_cast<int32_t>((vcmId << 16) + receiverId);
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/packet.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/packet.cc
@@ -5,16 +5,17 @@
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "webrtc/modules/interface/module_common_types.h"
 #include "webrtc/modules/video_coding/main/source/packet.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h"
 
 #include <assert.h>
 
 namespace webrtc {
 
 VCMPacket::VCMPacket()
   :
     payloadType(0),
@@ -85,38 +86,70 @@ void VCMPacket::Reset() {
   isFirstPacket = false;
   completeNALU = kNaluUnset;
   insertStartCode = false;
   width = 0;
   height = 0;
   memset(&codecSpecificHeader, 0, sizeof(RTPVideoHeader));
 }
 
-void VCMPacket::CopyCodecSpecifics(const RTPVideoHeader& videoHeader)
-{
-    switch(videoHeader.codec)
-    {
-        case kRtpVideoVp8:
-            {
-                // Handle all packets within a frame as depending on the previous packet
-                // TODO(holmer): This should be changed to make fragments independent
-                // when the VP8 RTP receiver supports fragments.
-                if (isFirstPacket && markerBit)
-                    completeNALU = kNaluComplete;
-                else if (isFirstPacket)
-                    completeNALU = kNaluStart;
-                else if (markerBit)
-                    completeNALU = kNaluEnd;
-                else
-                    completeNALU = kNaluIncomplete;
+void VCMPacket::CopyCodecSpecifics(const RTPVideoHeader& videoHeader) {
+  switch (videoHeader.codec) {
+    case kRtpVideoVp8: {
+      // Handle all packets within a frame as depending on the previous packet
+      // TODO(holmer): This should be changed to make fragments independent
+      // when the VP8 RTP receiver supports fragments.
+      if (isFirstPacket && markerBit)
+          completeNALU = kNaluComplete;
+      else if (isFirstPacket)
+          completeNALU = kNaluStart;
+      else if (markerBit)
+          completeNALU = kNaluEnd;
+      else
+          completeNALU = kNaluIncomplete;
 
-                codec = kVideoCodecVP8;
-                break;
-            }
-        default:
-            {
-                codec = kVideoCodecUnknown;
-                break;
-            }
+      codec = kVideoCodecVP8;
+      break;
     }
+    case kRtpVideoH264: {
+      unsigned char nal_type = videoHeader.codecHeader.H264.nalu_header & 0x1F;
+      if (videoHeader.codecHeader.H264.single_nalu) {
+        if (nal_type == RtpFormatH264::kH264NALU_SPS ||
+            nal_type == RtpFormatH264::kH264NALU_PPS) {
+          insertStartCode = true;
+          isFirstPacket   = false;
+          markerBit       = false;
+        } else {
+          isFirstPacket   = true;
+          markerBit       = true;
+          insertStartCode = true;
+        }
+      } else {
+        // Fragmented NALU
+        if (isFirstPacket) {
+          insertStartCode = true;
+          if (nal_type == RtpFormatH264::kH264NALU_IDR) {
+            // We always assume IDR is pre-leaded with a PPS or SPS/PPS.
+            isFirstPacket = false;
+          }
+        } else {
+          insertStartCode = false;
+        }
+      }
+
+      if (isFirstPacket && markerBit)
+         completeNALU = kNaluComplete;
+      else if (isFirstPacket)
+         completeNALU = kNaluStart;
+      else if (markerBit)
+         completeNALU = kNaluEnd;
+      else
+         completeNALU = kNaluIncomplete;
+      codec = kVideoCodecH264;
+    }
+    default: {
+      codec = kVideoCodecUnknown;
+      break;
+    }
+  }
 }
 
-}
+}  // namespace webrtc
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/session_info.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/session_info.cc
@@ -6,16 +6,17 @@
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "webrtc/modules/video_coding/main/source/session_info.h"
 
 #include "webrtc/modules/video_coding/main/source/packet.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h"
 
 namespace webrtc {
 
 // Used in determining whether a frame is decodable.
 enum {kRttThreshold = 100};  // Not decodable if Rtt is lower than this.
 
 // Do not decode frames if the number of packets is between these two
 // thresholds.
@@ -413,45 +414,92 @@ int VCMSessionInfo::InsertPacket(const V
     if (LatestSequenceNumber(packet.seqNum, (*rit).seqNum) == packet.seqNum)
       break;
 
   // Check for duplicate packets.
   if (rit != packets_.rend() &&
       (*rit).seqNum == packet.seqNum && (*rit).sizeBytes > 0)
     return -2;
 
-  // Only insert media packets between first and last packets (when available).
-  // Placing check here, as to properly account for duplicate packets.
-  // Check if this is first packet (only valid for some codecs)
-  // Should only be set for one packet per session.
-  if (packet.isFirstPacket && first_packet_seq_num_ == -1) {
-    // The first packet in a frame signals the frame type.
-    frame_type_ = packet.frameType;
-    // Store the sequence number for the first packet.
-    first_packet_seq_num_ = static_cast<int>(packet.seqNum);
-  } else if (first_packet_seq_num_ != -1 &&
-        !IsNewerSequenceNumber(packet.seqNum, first_packet_seq_num_)) {
-    return -3;
-  } else if (frame_type_ == kFrameEmpty && packet.frameType != kFrameEmpty) {
-    // Update the frame type with the type of the first media packet.
-    // TODO(mikhal): Can this trigger?
-    frame_type_ = packet.frameType;
+  PacketIterator packet_list_it;
+  if (packet.codec == kVideoCodecH264) {
+    RTPVideoHeaderH264 h264 = packet.codecSpecificHeader.codecHeader.H264;
+    unsigned char nal_type = h264.nalu_header & 0x1F;
+    bool potential_start = false;
+    if (nal_type == RtpFormatH264::kH264NALU_SPS ||
+        nal_type == RtpFormatH264::kH264NALU_PPS ||
+        packet.codecSpecificHeader.codecHeader.H264.single_nalu) {
+      potential_start = true;
+    } else {
+      potential_start = packet.isFirstPacket;
+    }
+    if (potential_start) {
+      if (HaveFirstPacket() == false ||
+          IsNewerSequenceNumber(first_packet_seq_num_, packet.seqNum)) {
+        first_packet_seq_num_ = packet.seqNum;
+        frame_type_ = packet.frameType;
+      }
+    }
+
+    // Track the marker bit, should only be set for one packet per session.
+    if (packet.markerBit && last_packet_seq_num_ == -1) {
+      last_packet_seq_num_ = static_cast<int>(packet.seqNum);
+    } else if (last_packet_seq_num_ != -1 &&
+      IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) {
+      LOG(LS_WARNING) << "Received packet with a sequence number which is out "
+                       " of frame boundaries";
+      return -3;
+    }
+
+    if (first_packet_seq_num_ == packet.seqNum &&
+        packet.completeNALU != kNaluComplete) {
+      VCMPacket& npacket = const_cast<VCMPacket&> (packet);
+      npacket.isFirstPacket = true;
+      npacket.completeNALU = kNaluStart;
+      // The insert operation invalidates the iterator |rit|.
+      packet_list_it = packets_.insert(rit.base(), npacket);
+    } else {
+      // The insert operation invalidates the iterator |rit|.
+      packet_list_it = packets_.insert(rit.base(), packet);
+    }
+  } else {
+    // Only insert media packets between first and last packets (when available).
+    // Placing check here, as to properly account for duplicate packets.
+    // Check if this is first packet (only valid for some codecs)
+    // Should only be set for one packet per session.
+    if (packet.isFirstPacket && first_packet_seq_num_ == -1) {
+      // The first packet in a frame signals the frame type.
+      frame_type_ = packet.frameType;
+      // Store the sequence number for the first packet.
+      first_packet_seq_num_ = static_cast<int>(packet.seqNum);
+    } else if (first_packet_seq_num_ != -1 &&
+      !IsNewerSequenceNumber(packet.seqNum, first_packet_seq_num_)) {
+      LOG(LS_WARNING) << "Received packet with a sequence number which is out "
+                       "of frame boundaries";
+      return -3;
+    } else if (frame_type_ == kFrameEmpty && packet.frameType != kFrameEmpty) {
+      // Update the frame type with the type of the first media packet.
+      // TODO(mikhal): Can this trigger?
+      frame_type_ = packet.frameType;
+    }
+
+    // Track the marker bit, should only be set for one packet per session.
+    if (packet.markerBit && last_packet_seq_num_ == -1) {
+      last_packet_seq_num_ = static_cast<int>(packet.seqNum);
+    } else if (last_packet_seq_num_ != -1 &&
+        IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) {
+      LOG(LS_WARNING) << "Received packet with a sequence number which is out "
+                       "of frame boundaries";
+      return -3;
+    }
+
+    // The insert operation invalidates the iterator |rit|.
+    packet_list_it = packets_.insert(rit.base(), packet);
   }
 
-  // Track the marker bit, should only be set for one packet per session.
-  if (packet.markerBit && last_packet_seq_num_ == -1) {
-    last_packet_seq_num_ = static_cast<int>(packet.seqNum);
-  } else if (last_packet_seq_num_ != -1 &&
-      IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) {
-    return -3;
-  }
-
-  // The insert operation invalidates the iterator |rit|.
-  PacketIterator packet_list_it = packets_.insert(rit.base(), packet);
-
   int returnLength = InsertBuffer(frame_buffer, packet_list_it);
   UpdateCompleteSession();
   if (decode_error_mode == kWithErrors)
     decodable_ = true;
   else if (decode_error_mode == kSelectiveErrors)
     UpdateDecodableSession(frame_data);
   return returnLength;
 }
--- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
@@ -99,16 +99,19 @@ void ViEAutoTest::PrintVideoCodec(const 
     switch (videoCodec.codecType)
     {
         case webrtc::kVideoCodecVP8:
             ViETest::Log("\tcodecType: VP8");
             break;
         case webrtc::kVideoCodecI420:
             ViETest::Log("\tcodecType: I420");
             break;
+        case webrtc::kVideoCodecH264:
+            ViETest::Log("\tcodecType: H264");
+            break;
         case webrtc::kVideoCodecRED:
             ViETest::Log("\tcodecType: RED");
             break;
         case webrtc::kVideoCodecULPFEC:
             ViETest::Log("\tcodecType: ULPFEC");
             break;
         case webrtc::kVideoCodecGeneric:
             ViETest::Log("\tcodecType: GENERIC");
--- a/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc
@@ -738,16 +738,18 @@ bool ViECodecImpl::CodecValid(const Vide
       // We only care about the type and name for ULPFEC.
       return true;
     }
     WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
                  "Codec type doesn't match pl_name", video_codec.plType);
     return false;
   } else if ((video_codec.codecType == kVideoCodecVP8 &&
               strncmp(video_codec.plName, "VP8", 4) == 0) ||
+             (video_codec.codecType == kVideoCodecH264 &&
+              strncmp(video_codec.plName, "H264", 4) == 0) ||
              (video_codec.codecType == kVideoCodecI420 &&
               strncmp(video_codec.plName, "I420", 4) == 0)) {
     // OK.
   } else if (video_codec.codecType != kVideoCodecGeneric) {
     WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
                  "Codec type doesn't match pl_name", video_codec.plType);
     return false;
   }