summaryrefslogtreecommitdiff
path: root/dom/media/MediaData.cpp
diff options
context:
space:
mode:
authorJeremy Andrews <athenian200@outlook.com>2023-10-23 22:20:36 -0500
committerJeremy Andrews <athenian200@outlook.com>2023-10-24 00:58:50 -0500
commitc48055d6ea9a63ee8a19a38c3e8759e3630b00fe (patch)
tree9efd7e9163ab4a6fbb296986101a1a027723efc7 /dom/media/MediaData.cpp
parent8b746b6c127dcf9c83ef860f28ebd2f2e367f5df (diff)
downloaduxp-c48055d6ea9a63ee8a19a38c3e8759e3630b00fe.tar.gz
Issue #2357 - VPXDecoder does not decode alpha frames.
Another requirement to have transparency in videos. Straight port of Firefox 53 implementation, save for some oddities relating to needing to put uint8_t instead of uint8 in yuv_convert to get this to compile. Ref: BZ 1321076, 1329104
Diffstat (limited to 'dom/media/MediaData.cpp')
-rw-r--r--dom/media/MediaData.cpp139
1 files changed, 109 insertions, 30 deletions
diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp
index c113b62fe6..9f1205a0e1 100644
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -7,6 +7,8 @@
#include "MediaInfo.h"
#include "VideoUtils.h"
#include "ImageContainer.h"
+#include "mozilla/layers/SharedRGBImage.h"
+#include "YCbCrUtils.h"
#include <stdint.h>
@@ -89,6 +91,45 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride;
}
+static bool ValidateBufferAndPicture(const VideoData::YCbCrBuffer& aBuffer,
+ const IntRect& aPicture)
+{
+ // The following situation should never happen unless there is a bug
+ // in the decoder
+ if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth ||
+ aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) {
+ NS_ERROR("C planes with different sizes");
+ return false;
+ }
+
+ // The following situations could be triggered by invalid input
+ if (aPicture.width <= 0 || aPicture.height <= 0) {
+ // In debug mode, makes the error more noticeable
+ MOZ_ASSERT(false, "Empty picture rect");
+ return false;
+ }
+ if (!ValidatePlane(aBuffer.mPlanes[0]) ||
+ !ValidatePlane(aBuffer.mPlanes[1]) ||
+ !ValidatePlane(aBuffer.mPlanes[2])) {
+ NS_WARNING("Invalid plane size");
+ return false;
+ }
+
+ // Ensure the picture size specified in the headers can be extracted out of
+ // the frame we've been supplied without indexing out of bounds.
+ CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
+ CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
+ if (!xLimit.isValid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
+ !yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
+ {
+ // The specified picture dimensions can't be contained inside the video
+ // frame, we'll stomp memory if we try to copy it. Fail.
+ NS_WARNING("Overflowing picture rect");
+ return false;
+ }
+ return true;
+}
+
VideoData::VideoData(int64_t aOffset,
int64_t aTime,
int64_t aDuration,
@@ -242,36 +283,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
return v.forget();
}
- // The following situation should never happen unless there is a bug
- // in the decoder
- if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth ||
- aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) {
- NS_ERROR("C planes with different sizes");
- return nullptr;
- }
-
- // The following situations could be triggered by invalid input
- if (aPicture.width <= 0 || aPicture.height <= 0) {
- // In debug mode, makes the error more noticeable
- MOZ_ASSERT(false, "Empty picture rect");
- return nullptr;
- }
- if (!ValidatePlane(aBuffer.mPlanes[0]) || !ValidatePlane(aBuffer.mPlanes[1]) ||
- !ValidatePlane(aBuffer.mPlanes[2])) {
- NS_WARNING("Invalid plane size");
- return nullptr;
- }
-
- // Ensure the picture size specified in the headers can be extracted out of
- // the frame we've been supplied without indexing out of bounds.
- CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
- CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
- if (!xLimit.isValid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
- !yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
- {
- // The specified picture dimensions can't be contained inside the video
- // frame, we'll stomp memory if we try to copy it. Fail.
- NS_WARNING("Overflowing picture rect");
+ if (!ValidateBufferAndPicture(aBuffer, aPicture)) {
return nullptr;
}
@@ -307,6 +319,73 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
/* static */
already_AddRefed<VideoData>
+VideoData::CreateAndCopyData(const VideoInfo& aInfo,
+ ImageContainer* aContainer,
+ int64_t aOffset,
+ int64_t aTime,
+ int64_t aDuration,
+ const YCbCrBuffer& aBuffer,
+ const YCbCrBuffer::Plane &aAlphaPlane,
+ bool aKeyframe,
+ int64_t aTimecode,
+ const IntRect& aPicture)
+{
+ if (!aContainer) {
+ // Create a dummy VideoData with no image. This gives us something to
+ // send to media streams if necessary.
+ RefPtr<VideoData> v(new VideoData(aOffset,
+ aTime,
+ aDuration,
+ aKeyframe,
+ aTimecode,
+ aInfo.mDisplay,
+ 0));
+ return v.forget();
+ }
+
+ if (!ValidateBufferAndPicture(aBuffer, aPicture)) {
+ return nullptr;
+ }
+
+ RefPtr<VideoData> v(new VideoData(aOffset,
+ aTime,
+ aDuration,
+ aKeyframe,
+ aTimecode,
+ aInfo.mDisplay,
+ 0));
+
+ // Convert from YUVA to BGRA format on the software side.
+ RefPtr<layers::SharedRGBImage> videoImage =
+ aContainer->CreateSharedRGBImage();
+ v->mImage = videoImage;
+
+ if (!v->mImage) {
+ return nullptr;
+ }
+ if (!videoImage->Allocate(IntSize(aBuffer.mPlanes[0].mWidth,
+ aBuffer.mPlanes[0].mHeight),
+ SurfaceFormat::B8G8R8A8)) {
+ return nullptr;
+ }
+ uint8_t* argb_buffer = videoImage->GetBuffer();
+ IntSize size = videoImage->GetSize();
+
+ // The naming convention for libyuv and associated utils is word-order.
+ // The naming convention in the gfx stack is byte-order.
+ ConvertYCbCrAToARGB(aBuffer.mPlanes[0].mData,
+ aBuffer.mPlanes[1].mData,
+ aBuffer.mPlanes[2].mData,
+ aAlphaPlane.mData,
+ aBuffer.mPlanes[0].mStride, aBuffer.mPlanes[1].mStride,
+ argb_buffer, size.width * 4,
+ size.width, size.height);
+
+ return v.forget();
+}
+
+/* static */
+already_AddRefed<VideoData>
VideoData::CreateFromImage(const VideoInfo& aInfo,
int64_t aOffset,
int64_t aTime,