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 246941 bf6cd84214a546ecb053ef9df037a2ed0a74b023
parent 246940 8f725bbaff1cbff02442431982c13356e3ba5dc5
child 246942 29c8632b348e9f0a55c76f28665228ec3e319026
push id884
push userdburns@mozilla.com
push dateTue, 03 Mar 2015 15:29:12 +0000
reviewerspkerr
bugs1137474
milestone39.0a1
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;
     }