michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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: #if !defined(MediaData_h) michael@0: #define MediaData_h michael@0: michael@0: #include "nsSize.h" michael@0: #include "mozilla/gfx/Rect.h" michael@0: #include "nsRect.h" michael@0: #include "AudioSampleFormat.h" michael@0: #include "nsIMemoryReporter.h" michael@0: #include "SharedBuffer.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace layers { michael@0: class Image; michael@0: class ImageContainer; michael@0: } michael@0: michael@0: // Container that holds media samples. michael@0: class MediaData { michael@0: public: michael@0: michael@0: enum Type { michael@0: AUDIO_SAMPLES = 0, michael@0: VIDEO_FRAME = 1 michael@0: }; michael@0: michael@0: MediaData(Type aType, michael@0: int64_t aOffset, michael@0: int64_t aTimestamp, michael@0: int64_t aDuration) michael@0: : mType(aType) michael@0: , mOffset(aOffset) michael@0: , mTime(aTimestamp) michael@0: , mDuration(aDuration) michael@0: {} michael@0: michael@0: virtual ~MediaData() {} michael@0: michael@0: // Type of contained data. michael@0: const Type mType; michael@0: michael@0: // Approximate byte offset where this data was demuxed from its media. michael@0: const int64_t mOffset; michael@0: michael@0: // Start time of sample, in microseconds. michael@0: const int64_t mTime; michael@0: michael@0: // Duration of sample, in microseconds. michael@0: const int64_t mDuration; michael@0: michael@0: int64_t GetEndTime() const { return mTime + mDuration; } michael@0: michael@0: }; michael@0: michael@0: // Holds chunk a decoded audio frames. michael@0: class AudioData : public MediaData { michael@0: public: michael@0: michael@0: AudioData(int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: uint32_t aFrames, michael@0: AudioDataValue* aData, michael@0: uint32_t aChannels) michael@0: : MediaData(AUDIO_SAMPLES, aOffset, aTime, aDuration) michael@0: , mFrames(aFrames) michael@0: , mChannels(aChannels) michael@0: , mAudioData(aData) michael@0: { michael@0: MOZ_COUNT_CTOR(AudioData); michael@0: } michael@0: michael@0: ~AudioData() michael@0: { michael@0: MOZ_COUNT_DTOR(AudioData); michael@0: } michael@0: michael@0: size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { michael@0: size_t size = aMallocSizeOf(this) + aMallocSizeOf(mAudioData); michael@0: if (mAudioBuffer) { michael@0: size += mAudioBuffer->SizeOfIncludingThis(aMallocSizeOf); michael@0: } michael@0: return size; michael@0: } michael@0: michael@0: // If mAudioBuffer is null, creates it from mAudioData. michael@0: void EnsureAudioBuffer(); michael@0: michael@0: const uint32_t mFrames; michael@0: const uint32_t mChannels; michael@0: // At least one of mAudioBuffer/mAudioData must be non-null. michael@0: // mChannels channels, each with mFrames frames michael@0: nsRefPtr mAudioBuffer; michael@0: // mFrames frames, each with mChannels values michael@0: nsAutoArrayPtr mAudioData; michael@0: }; michael@0: michael@0: namespace layers { michael@0: class TextureClient; michael@0: class PlanarYCbCrImage; michael@0: } michael@0: michael@0: class VideoInfo; michael@0: michael@0: // Holds a decoded video frame, in YCbCr format. These are queued in the reader. michael@0: class VideoData : public MediaData { michael@0: public: michael@0: typedef gfx::IntRect IntRect; michael@0: typedef gfx::IntSize IntSize; michael@0: typedef layers::ImageContainer ImageContainer; michael@0: typedef layers::Image Image; michael@0: typedef layers::PlanarYCbCrImage PlanarYCbCrImage; michael@0: michael@0: // YCbCr data obtained from decoding the video. The index's are: michael@0: // 0 = Y michael@0: // 1 = Cb michael@0: // 2 = Cr michael@0: struct YCbCrBuffer { michael@0: struct Plane { michael@0: uint8_t* mData; michael@0: uint32_t mWidth; michael@0: uint32_t mHeight; michael@0: uint32_t mStride; michael@0: uint32_t mOffset; michael@0: uint32_t mSkip; michael@0: }; michael@0: michael@0: Plane mPlanes[3]; michael@0: }; michael@0: michael@0: // Constructs a VideoData object. If aImage is nullptr, creates a new Image michael@0: // holding a copy of the YCbCr data passed in aBuffer. If aImage is not michael@0: // nullptr, it's stored as the underlying video image and aBuffer is assumed michael@0: // to point to memory within aImage so no copy is made. aTimecode is a codec michael@0: // specific number representing the timestamp of the frame of video data. michael@0: // Returns nsnull if an error occurs. This may indicate that memory couldn't michael@0: // be allocated to create the VideoData object, or it may indicate some michael@0: // problem with the input data (e.g. negative stride). michael@0: static VideoData* Create(VideoInfo& aInfo, michael@0: ImageContainer* aContainer, michael@0: Image* aImage, michael@0: int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: const YCbCrBuffer &aBuffer, michael@0: bool aKeyframe, michael@0: int64_t aTimecode, michael@0: const IntRect& aPicture); michael@0: michael@0: // Variant that always makes a copy of aBuffer michael@0: static VideoData* Create(VideoInfo& aInfo, michael@0: ImageContainer* aContainer, michael@0: int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: const YCbCrBuffer &aBuffer, michael@0: bool aKeyframe, michael@0: int64_t aTimecode, michael@0: const IntRect& aPicture); michael@0: michael@0: // Variant to create a VideoData instance given an existing aImage michael@0: static VideoData* Create(VideoInfo& aInfo, michael@0: Image* aImage, michael@0: int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: const YCbCrBuffer &aBuffer, michael@0: bool aKeyframe, michael@0: int64_t aTimecode, michael@0: const IntRect& aPicture); michael@0: michael@0: static VideoData* Create(VideoInfo& aInfo, michael@0: ImageContainer* aContainer, michael@0: int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: layers::TextureClient* aBuffer, michael@0: bool aKeyframe, michael@0: int64_t aTimecode, michael@0: const IntRect& aPicture); michael@0: michael@0: static VideoData* CreateFromImage(VideoInfo& aInfo, michael@0: ImageContainer* aContainer, michael@0: int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: const nsRefPtr& aImage, michael@0: bool aKeyframe, michael@0: int64_t aTimecode, michael@0: const IntRect& aPicture); michael@0: michael@0: // Creates a new VideoData identical to aOther, but with a different michael@0: // specified duration. All data from aOther is copied into the new michael@0: // VideoData. The new VideoData's mImage field holds a reference to michael@0: // aOther's mImage, i.e. the Image is not copied. This function is useful michael@0: // in reader backends that can't determine the duration of a VideoData michael@0: // until the next frame is decoded, i.e. it's a way to change the const michael@0: // duration field on a VideoData. michael@0: static VideoData* ShallowCopyUpdateDuration(VideoData* aOther, michael@0: int64_t aDuration); michael@0: michael@0: // Creates a new VideoData identical to aOther, but with a different michael@0: // specified timestamp. All data from aOther is copied into the new michael@0: // VideoData, as ShallowCopyUpdateDuration() does. michael@0: static VideoData* ShallowCopyUpdateTimestamp(VideoData* aOther, michael@0: int64_t aTimestamp); michael@0: michael@0: // Initialize PlanarYCbCrImage. Only When aCopyData is true, michael@0: // video data is copied to PlanarYCbCrImage. michael@0: static void SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, michael@0: VideoInfo& aInfo, michael@0: const YCbCrBuffer &aBuffer, michael@0: const IntRect& aPicture, michael@0: bool aCopyData); michael@0: michael@0: // Constructs a duplicate VideoData object. This intrinsically tells the michael@0: // player that it does not need to update the displayed frame when this michael@0: // frame is played; this frame is identical to the previous. michael@0: static VideoData* CreateDuplicate(int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: int64_t aTimecode) michael@0: { michael@0: return new VideoData(aOffset, aTime, aDuration, aTimecode); michael@0: } michael@0: michael@0: ~VideoData(); michael@0: michael@0: size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; michael@0: michael@0: // Dimensions at which to display the video frame. The picture region michael@0: // will be scaled to this size. This is should be the picture region's michael@0: // dimensions scaled with respect to its aspect ratio. michael@0: const IntSize mDisplay; michael@0: michael@0: // Codec specific internal time code. For Ogg based codecs this is the michael@0: // granulepos. michael@0: const int64_t mTimecode; michael@0: michael@0: // This frame's image. michael@0: nsRefPtr mImage; michael@0: michael@0: // When true, denotes that this frame is identical to the frame that michael@0: // came before; it's a duplicate. mBuffer will be empty. michael@0: const bool mDuplicate; michael@0: const bool mKeyframe; michael@0: michael@0: public: michael@0: VideoData(int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: int64_t aTimecode); michael@0: michael@0: VideoData(int64_t aOffset, michael@0: int64_t aTime, michael@0: int64_t aDuration, michael@0: bool aKeyframe, michael@0: int64_t aTimecode, michael@0: IntSize aDisplay); michael@0: michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif // MediaData_h