EncoderConfig.cpp (5896B)
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 #include "EncoderConfig.h" 8 9 #include "ImageContainer.h" 10 #include "MP4Decoder.h" 11 #include "VPXDecoder.h" 12 #include "mozilla/dom/BindingUtils.h" 13 #include "mozilla/dom/ImageUtils.h" 14 15 namespace mozilla { 16 17 nsCString EncoderConfig::ToString() const { 18 nsCString rv(EnumValueToString(mCodec)); 19 rv.AppendLiteral(mBitrateMode == BitrateMode::Constant ? " (CBR)" : " (VBR)"); 20 rv.AppendPrintf("%" PRIu32 "bps", mBitrate); 21 if (mUsage == Usage::Realtime) { 22 rv.AppendLiteral(", realtime"); 23 } else { 24 rv.AppendLiteral(", record"); 25 } 26 if (IsVideo()) { 27 rv.AppendPrintf(" [%dx%d]", mSize.Width(), mSize.Height()); 28 if (mHardwarePreference == HardwarePreference::RequireHardware) { 29 rv.AppendLiteral(", hw required"); 30 } else if (mHardwarePreference == HardwarePreference::RequireSoftware) { 31 rv.AppendLiteral(", sw required"); 32 } else { 33 rv.AppendLiteral(", hw: no preference"); 34 } 35 rv.AppendPrintf(", %s", mFormat.ToString().get()); 36 if (mScalabilityMode == ScalabilityMode::L1T2) { 37 rv.AppendLiteral(", L1T2"); 38 } else if (mScalabilityMode == ScalabilityMode::L1T3) { 39 rv.AppendLiteral(", L1T3"); 40 } 41 rv.AppendPrintf(", %" PRIu8 " fps", mFramerate); 42 rv.AppendPrintf(", kf interval: %zu", mKeyframeInterval); 43 } else { 44 MOZ_ASSERT(IsAudio()); 45 rv.AppendPrintf(", ch: %" PRIu32 ", %" PRIu32 "Hz", mNumberOfChannels, 46 mSampleRate); 47 } 48 const char* specificStr = ""; 49 if (mCodecSpecific.is<void_t>()) { 50 specificStr = "o"; 51 } else if (mCodecSpecific.is<H264Specific>()) { 52 specificStr = " H264"; 53 } else if (mCodecSpecific.is<OpusSpecific>()) { 54 specificStr = " Opus"; 55 } else if (mCodecSpecific.is<VP8Specific>()) { 56 specificStr = " VP8"; 57 } else if (mCodecSpecific.is<VP9Specific>()) { 58 specificStr = " VP9"; 59 } else { 60 MOZ_ASSERT_UNREACHABLE("Unexpected codec specific type"); 61 specificStr = " unknown"; 62 } 63 rv.AppendPrintf(" (w/%s codec specific)", specificStr); 64 return rv; 65 }; 66 67 const char* ColorRangeToString(const gfx::ColorRange& aColorRange) { 68 switch (aColorRange) { 69 case gfx::ColorRange::FULL: 70 return "FULL"; 71 case gfx::ColorRange::LIMITED: 72 return "LIMITED"; 73 } 74 MOZ_ASSERT_UNREACHABLE("unknown ColorRange"); 75 return "unknown"; 76 } 77 78 const char* YUVColorSpaceToString(const gfx::YUVColorSpace& aYUVColorSpace) { 79 switch (aYUVColorSpace) { 80 case gfx::YUVColorSpace::BT601: 81 return "BT601"; 82 case gfx::YUVColorSpace::BT709: 83 return "BT709"; 84 case gfx::YUVColorSpace::BT2020: 85 return "BT2020"; 86 case gfx::YUVColorSpace::Identity: 87 return "Identity"; 88 } 89 MOZ_ASSERT_UNREACHABLE("unknown YUVColorSpace"); 90 return "unknown"; 91 } 92 93 const char* ColorSpace2ToString(const gfx::ColorSpace2& aColorSpace2) { 94 switch (aColorSpace2) { 95 case gfx::ColorSpace2::Display: 96 return "Display"; 97 case gfx::ColorSpace2::SRGB: 98 return "SRGB"; 99 case gfx::ColorSpace2::DISPLAY_P3: 100 return "DISPLAY_P3"; 101 case gfx::ColorSpace2::BT601_525: 102 return "BT601_525"; 103 case gfx::ColorSpace2::BT709: 104 return "BT709"; 105 case gfx::ColorSpace2::BT2020: 106 return "BT2020"; 107 } 108 MOZ_ASSERT_UNREACHABLE("unknown ColorSpace2"); 109 return "unknown"; 110 } 111 112 const char* TransferFunctionToString( 113 const gfx::TransferFunction& aTransferFunction) { 114 switch (aTransferFunction) { 115 case gfx::TransferFunction::BT709: 116 return "BT709"; 117 case gfx::TransferFunction::SRGB: 118 return "SRGB"; 119 case gfx::TransferFunction::PQ: 120 return "PQ"; 121 case gfx::TransferFunction::HLG: 122 return "HLG"; 123 } 124 MOZ_ASSERT_UNREACHABLE("unknown TransferFunction"); 125 return "unknown"; 126 } 127 128 nsCString EncoderConfig::VideoColorSpace::ToString() const { 129 nsCString ret; 130 ret.AppendFmt( 131 "VideoColorSpace: [range: {}, matrix: {}, primaries: {}, transfer: {}]", 132 mRange ? ColorRangeToString(mRange.value()) : "none", 133 mMatrix ? YUVColorSpaceToString(mMatrix.value()) : "none", 134 mPrimaries ? ColorSpace2ToString(mPrimaries.value()) : "none", 135 mTransferFunction ? TransferFunctionToString(mTransferFunction.value()) 136 : "none"); 137 return ret; 138 } 139 140 nsCString EncoderConfig::SampleFormat::ToString() const { 141 return nsPrintfCString("SampleFormat - [PixelFormat: %s, %s]", 142 dom::GetEnumString(mPixelFormat).get(), 143 mColorSpace.ToString().get()); 144 } 145 146 Result<EncoderConfig::SampleFormat, MediaResult> 147 EncoderConfig::SampleFormat::FromImage(layers::Image* aImage) { 148 if (!aImage) { 149 return Err(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "No image")); 150 } 151 152 const dom::ImageUtils imageUtils(aImage); 153 Maybe<dom::ImageBitmapFormat> format = imageUtils.GetFormat(); 154 if (format.isNothing()) { 155 return Err( 156 MediaResult(NS_ERROR_NOT_IMPLEMENTED, 157 nsPrintfCString("unsupported image format: %d", 158 static_cast<int>(aImage->GetFormat())))); 159 } 160 161 if (layers::PlanarYCbCrImage* image = aImage->AsPlanarYCbCrImage()) { 162 if (const layers::PlanarYCbCrImage::Data* yuv = image->GetData()) { 163 return EncoderConfig::SampleFormat( 164 format.ref(), EncoderConfig::VideoColorSpace( 165 yuv->mColorRange, yuv->mYUVColorSpace, 166 yuv->mColorPrimaries, yuv->mTransferFunction)); 167 } 168 return Err(MediaResult(NS_ERROR_UNEXPECTED, 169 "failed to get YUV data from a YUV image")); 170 } 171 172 return EncoderConfig::SampleFormat(format.ref()); 173 } 174 175 } // namespace mozilla