Bug 1137474: Basic vp9 support added to upstream (using 'generic' packetization) r=pkerr
authorRandell Jesup <rjesup@jesup.org>
Tue, 03 Mar 2015 01:31:33 -0500
changeset 260383 bf6cd84214a546ecb053ef9df037a2ed0a74b023
parent 260382 8f725bbaff1cbff02442431982c13356e3ba5dc5
child 260384 29c8632b348e9f0a55c76f28665228ec3e319026
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspkerr
bugs1137474
milestone39.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 1137474: Basic vp9 support added to upstream (using 'generic' packetization) r=pkerr
media/webrtc/trunk/webrtc/modules/interface/module_common_types.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_format.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/source/encoded_frame.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/source/generic_encoder.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/source/packet.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/source/video_sender.cc
media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc
media/webrtc/trunk/webrtc/video_engine/vie_encoder.cc
--- a/media/webrtc/trunk/webrtc/modules/interface/module_common_types.h
+++ b/media/webrtc/trunk/webrtc/modules/interface/module_common_types.h
@@ -61,25 +61,54 @@ struct RTPVideoHeaderVP8 {
 };
 
 struct RTPVideoHeaderH264 {
   uint8_t nalu_header;    // us ********* REMOVE ME??? *********
   bool stap_a;            // them *** or this? ***
   bool single_nalu;
 };
 
+// XXX fix vp9 (bug 1138629)
+struct RTPVideoHeaderVP9 {
+  void InitRTPVideoHeaderVP9() {
+    nonReference = false;
+    pictureId = kNoPictureId;
+    tl0PicIdx = kNoTl0PicIdx;
+    temporalIdx = kNoTemporalIdx;
+    layerSync = false;
+    keyIdx = kNoKeyIdx;
+    partitionId = 0;
+    beginningOfPartition = false;
+  }
+
+  bool nonReference;          // Frame is discardable.
+  int16_t pictureId;          // Picture ID index, 15 bits;
+                              // kNoPictureId if PictureID does not exist.
+  int16_t tl0PicIdx;          // TL0PIC_IDX, 8 bits;
+                              // kNoTl0PicIdx means no value provided.
+  uint8_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;            // VP9 partition ID
+  bool beginningOfPartition;  // True if this packet is the first
+                              // in a VP9 partition. Otherwise false
+};
+
 union RTPVideoTypeHeader {
   RTPVideoHeaderVP8 VP8;
+  RTPVideoHeaderVP9 VP9;
   RTPVideoHeaderH264 H264;
 };
 
 enum RtpVideoCodecTypes {
   kRtpVideoNone,
   kRtpVideoGeneric,
   kRtpVideoVp8,
+  kRtpVideoVp9,
   kRtpVideoH264
 };
 struct RTPVideoHeader {
   uint16_t width;  // size
   uint16_t height;
 
   bool isFirstPacket;    // first packet in frame (or NAL for H.264)
   uint8_t simulcastIdx;  // Index if the simulcast encoder creating
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_format.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_format.cc
@@ -20,30 +20,32 @@ RtpPacketizer* RtpPacketizer::Create(Rtp
                                      const RTPVideoTypeHeader* rtp_type_header,
                                      FrameType frame_type) {
   switch (type) {
     case kRtpVideoH264:
       return new RtpPacketizerH264(frame_type, max_payload_len);
     case kRtpVideoVp8:
       assert(rtp_type_header != NULL);
       return new RtpPacketizerVp8(rtp_type_header->VP8, max_payload_len);
+    case kRtpVideoVp9:
     case kRtpVideoGeneric:
       return new RtpPacketizerGeneric(frame_type, max_payload_len);
     case kRtpVideoNone:
       assert(false);
   }
   return NULL;
 }
 
 RtpDepacketizer* RtpDepacketizer::Create(RtpVideoCodecTypes type) {
   switch (type) {
     case kRtpVideoH264:
       return new RtpDepacketizerH264();
     case kRtpVideoVp8:
       return new RtpDepacketizerVp8();
+    case kRtpVideoVp9: // XXX fix vp9 packetization (bug 1138629)
     case kRtpVideoGeneric:
       return new RtpDepacketizerGeneric();
     case kRtpVideoNone:
       assert(false);
   }
   return NULL;
 }
 }  // namespace webrtc
