Bug 1003712: Codec availability support and prioritization r=ehugg
authorRandell Jesup <rjesup@jesup.org>
Wed, 04 Jun 2014 14:52:32 -0400
changeset 205891 9e0dfff3fdb2803515c5fdf5591ccc412f2ac89f
parent 205890 eb336259b85f050b59a5cd516bdfa28cb2a8f65e
child 205892 504404fcc7dc988b88c4a7bcadbea79e83c64a04
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)
reviewersehugg
bugs1003712
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 1003712: Codec availability support and prioritization r=ehugg
content/media/omx/OMXCodecWrapper.h
media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
media/webrtc/signaling/src/media/VcmSIPCCBinding.h
media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
media/webrtc/signaling/src/sipcc/include/vcm.h
media/webrtc/trunk/webrtc/modules/video_coding/main/source/codec_database.cc
--- a/content/media/omx/OMXCodecWrapper.h
+++ b/content/media/omx/OMXCodecWrapper.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef OMXCodecWrapper_h_
 #define OMXCodecWrapper_h_
 
 #include <gui/Surface.h>
+#include <utils/RefBase.h>
 #include <stagefright/foundation/ABuffer.h>
 #include <stagefright/foundation/AMessage.h>
 #include <stagefright/MediaCodec.h>
 
 #include "AudioSegment.h"
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 
--- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
+++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
@@ -38,16 +38,17 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <ssl.h>
 #include <sslproto.h>
 #include <algorithm>
 
 #ifdef MOZ_WEBRTC_OMX
 #include "OMXVideoCodec.h"
