Bug 839031 - Implement WMFByteStream::Read(). r=padenot
authorChris Pearce <cpearce@mozilla.com>
Fri, 15 Feb 2013 14:10:21 +1300
changeset 122262 83e2c0975a620ad51de68acd1654bf4680d0dee9
parent 122261 f598352c7f7f0dc2be8adb1073bee5fb58b5d1a3
child 122263 e50df4a601e4d9743038a7c881fa5fcb4b51f27e
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 - Implement WMFByteStream::Read(). r=padenot
content/media/wmf/WMFByteStream.cpp
content/media/wmf/WMFByteStream.h
--- a/content/media/wmf/WMFByteStream.cpp
+++ b/content/media/wmf/WMFByteStream.cpp
@@ -187,19 +187,19 @@ WMFByteStream::QueryInterface(REFIID aII
   return E_NOINTERFACE;
 }
 
 NS_IMPL_THREADSAFE_ADDREF(WMFByteStream)
 NS_IMPL_THREADSAFE_RELEASE(WMFByteStream)
 
 
 // Stores data regarding an async read opreation.
-class AsyncReadRequest MOZ_FINAL : public IUnknown {
+class ReadRequest MOZ_FINAL : public IUnknown {
 public:
-  AsyncReadRequest(int64_t aOffset, BYTE* aBuffer, ULONG aLength)
+  ReadRequest(int64_t aOffset, BYTE* aBuffer, ULONG aLength)
     : mOffset(aOffset),
       mBuffer(aBuffer),
       mBufferLength(aLength),
       mBytesRead(0)
   {}
 
   // IUnknown Methods
   STDMETHODIMP QueryInterface(REFIID aRIID, LPVOID *aOutObject);
@@ -211,50 +211,50 @@ public:
   ULONG mBufferLength;
   ULONG mBytesRead;
 
   // IUnknown ref counting.
   nsAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 };
 
-NS_IMPL_THREADSAFE_ADDREF(AsyncReadRequest)
-NS_IMPL_THREADSAFE_RELEASE(AsyncReadRequest)
+NS_IMPL_THREADSAFE_ADDREF(ReadRequest)
+NS_IMPL_THREADSAFE_RELEASE(ReadRequest)
 
 // IUnknown Methods
 STDMETHODIMP
-AsyncReadRequest::QueryInterface(REFIID aIId, void **aInterface)
+ReadRequest::QueryInterface(REFIID aIId, void **aInterface)
 {
-  LOG("AsyncReadRequest::QueryInterface %s", GetGUIDName(aIId).get());
+  LOG("ReadRequest::QueryInterface %s", GetGUIDName(aIId).get());
 
   if (aIId == IID_IUnknown) {
     return DoGetInterface(static_cast<IUnknown*>(this), aInterface);
   }
 
   *aInterface = NULL;
   return E_NOINTERFACE;
 }
 
 class ProcessReadRequestEvent MOZ_FINAL : public nsRunnable {
 public:
   ProcessReadRequestEvent(WMFByteStream* aStream,
                           IMFAsyncResult* aResult,
-                          AsyncReadRequest* aRequestState)
+                          ReadRequest* aRequestState)
     : mStream(aStream),
       mResult(aResult),
       mRequestState(aRequestState) {}
 
   NS_IMETHOD Run() {
     mStream->ProcessReadRequest(mResult, mRequestState);
     return NS_OK;
   }
 private:
   RefPtr<WMFByteStream> mStream;
   RefPtr<IMFAsyncResult> mResult;
-  RefPtr<AsyncReadRequest> mRequestState;
+  RefPtr<ReadRequest> mRequestState;
 };
 
 // IMFByteStream Methods
 STDMETHODIMP
 WMFByteStream::BeginRead(BYTE *aBuffer,
                          ULONG aLength,
                          IMFAsyncCallback *aCallback,
                          IUnknown *aCallerState)
@@ -266,17 +266,17 @@ WMFByteStream::BeginRead(BYTE *aBuffer,
   LOG("WMFByteStream::BeginRead() mOffset=%lld tell=%lld length=%lu mIsShutdown=%d",
       mOffset, mResource->Tell(), aLength, mIsShutdown);
 
   if (mIsShutdown || mOffset < 0) {
     return E_INVALIDARG;
   }
 
   // Create an object to store our state.
-  RefPtr<AsyncReadRequest> requestState = new AsyncReadRequest(mOffset, aBuffer, aLength);
+  RefPtr<ReadRequest> requestState = new ReadRequest(mOffset, aBuffer, aLength);
 
   // Create an IMFAsyncResult, this is passed back to the caller as a token to
   // retrieve the number of bytes read.
   RefPtr<IMFAsyncResult> callersResult;
   HRESULT hr = wmf::MFCreateAsyncResult(requestState,
                                         aCallback,
                                         aCallerState,
                                         byRef(callersResult));
@@ -293,17 +293,17 @@ WMFByteStream::BeginRead(BYTE *aBuffer,
   } else {
     mOffset += aLength;
   }
 
   return NS_SUCCEEDED(rv) ? S_OK : E_FAIL;
 }
 
 nsresult
