Bug 839031 - Report Content-Type on WMFByteStream to faciliate WMF selecting the right decoder. r=padenot
authorChris Pearce <cpearce@mozilla.com>
Fri, 15 Feb 2013 14:11:05 +1300
changeset 122264 40f6ab9cf2f3db2818b1f8125f71bb2fc5aaf6f0
parent 122263 e50df4a601e4d9743038a7c881fa5fcb4b51f27e
child 122265 48bf677726b8dcc7bd4510b0b6c81279d83f33ba
push id24327
push usergszorc@mozilla.com
push dateTue, 19 Feb 2013 05:22:32 +0000
treeherdermozilla-central@e8f8a3f6f1f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs839031
milestone21.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 839031 - Report Content-Type on WMFByteStream to faciliate WMF selecting the right decoder. r=padenot
content/media/wmf/WMF.h
content/media/wmf/WMFByteStream.cpp
content/media/wmf/WMFByteStream.h
content/media/wmf/WMFUtils.cpp
--- a/content/media/wmf/WMF.h
+++ b/content/media/wmf/WMF.h
@@ -79,16 +79,18 @@ HRESULT MFGetStrideForBitmapInfoHeader(D
 
 // Note: We shouldn't use this in production code; it's really only
 // here so we can compare behaviour of the SourceReader using WMF's
 // byte stream and ours when debugging.
 HRESULT MFCreateSourceReaderFromURL(LPCWSTR aURL,
                                     IMFAttributes *aAttributes,
                                     IMFSourceReader **aSourceReader);
 
+HRESULT MFCreateAttributes(IMFAttributes **ppMFAttributes, UINT32 cInitialSize);
+
 } // end namespace wmf
 } // end namespace mozilla
 
 
 
 #pragma pop_macro("WINVER")
 
 #endif
--- a/content/media/wmf/WMFByteStream.cpp
+++ b/content/media/wmf/WMFByteStream.cpp
@@ -154,16 +154,27 @@ WMFByteStream::Init()
     NS_ENSURE_SUCCESS(rv, rv);
   }
   sThreadPoolRefCnt++;
 
   // Store a ref to the thread pool, so that we keep the pool alive as long as
   // we're alive.
   mThreadPool = sThreadPool;
 
+  NS_ConvertUTF8toUTF16 contentTypeUTF16(mResource->GetContentType());
+  if (!contentTypeUTF16.IsEmpty()) {
+    HRESULT hr = wmf::MFCreateAttributes(byRef(mAttributes), 1);
+    NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
+
+    hr = mAttributes->SetString(MF_BYTESTREAM_CONTENT_TYPE,
+                                contentTypeUTF16.get());
+    NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
+
+    LOG("WMFByteStream has Content-Type=%s", mResource->GetContentType());
+  }
   return NS_OK;
 }
 
 nsresult
 WMFByteStream::Shutdown()
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   mIsShutdown = true;
@@ -177,16 +188,19 @@ WMFByteStream::QueryInterface(REFIID aII
   LOG("WMFByteStream::QueryInterface %s", GetGUIDName(aIId).get());
 
   if (aIId == IID_IMFByteStream) {
     return DoGetInterface(static_cast<IMFByteStream*>(this), aInterface);
   }
   if (aIId == IID_IUnknown) {
     return DoGetInterface(static_cast<IMFByteStream*>(this), aInterface);
   }
+  if (aIId == IID_IMFAttributes) {
+    return DoGetInterface(static_cast<IMFAttributes*>(this), aInterface);
+  }
 
   *aInterface = NULL;
   return E_NOINTERFACE;
 }
 
 NS_IMPL_THREADSAFE_ADDREF(WMFByteStream)
 NS_IMPL_THREADSAFE_RELEASE(WMFByteStream)
 
@@ -549,9 +563,222 @@ WMFByteStream::SetLength(QWORD)
 
 STDMETHODIMP
 WMFByteStream::Write(const BYTE *, ULONG, ULONG *)
 {
   LOG("WMFByteStream::Write()");
   return E_NOTIMPL;
 }
 
