Bug 584259 - Add support for StereoMode element. r=roc a=roc
authorMatthew Gregan <kinetik@flim.org>
Wed, 03 Nov 2010 12:43:29 +1300
changeset 59431 df3122f033283062d715cf9a66700073ce4f3275
parent 59430 28f582d9b6d8a24dca02b3937a283689344bacdb
child 59432 b9dcbc836bb37bbea71a9c688cd5cd3e5620d5df
push idunknown
push userunknown
push dateunknown
reviewersroc, roc
bugs584259
milestone2.0b9pre
Bug 584259 - Add support for StereoMode element. r=roc a=roc
content/media/nsBuiltinDecoderReader.cpp
content/media/nsBuiltinDecoderReader.h
content/media/webm/nsWebMReader.cpp
gfx/layers/ImageLayers.h
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/d3d9/LayerManagerD3D9.cpp
gfx/layers/d3d9/LayerManagerD3D9.h
gfx/layers/d3d9/Nv3DVUtils.cpp
gfx/layers/d3d9/Nv3DVUtils.h
modules/libpref/src/init/all.js
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -143,16 +143,17 @@ VideoData* VideoData::Create(nsVideoInfo
   data.mYStride = aBuffer.mPlanes[0].mStride;
   data.mCbChannel = aBuffer.mPlanes[1].mData;
   data.mCrChannel = aBuffer.mPlanes[2].mData;
   data.mCbCrSize = gfxIntSize(aBuffer.mPlanes[1].mWidth, aBuffer.mPlanes[1].mHeight);
   data.mCbCrStride = aBuffer.mPlanes[1].mStride;
   data.mPicX = aInfo.mPicture.x;
   data.mPicY = aInfo.mPicture.y;
   data.mPicSize = gfxIntSize(aInfo.mPicture.width, aInfo.mPicture.height);
+  data.mStereoMode = aInfo.mStereoMode;
 
   videoImage->SetData(data); // Copies buffer
   return v.forget();
 }
 
 nsBuiltinDecoderReader::nsBuiltinDecoderReader(nsBuiltinDecoder* aDecoder)
   : mMonitor("media.decoderreader"),
     mDecoder(aDecoder),
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -54,16 +54,17 @@ class nsBuiltinDecoderStateMachine;
 // Stores info relevant to presenting media samples.
 class nsVideoInfo {
 public:
   nsVideoInfo()
     : mPixelAspectRatio(1.0),
       mAudioRate(0),
       mAudioChannels(0),
       mFrame(0,0),
+      mStereoMode(mozilla::layers::STEREO_MODE_MONO),
       mHasAudio(PR_FALSE),
       mHasVideo(PR_FALSE)
   {}
 
   // Pixel aspect ratio, as stored in the metadata.
   float mPixelAspectRatio;
 
   // Samples per second.
@@ -77,16 +78,19 @@ public:
 
   // The picture region inside the video frame to be displayed.
   nsIntRect mPicture;
 
   // The offset of the first non-header page in the file, in bytes.
   // Used to seek to the start of the media.
   PRInt64 mDataOffset;
 
+  // Indicates the frame layout for single track stereo videos.
+  mozilla::layers::StereoMode mStereoMode;
+
   // PR_TRUE if we have an active audio bitstream.
   PRPackedBool mHasAudio;
 
   // PR_TRUE if we have an active video bitstream.
   PRPackedBool mHasVideo;
 };
 
 #ifdef MOZ_TREMOR
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -38,18 +38,21 @@
  * ***** END LICENSE BLOCK ***** */
 #include "nsError.h"
 #include "nsBuiltinDecoderStateMachine.h"
 #include "nsBuiltinDecoder.h"
 #include "nsMediaStream.h"
 #include "nsWebMReader.h"
 #include "VideoUtils.h"
 #include "nsTimeRanges.h"
+#include "nsIServiceManager.h"
+#include "nsIPrefService.h"
 
 using namespace mozilla;
+using namespace mozilla::layers;
 
 // Un-comment to enable logging of seek bisections.
 //#define SEEK_LOGGING
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gBuiltinDecoderLog;
 #define LOG(type, msg) PR_LOG(gBuiltinDecoderLog, type, msg)
 #ifdef SEEK_LOGGING
@@ -263,16 +266,55 @@ nsresult nsWebMReader::ReadMetadata()
       // If the cropping data appears invalid then use the frame data
       if (mInfo.mPicture.width <= 0 || mInfo.mPicture.height <= 0) {
         mInfo.mPicture.x = 0;
         mInfo.mPicture.y = 0;
         mInfo.mPicture.width = params.width;
         mInfo.mPicture.height = params.height;
       }
 
