diff --git a/dom/media/MediaResource.cpp b/dom/media/MediaResource.cpp index 329b03b4e39..80ceff511de 100644 --- a/dom/media/MediaResource.cpp +++ b/dom/media/MediaResource.cpp @@ -759,25 +759,27 @@ nsresult ChannelMediaResource::ReadAt(int64_t aOffset, } already_AddRefed -ChannelMediaResource::SilentReadAt(int64_t aOffset, uint32_t aCount) +ChannelMediaResource::MediaReadAt(int64_t aOffset, uint32_t aCount) { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); nsRefPtr bytes = new MediaByteBuffer(); - bool ok = bytes->SetCapacity(aCount, fallible); + bool ok = bytes->SetLength(aCount, fallible); NS_ENSURE_TRUE(ok, nullptr); - int64_t pos = mCacheStream.Tell(); char* curr = reinterpret_cast(bytes->Elements()); + const char* start = curr; while (aCount > 0) { uint32_t bytesRead; nsresult rv = mCacheStream.ReadAt(aOffset, curr, aCount, &bytesRead); NS_ENSURE_SUCCESS(rv, nullptr); - NS_ENSURE_TRUE(bytesRead > 0, nullptr); + if (!bytesRead) { + break; + } aOffset += bytesRead; aCount -= bytesRead; curr += bytesRead; } - mCacheStream.Seek(nsISeekableStream::NS_SEEK_SET, pos); + bytes->SetLength(curr - start); return bytes.forget(); } @@ -1217,6 +1219,7 @@ public: virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) override; virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, uint32_t* aBytes) override; + virtual already_AddRefed MediaReadAt(int64_t aOffset, uint32_t aCount) override; virtual already_AddRefed SilentReadAt(int64_t aOffset, uint32_t aCount) override; virtual nsresult Seek(int32_t aWhence, int64_t aOffset) override; virtual int64_t Tell() override; @@ -1281,6 +1284,8 @@ private: // Ensures mSize is initialized, if it can be. // mLock must be held when this is called, and mInput must be non-null. void EnsureSizeInitialized(); + already_AddRefed UnsafeMediaReadAt( + int64_t aOffset, uint32_t aCount); // The file size, or -1 if not known. Immutable after Open(). // Can be used from any thread. @@ -1541,31 +1546,52 @@ nsresult FileMediaResource::ReadAt(int64_t aOffset, char* aBuffer, return rv; } +already_AddRefed +FileMediaResource::MediaReadAt(int64_t aOffset, uint32_t aCount) +{ + NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); + + MutexAutoLock lock(mLock); + return UnsafeMediaReadAt(aOffset, aCount); +} + +already_AddRefed +FileMediaResource::UnsafeMediaReadAt(int64_t aOffset, uint32_t aCount) +{ + nsRefPtr bytes = new MediaByteBuffer(); + bool ok = bytes->SetLength(aCount, fallible); + NS_ENSURE_TRUE(ok, nullptr); + nsresult rv = UnsafeSeek(nsISeekableStream::NS_SEEK_SET, aOffset); + NS_ENSURE_SUCCESS(rv, nullptr); + char* curr = reinterpret_cast(bytes->Elements()); + const char* start = curr; + while (aCount > 0) { + uint32_t bytesRead; + rv = UnsafeRead(curr, aCount, &bytesRead); + NS_ENSURE_SUCCESS(rv, nullptr); + if (!bytesRead) { + break; + } + aCount -= bytesRead; + curr += bytesRead; + } + bytes->SetLength(curr - start); + return bytes.forget(); +} + already_AddRefed FileMediaResource::SilentReadAt(int64_t aOffset, uint32_t aCount) { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); MutexAutoLock lock(mLock); - nsRefPtr bytes = new MediaByteBuffer(); - bool ok = bytes->SetCapacity(aCount, fallible); - NS_ENSURE_TRUE(ok, nullptr); int64_t pos = 0; NS_ENSURE_TRUE(mSeekable, nullptr); nsresult rv = mSeekable->Tell(&pos); NS_ENSURE_SUCCESS(rv, nullptr); - rv = UnsafeSeek(nsISeekableStream::NS_SEEK_SET, aOffset); - NS_ENSURE_SUCCESS(rv, nullptr); - char* curr = reinterpret_cast(bytes->Elements()); - while (aCount > 0) { - uint32_t bytesRead; - rv = UnsafeRead(curr, aCount, &bytesRead); - NS_ENSURE_SUCCESS(rv, nullptr); - NS_ENSURE_TRUE(bytesRead > 0, nullptr); - aCount -= bytesRead; - curr += bytesRead; - } + nsRefPtr bytes = UnsafeMediaReadAt(aOffset, aCount); UnsafeSeek(nsISeekableStream::NS_SEEK_SET, pos); + NS_ENSURE_TRUE(bytes && bytes->Length() == aCount, nullptr); return bytes.forget(); } diff --git a/dom/media/MediaResource.h b/dom/media/MediaResource.h index 8bd5a58d48b..b1873861d28 100644 --- a/dom/media/MediaResource.h +++ b/dom/media/MediaResource.h @@ -289,6 +289,31 @@ public: // results and requirements are the same as per the Read method. virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, uint32_t* aBytes) = 0; + // This method returns nullptr if anything fails. + // Otherwise, it returns an owned buffer. + // MediaReadAt may return fewer bytes than requested if end of stream is + // encountered. There is no need to call it again to get more data. + virtual already_AddRefed MediaReadAt(int64_t aOffset, uint32_t aCount) + { + nsRefPtr bytes = new MediaByteBuffer(); + bool ok = bytes->SetLength(aCount, fallible); + NS_ENSURE_TRUE(ok, nullptr); + char* curr = reinterpret_cast(bytes->Elements()); + const char* start = curr; + while (aCount > 0) { + uint32_t bytesRead; + nsresult rv = ReadAt(aOffset, curr, aCount, &bytesRead); + NS_ENSURE_SUCCESS(rv, nullptr); + if (!bytesRead) { + break; + } + aOffset += bytesRead; + aCount -= bytesRead; + curr += bytesRead; + } + bytes->SetLength(curr - start); + return bytes.forget(); + } // ReadAt without side-effects. Given that our MediaResource infrastructure // is very side-effecty, this accomplishes its job by checking the initial @@ -299,21 +324,10 @@ public: // aCount bytes. Otherwise, it returns an owned buffer. virtual already_AddRefed SilentReadAt(int64_t aOffset, uint32_t aCount) { - nsRefPtr bytes = new MediaByteBuffer(); - bool ok = bytes->SetCapacity(aCount, fallible); - NS_ENSURE_TRUE(ok, nullptr); int64_t pos = Tell(); - char* curr = reinterpret_cast(bytes->Elements()); - while (aCount > 0) { - uint32_t bytesRead; - nsresult rv = ReadAt(aOffset, curr, aCount, &bytesRead); - NS_ENSURE_SUCCESS(rv, nullptr); - NS_ENSURE_TRUE(bytesRead > 0, nullptr); - aOffset += bytesRead; - aCount -= bytesRead; - curr += bytesRead; - } + nsRefPtr bytes = MediaReadAt(aOffset, aCount); Seek(nsISeekableStream::NS_SEEK_SET, pos); + NS_ENSURE_TRUE(bytes && bytes->Length() == aCount, nullptr); return bytes.forget(); } @@ -640,7 +654,7 @@ public: virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) override; virtual nsresult ReadAt(int64_t offset, char* aBuffer, uint32_t aCount, uint32_t* aBytes) override; - virtual already_AddRefed SilentReadAt(int64_t aOffset, uint32_t aCount) override; + virtual already_AddRefed MediaReadAt(int64_t aOffset, uint32_t aCount) override; virtual nsresult Seek(int32_t aWhence, int64_t aOffset) override; virtual int64_t Tell() override;