+// IMFAttributes methods
+STDMETHODIMP
+WMFByteStream::GetItem(REFGUID guidKey, PROPVARIANT* pValue)
+{
+    MOZ_ASSERT(mAttributes);
+    return mAttributes->GetItem(guidKey, pValue);
+}
+
+STDMETHODIMP
+WMFByteStream::GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType)
+{
+    assert(mAttributes);
+    return mAttributes->GetItemType(guidKey, pType);
+}
+
+STDMETHODIMP
+WMFByteStream::CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL* pbResult)
+{
+    assert(mAttributes);
+    return mAttributes->CompareItem(guidKey, Value, pbResult);
+}
+
+STDMETHODIMP
+WMFByteStream::Compare(IMFAttributes* pTheirs,
+                       MF_ATTRIBUTES_MATCH_TYPE MatchType,
+                       BOOL* pbResult)
+{
+    assert(mAttributes);
+    return mAttributes->Compare(pTheirs, MatchType, pbResult);
+}
+
+STDMETHODIMP
+WMFByteStream::GetUINT32(REFGUID guidKey, UINT32* punValue)
+{
+    assert(mAttributes);
+    return mAttributes->GetUINT32(guidKey, punValue);
+}
+
+STDMETHODIMP
+WMFByteStream::GetUINT64(REFGUID guidKey, UINT64* punValue)
+{
+    assert(mAttributes);
+    return mAttributes->GetUINT64(guidKey, punValue);
+}
+
+STDMETHODIMP
+WMFByteStream::GetDouble(REFGUID guidKey, double* pfValue)
+{
+    assert(mAttributes);
+    return mAttributes->GetDouble(guidKey, pfValue);
+}
+
+STDMETHODIMP
+WMFByteStream::GetGUID(REFGUID guidKey, GUID* pguidValue)
+{
+    assert(mAttributes);
+    return mAttributes->GetGUID(guidKey, pguidValue);
+}
+
+STDMETHODIMP
+WMFByteStream::GetStringLength(REFGUID guidKey, UINT32* pcchLength)
+{
+    assert(mAttributes);
+    return mAttributes->GetStringLength(guidKey, pcchLength);
+}
+
+STDMETHODIMP
+WMFByteStream::GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32* pcchLength)
+{
+    assert(mAttributes);
+    return mAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength);
+}
+
+STDMETHODIMP
+WMFByteStream::GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue, UINT32* pcchLength)
+{
+    assert(mAttributes);
+    return mAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength);
+}
+
+STDMETHODIMP
+WMFByteStream::GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize)
+{
+    assert(mAttributes);
+    return mAttributes->GetBlobSize(guidKey, pcbBlobSize);
+}
+
+STDMETHODIMP
+WMFByteStream::GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize, UINT32* pcbBlobSize)
+{
+    assert(mAttributes);
+    return mAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize);
+}
+
+STDMETHODIMP
+WMFByteStream::GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf, UINT32* pcbSize)
+{
+    assert(mAttributes);
+    return mAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize);
+}
+
+STDMETHODIMP
+WMFByteStream::GetUnknown(REFGUID guidKey, REFIID riid, LPVOID* ppv)
+{
+    assert(mAttributes);
+    return mAttributes->GetUnknown(guidKey, riid, ppv);
+}
+
+STDMETHODIMP
+WMFByteStream::SetItem(REFGUID guidKey, REFPROPVARIANT Value)
+{
+    assert(mAttributes);
+    return mAttributes->SetItem(guidKey, Value);
+}
+
+STDMETHODIMP
+WMFByteStream::DeleteItem(REFGUID guidKey)
+{
+    assert(mAttributes);
+    return mAttributes->DeleteItem(guidKey);
+}
+
+STDMETHODIMP
+WMFByteStream::DeleteAllItems()
+{
+    assert(mAttributes);
+    return mAttributes->DeleteAllItems();
+}
+
+STDMETHODIMP
+WMFByteStream::SetUINT32(REFGUID guidKey, UINT32 unValue)
+{
+    assert(mAttributes);
+    return mAttributes->SetUINT32(guidKey, unValue);
+}
+
+STDMETHODIMP
+WMFByteStream::SetUINT64(REFGUID guidKey,UINT64 unValue)
+{
+    assert(mAttributes);
+    return mAttributes->SetUINT64(guidKey, unValue);
+}
+
+STDMETHODIMP
+WMFByteStream::SetDouble(REFGUID guidKey, double fValue)
+{
+    assert(mAttributes);
+    return mAttributes->SetDouble(guidKey, fValue);
+}
+
+STDMETHODIMP
+WMFByteStream::SetGUID(REFGUID guidKey, REFGUID guidValue)
+{
+    assert(mAttributes);
+    return mAttributes->SetGUID(guidKey, guidValue);
+}
+
+STDMETHODIMP
+WMFByteStream::SetString(REFGUID guidKey, LPCWSTR wszValue)
+{
+    assert(mAttributes);
+    return mAttributes->SetString(guidKey, wszValue);
+}
+
+STDMETHODIMP
+WMFByteStream::SetBlob(REFGUID guidKey, const UINT8* pBuf, UINT32 cbBufSize)
+{
+    assert(mAttributes);
+    return mAttributes->SetBlob(guidKey, pBuf, cbBufSize);
+}
+
+STDMETHODIMP
+WMFByteStream::SetUnknown(REFGUID guidKey, IUnknown* pUnknown)
+{
+    assert(mAttributes);
+    return mAttributes->SetUnknown(guidKey, pUnknown);
+}
+
+STDMETHODIMP
+WMFByteStream::LockStore()
+{
+    assert(mAttributes);
+    return mAttributes->LockStore();
+}
+
+STDMETHODIMP
+WMFByteStream::UnlockStore()
+{
+    assert(mAttributes);
+    return mAttributes->UnlockStore();
+}
+
+STDMETHODIMP
+WMFByteStream::GetCount(UINT32* pcItems)
+{
+    assert(mAttributes);
+    return mAttributes->GetCount(pcItems);
+}
+
+STDMETHODIMP
+WMFByteStream::GetItemByIndex(UINT32 unIndex, GUID* pguidKey, PROPVARIANT* pValue)
+{
+    assert(mAttributes);
+    return mAttributes->GetItemByIndex(unIndex, pguidKey, pValue);
+}
+
+STDMETHODIMP
+WMFByteStream::CopyAllItems(IMFAttributes* pDest)
+{
+    assert(mAttributes);
+    return mAttributes->CopyAllItems(pDest);
+}
+
 } // namespace mozilla
