Files
palemoon27/dom/media/platforms/agnostic/BlankDecoderModule.cpp
T
roytam1 6b21bacef6 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1206298 - Part 1: Update the expiration time on the fake cache entry object for an intercepted request in the non-e10s case; r=mcmanus (0fa1afb14d)
- Bug 1206298 - Part 2: Add a test to make sure that we respect Cache-Control headers on the synthesized response; r=jdm (c7a05d4415)
- Bug 121442 - Add platform to GMP storage base dir. r=gerald (6f40a18f39)
- Bug 1214967 - Proxy observer service notification across to content process when GMPs are added/removed. r=billm,jwwang (088f770b47)
- Bug 1211812 - Add pref to select GMP to use for unencrypted decoding. r=jwwang Bug 1212670 - Implement GMPDecoderModule::SupportsMimeType() and EMEDecoderModule::SupportsMimeType(). r=jwwang (10acef26cd)
- Bug 1214932 - Remove fragmented-mp4 from media prefs. r=jya (f2935767c1)
- Bug 1214967 - Create a list of GMPs/codecs that can be used for <video> decoding. r=jwwang (3c68f6e08b)
- import some vars and prefs to compile again (5456bb7124)
- Bug 1205083 - Don't enable low latency WMF video decoding as it crashes sometimes. r=jya (353e727811)
- Bug 1101885: P1. Make pref dynamic. r=cpearce (8a3de82e1e)
- Bug 1189776: Store our audio decode time in TimeUnits. r=cpearce (0a01637580)
- Bug 1202296 - Hide the MFTDecoder within MFTManager so that we can recreate it opaquely. r=cpearce (148e4d1923)
- Bug 1211339 - Ensure WMFDecoderModule::SupportsMimeType checks it can create decoders. r=jya (f6e53ff08c)
- Bug 1101885: P2. Don't shutdown WMF framework before releasing decoder. r=cpearce (b373402e74)
- Bug 1101885: P3. Allow decoder creation fallback. r=cpearce (650ef55564)
- Bug 1219300 - Add mutex to protect the |result| because the variable will be access by multiple threads at the same time. r=cpearce (a0f489cbcf)
- Bug 1101885: P4. Enable Intel VP8/VP9 HW decoder by default. r=cpearce (cffbca2905)
- Bug 1101885: P5. Only attempt to use HW VP decoder if DXVA active. r=cpearce (fd0f12c118)
- spaces (f110c8ab3d)
- Bug 1203217 - Add some logging when we detect and skip an ID3v2 tag. r=kinetik (74533f7c1e)
- small changes (1ab8008527)
- Bug 1164453 - Assert that decoder callback is set before using it. r=snorp (79bee3ccbe)
- Bug 1190379 - Use AndroidDecoderModule for VP8/9. r=jya (2c672b6630)
- Bug 1188871: P2. Call DrainComplete should an error occurs while draining. r=snorp (81f5669010)
- Bug 1163667 - [5.1] Ensure empty demuxer sample queue before initiating draining. r=snorp (8a4dd86a28)
- Bug 1204483 - Fix busted audio decoding output on Android r=esawin (b0c7dca1ce)
- Bug 1220491 - clarify ownership relationships for creators of AudioData; r=gerald (cd043d3ef1)
- bug 1162364 detect and abort MF_E_TRANSFORM_STREAM_CHANGE infinite loops r=cpearce (a0f3e17e5f)
- Bug 1214065 - Remove unused arguments from MediaDecoder::Load() and its friends. r=kinetik. (6e610f3aed)
- Bug 1211766 - Remove AbstractMediaDecoder::GetReentrantMonitor(). r=jya. (beb1a22439)
- some cleanup and add back some gestreamer stuff (55c4a19f78)
- Bug 1204434 - Remove check of MediaDecoder::IsMediaSeekable from OggReader::ReadMetadata. r=cpearce. (75bf15a1f5)
- Bug 1209888 - Remove usage of decoder monitor from OggReader. r=jya. (4e92df9c1c)
- Bug 1204882 - Move MediaDecoder::FrameStatistics out of MediaDecoder for easier use in other classes. r=jwwang (7f5d6035be)
- Bug 1209887. Part 1 - add assertions. r=jya. (d5a7057c79)
- Bug 1209887. Part 2 - remove usage of decoder monitor. r=jya. (56a6de8874)
- Bug 1209887. Part 3 - remove unused code. r=jya. (7cd48c424b)
- missing bit of 1208930 (045f09408a)
- Bug 1211327 - Remove unnecessary usage of decoder monitor from MediaDecoderReader and sub-classes. r=jya. (2a15ac759a)
- missing bit 1211766 (221c0a957f)
- Bug 1214519 - Fix the coding style of member initializer lists of MediaDecoder. r=jya. (654636af36)
- Bug 1206977: P12. Properly shutdown all created test decoders. r=cpearce (79cd0ebc83)
- Bug 1206977: P14. Remove obsolete / redundant code. r=cpearce (b5a85ee060)
- Bug 1208348 - Check whether DirectShow can decode MP3 before assuming it will work. r=jya (988030aec7)
- Bug 1209886 - Clean up InstantiateDecoder() in DecoderTraits.cpp. r=kinetik. (822cac0dee)
- Bug 1213176: P1. Remove most MediaFormatReader dependencies on its MediaDecoder parent. r=jwwang (7b5b000408)
- Bug 1214989. Part 1 - add MediaDecoderOwner to the constructors of MediaDecoder and sub-classes. r=gerald. (f2f6df4bf2)
- Bug 1214989. Part 2 - add MediaDecoderOwner to Clone() and overrides. r=gerald. (db9947115d)
- Bug 1214989. Part 3 - remove MediaDecoder::Init() and its callers. r=gerald. (4353925106)
- Bug 1217714 - Remove some unused functions from MediaDecoderReader. r=jya. (ae50a0f881)
- Bug 1194524 - Use channel->ascynOpen2 in dom/media/MediaResource.cpp (r=sicking) (2a28e80f82)
- Bug 1218280. Part 1 - create MediaResourceCallback for MediaResource to send notifications. r=roc. (54c5f58cb0)
- Bug 1218280. Part 2 - remove unused code. r=roc. (161d4e28bb)
- Bug 1219169. Part 1 - Remove AbstractMediaDecoder::OnStateMachineTaskQueue(). r=jya. (1836fb4bbc)
- Bug 1219169. Part 2 - move MediaDecoderStateMachine::OnTaskQueue() to private. r=jya. (873ecac93a)
- Bug 1217692. Part 1 - move members that don't have to be public to protected or private sections. r=jya. (25ea01b514)
- Bug 1217692. Part 2 - fix some styles to keep 80 cols limit. r=jya. (0aabebd4ed)
- Bug 1220558. Part 1 - remove unused arguments from MediaDecoderReader::DispatchNotifyDataArrived() and its callees/callers. r=jya. (0e57bafdb4)
- Bug 1218157: Only ever read from cached data in NotifyDataArrived. r=cpearce (235ef09e63)
- Bug 1220551. Part 1 - fix the parameters passed to mBufferedState->NotifyDataArrived(). r=jya. (61bdc160b1)
- Bug 1220551. Part 2 - remove arguments from NotifyDataArrivedInternal(). r=jya. (edc0c18550)
2022-12-03 11:38:18 +08:00

