|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 #if !defined(WMFByteStream_h_) |
|
7 #define WMFByteStream_h_ |
|
8 |
|
9 #include "WMF.h" |
|
10 |
|
11 #include "nsISupportsImpl.h" |
|
12 #include "nsCOMPtr.h" |
|
13 #include "mozilla/ReentrantMonitor.h" |
|
14 #include "mozilla/Attributes.h" |
|
15 #include "nsAutoPtr.h" |
|
16 #include "mozilla/RefPtr.h" |
|
17 |
|
18 namespace mozilla { |
|
19 |
|
20 class MediaResource; |
|
21 class ReadRequest; |
|
22 class WMFSourceReaderCallback; |
|
23 class SharedThreadPool; |
|
24 |
|
25 // Wraps a MediaResource around an IMFByteStream interface, so that it can |
|
26 // be used by the IMFSourceReader. Each WMFByteStream creates a WMF Work Queue |
|
27 // on which blocking I/O is performed. The SourceReader requests reads |
|
28 // asynchronously using {Begin,End}Read(), and more rarely synchronously |
|
29 // using Read(). |
|
30 // |
|
31 // Note: This implementation attempts to be bug-compatible with Windows Media |
|
32 // Foundation's implementation of IMFByteStream. The behaviour of WMF's |
|
33 // IMFByteStream was determined by creating it and testing the edge cases. |
|
34 // For details see the test code at: |
|
35 // https://github.com/cpearce/IMFByteStreamBehaviour/ |
|
36 class WMFByteStream MOZ_FINAL : public IMFByteStream |
|
37 , public IMFAttributes |
|
38 { |
|
39 public: |
|
40 WMFByteStream(MediaResource* aResource, WMFSourceReaderCallback* aCallback); |
|
41 ~WMFByteStream(); |
|
42 |
|
43 nsresult Init(); |
|
44 nsresult Shutdown(); |
|
45 |
|
46 // IUnknown Methods. |
|
47 STDMETHODIMP QueryInterface(REFIID aIId, LPVOID *aInterface); |
|
48 STDMETHODIMP_(ULONG) AddRef(); |
|
49 STDMETHODIMP_(ULONG) Release(); |
|
50 |
|
51 // IMFByteStream Methods. |
|
52 STDMETHODIMP BeginRead(BYTE *aBuffer, |
|
53 ULONG aLength, |
|
54 IMFAsyncCallback *aCallback, |
|
55 IUnknown *aCallerState); |
|
56 STDMETHODIMP BeginWrite(const BYTE *, ULONG , |
|
57 IMFAsyncCallback *, |
|
58 IUnknown *); |
|
59 STDMETHODIMP Close(); |
|
60 STDMETHODIMP EndRead(IMFAsyncResult* aResult, ULONG *aBytesRead); |
|
61 STDMETHODIMP EndWrite(IMFAsyncResult *, ULONG *); |
|
62 STDMETHODIMP Flush(); |
|
63 STDMETHODIMP GetCapabilities(DWORD *aCapabilities); |
|
64 STDMETHODIMP GetCurrentPosition(QWORD *aPosition); |
|
65 STDMETHODIMP GetLength(QWORD *pqwLength); |
|
66 STDMETHODIMP IsEndOfStream(BOOL *aIsEndOfStream); |
|
67 STDMETHODIMP Read(BYTE *, ULONG, ULONG *); |
|
68 STDMETHODIMP Seek(MFBYTESTREAM_SEEK_ORIGIN aSeekOrigin, |
|
69 LONGLONG aSeekOffset, |
|
70 DWORD aSeekFlags, |
|
71 QWORD *aCurrentPosition); |
|
72 STDMETHODIMP SetCurrentPosition(QWORD aPosition); |
|
73 STDMETHODIMP SetLength(QWORD); |
|
74 STDMETHODIMP Write(const BYTE *, ULONG, ULONG *); |
|
75 |
|
76 // IMFAttributes methods |
|
77 STDMETHODIMP GetItem(REFGUID guidKey, PROPVARIANT* pValue); |
|
78 STDMETHODIMP GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType); |
|
79 STDMETHODIMP CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL* pbResult); |
|
80 STDMETHODIMP Compare(IMFAttributes* pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL* pbResult); |
|
81 STDMETHODIMP GetUINT32(REFGUID guidKey, UINT32* punValue); |
|
82 STDMETHODIMP GetUINT64(REFGUID guidKey, UINT64* punValue); |
|
83 STDMETHODIMP GetDouble(REFGUID guidKey, double* pfValue); |
|
84 STDMETHODIMP GetGUID(REFGUID guidKey, GUID* pguidValue); |
|
85 STDMETHODIMP GetStringLength(REFGUID guidKey, UINT32* pcchLength); |
|
86 STDMETHODIMP GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32* pcchLength); |
|
87 STDMETHODIMP GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue, UINT32* pcchLength); |
|
88 STDMETHODIMP GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize); |
|
89 STDMETHODIMP GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize, UINT32* pcbBlobSize); |
|
90 STDMETHODIMP GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf, UINT32* pcbSize); |
|
91 STDMETHODIMP GetUnknown(REFGUID guidKey, REFIID riid, LPVOID* ppv); |
|
92 STDMETHODIMP SetItem(REFGUID guidKey, REFPROPVARIANT Value); |
|
93 STDMETHODIMP DeleteItem(REFGUID guidKey); |
|
94 STDMETHODIMP DeleteAllItems(); |
|
95 STDMETHODIMP SetUINT32(REFGUID guidKey, UINT32 unValue); |
|
96 STDMETHODIMP SetUINT64(REFGUID guidKey,UINT64 unValue); |
|
97 STDMETHODIMP SetDouble(REFGUID guidKey, double fValue); |
|
98 STDMETHODIMP SetGUID(REFGUID guidKey, REFGUID guidValue); |
|
99 STDMETHODIMP SetString(REFGUID guidKey, LPCWSTR wszValue); |
|
100 STDMETHODIMP SetBlob(REFGUID guidKey, const UINT8* pBuf, UINT32 cbBufSize); |
|
101 STDMETHODIMP SetUnknown(REFGUID guidKey, IUnknown* pUnknown); |
|
102 STDMETHODIMP LockStore(); |
|
103 STDMETHODIMP UnlockStore(); |
|
104 STDMETHODIMP GetCount(UINT32* pcItems); |
|
105 STDMETHODIMP GetItemByIndex(UINT32 unIndex, GUID* pguidKey, PROPVARIANT* pValue); |
|
106 STDMETHODIMP CopyAllItems(IMFAttributes* pDest); |
|
107 |
|
108 // We perform an async read operation in this callback implementation. |
|
109 // Processes an async read request, storing the result in aResult, and |
|
110 // notifying the caller when the read operation is complete. |
|
111 void ProcessReadRequest(IMFAsyncResult* aResult, |
|
112 ReadRequest* aRequestState); |
|
113 |
|
114 private: |
|
115 |
|
116 // Locks the MediaResource and performs the read. The other read methods |
|
117 // call this function. |
|
118 nsresult Read(ReadRequest* aRequestState); |
|
119 |
|
120 // Returns true if the current position of the stream is at end of stream. |
|
121 bool IsEOS(); |
|
122 |
|
123 // Reference to the thread pool in which we perform the reads asynchronously. |
|
124 // Note this is pool is shared amongst all active WMFByteStreams. |
|
125 RefPtr<SharedThreadPool> mThreadPool; |
|
126 |
|
127 // Reference to the source reader's callback. We use this reference to |
|
128 // notify threads waiting on a ReadSample() callback to stop waiting |
|
129 // if the stream is closed, which happens when the media element is |
|
130 // shutdown. |
|
131 RefPtr<WMFSourceReaderCallback> mSourceReaderCallback; |
|
132 |
|
133 // Resource we're wrapping. |
|
134 nsRefPtr<MediaResource> mResource; |
|
135 |
|
136 // Protects mOffset, which is accessed by the SourceReaders thread(s), and |
|
137 // on the work queue thread. |
|
138 ReentrantMonitor mReentrantMonitor; |
|
139 |
|
140 // Current offset of the logical read cursor. We maintain this separately |
|
141 // from the media resource's offset since a partially complete read (in Invoke()) |
|
142 // would leave the resource's offset at a value unexpected by the caller, |
|
143 // since the read hadn't yet completed. |
|
144 int64_t mOffset; |
|
145 |
|
146 // We implement IMFAttributes by forwarding all calls to an instance of the |
|
147 // standard IMFAttributes class, which we store a reference to here. |
|
148 RefPtr<IMFAttributes> mAttributes; |
|
149 |
|
150 // True if the resource has been shutdown, either because the WMFReader is |
|
151 // shutting down, or because the underlying MediaResource has closed. |
|
152 bool mIsShutdown; |
|
153 |
|
154 // IUnknown ref counting. |
|
155 ThreadSafeAutoRefCnt mRefCnt; |
|
156 NS_DECL_OWNINGTHREAD |
|
157 }; |
|
158 |
|
159 } // namespace mozilla |
|
160 |
|
161 #endif |