--- a/content/media/wmf/WMFByteStream.h
+++ b/content/media/wmf/WMFByteStream.h
@@ -8,16 +8,17 @@
 
 #include "WMF.h"
 
 #include "nsISupportsImpl.h"
 #include "nsCOMPtr.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/Attributes.h"
 #include "nsAutoPtr.h"
+#include "mozilla/RefPtr.h"
 
 class nsIThreadPool;
 
 namespace mozilla {
 
 class MediaResource;
 class ReadRequest;
 
@@ -28,16 +29,17 @@ class ReadRequest;
 // using Read().
 //
 // Note: This implementation attempts to be bug-compatible with Windows Media
 //       Foundation's implementation of IMFByteStream. The behaviour of WMF's
 //       IMFByteStream was determined by creating it and testing the edge cases.
 //       For details see the test code at:
 //       https://github.com/cpearce/IMFByteStreamBehaviour/
 class WMFByteStream MOZ_FINAL : public IMFByteStream
+                              , public IMFAttributes
 {
 public:
   WMFByteStream(MediaResource* aResource);
   ~WMFByteStream();
 
   nsresult Init();
   nsresult Shutdown();
 
@@ -66,16 +68,48 @@ public:
   STDMETHODIMP Seek(MFBYTESTREAM_SEEK_ORIGIN aSeekOrigin,
                     LONGLONG aSeekOffset,
                     DWORD aSeekFlags,
                     QWORD *aCurrentPosition);
   STDMETHODIMP SetCurrentPosition(QWORD aPosition);
   STDMETHODIMP SetLength(QWORD);
   STDMETHODIMP Write(const BYTE *, ULONG, ULONG *);
 
+  // IMFAttributes methods
+  STDMETHODIMP GetItem(REFGUID guidKey, PROPVARIANT* pValue);
+  STDMETHODIMP GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType);
+  STDMETHODIMP CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL* pbResult);
+  STDMETHODIMP Compare(IMFAttributes* pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL* pbResult);
+  STDMETHODIMP GetUINT32(REFGUID guidKey, UINT32* punValue);
+  STDMETHODIMP GetUINT64(REFGUID guidKey, UINT64* punValue);
+  STDMETHODIMP GetDouble(REFGUID guidKey, double* pfValue);
+  STDMETHODIMP GetGUID(REFGUID guidKey, GUID* pguidValue);
+  STDMETHODIMP GetStringLength(REFGUID guidKey, UINT32* pcchLength);
+  STDMETHODIMP GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32* pcchLength);
+  STDMETHODIMP GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue, UINT32* pcchLength);
+  STDMETHODIMP GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize);
+  STDMETHODIMP GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize, UINT32* pcbBlobSize);
+  STDMETHODIMP GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf, UINT32* pcbSize);
+  STDMETHODIMP GetUnknown(REFGUID guidKey, REFIID riid, LPVOID* ppv);
+  STDMETHODIMP SetItem(REFGUID guidKey, REFPROPVARIANT Value);
+  STDMETHODIMP DeleteItem(REFGUID guidKey);
+  STDMETHODIMP DeleteAllItems();
+  STDMETHODIMP SetUINT32(REFGUID guidKey, UINT32 unValue);
+  STDMETHODIMP SetUINT64(REFGUID guidKey,UINT64 unValue);
+  STDMETHODIMP SetDouble(REFGUID guidKey, double fValue);
+  STDMETHODIMP SetGUID(REFGUID guidKey, REFGUID guidValue);
+  STDMETHODIMP SetString(REFGUID guidKey, LPCWSTR wszValue);
+  STDMETHODIMP SetBlob(REFGUID guidKey, const UINT8* pBuf, UINT32 cbBufSize);
+  STDMETHODIMP SetUnknown(REFGUID guidKey, IUnknown* pUnknown);
+  STDMETHODIMP LockStore();
+  STDMETHODIMP UnlockStore();
+  STDMETHODIMP GetCount(UINT32* pcItems);
+  STDMETHODIMP GetItemByIndex(UINT32 unIndex, GUID* pguidKey, PROPVARIANT* pValue);
+  STDMETHODIMP CopyAllItems(IMFAttributes* pDest);
+
   // We perform an async read operation in this callback implementation.
   // Processes an async read request, storing the result in aResult, and
   // notifying the caller when the read operation is complete.
   void ProcessReadRequest(IMFAsyncResult* aResult,
                           ReadRequest* aRequestState);
 private:
 
   // Locks the MediaResource and performs the read. The other read methods