269 lines
8.5 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaDecoderReader.h"
#include "PlatformDecoderModule.h"
#include "nsRect.h"
#include "mozilla/RefPtr.h"
#include "mozilla/CheckedInt.h"
#include "VideoUtils.h"
#include "ImageContainer.h"
#include "MediaInfo.h"
#include "mozilla/TaskQueue.h"
#include "TimeUnits.h"
namespace mozilla {
// Decoder that uses a passed in object's Create function to create blank
// MediaData objects.
template<class BlankMediaDataCreator>
class BlankMediaDataDecoder : public MediaDataDecoder {
public:
BlankMediaDataDecoder(BlankMediaDataCreator* aCreator,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
TrackInfo::TrackType aType)
: mCreator(aCreator)
, mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mType(aType)
{
}
RefPtr<InitPromise> Init() override {
return InitPromise::CreateAndResolve(mType, __func__);
}
nsresult Shutdown() override {
return NS_OK;
}
class OutputEvent : public nsRunnable {
public:
OutputEvent(MediaRawData* aSample,
MediaDataDecoderCallback* aCallback,
BlankMediaDataCreator* aCreator)
: mSample(aSample)
, mCreator(aCreator)
, mCallback(aCallback)
{
}
NS_IMETHOD Run() override
{
RefPtr<MediaData> data =
mCreator->Create(media::TimeUnit::FromMicroseconds(mSample->mTime),
media::TimeUnit::FromMicroseconds(mSample->mDuration),
mSample->mOffset);
mCallback->Output(data);
return NS_OK;
}
private:
RefPtr<MediaRawData> mSample;
BlankMediaDataCreator* mCreator;
MediaDataDecoderCallback* mCallback;
};
nsresult Input(MediaRawData* aSample) override
{
// The MediaDataDecoder must delete the sample when we're finished
// with it, so the OutputEvent stores it in an nsAutoPtr and deletes
// it once it's run.
RefPtr<nsIRunnable> r(new OutputEvent(aSample, mCallback, mCreator));
mTaskQueue->Dispatch(r.forget());
return NS_OK;
}
nsresult Flush() override {
mTaskQueue->Flush();
return NS_OK;
}
nsresult Drain() override {
mCallback->DrainComplete();
return NS_OK;
}
private:
nsAutoPtr<BlankMediaDataCreator> mCreator;
RefPtr<FlushableTaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
TrackInfo::TrackType mType;
};
class BlankVideoDataCreator {
public:
BlankVideoDataCreator(uint32_t aFrameWidth,
uint32_t aFrameHeight,
layers::ImageContainer* aImageContainer)
: mFrameWidth(aFrameWidth)
, mFrameHeight(aFrameHeight)
, mImageContainer(aImageContainer)
{
mInfo.mDisplay = nsIntSize(mFrameWidth, mFrameHeight);
mPicture = gfx::IntRect(0, 0, mFrameWidth, mFrameHeight);
}
already_AddRefed<MediaData>
Create(const media::TimeUnit& aDTS, const media::TimeUnit& aDuration, int64_t aOffsetInStream)
{
// Create a fake YUV buffer in a 420 format. That is, an 8bpp Y plane,
// with a U and V plane that are half the size of the Y plane, i.e 8 bit,
// 2x2 subsampled. Have the data pointers of each frame point to the
// first plane, they'll always be zero'd memory anyway.
nsAutoArrayPtr<uint8_t> frame(new uint8_t[mFrameWidth * mFrameHeight]);
memset(frame, 0, mFrameWidth * mFrameHeight);
VideoData::YCbCrBuffer buffer;
// Y plane.
buffer.mPlanes[0].mData = frame;
buffer.mPlanes[0].mStride = mFrameWidth;
buffer.mPlanes[0].mHeight = mFrameHeight;
buffer.mPlanes[0].mWidth = mFrameWidth;
buffer.mPlanes[0].mOffset = 0;
buffer.mPlanes[0].mSkip = 0;
// Cb plane.
buffer.mPlanes[1].mData = frame;
buffer.mPlanes[1].mStride = mFrameWidth / 2;
buffer.mPlanes[1].mHeight = mFrameHeight / 2;
buffer.mPlanes[1].mWidth = mFrameWidth / 2;
buffer.mPlanes[1].mOffset = 0;
buffer.mPlanes[1].mSkip = 0;
// Cr plane.
buffer.mPlanes[2].mData = frame;
buffer.mPlanes[2].mStride = mFrameWidth / 2;
buffer.mPlanes[2].mHeight = mFrameHeight / 2;
buffer.mPlanes[2].mWidth = mFrameWidth / 2;
buffer.mPlanes[2].mOffset = 0;
buffer.mPlanes[2].mSkip = 0;
return VideoData::Create(mInfo,
mImageContainer,
nullptr,
aOffsetInStream,
aDTS.ToMicroseconds(),
aDuration.ToMicroseconds(),
buffer,
true,
aDTS.ToMicroseconds(),
mPicture);
}
private:
VideoInfo mInfo;
gfx::IntRect mPicture;
uint32_t mFrameWidth;
uint32_t mFrameHeight;
RefPtr<layers::ImageContainer> mImageContainer;
};
class BlankAudioDataCreator {
public:
BlankAudioDataCreator(uint32_t aChannelCount, uint32_t aSampleRate)
: mFrameSum(0), mChannelCount(aChannelCount), mSampleRate(aSampleRate)
{
}
MediaData* Create(const media::TimeUnit& aDTS,
const media::TimeUnit& aDuration,
int64_t aOffsetInStream)
{
// Convert duration to frames. We add 1 to duration to account for
// rounding errors, so we get a consistent tone.
CheckedInt64 frames =
UsecsToFrames(aDuration.ToMicroseconds()+1, mSampleRate);
if (!frames.isValid() ||
!mChannelCount ||
!mSampleRate ||
frames.value() > (UINT32_MAX / mChannelCount)) {
return nullptr;
}
auto samples = MakeUnique<AudioDataValue[]>(frames.value() * mChannelCount);
// Fill the sound buffer with an A4 tone.
static const float pi = 3.14159265f;
static const float noteHz = 440.0f;
for (int i = 0; i < frames.value(); i++) {
float f = sin(2 * pi * noteHz * mFrameSum / mSampleRate);
for (unsigned c = 0; c < mChannelCount; c++) {
samples[i * mChannelCount + c] = AudioDataValue(f);
}
mFrameSum++;
}
return new AudioData(aOffsetInStream,
aDTS.ToMicroseconds(),
aDuration.ToMicroseconds(),
uint32_t(frames.value()),
Move(samples),
mChannelCount,
mSampleRate);
}
private:
int64_t mFrameSum;
uint32_t mChannelCount;
uint32_t mSampleRate;
};
class BlankDecoderModule : public PlatformDecoderModule {
public:
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) override {
BlankVideoDataCreator* creator = new BlankVideoDataCreator(
aConfig.mDisplay.width, aConfig.mDisplay.height, aImageContainer);
RefPtr<MediaDataDecoder> decoder =
new BlankMediaDataDecoder<BlankVideoDataCreator>(creator,
aVideoTaskQueue,
aCallback,
TrackInfo::kVideoTrack);
return decoder.forget();
}
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override {
BlankAudioDataCreator* creator = new BlankAudioDataCreator(
aConfig.mChannels, aConfig.mRate);
RefPtr<MediaDataDecoder> decoder =
new BlankMediaDataDecoder<BlankAudioDataCreator>(creator,
aAudioTaskQueue,
aCallback,
TrackInfo::kAudioTrack);
return decoder.forget();
}
bool
SupportsMimeType(const nsACString& aMimeType) override
{
return true;
}
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override
{
return kNeedNone;
}
};
already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule()
{
RefPtr<PlatformDecoderModule> pdm = new BlankDecoderModule();
return pdm.forget();
}
} // namespace mozilla