--- 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
@@ -422,16 +422,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 (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
       videoType = kRtpVideoVp8;
+    } else if (RtpUtility::StringCompare(payloadName, "VP9", 3)) {
+      videoType = kRtpVideoVp9;
     } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
       videoType = kRtpVideoH264;
     } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
       videoType = kRtpVideoGeneric;
     } else if (RtpUtility::StringCompare(payloadName, "ULPFEC", 6)) {
       videoType = kRtpVideoNone;
     } else {
       videoType = kRtpVideoGeneric;
--- 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
@@ -79,16 +79,18 @@ int32_t RTPSenderVideo::RegisterVideoPay
     const int8_t payloadType,
     const uint32_t maxBitRate,
     RtpUtility::Payload*& payload) {
   CriticalSectionScoped cs(_sendVideoCritsect);
 
   RtpVideoCodecTypes videoType = kRtpVideoGeneric;
   if (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
     videoType = kRtpVideoVp8;
+  } else if (RtpUtility::StringCompare(payloadName, "VP9", 3)) {
+    videoType = kRtpVideoVp9;
   } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
     videoType = kRtpVideoH264;
   } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
     videoType = kRtpVideoGeneric;
   } else {
     videoType = kRtpVideoGeneric;
   }
   payload = new RtpUtility::Payload;
@@ -331,17 +333,17 @@ bool RTPSenderVideo::Send(const RtpVideo
 
   scoped_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create(
       videoType, max_payload_length, rtpTypeHdr, frameType));
 
   // TODO(changbin): we currently don't support to configure the codec to
   // output multiple partitions for VP8. Should remove below check after the
   // issue is fixed.
   const RTPFragmentationHeader* frag =
-      (videoType == kRtpVideoVp8) ? NULL : fragmentation;
+      (videoType == kRtpVideoVp8 || videoType == kRtpVideoVp9) ? NULL : fragmentation;
 
   packetizer->SetPayloadData(data, payload_bytes_to_send, frag);
 
   bool last = false;
   while (!last) {
     uint8_t dataBuffer[IP_PACKET_SIZE] = {0};
     size_t payload_bytes_in_packet = 0;
     if (!packetizer->NextPacket(
--- 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
@@ -132,16 +132,43 @@ void VCMEncodedFrame::CopyCodecSpecific(
       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;
       }
+      case kRtpVideoVp9: {
+        if (_codecSpecificInfo.codecType != kVideoCodecVP9) {
+          // This is the first packet for this frame.
+          _codecSpecificInfo.codecSpecific.VP9.pictureId = -1;
+          _codecSpecificInfo.codecSpecific.VP9.temporalIdx = 0;
+          _codecSpecificInfo.codecSpecific.VP9.layerSync = false;
+          _codecSpecificInfo.codecSpecific.VP9.keyIdx = -1;
+          _codecSpecificInfo.codecType = kVideoCodecVP9;
+        }
+        _codecSpecificInfo.codecSpecific.VP9.nonReference =
+            header->codecHeader.VP9.nonReference;
+        if (header->codecHeader.VP9.pictureId != kNoPictureId) {
+          _codecSpecificInfo.codecSpecific.VP9.pictureId =
+              header->codecHeader.VP9.pictureId;
+        }
+        if (header->codecHeader.VP9.temporalIdx != kNoTemporalIdx) {
+          _codecSpecificInfo.codecSpecific.VP9.temporalIdx =
+              header->codecHeader.VP9.temporalIdx;
+          _codecSpecificInfo.codecSpecific.VP9.layerSync =
+              header->codecHeader.VP9.layerSync;
+        }
+        if (header->codecHeader.VP9.keyIdx != kNoKeyIdx) {
+          _codecSpecificInfo.codecSpecific.VP9.keyIdx =
+              header->codecHeader.VP9.keyIdx;
+        }
+        break;
+      }
       default: {
         _codecSpecificInfo.codecType = kVideoCodecUnknown;
         break;
       }
     }
   }
 }
 
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/generic_encoder.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/generic_encoder.cc
@@ -37,16 +37,27 @@ void CopyCodecSpecific(const CodecSpecif
       (*rtp)->codecHeader.VP8.keyIdx = info->codecSpecific.VP8.keyIdx;
       (*rtp)->simulcastIdx = info->codecSpecific.VP8.simulcastIdx;
       return;
     }
     case kVideoCodecH264:
       (*rtp)->codec = kRtpVideoH264;
       (*rtp)->simulcastIdx = info->codecSpecific.H264.simulcastIdx;
       return;
