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(MediaInfo_h)
9 # include "mozilla/UniquePtr.h"
10 # include "mozilla/RefPtr.h"
11 # include "nsTHashMap.h"
12 # include "nsString.h"
13 # include "nsTArray.h"
14 # include "AudioConfig.h"
15 # include "ImageTypes.h"
16 # include "MediaData.h"
17 # include "TimeUnits.h"
18 # include "mozilla/gfx/Point.h" // for gfx::IntSize
19 # include "mozilla/gfx/Rect.h" // for gfx::IntRect
20 # include "mozilla/gfx/Types.h" // for gfx::ColorDepth
30 MetadataTag(const nsACString
& aKey
, const nsACString
& aValue
)
31 : mKey(aKey
), mValue(aValue
) {}
34 bool operator==(const MetadataTag
& rhs
) const {
35 return mKey
== rhs
.mKey
&& mValue
== rhs
.mValue
;
39 typedef nsTHashMap
<nsCStringHashKey
, nsCString
> MetadataTags
;
43 enum TrackType
{ kUndefinedTrack
, kAudioTrack
, kVideoTrack
, kTextTrack
};
44 TrackInfo(TrackType aType
, const nsAString
& aId
, const nsAString
& aKind
,
45 const nsAString
& aLabel
, const nsAString
& aLanguage
, bool aEnabled
,
53 mIsRenderedExternally(false),
55 MOZ_COUNT_CTOR(TrackInfo
);
58 // Only used for backward compatibility. Do not use in new code.
59 void Init(const nsAString
& aId
, const nsAString
& aKind
,
60 const nsAString
& aLabel
, const nsAString
& aLanguage
,
65 mLanguage
= aLanguage
;
69 // Fields common with MediaTrack object.
79 media::TimeUnit mDuration
;
80 media::TimeUnit mMediaTime
;
83 CopyableTArray
<MetadataTag
> mTags
;
85 // True if the track is gonna be (decrypted)/decoded and
86 // rendered directly by non-gecko components.
87 bool mIsRenderedExternally
;
89 virtual AudioInfo
* GetAsAudioInfo() { return nullptr; }
90 virtual VideoInfo
* GetAsVideoInfo() { return nullptr; }
91 virtual TextInfo
* GetAsTextInfo() { return nullptr; }
92 virtual const AudioInfo
* GetAsAudioInfo() const { return nullptr; }
93 virtual const VideoInfo
* GetAsVideoInfo() const { return nullptr; }
94 virtual const TextInfo
* GetAsTextInfo() const { return nullptr; }
96 bool IsAudio() const { return !!GetAsAudioInfo(); }
97 bool IsVideo() const { return !!GetAsVideoInfo(); }
98 bool IsText() const { return !!GetAsTextInfo(); }
99 TrackType
GetType() const { return mType
; }
101 bool virtual IsValid() const = 0;
103 virtual UniquePtr
<TrackInfo
> Clone() const = 0;
105 MOZ_COUNTED_DTOR_VIRTUAL(TrackInfo
)
108 TrackInfo(const TrackInfo
& aOther
) {
110 mKind
= aOther
.mKind
;
111 mLabel
= aOther
.mLabel
;
112 mLanguage
= aOther
.mLanguage
;
113 mEnabled
= aOther
.mEnabled
;
114 mTrackId
= aOther
.mTrackId
;
115 mMimeType
= aOther
.mMimeType
;
116 mDuration
= aOther
.mDuration
;
117 mMediaTime
= aOther
.mMediaTime
;
118 mCrypto
= aOther
.mCrypto
;
119 mIsRenderedExternally
= aOther
.mIsRenderedExternally
;
120 mType
= aOther
.mType
;
121 mTags
= aOther
.mTags
.Clone();
122 MOZ_COUNT_CTOR(TrackInfo
);
124 bool IsEqualTo(const TrackInfo
& rhs
) const;
130 // String version of track type.
131 const char* TrackTypeToStr(TrackInfo::TrackType aTrack
);
133 // Stores info relevant to presenting media frames.
134 class VideoInfo
: public TrackInfo
{
142 VideoInfo() : VideoInfo(-1, -1) {}
144 VideoInfo(int32_t aWidth
, int32_t aHeight
)
145 : VideoInfo(gfx::IntSize(aWidth
, aHeight
)) {}
147 explicit VideoInfo(const gfx::IntSize
& aSize
)
148 : TrackInfo(kVideoTrack
, u
"2"_ns
, u
"main"_ns
, u
""_ns
, u
""_ns
, true, 2),
150 mStereoMode(StereoMode::MONO
),
152 mCodecSpecificConfig(new MediaByteBuffer
),
153 mExtraData(new MediaByteBuffer
),
154 mRotation(kDegree_0
) {}
156 VideoInfo(const VideoInfo
& aOther
) = default;
158 bool operator==(const VideoInfo
& rhs
) const;
160 bool IsValid() const override
{
161 return mDisplay
.width
> 0 && mDisplay
.height
> 0;
164 VideoInfo
* GetAsVideoInfo() override
{ return this; }
166 const VideoInfo
* GetAsVideoInfo() const override
{ return this; }
168 UniquePtr
<TrackInfo
> Clone() const override
{
169 return MakeUnique
<VideoInfo
>(*this);
172 void SetAlpha(bool aAlphaPresent
) { mAlphaPresent
= aAlphaPresent
; }
174 bool HasAlpha() const { return mAlphaPresent
; }
176 gfx::IntRect
ImageRect() const {
178 return gfx::IntRect(0, 0, mImage
.width
, mImage
.height
);
183 void SetImageRect(const gfx::IntRect
& aRect
) { mImageRect
= Some(aRect
); }
184 void ResetImageRect() { mImageRect
.reset(); }
186 // Returned the crop rectangle scaled to aWidth/aHeight size relative to
188 // If aWidth and aHeight are identical to the original
189 // mImage.width/mImage.height then the scaling ratio will be 1. This is used
190 // for when the frame size is different from what the container reports. This
191 // is legal in WebM, and we will preserve the ratio of the crop rectangle as
192 // it was reported relative to the picture size reported by the container.
193 gfx::IntRect
ScaledImageRect(int64_t aWidth
, int64_t aHeight
) const {
194 if ((aWidth
== mImage
.width
&& aHeight
== mImage
.height
) || !mImage
.width
||
199 gfx::IntRect imageRect
= ImageRect();
200 int64_t w
= (aWidth
* imageRect
.Width()) / mImage
.width
;
201 int64_t h
= (aHeight
* imageRect
.Height()) / mImage
.height
;
206 imageRect
.x
= (imageRect
.x
* aWidth
) / mImage
.width
;
207 imageRect
.y
= (imageRect
.y
* aHeight
) / mImage
.height
;
208 imageRect
.SetWidth(w
);
209 imageRect
.SetHeight(h
);
213 Rotation
ToSupportedRotation(int32_t aDegree
) const {
222 NS_WARNING_ASSERTION(aDegree
== 0, "Invalid rotation degree, ignored");
227 // Size in pixels at which the video is rendered. This is after it has
228 // been scaled by its aspect ratio.
229 gfx::IntSize mDisplay
;
231 // Indicates the frame layout for single track stereo videos.
232 StereoMode mStereoMode
;
234 // Size of the decoded video's image.
237 RefPtr
<MediaByteBuffer
> mCodecSpecificConfig
;
238 RefPtr
<MediaByteBuffer
> mExtraData
;
240 // Describing how many degrees video frames should be rotated in clock-wise to
244 // Should be 8, 10 or 12. Default value is 8.
245 gfx::ColorDepth mColorDepth
= gfx::ColorDepth::COLOR_8
;
247 Maybe
<gfx::YUVColorSpace
> mColorSpace
;
249 // True indicates no restriction on Y, U, V values (otherwise 16-235 for 8
251 gfx::ColorRange mColorRange
= gfx::ColorRange::LIMITED
;
253 Maybe
<int32_t> GetFrameRate() const { return mFrameRate
; }
254 void SetFrameRate(int32_t aRate
) { mFrameRate
= Some(aRate
); }
257 friend struct IPC::ParamTraits
<VideoInfo
>;
259 // mImage may be cropped; currently only used with the WebM container.
260 // If unset, no cropping is to occur.
261 Maybe
<gfx::IntRect
> mImageRect
;
263 // Indicates whether or not frames may contain alpha information.
264 bool mAlphaPresent
= false;
266 Maybe
<int32_t> mFrameRate
;
269 class AudioInfo
: public TrackInfo
{
272 : TrackInfo(kAudioTrack
, u
"1"_ns
, u
"main"_ns
, u
""_ns
, u
""_ns
, true, 1),
275 mChannelMap(AudioConfig::ChannelLayout::UNKNOWN_MAP
),
279 mCodecSpecificConfig(new MediaByteBuffer
),
280 mExtraData(new MediaByteBuffer
) {}
282 AudioInfo(const AudioInfo
& aOther
) = default;
284 bool operator==(const AudioInfo
& rhs
) const;
286 static const uint32_t MAX_RATE
= 640000;
288 bool IsValid() const override
{
289 return mChannels
> 0 && mRate
> 0 && mRate
<= MAX_RATE
;
292 AudioInfo
* GetAsAudioInfo() override
{ return this; }
294 const AudioInfo
* GetAsAudioInfo() const override
{ return this; }
296 UniquePtr
<TrackInfo
> Clone() const override
{
297 return MakeUnique
<AudioInfo
>(*this);
303 // Number of audio channels.
305 // The AudioConfig::ChannelLayout map. Channels are ordered as per SMPTE
306 // definition. A value of UNKNOWN_MAP indicates unknown layout.
307 // ChannelMap is an unsigned bitmap compatible with Windows' WAVE and FFmpeg
309 AudioConfig::ChannelLayout::ChannelMap mChannelMap
;
317 // Extended codec profile.
318 int8_t mExtendedProfile
;
320 RefPtr
<MediaByteBuffer
> mCodecSpecificConfig
;
321 RefPtr
<MediaByteBuffer
> mExtraData
;
324 class EncryptionInfo
{
326 EncryptionInfo() : mEncrypted(false) {}
329 template <typename AInitDatas
>
330 InitData(const nsAString
& aType
, AInitDatas
&& aInitData
)
331 : mType(aType
), mInitData(std::forward
<AInitDatas
>(aInitData
)) {}
333 // Encryption type to be passed to JS. Usually `cenc'.
337 CopyableTArray
<uint8_t> mInitData
;
339 typedef CopyableTArray
<InitData
> InitDatas
;
341 // True if the stream has encryption metadata
342 bool IsEncrypted() const { return mEncrypted
; }
349 template <typename AInitDatas
>
350 void AddInitData(const nsAString
& aType
, AInitDatas
&& aInitData
) {
351 mInitDatas
.AppendElement(
352 InitData(aType
, std::forward
<AInitDatas
>(aInitData
)));
356 void AddInitData(const EncryptionInfo
& aInfo
) {
357 mInitDatas
.AppendElements(aInfo
.mInitDatas
);
358 mEncrypted
= !!mInitDatas
.Length();
361 // One 'InitData' per encrypted buffer.
362 InitDatas mInitDatas
;
370 bool HasVideo() const { return mVideo
.IsValid(); }
376 // Set dummy values so that HasVideo() will return true;
377 // See VideoInfo::IsValid()
378 mVideo
.mDisplay
= gfx::IntSize(1, 1);
381 bool HasAudio() const { return mAudio
.IsValid(); }
387 // Set dummy values so that HasAudio() will return true;
388 // See AudioInfo::IsValid()
389 mAudio
.mChannels
= 2;
390 mAudio
.mRate
= 44100;
393 bool IsEncrypted() const {
394 return (HasAudio() && mAudio
.mCrypto
.IsEncrypted()) ||
395 (HasVideo() && mVideo
.mCrypto
.IsEncrypted());
398 bool HasValidMedia() const { return HasVideo() || HasAudio(); }
400 // TODO: Store VideoInfo and AudioIndo in arrays to support multi-tracks.
404 // If the metadata includes a duration, we store it here.
405 media::NullableTimeUnit mMetadataDuration
;
407 // The Ogg reader tries to kinda-sorta compute the duration by seeking to the
408 // end and determining the timestamp of the last frame. This isn't useful as
409 // a duration until we know the start time, so we need to track it separately.
410 media::NullableTimeUnit mUnadjustedMetadataEndTime
;
412 // True if the media is seekable (i.e. supports random access).
413 bool mMediaSeekable
= true;
415 // True if the media is only seekable within its buffered ranges.
416 bool mMediaSeekableOnlyInBufferedRanges
= false;
418 EncryptionInfo mCrypto
;
420 // The minimum of start times of audio and video tracks.
421 // Use to map the zero time on the media timeline to the first frame.
422 media::TimeUnit mStartTime
;
425 class TrackInfoSharedPtr
{
426 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackInfoSharedPtr
)
428 TrackInfoSharedPtr(const TrackInfo
& aOriginal
, uint32_t aStreamID
)
429 : mInfo(aOriginal
.Clone()),
430 mStreamSourceID(aStreamID
),
431 mMimeType(mInfo
->mMimeType
) {}
433 uint32_t GetID() const { return mStreamSourceID
; }
435 operator const TrackInfo
*() const { return mInfo
.get(); }
437 const TrackInfo
* operator*() const { return mInfo
.get(); }
439 const TrackInfo
* operator->() const {
440 MOZ_ASSERT(mInfo
.get(), "dereferencing a UniquePtr containing nullptr");
444 const AudioInfo
* GetAsAudioInfo() const {
445 return mInfo
? mInfo
->GetAsAudioInfo() : nullptr;
448 const VideoInfo
* GetAsVideoInfo() const {
449 return mInfo
? mInfo
->GetAsVideoInfo() : nullptr;
452 const TextInfo
* GetAsTextInfo() const {
453 return mInfo
? mInfo
->GetAsTextInfo() : nullptr;
457 ~TrackInfoSharedPtr() = default;
458 UniquePtr
<TrackInfo
> mInfo
;
459 // A unique ID, guaranteed to change when changing streams.
460 uint32_t mStreamSourceID
;
463 const nsCString
& mMimeType
;
466 } // namespace mozilla
468 #endif // MediaInfo_h