michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 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 file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef MOZILLA_VIDEOSEGMENT_H_ michael@0: #define MOZILLA_VIDEOSEGMENT_H_ michael@0: michael@0: #include "MediaSegment.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "gfxPoint.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "ImageContainer.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace layers { michael@0: class Image; michael@0: } michael@0: michael@0: class VideoFrame { michael@0: public: michael@0: typedef mozilla::layers::Image Image; michael@0: michael@0: VideoFrame(already_AddRefed& aImage, const gfxIntSize& aIntrinsicSize); michael@0: VideoFrame(); michael@0: ~VideoFrame(); michael@0: michael@0: bool operator==(const VideoFrame& aFrame) const michael@0: { michael@0: return mIntrinsicSize == aFrame.mIntrinsicSize && michael@0: mForceBlack == aFrame.mForceBlack && michael@0: ((mForceBlack && aFrame.mForceBlack) || mImage == aFrame.mImage); michael@0: } michael@0: bool operator!=(const VideoFrame& aFrame) const michael@0: { michael@0: return !operator==(aFrame); michael@0: } michael@0: michael@0: Image* GetImage() const { return mImage; } michael@0: void SetForceBlack(bool aForceBlack) { mForceBlack = aForceBlack; } michael@0: bool GetForceBlack() const { return mForceBlack; } michael@0: const gfxIntSize& GetIntrinsicSize() const { return mIntrinsicSize; } michael@0: void SetNull(); michael@0: void TakeFrom(VideoFrame* aFrame); michael@0: michael@0: protected: michael@0: // mImage can be null to indicate "no video" (aka "empty frame"). It can michael@0: // still have an intrinsic size in this case. michael@0: nsRefPtr mImage; michael@0: // The desired size to render the video frame at. michael@0: gfxIntSize mIntrinsicSize; michael@0: bool mForceBlack; michael@0: }; michael@0: michael@0: struct VideoChunk { michael@0: VideoChunk(); michael@0: ~VideoChunk(); michael@0: void SliceTo(TrackTicks aStart, TrackTicks aEnd) michael@0: { michael@0: NS_ASSERTION(aStart >= 0 && aStart < aEnd && aEnd <= mDuration, michael@0: "Slice out of bounds"); michael@0: mDuration = aEnd - aStart; michael@0: } michael@0: TrackTicks GetDuration() const { return mDuration; } michael@0: bool CanCombineWithFollowing(const VideoChunk& aOther) const michael@0: { michael@0: return aOther.mFrame == mFrame; michael@0: } michael@0: bool IsNull() const { return !mFrame.GetImage(); } michael@0: void SetNull(TrackTicks aDuration) michael@0: { michael@0: mDuration = aDuration; michael@0: mFrame.SetNull(); michael@0: mTimeStamp = TimeStamp(); michael@0: } michael@0: void SetForceBlack(bool aForceBlack) { mFrame.SetForceBlack(aForceBlack); } michael@0: michael@0: size_t SizeOfExcludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: // Future: michael@0: // - mFrame michael@0: return 0; michael@0: } michael@0: michael@0: TrackTicks mDuration; michael@0: VideoFrame mFrame; michael@0: mozilla::TimeStamp mTimeStamp; michael@0: }; michael@0: michael@0: class VideoSegment : public MediaSegmentBase { michael@0: public: michael@0: typedef mozilla::layers::Image Image; michael@0: typedef mozilla::gfx::IntSize IntSize; michael@0: michael@0: VideoSegment(); michael@0: ~VideoSegment(); michael@0: michael@0: void AppendFrame(already_AddRefed&& aImage, TrackTicks aDuration, michael@0: const IntSize& aIntrinsicSize); michael@0: const VideoFrame* GetFrameAt(TrackTicks aOffset, TrackTicks* aStart = nullptr) michael@0: { michael@0: VideoChunk* c = FindChunkContaining(aOffset, aStart); michael@0: if (!c) { michael@0: return nullptr; michael@0: } michael@0: return &c->mFrame; michael@0: } michael@0: const VideoFrame* GetLastFrame(TrackTicks* aStart = nullptr) michael@0: { michael@0: VideoChunk* c = GetLastChunk(); michael@0: if (!c) { michael@0: return nullptr; michael@0: } michael@0: if (aStart) { michael@0: *aStart = mDuration - c->mDuration; michael@0: } michael@0: return &c->mFrame; michael@0: } michael@0: // Override default impl michael@0: virtual void ReplaceWithDisabled() MOZ_OVERRIDE { michael@0: for (ChunkIterator i(*this); michael@0: !i.IsEnded(); i.Next()) { michael@0: VideoChunk& chunk = *i; michael@0: chunk.SetForceBlack(true); michael@0: } michael@0: } michael@0: michael@0: // Segment-generic methods not in MediaSegmentBase michael@0: static Type StaticType() { return VIDEO; } michael@0: michael@0: virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE michael@0: { michael@0: return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); michael@0: } michael@0: }; michael@0: michael@0: } michael@0: michael@0: #endif /* MOZILLA_VIDEOSEGMENT_H_ */