+    case kVideoCodecVP9:
+      (*rtp)->codec = kRtpVideoVp9;
+      (*rtp)->codecHeader.VP9.InitRTPVideoHeaderVP9();
+      (*rtp)->codecHeader.VP9.pictureId = info->codecSpecific.VP9.pictureId;
+      (*rtp)->codecHeader.VP9.nonReference =
+          info->codecSpecific.VP9.nonReference;
+      (*rtp)->codecHeader.VP9.temporalIdx = info->codecSpecific.VP9.temporalIdx;
+      (*rtp)->codecHeader.VP9.layerSync = info->codecSpecific.VP9.layerSync;
+      (*rtp)->codecHeader.VP9.tl0PicIdx = info->codecSpecific.VP9.tl0PicIdx;
+      (*rtp)->codecHeader.VP9.keyIdx = info->codecSpecific.VP9.keyIdx;
+      return;
     case kVideoCodecGeneric:
       (*rtp)->codec = kRtpVideoGeneric;
       (*rtp)->simulcastIdx = info->codecSpecific.generic.simulcast_idx;
       return;
     default:
       // No codec specific info. Change RTP header pointer to NULL.
       *rtp = NULL;
       return;
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/packet.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/packet.cc
@@ -93,29 +93,30 @@ void VCMPacket::Reset() {
   width = 0;
   height = 0;
   memset(&codecSpecificHeader, 0, sizeof(RTPVideoHeader));
 }
 
 void VCMPacket::CopyCodecSpecifics(const RTPVideoHeader& videoHeader) {
   switch (videoHeader.codec) {
     case kRtpVideoVp8:
+    case kRtpVideoVp9:
       // 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;
+      codec = videoHeader.codec == kRtpVideoVp8 ? kVideoCodecVP8 : kVideoCodecVP9;
       return;
     case kRtpVideoH264:
       isFirstPacket = videoHeader.isFirstPacket;
       if (isFirstPacket) {
         insertStartCode = true;
       }
       if (videoHeader.codecHeader.H264.single_nalu) {
         completeNALU = kNaluComplete;
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/video_sender.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/video_sender.cc
@@ -132,16 +132,17 @@ int32_t VideoSender::RegisterSendCodec(c
   _encoder = _codecDataBase.GetEncoder();
 
   if (!ret) {
     LOG(LS_ERROR) << "Failed to initialize the encoder with payload name "
                   << sendCodec->plName << ". Error code: " << ret;
     return VCM_CODEC_ERROR;
   }
 
+  // XXX fix VP9 (bug 1138629)
   int numLayers = (sendCodec->codecType != kVideoCodecVP8)
                       ? 1
                       : sendCodec->codecSpecific.VP8.numberOfTemporalLayers;
   // If we have screensharing and we have layers, we disable frame dropper.
   bool disable_frame_dropper =
       numLayers > 1 && sendCodec->mode == kScreensharing;
   if (disable_frame_dropper) {
     _mediaOpt.EnableFrameDropper(false);
--- a/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc
@@ -82,16 +82,18 @@ static void LogCodec(const VideoCodec& c
                  << ", framedropping: "
                  << codec.codecSpecific.H264.frameDroppingOn
                  << ", keyFrameInterval: "
                  << codec.codecSpecific.H264.keyFrameInterval
                  << ", spslen: "
                  << codec.codecSpecific.H264.spsLen
                  << ", ppslen: "
                  << codec.codecSpecific.H264.ppsLen;
+  } else if (codec.codecType == kVideoCodecVP9) {
+    LOG(LS_INFO) << "VP9 specific settings";
   }
 }
 
 
 ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
 #ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
   if (!video_engine) {
     return NULL;
--- a/media/webrtc/trunk/webrtc/video_engine/vie_encoder.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_encoder.cc
@@ -631,16 +631,17 @@ void ViEEncoder::DeliverFrame(int id,
       has_received_rpsi_ = false;
     }
 
     vcm_.AddVideoFrame(*decimated_frame, vpm_.ContentMetrics(),
                        &codec_specific_info);
     return;
   }
 #endif
+  // XXX fix VP9 (bug 1138629)
 
 #ifdef MOZ_WEBRTC_OMX
   // XXX effectively disable resolution changes until Bug 1067437 is resolved with new DSP code
   if (qm_callback_ && vcm_.SendCodec() == webrtc::kVideoCodecH264) {
     if (vcm_.RegisterVideoQMCallback(NULL) != 0) {
       LOG_F(LS_ERROR) << "VCM::RegisterQMCallback(NULL) failure";
       return;
     }