1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 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 7 #ifndef MediaMIMETypes_h_ 8 #define MediaMIMETypes_h_ 9 10 #include "VideoUtils.h" 11 #include "mozilla/Maybe.h" 12 #include "nsString.h" 13 14 namespace mozilla { 15 16 namespace dom { 17 struct AudioConfiguration; 18 struct VideoConfiguration; 19 } // namespace dom 20 21 // Class containing pointing at a media MIME "type/subtype" string literal. 22 // See IsMediaMIMEType for restrictions. 23 // Mainly used to help construct a MediaMIMEType through the statically-checked 24 // MEDIAMIMETYPE macro, or to compare a MediaMIMEType to a literal. 25 class DependentMediaMIMEType { 26 public: 27 // Construction from a literal. Checked in debug builds. 28 // Use MEDIAMIMETYPE macro instead, for static checking. 29 template <size_t N> DependentMediaMIMEType(const char (& aType)[N])30 explicit DependentMediaMIMEType(const char (&aType)[N]) 31 : mMIMEType(aType, N - 1) { 32 MOZ_ASSERT(IsMediaMIMEType(aType, N - 1), "Invalid media MIME type"); 33 } 34 35 // MIME "type/subtype". AsDependentString()36 const nsDependentCString& AsDependentString() const { return mMIMEType; } 37 38 private: 39 nsDependentCString mMIMEType; 40 }; 41 42 // Instantiate a DependentMediaMIMEType from a literal. Statically checked. 43 #define MEDIAMIMETYPE(LIT) \ 44 static_cast<const DependentMediaMIMEType&>([]() { \ 45 static_assert(IsMediaMIMEType(LIT), "Invalid media MIME type"); \ 46 return DependentMediaMIMEType(LIT); \ 47 }()) 48 49 // Class containing only pre-parsed lowercase media MIME type/subtype. 50 class MediaMIMEType { 51 public: 52 // Construction from a DependentMediaMIMEType, with its inherent checks. 53 // Implicit so MEDIAMIMETYPE can be used wherever a MediaMIMEType is expected. MediaMIMEType(const DependentMediaMIMEType & aType)54 MOZ_IMPLICIT MediaMIMEType(const DependentMediaMIMEType& aType) 55 : mMIMEType(aType.AsDependentString()) {} 56 57 // MIME "type/subtype", always lowercase. AsString()58 const nsCString& AsString() const { return mMIMEType; } 59 60 // Comparison with DependentMediaMIMEType. 61 // Useful to compare to MEDIAMIMETYPE literals. 62 bool operator==(const DependentMediaMIMEType& aOther) const { 63 return mMIMEType.Equals(aOther.AsDependentString()); 64 } 65 bool operator!=(const DependentMediaMIMEType& aOther) const { 66 return !mMIMEType.Equals(aOther.AsDependentString()); 67 } 68 69 bool operator==(const MediaMIMEType& aOther) const { 70 return mMIMEType.Equals(aOther.mMIMEType); 71 } 72 bool operator!=(const MediaMIMEType& aOther) const { 73 return !mMIMEType.Equals(aOther.mMIMEType); 74 } 75 76 // True if type starts with "application/". 77 bool HasApplicationMajorType() const; 78 // True if type starts with "audio/". 79 // Note that some audio content could be stored in a "video/..." container! 80 bool HasAudioMajorType() const; 81 // True if type starts with "video/". 82 // Note that this does not guarantee 100% that the content is actually video! 83 // (e.g., "video/webm" could contain a vorbis audio track.) 84 bool HasVideoMajorType() const; 85 86 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 87 88 private: 89 friend Maybe<MediaMIMEType> MakeMediaMIMEType(const nsAString& aType); 90 friend class MediaExtendedMIMEType; 91 explicit MediaMIMEType(const nsACString& aType); 92 93 nsCString mMIMEType; // UTF8 MIME "type/subtype". 94 }; 95 96 Maybe<MediaMIMEType> MakeMediaMIMEType(const nsAString& aType); 97 Maybe<MediaMIMEType> MakeMediaMIMEType(const nsACString& aType); 98 Maybe<MediaMIMEType> MakeMediaMIMEType(const char* aType); 99 100 // A list of case-sensitive codecs attached to a MediaExtendedMIMEType. 101 class MediaCodecs { 102 public: 103 MediaCodecs() = default; 104 // Construction from a comma-separated list of codecs. Unchecked. MediaCodecs(const nsAString & aCodecs)105 explicit MediaCodecs(const nsAString& aCodecs) : mCodecs(aCodecs) {} 106 // Construction from a literal comma-separated list of codecs. Unchecked. 107 template <size_t N> MediaCodecs(const char (& aCodecs)[N])108 explicit MediaCodecs(const char (&aCodecs)[N]) 109 : mCodecs(NS_ConvertUTF8toUTF16(aCodecs, N - 1)) {} 110 IsEmpty()111 bool IsEmpty() const { return mCodecs.IsEmpty(); } AsString()112 const nsString& AsString() const { return mCodecs; } 113 114 using RangeType = 115 const StringListRange<nsString, 116 StringListRangeEmptyItems::ProcessEmptyItems>; 117 118 // Produces a range object with begin()&end(), can be used in range-for loops. 119 // This will iterate through all codecs, even empty ones (except if the 120 // original list was an empty string). Iterators dereference to 121 // 'const nsDependentString', valid for as long as this MediaCodecs object. Range()122 RangeType Range() const { return RangeType(mCodecs); }; 123 124 // Does this list of codecs contain the given aCodec? 125 bool Contains(const nsAString& aCodec) const; 126 // Does this list of codecs contain *all* the codecs in the given list? 127 bool ContainsAll(const MediaCodecs& aCodecs) const; 128 129 // Does this list of codecs contain a codec starting with the given prefix? 130 bool ContainsPrefix(const nsAString& aCodecPrefix) const; 131 132 template <size_t N> 133 bool operator==(const char (&aType)[N]) const { 134 return mCodecs.EqualsASCII(aType, N - 1); 135 } 136 137 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 138 139 private: 140 // UTF16 comma-separated list of codecs. 141 // See http://www.rfc-editor.org/rfc/rfc4281.txt for the description 142 // of the 'codecs' parameter. 143 nsString mCodecs; 144 }; 145 146 // Class containing pre-parsed media MIME type parameters, e.g.: 147 // MIME type/subtype, optional codecs, etc. 148 class MediaExtendedMIMEType { 149 public: 150 explicit MediaExtendedMIMEType(const MediaMIMEType& aType); 151 explicit MediaExtendedMIMEType(MediaMIMEType&& aType); 152 153 // MIME "type/subtype". Type()154 const MediaMIMEType& Type() const { return mMIMEType; } 155 156 // Was there an explicit 'codecs' parameter provided? HaveCodecs()157 bool HaveCodecs() const { return mHaveCodecs; } 158 // Codecs. May be empty if not provided or explicitly provided as empty. Codecs()159 const MediaCodecs& Codecs() const { return mCodecs; } 160 161 // Sizes and rates. GetWidth()162 Maybe<int32_t> GetWidth() const { return GetMaybeNumber(mWidth); } GetHeight()163 Maybe<int32_t> GetHeight() const { return GetMaybeNumber(mHeight); } GetFramerate()164 Maybe<double> GetFramerate() const { return GetMaybeNumber(mFramerate); } GetBitrate()165 Maybe<int32_t> GetBitrate() const { return GetMaybeNumber(mBitrate); } GetChannels()166 Maybe<int32_t> GetChannels() const { return GetMaybeNumber(mChannels); } GetSamplerate()167 Maybe<int32_t> GetSamplerate() const { return GetMaybeNumber(mSamplerate); } 168 169 // Original string. Note that "type/subtype" may not be lowercase, 170 // use Type().AsString() instead to get the normalized "type/subtype". OriginalString()171 const nsCString& OriginalString() const { return mOriginalString; } 172 173 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 174 175 private: 176 friend Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType( 177 const nsAString& aType); 178 friend Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType( 179 const dom::VideoConfiguration& aConfig); 180 friend Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType( 181 const dom::AudioConfiguration& aConfig); 182 183 MediaExtendedMIMEType(const nsACString& aOriginalString, 184 const nsACString& aMIMEType, bool aHaveCodecs, 185 const nsAString& aCodecs, int32_t aWidth, 186 int32_t aHeight, double aFramerate, int32_t aBitrate); 187 MediaExtendedMIMEType(const nsACString& aOriginalString, 188 const nsACString& aMIMEType, bool aHaveCodecs, 189 const nsAString& aCodecs, int32_t aChannels, 190 int32_t aSamplerate, int32_t aBitrate); 191 192 template <typename T> GetMaybeNumber(T aNumber)193 Maybe<T> GetMaybeNumber(T aNumber) const { 194 return (aNumber < 0) ? Maybe<T>(Nothing()) : Some(T(aNumber)); 195 } 196 197 nsCString mOriginalString; // Original full string. 198 MediaMIMEType mMIMEType; // MIME type/subtype. 199 bool mHaveCodecs = false; // If false, mCodecs must be empty. 200 MediaCodecs mCodecs; 201 // For video 202 int32_t mWidth = -1; // -1 if not provided. 203 int32_t mHeight = -1; // -1 if not provided. 204 double mFramerate = -1; // -1 if not provided. 205 // For audio 206 int32_t mChannels = -1; // -1 if not provided. 207 int32_t mSamplerate = -1; // -1 if not provided. 208 // For both audio and video. 209 int32_t mBitrate = -1; // -1 if not provided. 210 }; 211 212 Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(const nsAString& aType); 213 Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(const nsACString& aType); 214 Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(const char* aType); 215 Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType( 216 const dom::VideoConfiguration& aConfig); 217 Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType( 218 const dom::AudioConfiguration& aConfig); 219 220 } // namespace mozilla 221 222 #endif // MediaMIMETypes_h_ 223