BlankDecoderModule.cpp (5619B)
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 "BlankDecoderModule.h" 8 9 #include "ImageContainer.h" 10 #include "MediaData.h" 11 #include "MediaInfo.h" 12 #include "VideoUtils.h" 13 #include "mozilla/CheckedInt.h" 14 #include "mozilla/RefPtr.h" 15 #include "mozilla/UniquePtrExtensions.h" 16 #include "mozilla/gfx/Point.h" 17 #include "mozilla/gfx/Rect.h" 18 19 namespace mozilla { 20 21 BlankVideoDataCreator::BlankVideoDataCreator( 22 uint32_t aFrameWidth, uint32_t aFrameHeight, 23 layers::ImageContainer* aImageContainer) 24 : mFrameWidth(aFrameWidth), 25 mFrameHeight(aFrameHeight), 26 mImageContainer(aImageContainer) { 27 mInfo.mDisplay = gfx::IntSize(mFrameWidth, mFrameHeight); 28 mPicture = gfx::IntRect(0, 0, mFrameWidth, mFrameHeight); 29 } 30 31 already_AddRefed<MediaData> BlankVideoDataCreator::Create( 32 MediaRawData* aSample) { 33 // Create a fake YUV buffer in a 420 format. That is, an 8bpp Y plane, 34 // with a U and V plane that are half the size of the Y plane, i.e 8 bit, 35 // 2x2 subsampled. Have the data pointer of each frame point to the 36 // first plane, they'll always be zero'd memory anyway. 37 const CheckedUint32 size = CheckedUint32(mFrameWidth) * mFrameHeight; 38 if (!size.isValid()) { 39 // Overflow happened. 40 return nullptr; 41 } 42 auto frame = MakeUniqueFallible<uint8_t[]>(size.value()); 43 if (!frame) { 44 return nullptr; 45 } 46 memset(frame.get(), 0, mFrameWidth * mFrameHeight); 47 VideoData::YCbCrBuffer buffer; 48 49 // Y plane. 50 buffer.mPlanes[0].mData = frame.get(); 51 buffer.mPlanes[0].mStride = mFrameWidth; 52 buffer.mPlanes[0].mHeight = mFrameHeight; 53 buffer.mPlanes[0].mWidth = mFrameWidth; 54 buffer.mPlanes[0].mSkip = 0; 55 56 // Cb plane. 57 buffer.mPlanes[1].mData = frame.get(); 58 buffer.mPlanes[1].mStride = (mFrameWidth + 1) / 2; 59 buffer.mPlanes[1].mHeight = (mFrameHeight + 1) / 2; 60 buffer.mPlanes[1].mWidth = (mFrameWidth + 1) / 2; 61 buffer.mPlanes[1].mSkip = 0; 62 63 // Cr plane. 64 buffer.mPlanes[2].mData = frame.get(); 65 buffer.mPlanes[2].mStride = (mFrameWidth + 1) / 2; 66 buffer.mPlanes[2].mHeight = (mFrameHeight + 1) / 2; 67 buffer.mPlanes[2].mWidth = (mFrameWidth + 1) / 2; 68 buffer.mPlanes[2].mSkip = 0; 69 70 buffer.mChromaSubsampling = gfx::ChromaSubsampling::HALF_WIDTH_AND_HEIGHT; 71 buffer.mYUVColorSpace = gfx::YUVColorSpace::BT601; 72 buffer.mColorPrimaries = gfx::ColorSpace2::BT709; 73 74 Result<already_AddRefed<VideoData>, MediaResult> result = 75 VideoData::CreateAndCopyData(mInfo, mImageContainer, aSample->mOffset, 76 aSample->mTime, aSample->mDuration, buffer, 77 aSample->mKeyframe, aSample->mTime, mPicture, 78 nullptr); 79 return result.unwrapOr(nullptr); 80 } 81 82 BlankAudioDataCreator::BlankAudioDataCreator(uint32_t aChannelCount, 83 uint32_t aSampleRate) 84 : mFrameSum(0), mChannelCount(aChannelCount), mSampleRate(aSampleRate) {} 85 86 already_AddRefed<MediaData> BlankAudioDataCreator::Create( 87 MediaRawData* aSample) { 88 // Convert duration to frames. We add 1 to duration to account for 89 // rounding errors, so we get a consistent tone. 90 CheckedInt64 frames = 91 UsecsToFrames(aSample->mDuration.ToMicroseconds() + 1, mSampleRate); 92 if (!frames.isValid() || !mChannelCount || !mSampleRate || 93 frames.value() > (UINT32_MAX / mChannelCount)) { 94 return nullptr; 95 } 96 AlignedAudioBuffer samples(frames.value() * mChannelCount); 97 if (!samples) { 98 return nullptr; 99 } 100 // Fill the sound buffer with an A4 tone. 101 static const float pi = 3.14159265f; 102 static const float noteHz = 440.0f; 103 for (int i = 0; i < frames.value(); i++) { 104 float f = sin(2 * pi * noteHz * mFrameSum / mSampleRate); 105 for (unsigned c = 0; c < mChannelCount; c++) { 106 samples[i * mChannelCount + c] = AudioDataValue(f); 107 } 108 mFrameSum++; 109 } 110 RefPtr<AudioData> data(new AudioData(aSample->mOffset, aSample->mTime, 111 std::move(samples), mChannelCount, 112 mSampleRate)); 113 return data.forget(); 114 } 115 116 already_AddRefed<MediaDataDecoder> BlankDecoderModule::CreateVideoDecoder( 117 const CreateDecoderParams& aParams) { 118 const VideoInfo& config = aParams.VideoConfig(); 119 UniquePtr<DummyDataCreator> creator = MakeUnique<BlankVideoDataCreator>( 120 config.mDisplay.width, config.mDisplay.height, aParams.mImageContainer); 121 RefPtr<MediaDataDecoder> decoder = new DummyMediaDataDecoder( 122 std::move(creator), "blank media data decoder"_ns, aParams); 123 return decoder.forget(); 124 } 125 126 already_AddRefed<MediaDataDecoder> BlankDecoderModule::CreateAudioDecoder( 127 const CreateDecoderParams& aParams) { 128 const AudioInfo& config = aParams.AudioConfig(); 129 UniquePtr<DummyDataCreator> creator = 130 MakeUnique<BlankAudioDataCreator>(config.mChannels, config.mRate); 131 RefPtr<MediaDataDecoder> decoder = new DummyMediaDataDecoder( 132 std::move(creator), "blank media data decoder"_ns, aParams); 133 return decoder.forget(); 134 } 135 136 media::DecodeSupportSet BlankDecoderModule::SupportsMimeType( 137 const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { 138 return media::DecodeSupport::SoftwareDecode; 139 } 140 141 /* static */ 142 already_AddRefed<PlatformDecoderModule> BlankDecoderModule::Create() { 143 return MakeAndAddRef<BlankDecoderModule>(); 144 } 145 146 } // namespace mozilla