michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "WMF.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "WMFByteStream.h" michael@0: #include "WMFSourceReaderCallback.h" michael@0: #include "WMFUtils.h" michael@0: #include "MediaResource.h" michael@0: #include "nsISeekableStream.h" michael@0: #include "mozilla/RefPtr.h" michael@0: #include "nsIThreadPool.h" michael@0: #include "nsXPCOMCIDInternal.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "mozilla/DebugOnly.h" michael@0: #include "SharedThreadPool.h" michael@0: #include michael@0: #include michael@0: michael@0: namespace mozilla { michael@0: michael@0: #ifdef PR_LOGGING michael@0: PRLogModuleInfo* gWMFByteStreamLog = nullptr; michael@0: #define WMF_BS_LOG(...) PR_LOG(gWMFByteStreamLog, PR_LOG_DEBUG, (__VA_ARGS__)) michael@0: #else michael@0: #define WMF_BS_LOG(...) michael@0: #endif michael@0: michael@0: WMFByteStream::WMFByteStream(MediaResource* aResource, michael@0: WMFSourceReaderCallback* aSourceReaderCallback) michael@0: : mSourceReaderCallback(aSourceReaderCallback), michael@0: mResource(aResource), michael@0: mReentrantMonitor("WMFByteStream.Data"), michael@0: mOffset(0), michael@0: mIsShutdown(false) michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Must be on main thread."); michael@0: NS_ASSERTION(mSourceReaderCallback, "Must have a source reader callback."); michael@0: michael@0: #ifdef PR_LOGGING michael@0: if (!gWMFByteStreamLog) { michael@0: gWMFByteStreamLog = PR_NewLogModule("WMFByteStream"); michael@0: } michael@0: #endif michael@0: WMF_BS_LOG("[%p] WMFByteStream CTOR", this); michael@0: MOZ_COUNT_CTOR(WMFByteStream); michael@0: } michael@0: michael@0: WMFByteStream::~WMFByteStream() michael@0: { michael@0: MOZ_COUNT_DTOR(WMFByteStream); michael@0: WMF_BS_LOG("[%p] WMFByteStream DTOR", this); michael@0: } michael@0: michael@0: nsresult michael@0: WMFByteStream::Init() michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Must be on main thread."); michael@0: michael@0: mThreadPool = SharedThreadPool::Get(NS_LITERAL_CSTRING("WMFByteStream IO"), 4); michael@0: NS_ENSURE_TRUE(mThreadPool, NS_ERROR_FAILURE); michael@0: michael@0: NS_ConvertUTF8toUTF16 contentTypeUTF16(mResource->GetContentType()); michael@0: if (!contentTypeUTF16.IsEmpty()) { michael@0: HRESULT hr = wmf::MFCreateAttributes(byRef(mAttributes), 1); michael@0: NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); michael@0: michael@0: hr = mAttributes->SetString(MF_BYTESTREAM_CONTENT_TYPE, michael@0: contentTypeUTF16.get()); michael@0: NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); michael@0: michael@0: WMF_BS_LOG("[%p] WMFByteStream has Content-Type=%s", this, mResource->GetContentType().get()); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: WMFByteStream::Shutdown() michael@0: { michael@0: { michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: mIsShutdown = true; michael@0: } michael@0: mSourceReaderCallback->Cancel(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // IUnknown Methods michael@0: STDMETHODIMP michael@0: WMFByteStream::QueryInterface(REFIID aIId, void **aInterface) michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::QueryInterface %s", this, GetGUIDName(aIId).get()); michael@0: michael@0: if (aIId == IID_IMFByteStream) { michael@0: return DoGetInterface(static_cast(this), aInterface); michael@0: } michael@0: if (aIId == IID_IUnknown) { michael@0: return DoGetInterface(static_cast(this), aInterface); michael@0: } michael@0: if (aIId == IID_IMFAttributes) { michael@0: return DoGetInterface(static_cast(this), aInterface); michael@0: } michael@0: michael@0: *aInterface = nullptr; michael@0: return E_NOINTERFACE; michael@0: } michael@0: michael@0: NS_IMPL_ADDREF(WMFByteStream) michael@0: NS_IMPL_RELEASE(WMFByteStream) michael@0: michael@0: michael@0: // Stores data regarding an async read opreation. michael@0: class ReadRequest MOZ_FINAL : public IUnknown { michael@0: public: michael@0: ReadRequest(int64_t aOffset, BYTE* aBuffer, ULONG aLength) michael@0: : mOffset(aOffset), michael@0: mBuffer(aBuffer), michael@0: mBufferLength(aLength), michael@0: mBytesRead(0) michael@0: {} michael@0: michael@0: // IUnknown Methods michael@0: STDMETHODIMP QueryInterface(REFIID aRIID, LPVOID *aOutObject); michael@0: STDMETHODIMP_(ULONG) AddRef(); michael@0: STDMETHODIMP_(ULONG) Release(); michael@0: michael@0: int64_t mOffset; michael@0: BYTE* mBuffer; michael@0: ULONG mBufferLength; michael@0: ULONG mBytesRead; michael@0: michael@0: // IUnknown ref counting. michael@0: ThreadSafeAutoRefCnt mRefCnt; michael@0: NS_DECL_OWNINGTHREAD michael@0: }; michael@0: michael@0: NS_IMPL_ADDREF(ReadRequest) michael@0: NS_IMPL_RELEASE(ReadRequest) michael@0: michael@0: // IUnknown Methods michael@0: STDMETHODIMP michael@0: ReadRequest::QueryInterface(REFIID aIId, void **aInterface) michael@0: { michael@0: WMF_BS_LOG("ReadRequest::QueryInterface %s", GetGUIDName(aIId).get()); michael@0: michael@0: if (aIId == IID_IUnknown) { michael@0: return DoGetInterface(static_cast(this), aInterface); michael@0: } michael@0: michael@0: *aInterface = nullptr; michael@0: return E_NOINTERFACE; michael@0: } michael@0: michael@0: class ProcessReadRequestEvent MOZ_FINAL : public nsRunnable { michael@0: public: michael@0: ProcessReadRequestEvent(WMFByteStream* aStream, michael@0: IMFAsyncResult* aResult, michael@0: ReadRequest* aRequestState) michael@0: : mStream(aStream), michael@0: mResult(aResult), michael@0: mRequestState(aRequestState) {} michael@0: michael@0: NS_IMETHOD Run() { michael@0: mStream->ProcessReadRequest(mResult, mRequestState); michael@0: return NS_OK; michael@0: } michael@0: private: michael@0: RefPtr mStream; michael@0: RefPtr mResult; michael@0: RefPtr mRequestState; michael@0: }; michael@0: michael@0: // IMFByteStream Methods michael@0: STDMETHODIMP michael@0: WMFByteStream::BeginRead(BYTE *aBuffer, michael@0: ULONG aLength, michael@0: IMFAsyncCallback *aCallback, michael@0: IUnknown *aCallerState) michael@0: { michael@0: NS_ENSURE_TRUE(aBuffer, E_POINTER); michael@0: NS_ENSURE_TRUE(aCallback, E_POINTER); michael@0: michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: WMF_BS_LOG("[%p] WMFByteStream::BeginRead() mOffset=%lld tell=%lld length=%lu mIsShutdown=%d", michael@0: this, mOffset, mResource->Tell(), aLength, mIsShutdown); michael@0: michael@0: if (mIsShutdown || mOffset < 0) { michael@0: return E_INVALIDARG; michael@0: } michael@0: michael@0: // Create an object to store our state. michael@0: RefPtr requestState = new ReadRequest(mOffset, aBuffer, aLength); michael@0: michael@0: // Create an IMFAsyncResult, this is passed back to the caller as a token to michael@0: // retrieve the number of bytes read. michael@0: RefPtr callersResult; michael@0: HRESULT hr = wmf::MFCreateAsyncResult(requestState, michael@0: aCallback, michael@0: aCallerState, michael@0: byRef(callersResult)); michael@0: NS_ENSURE_TRUE(SUCCEEDED(hr), hr); michael@0: michael@0: // Dispatch an event to perform the read in the thread pool. michael@0: nsCOMPtr r = new ProcessReadRequestEvent(this, michael@0: callersResult, michael@0: requestState); michael@0: nsresult rv = mThreadPool->Dispatch(r, NS_DISPATCH_NORMAL); michael@0: michael@0: if (mResource->GetLength() > -1) { michael@0: mOffset = std::min(mOffset + aLength, mResource->GetLength()); michael@0: } else { michael@0: mOffset += aLength; michael@0: } michael@0: michael@0: return NS_SUCCEEDED(rv) ? S_OK : E_FAIL; michael@0: } michael@0: michael@0: nsresult michael@0: WMFByteStream::Read(ReadRequest* aRequestState) michael@0: { michael@0: // Read in a loop to ensure we fill the buffer, when possible. michael@0: ULONG totalBytesRead = 0; michael@0: nsresult rv = NS_OK; michael@0: while (totalBytesRead < aRequestState->mBufferLength) { michael@0: BYTE* buffer = aRequestState->mBuffer + totalBytesRead; michael@0: ULONG bytesRead = 0; michael@0: ULONG length = aRequestState->mBufferLength - totalBytesRead; michael@0: rv = mResource->ReadAt(aRequestState->mOffset + totalBytesRead, michael@0: reinterpret_cast(buffer), michael@0: length, michael@0: reinterpret_cast(&bytesRead)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: totalBytesRead += bytesRead; michael@0: if (bytesRead == 0) { michael@0: break; michael@0: } michael@0: } michael@0: aRequestState->mBytesRead = totalBytesRead; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // Note: This is called on one of the thread pool's threads. michael@0: void michael@0: WMFByteStream::ProcessReadRequest(IMFAsyncResult* aResult, michael@0: ReadRequest* aRequestState) michael@0: { michael@0: if (mResource->GetLength() > -1 && michael@0: aRequestState->mOffset > mResource->GetLength()) { michael@0: aResult->SetStatus(S_OK); michael@0: wmf::MFInvokeCallback(aResult); michael@0: WMF_BS_LOG("[%p] WMFByteStream::ProcessReadRequest() read offset greater than length, soft-failing read", this); michael@0: return; michael@0: } michael@0: michael@0: nsresult rv = Read(aRequestState); michael@0: if (NS_FAILED(rv)) { michael@0: Shutdown(); michael@0: aResult->SetStatus(E_ABORT); michael@0: } else { michael@0: aResult->SetStatus(S_OK); michael@0: } michael@0: michael@0: WMF_BS_LOG("[%p] WMFByteStream::ProcessReadRequest() read %d at %lld finished rv=%x", michael@0: this, aRequestState->mBytesRead, aRequestState->mOffset, rv); michael@0: michael@0: // Let caller know read is complete. michael@0: DebugOnly hr = wmf::MFInvokeCallback(aResult); michael@0: NS_ASSERTION(SUCCEEDED(hr), "Failed to invoke callback!"); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::BeginWrite(const BYTE *, ULONG , michael@0: IMFAsyncCallback *, michael@0: IUnknown *) michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::BeginWrite()", this); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::Close() michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::Close()", this); michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::EndRead(IMFAsyncResult* aResult, ULONG *aBytesRead) michael@0: { michael@0: NS_ENSURE_TRUE(aResult, E_POINTER); michael@0: NS_ENSURE_TRUE(aBytesRead, E_POINTER); michael@0: michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: michael@0: // Extract our state object. michael@0: RefPtr unknown; michael@0: HRESULT hr = aResult->GetObject(byRef(unknown)); michael@0: if (FAILED(hr) || !unknown) { michael@0: return E_INVALIDARG; michael@0: } michael@0: ReadRequest* requestState = michael@0: static_cast(unknown.get()); michael@0: michael@0: // Report result. michael@0: *aBytesRead = requestState->mBytesRead; michael@0: michael@0: WMF_BS_LOG("[%p] WMFByteStream::EndRead() offset=%lld *aBytesRead=%u mOffset=%lld status=0x%x hr=0x%x eof=%d", michael@0: this, requestState->mOffset, *aBytesRead, mOffset, aResult->GetStatus(), hr, IsEOS()); michael@0: michael@0: return aResult->GetStatus(); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::EndWrite(IMFAsyncResult *, ULONG *) michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::EndWrite()", this); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::Flush() michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::Flush()", this); michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetCapabilities(DWORD *aCapabilities) michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::GetCapabilities()", this); michael@0: NS_ENSURE_TRUE(aCapabilities, E_POINTER); michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: bool seekable = mResource->IsTransportSeekable(); michael@0: bool cached = mResource->IsDataCachedToEndOfResource(0); michael@0: *aCapabilities = MFBYTESTREAM_IS_READABLE | michael@0: MFBYTESTREAM_IS_SEEKABLE | michael@0: (!cached ? MFBYTESTREAM_IS_PARTIALLY_DOWNLOADED : 0) | michael@0: (!seekable ? MFBYTESTREAM_HAS_SLOW_SEEK : 0); michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetCurrentPosition(QWORD *aPosition) michael@0: { michael@0: NS_ENSURE_TRUE(aPosition, E_POINTER); michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: // Note: Returning the length of stream as position when read michael@0: // cursor is < 0 seems to be the behaviour expected by WMF, but michael@0: // also note it doesn't seem to expect that the position is an michael@0: // unsigned value since if you seek to > length and read WMF michael@0: // expects the read to succeed after reading 0 bytes, but if you michael@0: // seek to < 0 and read, the read is expected to fails... So michael@0: // go figure... michael@0: *aPosition = mOffset < 0 ? mResource->GetLength() : mOffset; michael@0: WMF_BS_LOG("[%p] WMFByteStream::GetCurrentPosition() %lld", this, mOffset); michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetLength(QWORD *aLength) michael@0: { michael@0: NS_ENSURE_TRUE(aLength, E_POINTER); michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: *aLength = mResource->GetLength(); michael@0: WMF_BS_LOG("[%p] WMFByteStream::GetLength() %lld", this, *aLength); michael@0: return S_OK; michael@0: } michael@0: michael@0: bool michael@0: WMFByteStream::IsEOS() michael@0: { michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: return mResource->GetLength() > -1 && michael@0: (mOffset < 0 || michael@0: mOffset >= mResource->GetLength()); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::IsEndOfStream(BOOL *aEndOfStream) michael@0: { michael@0: NS_ENSURE_TRUE(aEndOfStream, E_POINTER); michael@0: *aEndOfStream = IsEOS(); michael@0: WMF_BS_LOG("[%p] WMFByteStream::IsEndOfStream() %d", this, *aEndOfStream); michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::Read(BYTE* aBuffer, ULONG aBufferLength, ULONG* aOutBytesRead) michael@0: { michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: ReadRequest request(mOffset, aBuffer, aBufferLength); michael@0: if (NS_FAILED(Read(&request))) { michael@0: WMF_BS_LOG("[%p] WMFByteStream::Read() offset=%lld failed!", this, mOffset); michael@0: return E_FAIL; michael@0: } michael@0: if (aOutBytesRead) { michael@0: *aOutBytesRead = request.mBytesRead; michael@0: } michael@0: WMF_BS_LOG("[%p] WMFByteStream::Read() offset=%lld length=%u bytesRead=%u", michael@0: this, mOffset, aBufferLength, request.mBytesRead); michael@0: mOffset += request.mBytesRead; michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::Seek(MFBYTESTREAM_SEEK_ORIGIN aSeekOrigin, michael@0: LONGLONG aSeekOffset, michael@0: DWORD aSeekFlags, michael@0: QWORD *aCurrentPosition) michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::Seek(%d, %lld)", this, aSeekOrigin, aSeekOffset); michael@0: michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: michael@0: int64_t offset = mOffset; michael@0: if (aSeekOrigin == msoBegin) { michael@0: offset = aSeekOffset; michael@0: } else { michael@0: offset += aSeekOffset; michael@0: } michael@0: int64_t length = mResource->GetLength(); michael@0: if (length > -1) { michael@0: mOffset = std::min(offset, length); michael@0: } else { michael@0: mOffset = offset; michael@0: } michael@0: if (aCurrentPosition) { michael@0: *aCurrentPosition = mOffset; michael@0: } michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetCurrentPosition(QWORD aPosition) michael@0: { michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: WMF_BS_LOG("[%p] WMFByteStream::SetCurrentPosition(%lld)", michael@0: this, aPosition); michael@0: michael@0: int64_t length = mResource->GetLength(); michael@0: if (length > -1) { michael@0: mOffset = std::min(aPosition, length); michael@0: } else { michael@0: mOffset = aPosition; michael@0: } michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetLength(QWORD) michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::SetLength()", this); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::Write(const BYTE *, ULONG, ULONG *) michael@0: { michael@0: WMF_BS_LOG("[%p] WMFByteStream::Write()", this); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: // IMFAttributes methods michael@0: STDMETHODIMP michael@0: WMFByteStream::GetItem(REFGUID guidKey, PROPVARIANT* pValue) michael@0: { michael@0: MOZ_ASSERT(mAttributes); michael@0: return mAttributes->GetItem(guidKey, pValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetItemType(guidKey, pType); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL* pbResult) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->CompareItem(guidKey, Value, pbResult); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::Compare(IMFAttributes* pTheirs, michael@0: MF_ATTRIBUTES_MATCH_TYPE MatchType, michael@0: BOOL* pbResult) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->Compare(pTheirs, MatchType, pbResult); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetUINT32(REFGUID guidKey, UINT32* punValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetUINT32(guidKey, punValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetUINT64(REFGUID guidKey, UINT64* punValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetUINT64(guidKey, punValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetDouble(REFGUID guidKey, double* pfValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetDouble(guidKey, pfValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetGUID(REFGUID guidKey, GUID* pguidValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetGUID(guidKey, pguidValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetStringLength(REFGUID guidKey, UINT32* pcchLength) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetStringLength(guidKey, pcchLength); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32* pcchLength) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue, UINT32* pcchLength) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetBlobSize(guidKey, pcbBlobSize); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize, UINT32* pcbBlobSize) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf, UINT32* pcbSize) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetUnknown(REFGUID guidKey, REFIID riid, LPVOID* ppv) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetUnknown(guidKey, riid, ppv); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetItem(REFGUID guidKey, REFPROPVARIANT Value) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->SetItem(guidKey, Value); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::DeleteItem(REFGUID guidKey) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->DeleteItem(guidKey); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::DeleteAllItems() michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->DeleteAllItems(); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetUINT32(REFGUID guidKey, UINT32 unValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->SetUINT32(guidKey, unValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetUINT64(REFGUID guidKey,UINT64 unValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->SetUINT64(guidKey, unValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetDouble(REFGUID guidKey, double fValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->SetDouble(guidKey, fValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetGUID(REFGUID guidKey, REFGUID guidValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->SetGUID(guidKey, guidValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetString(REFGUID guidKey, LPCWSTR wszValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->SetString(guidKey, wszValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetBlob(REFGUID guidKey, const UINT8* pBuf, UINT32 cbBufSize) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->SetBlob(guidKey, pBuf, cbBufSize); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::SetUnknown(REFGUID guidKey, IUnknown* pUnknown) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->SetUnknown(guidKey, pUnknown); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::LockStore() michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->LockStore(); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::UnlockStore() michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->UnlockStore(); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetCount(UINT32* pcItems) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetCount(pcItems); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::GetItemByIndex(UINT32 unIndex, GUID* pguidKey, PROPVARIANT* pValue) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->GetItemByIndex(unIndex, pguidKey, pValue); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFByteStream::CopyAllItems(IMFAttributes* pDest) michael@0: { michael@0: assert(mAttributes); michael@0: return mAttributes->CopyAllItems(pDest); michael@0: } michael@0: michael@0: } // namespace mozilla