-WMFByteStream::Read(AsyncReadRequest* aRequestState)
+WMFByteStream::Read(ReadRequest* aRequestState)
 {
   ReentrantMonitorAutoEnter mon(mResourceMonitor);
 
   // Ensure the read head is at the correct offset in the resource. It may not
   // be if the SourceReader seeked.
   if (mResource->Tell() != aRequestState->mOffset) {
     nsresult rv = mResource->Seek(nsISeekableStream::NS_SEEK_SET,
                                   aRequestState->mOffset);
@@ -329,17 +329,17 @@ WMFByteStream::Read(AsyncReadRequest* aR
   }
   aRequestState->mBytesRead = totalBytesRead;
   return NS_OK;
 }
 
 // Note: This is called on one of the thread pool's threads.
 void
 WMFByteStream::ProcessReadRequest(IMFAsyncResult* aResult,
-                                  AsyncReadRequest* aRequestState)
+                                  ReadRequest* aRequestState)
 {
   if (mResource->GetLength() > -1 &&
       aRequestState->mOffset > mResource->GetLength()) {
     aResult->SetStatus(S_OK);
     wmf::MFInvokeCallback(aResult);
     LOG("WMFByteStream::Invoke() read offset greater than length, soft-failing read");
     return;
   }
@@ -385,18 +385,18 @@ WMFByteStream::EndRead(IMFAsyncResult* a
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
   // Extract our state object.
   RefPtr<IUnknown> unknown;
   HRESULT hr = aResult->GetObject(byRef(unknown));
   if (FAILED(hr) || !unknown) {
     return E_INVALIDARG;
   }
-  AsyncReadRequest* requestState =
-    static_cast<AsyncReadRequest*>(unknown.get());
+  ReadRequest* requestState =
+    static_cast<ReadRequest*>(unknown.get());
 
   // Report result.
   *aBytesRead = requestState->mBytesRead;
 
   LOG("WMFByteStream::EndRead() offset=%lld *aBytesRead=%u mOffset=%lld status=0x%x hr=0x%x eof=%d",
       requestState->mOffset, *aBytesRead, mOffset, aResult->GetStatus(), hr, IsEOS());
 
   return aResult->GetStatus();
@@ -472,20 +472,31 @@ WMFByteStream::IsEndOfStream(BOOL *aEndO
 {
   NS_ENSURE_TRUE(aEndOfStream, E_POINTER);
   *aEndOfStream = IsEOS();
   LOG("WMFByteStream::IsEndOfStream() %d", *aEndOfStream);
   return S_OK;
 }
 
 STDMETHODIMP
-WMFByteStream::Read(BYTE*, ULONG, ULONG*)
+WMFByteStream::Read(BYTE* aBuffer, ULONG aBufferLength, ULONG* aOutBytesRead)
 {
-  LOG("WMFByteStream::Read()");
-  return E_NOTIMPL;
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+  ReadRequest request(mOffset, aBuffer, aBufferLength);
+  if (NS_FAILED(Read(&request))) {
+    LOG("WMFByteStream::Read() offset=%lld failed!", mOffset);
+    return E_FAIL;
+  }
+  if (aOutBytesRead) {
+    *aOutBytesRead = request.mBytesRead;
+  }
+  LOG("WMFByteStream::Read() offset=%lld length=%u bytesRead=%u",
+      mOffset, aBufferLength, request.mBytesRead);
+  mOffset += request.mBytesRead;
+  return S_OK;
 }
 
 STDMETHODIMP
 WMFByteStream::Seek(MFBYTESTREAM_SEEK_ORIGIN aSeekOrigin,
                     LONGLONG aSeekOffset,
                     DWORD aSeekFlags,
                     QWORD *aCurrentPosition)
 {
--- a/content/media/wmf/WMFByteStream.h
+++ b/content/media/wmf/WMFByteStream.h
@@ -14,23 +14,23 @@
 #include "mozilla/Attributes.h"
 #include "nsAutoPtr.h"
 
 class nsIThreadPool;
 
 namespace mozilla {
 
 class MediaResource;
-class AsyncReadRequest;
+class ReadRequest;
 
 // Wraps a MediaResource around an IMFByteStream interface, so that it can
 // be used by the IMFSourceReader. Each WMFByteStream creates a WMF Work Queue
 // on which blocking I/O is performed. The SourceReader requests reads
-// asynchronously using {Begin,End}Read(). The synchronous I/O methods aren't
-// used by the SourceReader, so they're not implemented on this class.
+// asynchronously using {Begin,End}Read(), and more rarely synchronously
+// 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
 {
@@ -70,22 +70,22 @@ public:
   STDMETHODIMP SetCurrentPosition(QWORD aPosition);
   STDMETHODIMP SetLength(QWORD);
   STDMETHODIMP Write(const BYTE *, ULONG, ULONG *);
 
   // 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,
-                          AsyncReadRequest* aRequestState);
+                          ReadRequest* aRequestState);
 private:
 
-  // Locks the MediaResource and performs the read. This is a helper
-  // for ProcessReadRequest().
-  nsresult Read(AsyncReadRequest* aRequestState);
+  // Locks the MediaResource and performs the read. The other read methods
+  // call this function.
+  nsresult Read(ReadRequest* aRequestState);
 
   // Returns true if the current position of the stream is at end of stream.
   bool IsEOS();
 
   // Reference to the thread pool in which we perform the reads asynchronously.
   // Note this is pool is shared amongst all active WMFByteStreams.
   nsCOMPtr<nsIThreadPool> mThreadPool;