@@ -106,16 +140,20 @@ private:
   ReentrantMonitor mReentrantMonitor;
 
   // Current offset of the logical read cursor. We maintain this separately
   // from the media resource's offset since a partially complete read (in Invoke())
   // would leave the resource's offset at a value unexpected by the caller,
   // since the read hadn't yet completed.
   int64_t mOffset;
 
+  // We implement IMFAttributes by forwarding all calls to an instance of the
+  // standard IMFAttributes class, which we store a reference to here.
+  RefPtr<IMFAttributes> mAttributes;
+
   // True if the resource has been shutdown, either because the WMFReader is
   // shutting down, or because the underlying MediaResource has closed.
   bool mIsShutdown;
 
   // IUnknown ref counting.
   nsAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 };
--- a/content/media/wmf/WMFUtils.cpp
+++ b/content/media/wmf/WMFUtils.cpp
@@ -375,10 +375,18 @@ HRESULT MFCreateSourceReaderFromURL(LPCW
                                     IMFAttributes *aAttributes,
                                     IMFSourceReader **aSourceReader)
 {
   DECL_FUNCTION_PTR(MFCreateSourceReaderFromURL, LPCWSTR, IMFAttributes*, IMFSourceReader**);
   ENSURE_FUNCTION_PTR(MFCreateSourceReaderFromURL, Mfreadwrite.dll)
   return (MFCreateSourceReaderFromURLPtr)(aURL, aAttributes, aSourceReader);
 }
 
+HRESULT
+MFCreateAttributes(IMFAttributes **ppMFAttributes, UINT32 cInitialSize)
+{
+  DECL_FUNCTION_PTR(MFCreateAttributes, IMFAttributes**, UINT32);
+  ENSURE_FUNCTION_PTR(MFCreateAttributes, mfplat.dll)
+  return (MFCreateAttributesPtr)(ppMFAttributes, cInitialSize);
+}
+
 } // end namespace wmf
 } // end namespace mozilla