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: #ifndef VideoUtils_h michael@0: #define VideoUtils_h michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/ReentrantMonitor.h" michael@0: #include "mozilla/CheckedInt.h" michael@0: michael@0: #if !(defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) || \ michael@0: defined(MOZ_ASAN) michael@0: // For MEDIA_THREAD_STACK_SIZE michael@0: #include "nsIThreadManager.h" michael@0: #endif michael@0: #include "nsThreadUtils.h" michael@0: #include "prtime.h" michael@0: #include "AudioSampleFormat.h" michael@0: michael@0: using mozilla::CheckedInt64; michael@0: using mozilla::CheckedUint64; michael@0: using mozilla::CheckedInt32; michael@0: using mozilla::CheckedUint32; michael@0: michael@0: struct nsIntSize; michael@0: struct nsIntRect; michael@0: michael@0: // This file contains stuff we'd rather put elsewhere, but which is michael@0: // dependent on other changes which we don't want to wait for. We plan to michael@0: // remove this file in the near future. michael@0: michael@0: michael@0: // This belongs in xpcom/monitor/Monitor.h, once we've made michael@0: // mozilla::Monitor non-reentrant. michael@0: namespace mozilla { michael@0: michael@0: /** michael@0: * ReentrantMonitorConditionallyEnter michael@0: * michael@0: * Enters the supplied monitor only if the conditional value |aEnter| is true. michael@0: * E.g. Used to allow unmonitored read access on the decode thread, michael@0: * and monitored access on all other threads. michael@0: */ michael@0: class MOZ_STACK_CLASS ReentrantMonitorConditionallyEnter michael@0: { michael@0: public: michael@0: ReentrantMonitorConditionallyEnter(bool aEnter, michael@0: ReentrantMonitor &aReentrantMonitor) : michael@0: mReentrantMonitor(nullptr) michael@0: { michael@0: MOZ_COUNT_CTOR(ReentrantMonitorConditionallyEnter); michael@0: if (aEnter) { michael@0: mReentrantMonitor = &aReentrantMonitor; michael@0: NS_ASSERTION(mReentrantMonitor, "null monitor"); michael@0: mReentrantMonitor->Enter(); michael@0: } michael@0: } michael@0: ~ReentrantMonitorConditionallyEnter(void) michael@0: { michael@0: if (mReentrantMonitor) { michael@0: mReentrantMonitor->Exit(); michael@0: } michael@0: MOZ_COUNT_DTOR(ReentrantMonitorConditionallyEnter); michael@0: } michael@0: private: michael@0: // Restrict to constructor and destructor defined above. michael@0: ReentrantMonitorConditionallyEnter(); michael@0: ReentrantMonitorConditionallyEnter(const ReentrantMonitorConditionallyEnter&); michael@0: ReentrantMonitorConditionallyEnter& operator =(const ReentrantMonitorConditionallyEnter&); michael@0: static void* operator new(size_t) CPP_THROW_NEW; michael@0: static void operator delete(void*); michael@0: michael@0: ReentrantMonitor* mReentrantMonitor; michael@0: }; michael@0: michael@0: // Shuts down a thread asynchronously. michael@0: class ShutdownThreadEvent : public nsRunnable michael@0: { michael@0: public: michael@0: ShutdownThreadEvent(nsIThread* aThread) : mThread(aThread) {} michael@0: ~ShutdownThreadEvent() {} michael@0: NS_IMETHOD Run() MOZ_OVERRIDE { michael@0: mThread->Shutdown(); michael@0: mThread = nullptr; michael@0: return NS_OK; michael@0: } michael@0: private: michael@0: nsCOMPtr mThread; michael@0: }; michael@0: michael@0: class MediaResource; michael@0: michael@0: namespace dom { michael@0: class TimeRanges; michael@0: } michael@0: michael@0: // Estimates the buffered ranges of a MediaResource using a simple michael@0: // (byteOffset/length)*duration method. Probably inaccurate, but won't michael@0: // do file I/O, and can be used when we don't have detailed knowledge michael@0: // of the byte->time mapping of a resource. aDurationUsecs is the duration michael@0: // of the media in microseconds. Estimated buffered ranges are stored in michael@0: // aOutBuffered. Ranges are 0-normalized, i.e. in the range of (0,duration]. michael@0: void GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream, michael@0: int64_t aDurationUsecs, michael@0: mozilla::dom::TimeRanges* aOutBuffered); michael@0: michael@0: // Converts from number of audio frames (aFrames) to microseconds, given michael@0: // the specified audio rate (aRate). Stores result in aOutUsecs. Returns true michael@0: // if the operation succeeded, or false if there was an integer overflow michael@0: // while calulating the conversion. michael@0: CheckedInt64 FramesToUsecs(int64_t aFrames, uint32_t aRate); michael@0: michael@0: // Converts from microseconds (aUsecs) to number of audio frames, given the michael@0: // specified audio rate (aRate). Stores the result in aOutFrames. Returns michael@0: // true if the operation succeeded, or false if there was an integer michael@0: // overflow while calulating the conversion. michael@0: CheckedInt64 UsecsToFrames(int64_t aUsecs, uint32_t aRate); michael@0: michael@0: // Number of microseconds per second. 1e6. michael@0: static const int64_t USECS_PER_S = 1000000; michael@0: michael@0: // Number of microseconds per millisecond. michael@0: static const int64_t USECS_PER_MS = 1000; michael@0: michael@0: // Converts seconds to milliseconds. michael@0: #define MS_TO_SECONDS(s) ((double)(s) / (PR_MSEC_PER_SEC)) michael@0: michael@0: // Converts from seconds to microseconds. Returns failure if the resulting michael@0: // integer is too big to fit in an int64_t. michael@0: nsresult SecondsToUsecs(double aSeconds, int64_t& aOutUsecs); michael@0: michael@0: // The maximum height and width of the video. Used for michael@0: // sanitizing the memory allocation of the RGB buffer. michael@0: // The maximum resolution we anticipate encountering in the michael@0: // wild is 2160p - 3840x2160 pixels. michael@0: static const int32_t MAX_VIDEO_WIDTH = 4000; michael@0: static const int32_t MAX_VIDEO_HEIGHT = 3000; michael@0: michael@0: // Scales the display rect aDisplay by aspect ratio aAspectRatio. michael@0: // Note that aDisplay must be validated by IsValidVideoRegion() michael@0: // before being used! michael@0: void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio); michael@0: michael@0: // The amount of virtual memory reserved for thread stacks. michael@0: #if (defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) && \ michael@0: !defined(MOZ_ASAN) michael@0: #define MEDIA_THREAD_STACK_SIZE (128 * 1024) michael@0: #else michael@0: // All other platforms use their system defaults. michael@0: #define MEDIA_THREAD_STACK_SIZE nsIThreadManager::DEFAULT_STACK_SIZE michael@0: #endif michael@0: michael@0: // Downmix multichannel Audio samples to Stereo. michael@0: // Input are the buffer contains multichannel data, michael@0: // the number of channels and the number of frames. michael@0: int DownmixAudioToStereo(mozilla::AudioDataValue* buffer, michael@0: int channels, michael@0: uint32_t frames); michael@0: michael@0: bool IsVideoContentType(const nsCString& aContentType); michael@0: michael@0: // Returns true if it's safe to use aPicture as the picture to be michael@0: // extracted inside a frame of size aFrame, and scaled up to and displayed michael@0: // at a size of aDisplay. You should validate the frame, picture, and michael@0: // display regions before using them to display video frames. michael@0: bool IsValidVideoRegion(const nsIntSize& aFrame, const nsIntRect& aPicture, michael@0: const nsIntSize& aDisplay); michael@0: michael@0: } // end namespace mozilla michael@0: michael@0: #endif