+      switch (params.stereo_mode) {
+      case NESTEGG_VIDEO_MONO:
+        mInfo.mStereoMode = STEREO_MODE_MONO;
+        break;
+      case NESTEGG_VIDEO_STEREO_LEFT_RIGHT:
+        mInfo.mStereoMode = STEREO_MODE_LEFT_RIGHT;
+        break;
+      case NESTEGG_VIDEO_STEREO_BOTTOM_TOP:
+        mInfo.mStereoMode = STEREO_MODE_BOTTOM_TOP;
+        break;
+      case NESTEGG_VIDEO_STEREO_TOP_BOTTOM:
+        mInfo.mStereoMode = STEREO_MODE_TOP_BOTTOM;
+        break;
+      case NESTEGG_VIDEO_STEREO_RIGHT_LEFT:
+        mInfo.mStereoMode = STEREO_MODE_RIGHT_LEFT;
+        break;
+      }
+
+      nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+      PRInt32 forceStereoMode;
+      if (NS_SUCCEEDED(prefs->GetIntPref("media.webm.force_stereo_mode", &forceStereoMode))) {
+        switch (forceStereoMode) {
+        case 1:
+          mInfo.mStereoMode = STEREO_MODE_LEFT_RIGHT;
+          break;
+        case 2:
+          mInfo.mStereoMode = STEREO_MODE_RIGHT_LEFT;
+          break;
+        case 3:
+          mInfo.mStereoMode = STEREO_MODE_TOP_BOTTOM;
+          break;
+        case 4:
+          mInfo.mStereoMode = STEREO_MODE_BOTTOM_TOP;
+          break;
+        default:
+          mInfo.mStereoMode = STEREO_MODE_MONO;
+        }
+      }
+
       // mDataOffset is not used by the WebM backend.
       // See bug 566779 for a suggestion to refactor
       // and remove it.
       mInfo.mDataOffset = -1;
     }
     else if (!mHasAudio && type == NESTEGG_TRACK_AUDIO) {
       nestegg_audio_params params;
       r = nestegg_track_audio_params(mContext, track, &params);
--- a/gfx/layers/ImageLayers.h
+++ b/gfx/layers/ImageLayers.h
@@ -41,16 +41,24 @@
 #include "Layers.h"
 
 #include "gfxPattern.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace layers {
 
+enum StereoMode {
+  STEREO_MODE_MONO,
+  STEREO_MODE_LEFT_RIGHT,
+  STEREO_MODE_RIGHT_LEFT,
+  STEREO_MODE_BOTTOM_TOP,
+  STEREO_MODE_TOP_BOTTOM
+};
+
 /**
  * A class representing a buffer of pixel data. The data can be in one
  * of various formats including YCbCr.
  * 
  * Create an image using an ImageContainer. Fill the image with data, and
  * then call ImageContainer::SetImage to display it. An image must not be
  * modified after calling SetImage. Image implementations do not need to
  * perform locking; when filling an Image, the Image client is responsible
@@ -272,16 +280,17 @@ public:
     PRUint8* mCbChannel;
     PRUint8* mCrChannel;
     PRInt32 mCbCrStride;
     gfxIntSize mCbCrSize;
     // Picture region
     PRUint32 mPicX;
     PRUint32 mPicY;
     gfxIntSize mPicSize;
+    StereoMode mStereoMode;
   };
 
   enum {
     MAX_DIMENSION = 16384
   };
 
   /**
    * This makes a copy of the data buffers.
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -171,27 +171,45 @@ ImageLayerD3D9::RenderLayer()
                                                           yuvImage->mSize.width,
                                                           yuvImage->mSize.height),
                                        1);
 
     SetShaderTransformAndOpacity();
 
     mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER);
 
-    /* 
-     * Send 3d control data and metadata 
-     */ 
-    if (mD3DManager->Is3DEnabled() && mD3DManager->GetNv3DVUtils()) { 
-      mD3DManager->GetNv3DVUtils()->SendNv3DVControl(STEREO_MODE_RIGHT_LEFT, true, FIREFOX_3DV_APP_HANDLE); 
+    if (yuvImage->mData.mStereoMode != STEREO_MODE_MONO) {
+      Nv_Stereo_Mode mode;
+      switch (yuvImage->mData.mStereoMode) {
+      case STEREO_MODE_LEFT_RIGHT:
+        mode = NV_STEREO_MODE_LEFT_RIGHT;
+        break;
+      case STEREO_MODE_RIGHT_LEFT:
+        mode = NV_STEREO_MODE_RIGHT_LEFT;
+        break;
+      case STEREO_MODE_BOTTOM_TOP:
+        mode = NV_STEREO_MODE_BOTTOM_TOP;
+        break;
+      case STEREO_MODE_TOP_BOTTOM:
+        mode = NV_STEREO_MODE_TOP_BOTTOM;
+        break;
+      }
 
-      nsRefPtr<IDirect3DSurface9> renderTarget; 
-      device()->GetRenderTarget(0, getter_AddRefs(renderTarget)); 
-      mD3DManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->mSize.width, 
-        (unsigned int)yuvImage->mSize.height, (HANDLE)(yuvImage->mYTexture), (HANDLE)(renderTarget)); 
-    } 
+      /*
+       * Send 3d control data and metadata
+       */
+      if (mD3DManager->GetNv3DVUtils()) {
+        mD3DManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
+
+        nsRefPtr<IDirect3DSurface9> renderTarget;
+        device()->GetRenderTarget(0, getter_AddRefs(renderTarget));
+        mD3DManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->mSize.width,
+                                                        (unsigned int)yuvImage->mSize.height, (HANDLE)(yuvImage->mYTexture), (HANDLE)(renderTarget));
+      }
+    }
 
     device()->SetTexture(0, yuvImage->mYTexture);
     device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
     device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     device()->SetTexture(1, yuvImage->mCbTexture);
     device()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
     device()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     device()->SetTexture(2, yuvImage->mCrTexture);
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -37,50 +37,43 @@
 
 #include "LayerManagerD3D9.h"
 
 #include "ThebesLayerD3D9.h"
 #include "ContainerLayerD3D9.h"
 #include "ImageLayerD3D9.h"
 #include "ColorLayerD3D9.h"
 #include "CanvasLayerD3D9.h"
