Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #ifndef VideoUtils_h |
michael@0 | 8 | #define VideoUtils_h |
michael@0 | 9 | |
michael@0 | 10 | #include "mozilla/Attributes.h" |
michael@0 | 11 | #include "mozilla/ReentrantMonitor.h" |
michael@0 | 12 | #include "mozilla/CheckedInt.h" |
michael@0 | 13 | |
michael@0 | 14 | #if !(defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) || \ |
michael@0 | 15 | defined(MOZ_ASAN) |
michael@0 | 16 | // For MEDIA_THREAD_STACK_SIZE |
michael@0 | 17 | #include "nsIThreadManager.h" |
michael@0 | 18 | #endif |
michael@0 | 19 | #include "nsThreadUtils.h" |
michael@0 | 20 | #include "prtime.h" |
michael@0 | 21 | #include "AudioSampleFormat.h" |
michael@0 | 22 | |
michael@0 | 23 | using mozilla::CheckedInt64; |
michael@0 | 24 | using mozilla::CheckedUint64; |
michael@0 | 25 | using mozilla::CheckedInt32; |
michael@0 | 26 | using mozilla::CheckedUint32; |
michael@0 | 27 | |
michael@0 | 28 | struct nsIntSize; |
michael@0 | 29 | struct nsIntRect; |
michael@0 | 30 | |
michael@0 | 31 | // This file contains stuff we'd rather put elsewhere, but which is |
michael@0 | 32 | // dependent on other changes which we don't want to wait for. We plan to |
michael@0 | 33 | // remove this file in the near future. |
michael@0 | 34 | |
michael@0 | 35 | |
michael@0 | 36 | // This belongs in xpcom/monitor/Monitor.h, once we've made |
michael@0 | 37 | // mozilla::Monitor non-reentrant. |
michael@0 | 38 | namespace mozilla { |
michael@0 | 39 | |
michael@0 | 40 | /** |
michael@0 | 41 | * ReentrantMonitorConditionallyEnter |
michael@0 | 42 | * |
michael@0 | 43 | * Enters the supplied monitor only if the conditional value |aEnter| is true. |
michael@0 | 44 | * E.g. Used to allow unmonitored read access on the decode thread, |
michael@0 | 45 | * and monitored access on all other threads. |
michael@0 | 46 | */ |
michael@0 | 47 | class MOZ_STACK_CLASS ReentrantMonitorConditionallyEnter |
michael@0 | 48 | { |
michael@0 | 49 | public: |
michael@0 | 50 | ReentrantMonitorConditionallyEnter(bool aEnter, |
michael@0 | 51 | ReentrantMonitor &aReentrantMonitor) : |
michael@0 | 52 | mReentrantMonitor(nullptr) |
michael@0 | 53 | { |
michael@0 | 54 | MOZ_COUNT_CTOR(ReentrantMonitorConditionallyEnter); |
michael@0 | 55 | if (aEnter) { |
michael@0 | 56 | mReentrantMonitor = &aReentrantMonitor; |
michael@0 | 57 | NS_ASSERTION(mReentrantMonitor, "null monitor"); |
michael@0 | 58 | mReentrantMonitor->Enter(); |
michael@0 | 59 | } |
michael@0 | 60 | } |
michael@0 | 61 | ~ReentrantMonitorConditionallyEnter(void) |
michael@0 | 62 | { |
michael@0 | 63 | if (mReentrantMonitor) { |
michael@0 | 64 | mReentrantMonitor->Exit(); |
michael@0 | 65 | } |
michael@0 | 66 | MOZ_COUNT_DTOR(ReentrantMonitorConditionallyEnter); |
michael@0 | 67 | } |
michael@0 | 68 | private: |
michael@0 | 69 | // Restrict to constructor and destructor defined above. |
michael@0 | 70 | ReentrantMonitorConditionallyEnter(); |
michael@0 | 71 | ReentrantMonitorConditionallyEnter(const ReentrantMonitorConditionallyEnter&); |
michael@0 | 72 | ReentrantMonitorConditionallyEnter& operator =(const ReentrantMonitorConditionallyEnter&); |
michael@0 | 73 | static void* operator new(size_t) CPP_THROW_NEW; |
michael@0 | 74 | static void operator delete(void*); |
michael@0 | 75 | |
michael@0 | 76 | ReentrantMonitor* mReentrantMonitor; |
michael@0 | 77 | }; |
michael@0 | 78 | |
michael@0 | 79 | // Shuts down a thread asynchronously. |
michael@0 | 80 | class ShutdownThreadEvent : public nsRunnable |
michael@0 | 81 | { |
michael@0 | 82 | public: |
michael@0 | 83 | ShutdownThreadEvent(nsIThread* aThread) : mThread(aThread) {} |
michael@0 | 84 | ~ShutdownThreadEvent() {} |
michael@0 | 85 | NS_IMETHOD Run() MOZ_OVERRIDE { |
michael@0 | 86 | mThread->Shutdown(); |
michael@0 | 87 | mThread = nullptr; |
michael@0 | 88 | return NS_OK; |
michael@0 | 89 | } |
michael@0 | 90 | private: |
michael@0 | 91 | nsCOMPtr<nsIThread> mThread; |
michael@0 | 92 | }; |
michael@0 | 93 | |
michael@0 | 94 | class MediaResource; |
michael@0 | 95 | |
michael@0 | 96 | namespace dom { |
michael@0 | 97 | class TimeRanges; |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | // Estimates the buffered ranges of a MediaResource using a simple |
michael@0 | 101 | // (byteOffset/length)*duration method. Probably inaccurate, but won't |
michael@0 | 102 | // do file I/O, and can be used when we don't have detailed knowledge |
michael@0 | 103 | // of the byte->time mapping of a resource. aDurationUsecs is the duration |
michael@0 | 104 | // of the media in microseconds. Estimated buffered ranges are stored in |
michael@0 | 105 | // aOutBuffered. Ranges are 0-normalized, i.e. in the range of (0,duration]. |
michael@0 | 106 | void GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream, |
michael@0 | 107 | int64_t aDurationUsecs, |
michael@0 | 108 | mozilla::dom::TimeRanges* aOutBuffered); |
michael@0 | 109 | |
michael@0 | 110 | // Converts from number of audio frames (aFrames) to microseconds, given |
michael@0 | 111 | // the specified audio rate (aRate). Stores result in aOutUsecs. Returns true |
michael@0 | 112 | // if the operation succeeded, or false if there was an integer overflow |
michael@0 | 113 | // while calulating the conversion. |
michael@0 | 114 | CheckedInt64 FramesToUsecs(int64_t aFrames, uint32_t aRate); |
michael@0 | 115 | |
michael@0 | 116 | // Converts from microseconds (aUsecs) to number of audio frames, given the |
michael@0 | 117 | // specified audio rate (aRate). Stores the result in aOutFrames. Returns |
michael@0 | 118 | // true if the operation succeeded, or false if there was an integer |
michael@0 | 119 | // overflow while calulating the conversion. |
michael@0 | 120 | CheckedInt64 UsecsToFrames(int64_t aUsecs, uint32_t aRate); |
michael@0 | 121 | |
michael@0 | 122 | // Number of microseconds per second. 1e6. |
michael@0 | 123 | static const int64_t USECS_PER_S = 1000000; |
michael@0 | 124 | |
michael@0 | 125 | // Number of microseconds per millisecond. |
michael@0 | 126 | static const int64_t USECS_PER_MS = 1000; |
michael@0 | 127 | |
michael@0 | 128 | // Converts seconds to milliseconds. |
michael@0 | 129 | #define MS_TO_SECONDS(s) ((double)(s) / (PR_MSEC_PER_SEC)) |
michael@0 | 130 | |
michael@0 | 131 | // Converts from seconds to microseconds. Returns failure if the resulting |
michael@0 | 132 | // integer is too big to fit in an int64_t. |
michael@0 | 133 | nsresult SecondsToUsecs(double aSeconds, int64_t& aOutUsecs); |
michael@0 | 134 | |
michael@0 | 135 | // The maximum height and width of the video. Used for |
michael@0 | 136 | // sanitizing the memory allocation of the RGB buffer. |
michael@0 | 137 | // The maximum resolution we anticipate encountering in the |
michael@0 | 138 | // wild is 2160p - 3840x2160 pixels. |
michael@0 | 139 | static const int32_t MAX_VIDEO_WIDTH = 4000; |
michael@0 | 140 | static const int32_t MAX_VIDEO_HEIGHT = 3000; |
michael@0 | 141 | |
michael@0 | 142 | // Scales the display rect aDisplay by aspect ratio aAspectRatio. |
michael@0 | 143 | // Note that aDisplay must be validated by IsValidVideoRegion() |
michael@0 | 144 | // before being used! |
michael@0 | 145 | void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio); |
michael@0 | 146 | |
michael@0 | 147 | // The amount of virtual memory reserved for thread stacks. |
michael@0 | 148 | #if (defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) && \ |
michael@0 | 149 | !defined(MOZ_ASAN) |
michael@0 | 150 | #define MEDIA_THREAD_STACK_SIZE (128 * 1024) |
michael@0 | 151 | #else |
michael@0 | 152 | // All other platforms use their system defaults. |
michael@0 | 153 | #define MEDIA_THREAD_STACK_SIZE nsIThreadManager::DEFAULT_STACK_SIZE |
michael@0 | 154 | #endif |
michael@0 | 155 | |
michael@0 | 156 | // Downmix multichannel Audio samples to Stereo. |
michael@0 | 157 | // Input are the buffer contains multichannel data, |
michael@0 | 158 | // the number of channels and the number of frames. |
michael@0 | 159 | int DownmixAudioToStereo(mozilla::AudioDataValue* buffer, |
michael@0 | 160 | int channels, |
michael@0 | 161 | uint32_t frames); |
michael@0 | 162 | |
michael@0 | 163 | bool IsVideoContentType(const nsCString& aContentType); |
michael@0 | 164 | |
michael@0 | 165 | // Returns true if it's safe to use aPicture as the picture to be |
michael@0 | 166 | // extracted inside a frame of size aFrame, and scaled up to and displayed |
michael@0 | 167 | // at a size of aDisplay. You should validate the frame, picture, and |
michael@0 | 168 | // display regions before using them to display video frames. |
michael@0 | 169 | bool IsValidVideoRegion(const nsIntSize& aFrame, const nsIntRect& aPicture, |
michael@0 | 170 | const nsIntSize& aDisplay); |
michael@0 | 171 | |
michael@0 | 172 | } // end namespace mozilla |
michael@0 | 173 | |
michael@0 | 174 | #endif |