1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/wmf/WMFByteStream.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,161 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 +#if !defined(WMFByteStream_h_) 1.10 +#define WMFByteStream_h_ 1.11 + 1.12 +#include "WMF.h" 1.13 + 1.14 +#include "nsISupportsImpl.h" 1.15 +#include "nsCOMPtr.h" 1.16 +#include "mozilla/ReentrantMonitor.h" 1.17 +#include "mozilla/Attributes.h" 1.18 +#include "nsAutoPtr.h" 1.19 +#include "mozilla/RefPtr.h" 1.20 + 1.21 +namespace mozilla { 1.22 + 1.23 +class MediaResource; 1.24 +class ReadRequest; 1.25 +class WMFSourceReaderCallback; 1.26 +class SharedThreadPool; 1.27 + 1.28 +// Wraps a MediaResource around an IMFByteStream interface, so that it can 1.29 +// be used by the IMFSourceReader. Each WMFByteStream creates a WMF Work Queue 1.30 +// on which blocking I/O is performed. The SourceReader requests reads 1.31 +// asynchronously using {Begin,End}Read(), and more rarely synchronously 1.32 +// using Read(). 1.33 +// 1.34 +// Note: This implementation attempts to be bug-compatible with Windows Media 1.35 +// Foundation's implementation of IMFByteStream. The behaviour of WMF's 1.36 +// IMFByteStream was determined by creating it and testing the edge cases. 1.37 +// For details see the test code at: 1.38 +// https://github.com/cpearce/IMFByteStreamBehaviour/ 1.39 +class WMFByteStream MOZ_FINAL : public IMFByteStream 1.40 + , public IMFAttributes 1.41 +{ 1.42 +public: 1.43 + WMFByteStream(MediaResource* aResource, WMFSourceReaderCallback* aCallback); 1.44 + ~WMFByteStream(); 1.45 + 1.46 + nsresult Init(); 1.47 + nsresult Shutdown(); 1.48 + 1.49 + // IUnknown Methods. 1.50 + STDMETHODIMP QueryInterface(REFIID aIId, LPVOID *aInterface); 1.51 + STDMETHODIMP_(ULONG) AddRef(); 1.52 + STDMETHODIMP_(ULONG) Release(); 1.53 + 1.54 + // IMFByteStream Methods. 1.55 + STDMETHODIMP BeginRead(BYTE *aBuffer, 1.56 + ULONG aLength, 1.57 + IMFAsyncCallback *aCallback, 1.58 + IUnknown *aCallerState); 1.59 + STDMETHODIMP BeginWrite(const BYTE *, ULONG , 1.60 + IMFAsyncCallback *, 1.61 + IUnknown *); 1.62 + STDMETHODIMP Close(); 1.63 + STDMETHODIMP EndRead(IMFAsyncResult* aResult, ULONG *aBytesRead); 1.64 + STDMETHODIMP EndWrite(IMFAsyncResult *, ULONG *); 1.65 + STDMETHODIMP Flush(); 1.66 + STDMETHODIMP GetCapabilities(DWORD *aCapabilities); 1.67 + STDMETHODIMP GetCurrentPosition(QWORD *aPosition); 1.68 + STDMETHODIMP GetLength(QWORD *pqwLength); 1.69 + STDMETHODIMP IsEndOfStream(BOOL *aIsEndOfStream); 1.70 + STDMETHODIMP Read(BYTE *, ULONG, ULONG *); 1.71 + STDMETHODIMP Seek(MFBYTESTREAM_SEEK_ORIGIN aSeekOrigin, 1.72 + LONGLONG aSeekOffset, 1.73 + DWORD aSeekFlags, 1.74 + QWORD *aCurrentPosition); 1.75 + STDMETHODIMP SetCurrentPosition(QWORD aPosition); 1.76 + STDMETHODIMP SetLength(QWORD); 1.77 + STDMETHODIMP Write(const BYTE *, ULONG, ULONG *); 1.78 + 1.79 + // IMFAttributes methods 1.80 + STDMETHODIMP GetItem(REFGUID guidKey, PROPVARIANT* pValue); 1.81 + STDMETHODIMP GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType); 1.82 + STDMETHODIMP CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL* pbResult); 1.83 + STDMETHODIMP Compare(IMFAttributes* pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL* pbResult); 1.84 + STDMETHODIMP GetUINT32(REFGUID guidKey, UINT32* punValue); 1.85 + STDMETHODIMP GetUINT64(REFGUID guidKey, UINT64* punValue); 1.86 + STDMETHODIMP GetDouble(REFGUID guidKey, double* pfValue); 1.87 + STDMETHODIMP GetGUID(REFGUID guidKey, GUID* pguidValue); 1.88 + STDMETHODIMP GetStringLength(REFGUID guidKey, UINT32* pcchLength); 1.89 + STDMETHODIMP GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32* pcchLength); 1.90 + STDMETHODIMP GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue, UINT32* pcchLength); 1.91 + STDMETHODIMP GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize); 1.92 + STDMETHODIMP GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize, UINT32* pcbBlobSize); 1.93 + STDMETHODIMP GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf, UINT32* pcbSize); 1.94 + STDMETHODIMP GetUnknown(REFGUID guidKey, REFIID riid, LPVOID* ppv); 1.95 + STDMETHODIMP SetItem(REFGUID guidKey, REFPROPVARIANT Value); 1.96 + STDMETHODIMP DeleteItem(REFGUID guidKey); 1.97 + STDMETHODIMP DeleteAllItems(); 1.98 + STDMETHODIMP SetUINT32(REFGUID guidKey, UINT32 unValue); 1.99 + STDMETHODIMP SetUINT64(REFGUID guidKey,UINT64 unValue); 1.100 + STDMETHODIMP SetDouble(REFGUID guidKey, double fValue); 1.101 + STDMETHODIMP SetGUID(REFGUID guidKey, REFGUID guidValue); 1.102 + STDMETHODIMP SetString(REFGUID guidKey, LPCWSTR wszValue); 1.103 + STDMETHODIMP SetBlob(REFGUID guidKey, const UINT8* pBuf, UINT32 cbBufSize); 1.104 + STDMETHODIMP SetUnknown(REFGUID guidKey, IUnknown* pUnknown); 1.105 + STDMETHODIMP LockStore(); 1.106 + STDMETHODIMP UnlockStore(); 1.107 + STDMETHODIMP GetCount(UINT32* pcItems); 1.108 + STDMETHODIMP GetItemByIndex(UINT32 unIndex, GUID* pguidKey, PROPVARIANT* pValue); 1.109 + STDMETHODIMP CopyAllItems(IMFAttributes* pDest); 1.110 + 1.111 + // We perform an async read operation in this callback implementation. 1.112 + // Processes an async read request, storing the result in aResult, and 1.113 + // notifying the caller when the read operation is complete. 1.114 + void ProcessReadRequest(IMFAsyncResult* aResult, 1.115 + ReadRequest* aRequestState); 1.116 + 1.117 +private: 1.118 + 1.119 + // Locks the MediaResource and performs the read. The other read methods 1.120 + // call this function. 1.121 + nsresult Read(ReadRequest* aRequestState); 1.122 + 1.123 + // Returns true if the current position of the stream is at end of stream. 1.124 + bool IsEOS(); 1.125 + 1.126 + // Reference to the thread pool in which we perform the reads asynchronously. 1.127 + // Note this is pool is shared amongst all active WMFByteStreams. 1.128 + RefPtr<SharedThreadPool> mThreadPool; 1.129 + 1.130 + // Reference to the source reader's callback. We use this reference to 1.131 + // notify threads waiting on a ReadSample() callback to stop waiting 1.132 + // if the stream is closed, which happens when the media element is 1.133 + // shutdown. 1.134 + RefPtr<WMFSourceReaderCallback> mSourceReaderCallback; 1.135 + 1.136 + // Resource we're wrapping. 1.137 + nsRefPtr<MediaResource> mResource; 1.138 + 1.139 + // Protects mOffset, which is accessed by the SourceReaders thread(s), and 1.140 + // on the work queue thread. 1.141 + ReentrantMonitor mReentrantMonitor; 1.142 + 1.143 + // Current offset of the logical read cursor. We maintain this separately 1.144 + // from the media resource's offset since a partially complete read (in Invoke()) 1.145 + // would leave the resource's offset at a value unexpected by the caller, 1.146 + // since the read hadn't yet completed. 1.147 + int64_t mOffset; 1.148 + 1.149 + // We implement IMFAttributes by forwarding all calls to an instance of the 1.150 + // standard IMFAttributes class, which we store a reference to here. 1.151 + RefPtr<IMFAttributes> mAttributes; 1.152 + 1.153 + // True if the resource has been shutdown, either because the WMFReader is 1.154 + // shutting down, or because the underlying MediaResource has closed. 1.155 + bool mIsShutdown; 1.156 + 1.157 + // IUnknown ref counting. 1.158 + ThreadSafeAutoRefCnt mRefCnt; 1.159 + NS_DECL_OWNINGTHREAD 1.160 +}; 1.161 + 1.162 +} // namespace mozilla 1.163 + 1.164 +#endif