-#include "nsIServiceManager.h"
-#include "nsIPrefService.h"
 #include "gfxWindowsPlatform.h"
 #include "nsIGfxInfo.h"
 
 #ifdef CAIRO_HAS_D2D_SURFACE
 #include "gfxD2DSurface.h"
 #endif
 
 namespace mozilla {
 namespace layers {
 
 DeviceManagerD3D9 *LayerManagerD3D9::mDefaultDeviceManager = nsnull;
 
 LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
-  : mIs3DEnabled(PR_FALSE)
 {
   mWidget = aWidget;
   mCurrentCallbackInfo.Callback = NULL;
   mCurrentCallbackInfo.CallbackData = NULL;
 }
 
 LayerManagerD3D9::~LayerManagerD3D9()
 {
   Destroy();
 }
 
 PRBool
 LayerManagerD3D9::Initialize()
 {
-  /* Check the user preference for whether 3d video is enabled or not */ 
-  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); 
-  prefs->GetBoolPref("gfx.3d_video.enabled", &mIs3DEnabled);
-
   nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   if (gfxInfo) {
     PRInt32 status;
     if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) {
       if (status != nsIGfxInfo::FEATURE_NO_INFO)
       {
         NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
         return PR_FALSE;
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -170,21 +170,16 @@ public:
   IDirect3DDevice9 *device() const { return mDeviceManager->device(); }
   DeviceManagerD3D9 *deviceManager() const { return mDeviceManager; }
 
   /** 
    * Return pointer to the Nv3DVUtils instance. Re-direct to mDeviceManager.
    */ 
   Nv3DVUtils *GetNv3DVUtils()  { return mDeviceManager ? mDeviceManager->GetNv3DVUtils() : NULL; } 
 
-  /** 
-   * Indicate whether 3D is enabled or not 
-   */ 
-  PRBool Is3DEnabled() { return mIs3DEnabled; } 
-
   static void OnDeviceManagerDestroy(DeviceManagerD3D9 *aDeviceManager) {
     if(aDeviceManager == mDefaultDeviceManager)
       mDefaultDeviceManager = nsnull;
   }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() const { return "D3D9"; }
 #endif // MOZ_LAYERS_HAVE_LOG
@@ -207,19 +202,16 @@ private:
   /*
    * Context target, NULL when drawing directly to our swap chain.
    */
   nsRefPtr<gfxContext> mTarget;
 
   /* Callback info for current transaction */
   CallbackInfo mCurrentCallbackInfo;
 
-  /* Flag that indicates whether 3D is enabled or not*/ 
-  PRBool mIs3DEnabled; 
-
   /*
    * Region we're clipping our current drawing to.
    */
   nsIntRegion mClippingRegion;
 
   /*
    * Render the current layer tree to the active target.
    */
--- a/gfx/layers/d3d9/Nv3DVUtils.cpp
+++ b/gfx/layers/d3d9/Nv3DVUtils.cpp
@@ -128,26 +128,26 @@ Nv3DVUtils::SetDeviceInfo(IUnknown *devU
 
   bool rv = false;
   rv = m3DVStreaming->Nv3DVSetDevice(devUnknown);
   NS_ASSERTION(rv, "Nv3DVStreaming Nv3DVControl failed!");
 
   if (!rv)
       return;
 
-  rv = m3DVStreaming->Nv3DVControl(STEREO_MODE_RIGHT_LEFT, true, FIREFOX_3DV_APP_HANDLE);
+  rv = m3DVStreaming->Nv3DVControl(NV_STEREO_MODE_RIGHT_LEFT, true, FIREFOX_3DV_APP_HANDLE);
   NS_ASSERTION(rv, "Nv3DVStreaming Nv3DVControl failed!");
 }
 
 /*
  * Send Stereo Control Information. Used mainly to re-route 
  * calls from ImageLayerD3D9 to the 3DV COM object
  */
 void 
-Nv3DVUtils::SendNv3DVControl(Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle)
+Nv3DVUtils::SendNv3DVControl(Nv_Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle)
 {
   if (!m3DVStreaming)
       return;
 
   bool rv = m3DVStreaming->Nv3DVControl(eStereoMode, bEnableStereo, dw3DVAppHandle);
   NS_ASSERTION(rv, "Nv3DVStreaming Nv3DVControl failed");
 }
 
--- a/gfx/layers/d3d9/Nv3DVUtils.h
+++ b/gfx/layers/d3d9/Nv3DVUtils.h
@@ -42,31 +42,31 @@
 #include <windows.h>
 #include <d3d9.h>
 
 namespace mozilla {
 namespace layers {
 
 #define FIREFOX_3DV_APP_HANDLE    0xECB992B6
 
-typedef enum _Stereo_Mode {
-  STEREO_MODE_LEFT_RIGHT = 0,
-  STEREO_MODE_RIGHT_LEFT = 1,
-  STEREO_MODE_TOP_BOTTOM = 2,
-  STEREO_MODE_BOTTOM_TOP = 3,
-  STEREO_MODE_LAST       = 4 
-} Stereo_Mode;
+enum Nv_Stereo_Mode {
+  NV_STEREO_MODE_LEFT_RIGHT = 0,
+  NV_STEREO_MODE_RIGHT_LEFT = 1,
+  NV_STEREO_MODE_TOP_BOTTOM = 2,
+  NV_STEREO_MODE_BOTTOM_TOP = 3,
+  NV_STEREO_MODE_LAST       = 4 
+};
 
 class INv3DVStreaming : public IUnknown {
 
 public:
   virtual bool Nv3DVInitialize()                  = 0;
   virtual bool Nv3DVRelease()                     = 0;
   virtual bool Nv3DVSetDevice(IUnknown* pDevice)  = 0;
-  virtual bool Nv3DVControl(Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle) = 0;
+  virtual bool Nv3DVControl(Nv_Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle) = 0;
   virtual bool Nv3DVMetaData(DWORD dwWidth, DWORD dwHeight, HANDLE hSrcLuma, HANDLE hDst) = 0;
 };
 
 /*
  * Nv3DVUtils class
  */
 class Nv3DVUtils {
 
@@ -90,17 +90,17 @@ public:
    * Pass the D3D9 device pointer is an IUnknown input argument
    */
   void SetDeviceInfo(IUnknown *devUnknown);
 
   /*
    * Send Stereo Control Information. Used mainly to re-route 
    * calls from ImageLayerD3D9 to the 3DV COM object
    */
-  void SendNv3DVControl(Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle);
+  void SendNv3DVControl(Nv_Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle);
 
   /*
    * Send Stereo Metadata. Used mainly to re-route calls 
    * from ImageLayerD3D9 to the 3DV COM object
    */
   void SendNv3DVMetaData(unsigned int dwWidth, unsigned int dwHeight, HANDLE hSrcLuma, HANDLE hDst);
 
 private:
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -184,18 +184,16 @@ pref("media.webm.enabled", true);
 pref("media.autoplay.enabled", true);
 
 // 0 = Off, 1 = Full, 2 = Tagged Images Only. 
 // See eCMSMode in gfx/thebes/gfxPlatform.h
 pref("gfx.color_management.mode", 2);
 pref("gfx.color_management.display_profile", "");
 pref("gfx.color_management.rendering_intent", 0);
 
-pref("gfx.3d_video.enabled", false);
-
 pref("gfx.downloadable_fonts.enabled", true);
 pref("gfx.downloadable_fonts.sanitize", true);
 #ifdef XP_MACOSX
 pref("gfx.downloadable_fonts.sanitize.preserve_otl_tables", false);
 #else
 pref("gfx.downloadable_fonts.sanitize.preserve_otl_tables", true);
 #endif