From a02f87eea0a0e85e4e99e6d02a7edd3266c54d8d Mon Sep 17 00:00:00 2001
From: Randell Jesup <rjesup@jesup.org>
Date: Wed, 4 Jun 2014 14:52:32 -0400
Subject: [PATCH] Bug 1003712: Codec availability support and prioritization
 r=ehugg

---
 content/media/omx/OMXCodecWrapper.h           |  1 +
 .../signaling/src/media/VcmSIPCCBinding.cpp   | 62 ++++++++++++++--
 .../signaling/src/media/VcmSIPCCBinding.h     |  4 ++
 .../src/sipcc/core/common/prot_configmgr.c    | 72 ++++++++++---------
 .../webrtc/signaling/src/sipcc/include/vcm.h  |  2 +
 .../main/source/codec_database.cc             |  5 ++
 6 files changed, 110 insertions(+), 36 deletions(-)

diff --git a/content/media/omx/OMXCodecWrapper.h b/content/media/omx/OMXCodecWrapper.h
index c7dd7135d945..2ea835b40179 100644
--- a/content/media/omx/OMXCodecWrapper.h
+++ b/content/media/omx/OMXCodecWrapper.h
@@ -7,6 +7,7 @@
 #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>
diff --git a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
index 29b43c29d129..cd8ebd688255 100644
--- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
+++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
@@ -43,6 +43,7 @@
 
 #ifdef MOZ_WEBRTC_OMX
 #include "OMXVideoCodec.h"
+#include "OMXCodecWrapper.h"
 #endif
 
 extern "C" {
@@ -88,6 +89,7 @@ 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;
@@ -224,6 +226,12 @@ void VcmSIPCCBinding::setVideoCodecs(int codecMask)
   VcmSIPCCBinding::gVideoCodecMask = codecMask;
 }
 
+void VcmSIPCCBinding::addVideoCodecsGmp(int codecMask)
+{
+  CSFLogDebug(logTag, "ADDING VIDEO: %d", codecMask);
+  VcmSIPCCBinding::gVideoCodecGmpMask |= codecMask;
+}
+
 int VcmSIPCCBinding::getAudioCodecs()
 {
   return VcmSIPCCBinding::gAudioCodecMask;
@@ -234,6 +242,35 @@ 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;
@@ -2725,12 +2762,29 @@ int vcmGetVideoCodecList(int request_type)
     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);
+  // 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
 
-  return codecMask;
+    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
 }
 
diff --git a/media/webrtc/signaling/src/media/VcmSIPCCBinding.h b/media/webrtc/signaling/src/media/VcmSIPCCBinding.h
index 7a274b71a653..3cf03f14bf2c 100644
--- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.h
+++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.h
@@ -58,9 +58,12 @@ namespace CSF
 
         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();
@@ -81,6 +84,7 @@ namespace CSF
         MediaProviderObserver *mediaProviderObserver;
         static int gAudioCodecMask;
         static int gVideoCodecMask;
+        static int gVideoCodecGmpMask;
 	static nsIThread *gMainThread;
 	static nsIEventTarget *gSTSThread;
         static nsCOMPtr<nsIPrefBranch> gBranch;
diff --git a/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c b/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
index 880f4db31e37..20ba61f3929f 100755
--- a/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
+++ b/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
@@ -593,6 +593,33 @@ config_get_video_max_fr(const rtp_ptype codec)
   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()
  *
@@ -604,6 +631,8 @@ sip_config_video_supported_codecs_get (rtp_ptype aSupportedCodecs[],
 {
     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);
@@ -613,38 +642,17 @@ sip_config_video_supported_codecs_get (rtp_ptype aSupportedCodecs[],
         //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;
 }
diff --git a/media/webrtc/signaling/src/sipcc/include/vcm.h b/media/webrtc/signaling/src/sipcc/include/vcm.h
index a013521ff3f7..a362ad224bd7 100755
--- a/media/webrtc/signaling/src/sipcc/include/vcm.h
+++ b/media/webrtc/signaling/src/sipcc/include/vcm.h
@@ -63,6 +63,8 @@
 #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)
 
diff --git 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
index 6fe1727bf090..01514d14c4c2 100644
--- 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
@@ -558,6 +558,11 @@ bool VCMCodecDataBase::SupportsRenderScheduling() const {
   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;