Line data Source code
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 :
7 : #include "MP4Stream.h"
8 : #include "MediaResource.h"
9 :
10 : namespace mozilla {
11 :
12 0 : MP4Stream::MP4Stream(MediaResource* aResource)
13 : : mResource(aResource)
14 0 : , mPinCount(0)
15 : {
16 0 : MOZ_COUNT_CTOR(MP4Stream);
17 0 : MOZ_ASSERT(aResource);
18 0 : }
19 :
20 0 : MP4Stream::~MP4Stream()
21 : {
22 0 : MOZ_COUNT_DTOR(MP4Stream);
23 0 : MOZ_ASSERT(mPinCount == 0);
24 0 : }
25 :
26 : bool
27 0 : MP4Stream::BlockingReadIntoCache(int64_t aOffset, size_t aCount, Monitor* aToUnlock)
28 : {
29 0 : MOZ_ASSERT(mPinCount > 0);
30 0 : CacheBlock block(aOffset, aCount);
31 0 : if (!block.Init()) {
32 0 : return false;
33 : }
34 :
35 0 : uint32_t bytesRead = 0;
36 : {
37 0 : MonitorAutoUnlock unlock(*aToUnlock);
38 0 : nsresult rv = mResource.ReadAt(aOffset, block.Buffer(), aCount, &bytesRead);
39 0 : if (NS_FAILED(rv)) {
40 0 : return false;
41 : }
42 : }
43 :
44 0 : MOZ_ASSERT(block.mCount >= bytesRead);
45 0 : block.mCount = bytesRead;
46 :
47 0 : mCache.AppendElement(Move(block));
48 0 : return true;
49 : }
50 :
51 : // We surreptitiously reimplement the supposedly-blocking ReadAt as a non-
52 : // blocking CachedReadAt, and record when it fails. This allows MP4Reader
53 : // to retry the read as an actual blocking read without holding the lock.
54 : bool
55 0 : MP4Stream::ReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
56 : size_t* aBytesRead)
57 : {
58 0 : if (mFailedRead.isSome()) {
59 0 : mFailedRead.reset();
60 : }
61 :
62 0 : if (!CachedReadAt(aOffset, aBuffer, aCount, aBytesRead)) {
63 0 : mFailedRead.emplace(aOffset, aCount);
64 0 : return false;
65 : }
66 :
67 0 : return true;
68 : }
69 :
70 : bool
71 0 : MP4Stream::CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
72 : size_t* aBytesRead)
73 : {
74 : // First, check our local cache.
75 0 : for (size_t i = 0; i < mCache.Length(); ++i) {
76 0 : if (mCache[i].mOffset == aOffset && mCache[i].mCount >= aCount) {
77 0 : memcpy(aBuffer, mCache[i].Buffer(), aCount);
78 0 : *aBytesRead = aCount;
79 0 : return true;
80 : }
81 : }
82 :
83 : nsresult rv =
84 0 : mResource.GetResource()->ReadFromCache(reinterpret_cast<char*>(aBuffer),
85 0 : aOffset, aCount);
86 0 : if (NS_FAILED(rv)) {
87 0 : *aBytesRead = 0;
88 0 : return false;
89 : }
90 0 : *aBytesRead = aCount;
91 0 : return true;
92 : }
93 :
94 : bool
95 0 : MP4Stream::Length(int64_t* aSize)
96 : {
97 0 : if (mResource.GetLength() < 0)
98 0 : return false;
99 0 : *aSize = mResource.GetLength();
100 0 : return true;
101 : }
102 :
103 : } // namespace mozilla
|