|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
|
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 #if !defined(MediaData_h) |
|
7 #define MediaData_h |
|
8 |
|
9 #include "nsSize.h" |
|
10 #include "mozilla/gfx/Rect.h" |
|
11 #include "nsRect.h" |
|
12 #include "AudioSampleFormat.h" |
|
13 #include "nsIMemoryReporter.h" |
|
14 #include "SharedBuffer.h" |
|
15 |
|
16 namespace mozilla { |
|
17 |
|
18 namespace layers { |
|
19 class Image; |
|
20 class ImageContainer; |
|
21 } |
|
22 |
|
23 // Container that holds media samples. |
|
24 class MediaData { |
|
25 public: |
|
26 |
|
27 enum Type { |
|
28 AUDIO_SAMPLES = 0, |
|
29 VIDEO_FRAME = 1 |
|
30 }; |
|
31 |
|
32 MediaData(Type aType, |
|
33 int64_t aOffset, |
|
34 int64_t aTimestamp, |
|
35 int64_t aDuration) |
|
36 : mType(aType) |
|
37 , mOffset(aOffset) |
|
38 , mTime(aTimestamp) |
|
39 , mDuration(aDuration) |
|
40 {} |
|
41 |
|
42 virtual ~MediaData() {} |
|
43 |
|
44 // Type of contained data. |
|
45 const Type mType; |
|
46 |
|
47 // Approximate byte offset where this data was demuxed from its media. |
|
48 const int64_t mOffset; |
|
49 |
|
50 // Start time of sample, in microseconds. |
|
51 const int64_t mTime; |
|
52 |
|
53 // Duration of sample, in microseconds. |
|
54 const int64_t mDuration; |
|
55 |
|
56 int64_t GetEndTime() const { return mTime + mDuration; } |
|
57 |
|
58 }; |
|
59 |
|
60 // Holds chunk a decoded audio frames. |
|
61 class AudioData : public MediaData { |
|
62 public: |
|
63 |
|
64 AudioData(int64_t aOffset, |
|
65 int64_t aTime, |
|
66 int64_t aDuration, |
|
67 uint32_t aFrames, |
|
68 AudioDataValue* aData, |
|
69 uint32_t aChannels) |
|
70 : MediaData(AUDIO_SAMPLES, aOffset, aTime, aDuration) |
|
71 , mFrames(aFrames) |
|
72 , mChannels(aChannels) |
|
73 , mAudioData(aData) |
|
74 { |
|
75 MOZ_COUNT_CTOR(AudioData); |
|
76 } |
|
77 |
|
78 ~AudioData() |
|
79 { |
|
80 MOZ_COUNT_DTOR(AudioData); |
|
81 } |
|
82 |
|
83 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { |
|
84 size_t size = aMallocSizeOf(this) + aMallocSizeOf(mAudioData); |
|
85 if (mAudioBuffer) { |
|
86 size += mAudioBuffer->SizeOfIncludingThis(aMallocSizeOf); |
|
87 } |
|
88 return size; |
|
89 } |
|
90 |
|
91 // If mAudioBuffer is null, creates it from mAudioData. |
|
92 void EnsureAudioBuffer(); |
|
93 |
|
94 const uint32_t mFrames; |
|
95 const uint32_t mChannels; |
|
96 // At least one of mAudioBuffer/mAudioData must be non-null. |
|
97 // mChannels channels, each with mFrames frames |
|
98 nsRefPtr<SharedBuffer> mAudioBuffer; |
|
99 // mFrames frames, each with mChannels values |
|
100 nsAutoArrayPtr<AudioDataValue> mAudioData; |
|
101 }; |
|
102 |
|
103 namespace layers { |
|
104 class TextureClient; |
|
105 class PlanarYCbCrImage; |
|
106 } |
|
107 |
|
108 class VideoInfo; |
|
109 |
|
110 // Holds a decoded video frame, in YCbCr format. These are queued in the reader. |
|
111 class VideoData : public MediaData { |
|
112 public: |
|
113 typedef gfx::IntRect IntRect; |
|
114 typedef gfx::IntSize IntSize; |
|
115 typedef layers::ImageContainer ImageContainer; |
|
116 typedef layers::Image Image; |
|
117 typedef layers::PlanarYCbCrImage PlanarYCbCrImage; |
|
118 |
|
119 // YCbCr data obtained from decoding the video. The index's are: |
|
120 // 0 = Y |
|
121 // 1 = Cb |
|
122 // 2 = Cr |
|
123 struct YCbCrBuffer { |
|
124 struct Plane { |
|
125 uint8_t* mData; |
|
126 uint32_t mWidth; |
|
127 uint32_t mHeight; |
|
128 uint32_t mStride; |
|
129 uint32_t mOffset; |
|
130 uint32_t mSkip; |
|
131 }; |
|
132 |
|
133 Plane mPlanes[3]; |
|
134 }; |
|
135 |
|
136 // Constructs a VideoData object. If aImage is nullptr, creates a new Image |
|
137 // holding a copy of the YCbCr data passed in aBuffer. If aImage is not |
|
138 // nullptr, it's stored as the underlying video image and aBuffer is assumed |
|
139 // to point to memory within aImage so no copy is made. aTimecode is a codec |
|
140 // specific number representing the timestamp of the frame of video data. |
|
141 // Returns nsnull if an error occurs. This may indicate that memory couldn't |
|
142 // be allocated to create the VideoData object, or it may indicate some |
|
143 // problem with the input data (e.g. negative stride). |
|
144 static VideoData* Create(VideoInfo& aInfo, |
|
145 ImageContainer* aContainer, |
|
146 Image* aImage, |
|
147 int64_t aOffset, |
|
148 int64_t aTime, |
|
149 int64_t aDuration, |
|
150 const YCbCrBuffer &aBuffer, |
|
151 bool aKeyframe, |
|
152 int64_t aTimecode, |
|
153 const IntRect& aPicture); |
|
154 |
|
155 // Variant that always makes a copy of aBuffer |
|
156 static VideoData* Create(VideoInfo& aInfo, |
|
157 ImageContainer* aContainer, |
|
158 int64_t aOffset, |
|
159 int64_t aTime, |
|
160 int64_t aDuration, |
|
161 const YCbCrBuffer &aBuffer, |
|
162 bool aKeyframe, |
|
163 int64_t aTimecode, |
|
164 const IntRect& aPicture); |
|
165 |
|
166 // Variant to create a VideoData instance given an existing aImage |
|
167 static VideoData* Create(VideoInfo& aInfo, |
|
168 Image* aImage, |
|
169 int64_t aOffset, |
|
170 int64_t aTime, |
|
171 int64_t aDuration, |
|
172 const YCbCrBuffer &aBuffer, |
|
173 bool aKeyframe, |
|
174 int64_t aTimecode, |
|
175 const IntRect& aPicture); |
|
176 |
|
177 static VideoData* Create(VideoInfo& aInfo, |
|
178 ImageContainer* aContainer, |
|
179 int64_t aOffset, |
|
180 int64_t aTime, |
|
181 int64_t aDuration, |
|
182 layers::TextureClient* aBuffer, |
|
183 bool aKeyframe, |
|
184 int64_t aTimecode, |
|
185 const IntRect& aPicture); |
|
186 |
|
187 static VideoData* CreateFromImage(VideoInfo& aInfo, |
|
188 ImageContainer* aContainer, |
|
189 int64_t aOffset, |
|
190 int64_t aTime, |
|
191 int64_t aDuration, |
|
192 const nsRefPtr<Image>& aImage, |
|
193 bool aKeyframe, |
|
194 int64_t aTimecode, |
|
195 const IntRect& aPicture); |
|
196 |
|
197 // Creates a new VideoData identical to aOther, but with a different |
|
198 // specified duration. All data from aOther is copied into the new |
|
199 // VideoData. The new VideoData's mImage field holds a reference to |
|
200 // aOther's mImage, i.e. the Image is not copied. This function is useful |
|
201 // in reader backends that can't determine the duration of a VideoData |
|
202 // until the next frame is decoded, i.e. it's a way to change the const |
|
203 // duration field on a VideoData. |
|
204 static VideoData* ShallowCopyUpdateDuration(VideoData* aOther, |
|
205 int64_t aDuration); |
|
206 |
|
207 // Creates a new VideoData identical to aOther, but with a different |
|
208 // specified timestamp. All data from aOther is copied into the new |
|
209 // VideoData, as ShallowCopyUpdateDuration() does. |
|
210 static VideoData* ShallowCopyUpdateTimestamp(VideoData* aOther, |
|
211 int64_t aTimestamp); |
|
212 |
|
213 // Initialize PlanarYCbCrImage. Only When aCopyData is true, |
|
214 // video data is copied to PlanarYCbCrImage. |
|
215 static void SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, |
|
216 VideoInfo& aInfo, |
|
217 const YCbCrBuffer &aBuffer, |
|
218 const IntRect& aPicture, |
|
219 bool aCopyData); |
|
220 |
|
221 // Constructs a duplicate VideoData object. This intrinsically tells the |
|
222 // player that it does not need to update the displayed frame when this |
|
223 // frame is played; this frame is identical to the previous. |
|
224 static VideoData* CreateDuplicate(int64_t aOffset, |
|
225 int64_t aTime, |
|
226 int64_t aDuration, |
|
227 int64_t aTimecode) |
|
228 { |
|
229 return new VideoData(aOffset, aTime, aDuration, aTimecode); |
|
230 } |
|
231 |
|
232 ~VideoData(); |
|
233 |
|
234 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; |
|
235 |
|
236 // Dimensions at which to display the video frame. The picture region |
|
237 // will be scaled to this size. This is should be the picture region's |
|
238 // dimensions scaled with respect to its aspect ratio. |
|
239 const IntSize mDisplay; |
|
240 |
|
241 // Codec specific internal time code. For Ogg based codecs this is the |
|
242 // granulepos. |
|
243 const int64_t mTimecode; |
|
244 |
|
245 // This frame's image. |
|
246 nsRefPtr<Image> mImage; |
|
247 |
|
248 // When true, denotes that this frame is identical to the frame that |
|
249 // came before; it's a duplicate. mBuffer will be empty. |
|
250 const bool mDuplicate; |
|
251 const bool mKeyframe; |
|
252 |
|
253 public: |
|
254 VideoData(int64_t aOffset, |
|
255 int64_t aTime, |
|
256 int64_t aDuration, |
|
257 int64_t aTimecode); |
|
258 |
|
259 VideoData(int64_t aOffset, |
|
260 int64_t aTime, |
|
261 int64_t aDuration, |
|
262 bool aKeyframe, |
|
263 int64_t aTimecode, |
|
264 IntSize aDisplay); |
|
265 |
|
266 }; |
|
267 |
|
268 } // namespace mozilla |
|
269 |
|
270 #endif // MediaData_h |