Bug 1749047 - harzar fix. CLOSED TREE

This patch uses RootedDictionary around `EncodedVideoChunkMetadata`,
`VideoDecoderConfig` and `VideoColorSpaceInit` in `OutputEncodedData` to
work around the JS hazard (unrooted) issues.

Differential Revision: https://phabricator.services.mozilla.com/D197228
This commit is contained in:
Chun-Min Chang 2023-12-23 08:17:11 +00:00
Родитель e07cea7e9d
Коммит e6d0f178af
5 изменённых файлов: 99 добавлений и 53 удалений

Просмотреть файл

@ -43,6 +43,15 @@ class VideoDecoderConfigInternal {
public:
static UniquePtr<VideoDecoderConfigInternal> Create(
const VideoDecoderConfig& aConfig);
VideoDecoderConfigInternal(const nsAString& aCodec,
Maybe<uint32_t>&& aCodedHeight,
Maybe<uint32_t>&& aCodedWidth,
Maybe<VideoColorSpaceInternal>&& aColorSpace,
Maybe<RefPtr<MediaByteBuffer>>&& aDescription,
Maybe<uint32_t>&& aDisplayAspectHeight,
Maybe<uint32_t>&& aDisplayAspectWidth,
const HardwareAcceleration& aHardwareAcceleration,
Maybe<bool>&& aOptimizeForLatency);
~VideoDecoderConfigInternal() = default;
nsString ToString() const;
@ -79,17 +88,6 @@ class VideoDecoderConfigInternal {
Maybe<uint32_t> mDisplayAspectWidth;
HardwareAcceleration mHardwareAcceleration;
Maybe<bool> mOptimizeForLatency;
private:
VideoDecoderConfigInternal(const nsAString& aCodec,
Maybe<uint32_t>&& aCodedHeight,
Maybe<uint32_t>&& aCodedWidth,
Maybe<VideoColorSpaceInternal>&& aColorSpace,
Maybe<RefPtr<MediaByteBuffer>>&& aDescription,
Maybe<uint32_t>&& aDisplayAspectHeight,
Maybe<uint32_t>&& aDisplayAspectWidth,
const HardwareAcceleration& aHardwareAcceleration,
Maybe<bool>&& aOptimizeForLatency);
};
class VideoDecoderTraits {

Просмотреть файл

@ -305,6 +305,14 @@ void EncoderTemplate<EncoderType>::OutputEncodedData(
MOZ_ASSERT(mState == CodecState::Configured);
MOZ_ASSERT(mActiveConfig);
// Get JSContext for RootedDictionary.
// The EncoderType::MetadataType, VideoDecoderConfig, and VideoColorSpaceInit
// below are rooted to work around the JS hazard issues.
AutoJSAPI jsapi;
DebugOnly<bool> ok =
jsapi.Init(GetParentObject()); // TODO: check returned value?
JSContext* cx = jsapi.cx();
RefPtr<typename EncoderType::OutputCallbackType> cb(mOutputCallback);
for (auto& data : aData) {
// It's possible to have reset() called in between this task having been
@ -317,15 +325,69 @@ void EncoderTemplate<EncoderType>::OutputEncodedData(
}
RefPtr<typename EncoderType::OutputType> encodedData =
EncodedDataToOutputType(GetParentObject(), data);
typename EncoderType::MetadataType metadata;
RootedDictionary<typename EncoderType::MetadataType> metadata(cx);
if (mOutputNewDecoderConfig) {
metadata.mDecoderConfig.Construct(EncoderConfigToDecoderConfig(
GetParentObject(), data, *mActiveConfig));
VideoDecoderConfigInternal decoderConfigInternal =
EncoderConfigToDecoderConfig(GetParentObject(), data, *mActiveConfig);
// Convert VideoDecoderConfigInternal to VideoDecoderConfig
RootedDictionary<VideoDecoderConfig> decoderConfig(cx);
decoderConfig.mCodec = decoderConfigInternal.mCodec;
if (decoderConfigInternal.mCodedHeight) {
decoderConfig.mCodedHeight.Construct(
decoderConfigInternal.mCodedHeight.value());
}
if (decoderConfigInternal.mCodedWidth) {
decoderConfig.mCodedWidth.Construct(
decoderConfigInternal.mCodedWidth.value());
}
if (decoderConfigInternal.mColorSpace) {
RootedDictionary<VideoColorSpaceInit> colorSpace(cx);
colorSpace.mFullRange =
MaybeToNullable(decoderConfigInternal.mColorSpace->mFullRange);
colorSpace.mMatrix =
MaybeToNullable(decoderConfigInternal.mColorSpace->mMatrix);
colorSpace.mPrimaries =
MaybeToNullable(decoderConfigInternal.mColorSpace->mPrimaries);
colorSpace.mTransfer =
MaybeToNullable(decoderConfigInternal.mColorSpace->mTransfer);
decoderConfig.mColorSpace.Construct(std::move(colorSpace));
}
if (decoderConfigInternal.mDescription &&
!decoderConfigInternal.mDescription.value()->IsEmpty()) {
auto& abov = decoderConfig.mDescription.Construct();
AutoEntryScript aes(GetParentObject(), "EncoderConfigToDecoderConfig");
size_t lengthBytes =
decoderConfigInternal.mDescription.value()->Length();
UniquePtr<uint8_t[], JS::FreePolicy> extradata(
new uint8_t[lengthBytes]);
PodCopy(extradata.get(),
decoderConfigInternal.mDescription.value()->Elements(),
lengthBytes);
JS::Rooted<JSObject*> description(
aes.cx(), JS::NewArrayBufferWithContents(aes.cx(), lengthBytes,
std::move(extradata)));
JS::Rooted<JS::Value> value(aes.cx(), JS::ObjectValue(*description));
DebugOnly<bool> rv = abov.Init(aes.cx(), value);
}
if (decoderConfigInternal.mDisplayAspectHeight) {
decoderConfig.mDisplayAspectHeight.Construct(
decoderConfigInternal.mDisplayAspectHeight.value());
}
if (decoderConfigInternal.mDisplayAspectWidth) {
decoderConfig.mDisplayAspectWidth.Construct(
decoderConfigInternal.mDisplayAspectWidth.value());
}
if (decoderConfigInternal.mOptimizeForLatency) {
decoderConfig.mOptimizeForLatency.Construct(
decoderConfigInternal.mOptimizeForLatency.value());
}
metadata.mDecoderConfig.Construct(std::move(decoderConfig));
mOutputNewDecoderConfig = false;
LOGE("New config passed to output callback: %s",
NS_ConvertUTF16toUTF8(ConfigToString(EncoderConfigToDecoderConfig(
GetParentObject(), data, *mActiveConfig)))
.get());
NS_ConvertUTF16toUTF8(decoderConfigInternal.ToString()).get());
}
LOG("EncoderTemplate:: output callback (ts: % " PRId64 " ), %s",
encodedData->Timestamp(),

Просмотреть файл

@ -77,7 +77,7 @@ class VideoEncoderTraits {
using ConfigTypeInternal = VideoEncoderConfigInternal;
using InputType = dom::VideoFrame;
using InputTypeInternal = mozilla::VideoData;
using OutputConfigType = mozilla::dom::VideoDecoderConfig;
using OutputConfigType = mozilla::dom::VideoDecoderConfigInternal;
using OutputType = EncodedVideoChunk;
using OutputCallbackType = EncodedVideoChunkOutputCallback;
using MetadataType = EncodedVideoChunkMetadata;

Просмотреть файл

@ -586,43 +586,29 @@ RefPtr<EncodedVideoChunk> VideoEncoder::EncodedDataToOutputType(
return encodedVideoChunk;
}
VideoDecoderConfig VideoEncoder::EncoderConfigToDecoderConfig(
VideoDecoderConfigInternal VideoEncoder::EncoderConfigToDecoderConfig(
nsIGlobalObject* aGlobal, const RefPtr<MediaRawData>& aRawData,
const VideoEncoderConfigInternal& mOutputConfig) const {
VideoDecoderConfig decoderConfig;
decoderConfig.mCodec = mOutputConfig.mCodec;
decoderConfig.mCodedWidth.Construct(mOutputConfig.mWidth);
decoderConfig.mCodedHeight.Construct(mOutputConfig.mHeight);
if (mOutputConfig.mDisplayWidth.isSome()) {
MOZ_ASSERT(mOutputConfig.mDisplayHeight.isSome());
decoderConfig.mDisplayAspectWidth.Construct(
mOutputConfig.mDisplayWidth.value());
decoderConfig.mDisplayAspectHeight.Construct(
mOutputConfig.mDisplayHeight.value());
}
// Colorspace is mandatory when outputing a decoder config after encode
VideoColorSpaceInit init;
init.mFullRange = false;
init.mMatrix = VideoMatrixCoefficients::Bt709;
init.mPrimaries = VideoColorPrimaries::Bt709;
init.mTransfer = VideoTransferCharacteristics::Bt709;
decoderConfig.mColorSpace.Construct(init);
VideoColorSpaceInternal init;
init.mFullRange.emplace(false);
init.mMatrix.emplace(VideoMatrixCoefficients::Bt709);
init.mPrimaries.emplace(VideoColorPrimaries::Bt709);
init.mTransfer.emplace(VideoTransferCharacteristics::Bt709);
if (aRawData->mExtraData) {
auto& abov = decoderConfig.mDescription.Construct();
AutoEntryScript aes(aGlobal, "EncoderConfigToDecoderConfig");
size_t lengthBytes = aRawData->mExtraData->Length();
UniquePtr<uint8_t[], JS::FreePolicy> extradata(new uint8_t[lengthBytes]);
PodCopy(extradata.get(), aRawData->mExtraData->Elements(), lengthBytes);
JS::Rooted<JSObject*> description(
aes.cx(), JS::NewArrayBufferWithContents(aes.cx(), lengthBytes,
std::move(extradata)));
JS::Rooted<JS::Value> value(aes.cx(), JS::ObjectValue(*description));
DebugOnly<bool> rv = abov.Init(aes.cx(), value);
}
return decoderConfig;
return VideoDecoderConfigInternal(
mOutputConfig.mCodec, /* aCodec */
Some(mOutputConfig.mHeight), /* aCodedHeight */
Some(mOutputConfig.mWidth), /* aCodedWidth */
Some(init), /* aColorSpace */
aRawData->mExtraData && !aRawData->mExtraData->IsEmpty()
? Some(aRawData->mExtraData)
: Nothing(), /* aDescription*/
Maybe<uint32_t>(mOutputConfig.mDisplayHeight), /* aDisplayAspectHeight*/
Maybe<uint32_t>(mOutputConfig.mDisplayWidth), /* aDisplayAspectWidth */
mOutputConfig.mHardwareAcceleration, /* aHardwareAcceleration */
Nothing() /* aOptimizeForLatency */
);
}
#undef LOG

Просмотреть файл

@ -67,8 +67,8 @@ class VideoEncoder final : public EncoderTemplate<VideoEncoderTraits> {
virtual RefPtr<EncodedVideoChunk> EncodedDataToOutputType(
nsIGlobalObject* aGlobal, RefPtr<MediaRawData>& aData) override;
virtual VideoDecoderConfig EncoderConfigToDecoderConfig(
nsIGlobalObject* aGlobal,
virtual VideoDecoderConfigInternal EncoderConfigToDecoderConfig(
nsIGlobalObject* aGlobal /* TODO: delete */,
const RefPtr<MediaRawData>& aRawData,
const VideoEncoderConfigInternal& mOutputConfig) const override;
};