+#include "OMXCodecWrapper.h"
 #endif
 
 extern "C" {
 #include "ccsdp.h"
 #include "vcm.h"
 #include "cc_call_feature.h"
 #include "cip_mmgr_mediadefinitions.h"
 #include "cip_Sipcc_CodecMask.h"
@@ -83,16 +84,17 @@ typedef enum {
 /* static */
 
 using namespace mozilla;
 using namespace CSF;
 
 VcmSIPCCBinding * VcmSIPCCBinding::gSelf = nullptr;
 int VcmSIPCCBinding::gAudioCodecMask = 0;
 int VcmSIPCCBinding::gVideoCodecMask = 0;
+int VcmSIPCCBinding::gVideoCodecGmpMask = 0;
 nsIThread *VcmSIPCCBinding::gMainThread = nullptr;
 nsIEventTarget *VcmSIPCCBinding::gSTSThread = nullptr;
 nsCOMPtr<nsIPrefBranch> VcmSIPCCBinding::gBranch = nullptr;
 
 static mozilla::RefPtr<TransportFlow> vcmCreateTransportFlow(
     sipcc::PeerConnectionImpl *pc,
     int level,
     bool rtcp,
@@ -219,26 +221,61 @@ void VcmSIPCCBinding::setAudioCodecs(int
 }
 
 void VcmSIPCCBinding::setVideoCodecs(int codecMask)
 {
   CSFLogDebug(logTag, "SETTING VIDEO: %d", codecMask);
   VcmSIPCCBinding::gVideoCodecMask = codecMask;
 }
 
+void VcmSIPCCBinding::addVideoCodecsGmp(int codecMask)
+{
+  CSFLogDebug(logTag, "ADDING VIDEO: %d", codecMask);
+  VcmSIPCCBinding::gVideoCodecGmpMask |= codecMask;
+}
+
 int VcmSIPCCBinding::getAudioCodecs()
 {
   return VcmSIPCCBinding::gAudioCodecMask;
 }
 
 int VcmSIPCCBinding::getVideoCodecs()
 {
   return VcmSIPCCBinding::gVideoCodecMask;
 }
 
+int VcmSIPCCBinding::getVideoCodecsGmp()
+{
+  return VcmSIPCCBinding::gVideoCodecGmpMask;
+}
+
+int VcmSIPCCBinding::getVideoCodecsHw()
+{
+  // Check to see if what HW codecs are available (not in use) at this moment.
+  // Note that streaming video decode can reserve a decoder
+
+  // XXX See bug 1018791 Implement W3 codec reservation policy
+  // Note that currently, OMXCodecReservation needs to be held by an sp<> because it puts
+  // 'this' into an sp<EventListener> to talk to the resource reservation code
+#ifdef MOZ_WEBRTC_OMX
+  android::sp<android::OMXCodecReservation> encode = new android::OMXCodecReservation(true);
+  android::sp<android::OMXCodecReservation> decode = new android::OMXCodecReservation(false);
+
+  // Currently we just check if they're available right now, which will fail if we're
+  // trying to call ourself, for example.  It will work for most real-world cases, like
+  // if we try to add a person to a 2-way call to make a 3-way mesh call
+  if (encode->ReserveOMXCodec() && decode->ReserveOMXCodec()) {
+    CSFLogDebug( logTag, "%s: H264 hardware codec available", __FUNCTION__);
+    return VCM_CODEC_RESOURCE_H264;
+  }
+#endif
+
+  return 0;
+}
+
 void VcmSIPCCBinding::setMainThread(nsIThread *thread)
 {
   gMainThread = thread;
 }
 
 void VcmSIPCCBinding::setSTSThread(nsIEventTarget *thread)
 {
   gSTSThread = thread;
@@ -2720,22 +2757,39 @@ int vcmGetVideoCodecList(int request_typ
     retVal = VcmSIPCCBinding::getVideoTermination() ? VcmSIPCCBinding::getVideoTermination()->getCodecList( map_codec_request_type(request_type) ) : 0;
 
     if ( retVal & VideoCodecMask_H264 )    codecMask |= DSP_H264;
     if ( retVal & VideoCodecMask_H263 )    codecMask |= DSP_H263;
 
     CSFLogDebug( logTag, "%s(codec_mask = %X)", fname, codecMask);
 
     //return codecMask;
-        return VCM_CODEC_RESOURCE_H264;
+    return VCM_CODEC_RESOURCE_H264;
 #else
-  int codecMask = VcmSIPCCBinding::getVideoCodecs();
-  CSFLogDebug(logTag, "GetVideoCodecList returning %X", codecMask);
-
-  return codecMask;
+  // Control if H264 is available and priority:
+  // If hardware codecs are available (VP8 or H264), use those as a preferred codec
+  // (question: on all platforms?)
+  // If OpenH264 is available, use that at lower priority to VP8
+  // (question: platform software or OS-unknown-impl codecs?  (Win8.x, etc)
+  // Else just use VP8 software
+
+    int codecMask;
+    switch (request_type) {
+      case VCM_DSP_FULLDUPLEX_HW:
+        codecMask = VcmSIPCCBinding::getVideoCodecsHw();
+        break;
+      case VCM_DSP_FULLDUPLEX_GMP:
+        codecMask = VcmSIPCCBinding::getVideoCodecsGmp();
+        break;
+      default: // VCM_DSP_FULLDUPLEX
+        codecMask = VcmSIPCCBinding::getVideoCodecs();
+        break;
+    }
+    CSFLogDebug(logTag, "GetVideoCodecList returning %X", codecMask);
+    return codecMask;
 #endif
 }
 
 /**
  * Get max supported H.264 video packetization mode.
  * @return maximum supported video packetization mode for H.264. Value returned
  * must be 0 or 1. Value 2 is not supported yet.
  */
--- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.h
+++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.h
@@ -53,19 +53,22 @@ namespace CSF
         static AudioControl * getAudioControl();
         static VideoControl * getVideoControl();
 
         void setMediaProviderObserver(MediaProviderObserver* obs);
         static MediaProviderObserver * getMediaProviderObserver();
 
         static void setAudioCodecs(int codecMask);
         static void setVideoCodecs(int codecMask);
+        static void addVideoCodecsGmp(int codecMask);
 
         static int getAudioCodecs();
         static int getVideoCodecs();
+        static int getVideoCodecsGmp();
+        static int getVideoCodecsHw();
 
 	static void setMainThread(nsIThread *thread);
 	static nsIThread *getMainThread();
 	static nsIEventTarget *getSTSThread();
 
 	static void setSTSThread(nsIEventTarget *thread);
 
 	static void connectCandidateSignal(mozilla::NrIceMediaStream* stream);
@@ -76,16 +79,17 @@ namespace CSF
 	void CandidateReady(mozilla::NrIceMediaStream* stream,
 			    const std::string& candidate);
 
         static VcmSIPCCBinding * gSelf;
         StreamObserver* streamObserver;
         MediaProviderObserver *mediaProviderObserver;
         static int gAudioCodecMask;
         static int gVideoCodecMask;
+        static int gVideoCodecGmpMask;
 	static nsIThread *gMainThread;
 	static nsIEventTarget *gSTSThread;
         static nsCOMPtr<nsIPrefBranch> gBranch;
     };
 }
 
 #endif
 
--- a/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
+++ b/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
@@ -588,68 +588,76 @@ config_get_video_max_fr(const rtp_ptype 
   uint32_t max_fr;
 
   if(vcmGetVideoMaxFr(codec, (int32_t *) &max_fr) == 0) {
     return max_fr;
   }
   return 0;
 }
 
+uint16_t
+sip_config_video_add_codecs (rtp_ptype aSupportedCodecs[],
+                             uint16_t supportedCodecsLen,
+                             uint16_t codec_mask)
+{
+  uint16_t count = 0;
+
+  // All things being equal, prefer VP8 > H.264 p1 > H.264 p0 -> H.263
+  if ( codec_mask & VCM_CODEC_RESOURCE_VP8) {
+    aSupportedCodecs[count] = RTP_VP8;
+    count++;
+  }
+  if ( codec_mask & VCM_CODEC_RESOURCE_H264) {
+    if (vcmGetVideoMaxSupportedPacketizationMode() == 1) {
+      aSupportedCodecs[count] = RTP_H264_P1;
+      count++;
+    }
+    aSupportedCodecs[count] = RTP_H264_P0;
+    count++;
+  }
+  if ( codec_mask & VCM_CODEC_RESOURCE_H263) {
+    aSupportedCodecs[count] = RTP_H263;
+    count++;
+  }
+  return count;
+}
+
 /*
  * sip_config_local_supported_codecs_get()
  *
  * Get the locally supported codec list.
  */
 uint16_t
 sip_config_video_supported_codecs_get (rtp_ptype aSupportedCodecs[],
                           uint16_t supportedCodecsLen, boolean isOffer)
 {
     uint16_t count = 0;
     int codec_mask;
+    int hw_codec_mask = vcmGetVideoCodecList(VCM_DSP_FULLDUPLEX_HW);
+    int gmp_codec_mask = vcmGetVideoCodecList(VCM_DSP_FULLDUPLEX_GMP);
 
     if ( isOffer ) {
         codec_mask = vcmGetVideoCodecList(VCM_DSP_FULLDUPLEX);
     } else {
         /* we are trying to match the answer then we
            already have the rx stream open */
         //codec_mask = vcmGetVideoCodecList(DSP_ENCODEONLY);
         codec_mask = vcmGetVideoCodecList(VCM_DSP_IGNORE);
     }
-#ifdef WEBRTC_GONK
-    if ( codec_mask & VCM_CODEC_RESOURCE_H264) {
-      if (vcmGetVideoMaxSupportedPacketizationMode() == 1) {
-        aSupportedCodecs[count] = RTP_H264_P1;
-        count++;
-      }
-      aSupportedCodecs[count] = RTP_H264_P0;
-      count++;
-    }
-    if ( codec_mask & VCM_CODEC_RESOURCE_VP8) {
-      aSupportedCodecs[count] = RTP_VP8;
-      count++;
-    }
-#else
-    // Apply video codecs with VP8 first on non gonk
-    if ( codec_mask & VCM_CODEC_RESOURCE_VP8) {
-      aSupportedCodecs[count] = RTP_VP8;
-      count++;
-    }
-    if ( codec_mask & VCM_CODEC_RESOURCE_H264) {
-      if (vcmGetVideoMaxSupportedPacketizationMode() == 1) {
-        aSupportedCodecs[count] = RTP_H264_P1;
-        count++;
-      }
-      aSupportedCodecs[count] = RTP_H264_P0;
-      count++;
-    }
-#endif
-    if ( codec_mask & VCM_CODEC_RESOURCE_H263) {
-      aSupportedCodecs[count] = RTP_H263;
-      count++;
-    }
+    // prefer HW codecs over SW
+    count = sip_config_video_add_codecs(aSupportedCodecs,
+                                        supportedCodecsLen, hw_codec_mask);
+    // Now add any codecs that weren't in the initial list
+    codec_mask &= ~hw_codec_mask;
+    count += sip_config_video_add_codecs(&aSupportedCodecs[count],
+                                         supportedCodecsLen, codec_mask);
+    // Now add any GMP codecs that aren't already in
+    gmp_codec_mask &= ~(hw_codec_mask | codec_mask);
+    count += sip_config_video_add_codecs(&aSupportedCodecs[count],
+                                         supportedCodecsLen, gmp_codec_mask);
 
     return count;
 }
 
 /**
  * The function fills in the given codec array based on the
  * platform bit mask of codecs.  Note, that the enumerated list
  * produced is also in the preferred order.
--- a/media/webrtc/signaling/src/sipcc/include/vcm.h
+++ b/media/webrtc/signaling/src/sipcc/include/vcm.h
@@ -58,16 +58,18 @@
 #define VCM_CODEC_RESOURCE_VP8      0x00000100
 #define VCM_CODEC_RESOURCE_I420     0x00000200
 #define VCM_CODEC_RESOURCE_OPUS     0x00000400
 
 #define VCM_DSP_DECODEONLY  0
 #define VCM_DSP_ENCODEONLY  1
 #define VCM_DSP_FULLDUPLEX  2
 #define VCM_DSP_IGNORE      3
+#define VCM_DSP_FULLDUPLEX_HW 4 // HW codecs
+#define VCM_DSP_FULLDUPLEX_GMP 5 // GMP-loaded codecs
 
 #define CC_KFACTOR_STAT_LEN   (256)
 
 /* Should be enough for any reasonable use-case */
 #define MAX_SSRCS_PER_MEDIA_LINE 16
 #define MAX_PTS_PER_MEDIA_LINE 16
 
 /**
--- 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
@@ -553,16 +553,21 @@ void VCMCodecDataBase::CopyDecoder(const
   }
 }
 
 bool VCMCodecDataBase::SupportsRenderScheduling() const {
   bool render_timing = true;
   if (current_dec_is_external_) {
     const VCMExtDecoderMapItem* ext_item = FindExternalDecoderItem(
         receive_codec_.plType);
+    if (!ext_item) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(id_),
+                   "Unknown payload type: %u", receive_codec_.plType);
+      return false;
+    }
     render_timing = ext_item->internal_render_timing;
   }
   return render_timing;
 }
 
 VCMGenericDecoder* VCMCodecDataBase::CreateAndInitDecoder(
     uint8_t payload_type,
     VideoCodec* new_codec,