Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  TestVideoData.cpp

  Sprache: C
 

/* 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 "ImageContainer.h"
#include "MediaData.h"
#include "MediaInfo.h"
#include "MediaResult.h"
#include "gtest/gtest.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/ResultVariant.h"
#include "mozilla/gfx/Types.h"
#include "nsIWidget.h"
#include "nsTArray.h"

using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::layers;

using media::TimeUnit;

static void BuildI420Buffer(uint32_t aWidth, uint32_t aHeight,
                            nsTArray<uint8_t>& aStorage,
                            VideoData::YCbCrBuffer& aBuffer) {
  uint32_t yLen = aWidth * aHeight;
  uint32_t uvW = (aWidth + 1) / 2;
  uint32_t uvH = (aHeight + 1) / 2;
  uint32_t uvLen = uvW * uvH;
  aStorage.SetLength(yLen + 2 * uvLen);
  memset(aStorage.Elements(), 0x10, yLen);
  memset(aStorage.Elements() + yLen, 0x80, 2 * uvLen);

  aBuffer.mPlanes[0] = {aStorage.Elements(), aWidth, aHeight, aWidth, 0};
  aBuffer.mPlanes[1] = {aStorage.Elements() + yLen, uvW, uvH, uvW, 0};
  aBuffer.mPlanes[2] = {aStorage.Elements() + yLen + uvLen, uvW, uvH, uvW, 0};
  aBuffer.mYUVColorSpace = YUVColorSpace::BT2020;
  aBuffer.mChromaSubsampling = ChromaSubsampling::HALF_WIDTH_AND_HEIGHT;
}

// Runs SetVideoDataToImage with the given HDR transfer function and full
// HDRMetadata (Smpte2086 + ContentLightLevel), then asserts all attributes.
static void TestHDRTransferFunctionPropagation(TransferFunction aTF) {
  const uint32_t w = 64, h = 48;

  nsTArray<uint8_t> storage;
  VideoData::YCbCrBuffer buf{};
  BuildI420Buffer(w, h, storage, buf);

  VideoInfo info;
  info.mDisplay = IntSize(w, h);
  info.mTransferFunction = Some(aTF);

  gfx::Smpte2086Metadata smpte2086;
  smpte2086.displayPrimaryRed = {0.708f, 0.292f};
  smpte2086.displayPrimaryGreen = {0.170f, 0.797f};
  smpte2086.displayPrimaryBlue = {0.131f, 0.046f};
  smpte2086.whitePoint = {0.3127f, 0.3290f};
  smpte2086.maxLuminance = 1000.0f;
  smpte2086.minLuminance = 0.001f;

  gfx::HDRMetadata hdrMetadata;
  hdrMetadata.mSmpte2086 = Some(smpte2086);
  hdrMetadata.mContentLightLevel = Some(gfx::ContentLightLevel{1000400});
  info.mHDRMetadata = Some(hdrMetadata);

  RefPtr<PlanarYCbCrImage> image =
      new RecyclingPlanarYCbCrImage(new BufferRecycleBin());

  MediaResult rv = VideoData::SetVideoDataToImage(image, info, buf,
                                                  IntRect(00, w, h), true);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  const PlanarYCbCrData* data = image->GetData();
  ASSERT_NE(data, nullptr);
  EXPECT_EQ(data->mTransferFunction, aTF);

  ASSERT_TRUE(data->mHDRMetadata.isSome());
  ASSERT_TRUE(data->mHDRMetadata->mSmpte2086.isSome());
  EXPECT_FLOAT_EQ(data->mHDRMetadata->mSmpte2086->maxLuminance, 1000.0f);
  EXPECT_FLOAT_EQ(data->mHDRMetadata->mSmpte2086->minLuminance, 0.001f);
  EXPECT_FLOAT_EQ(data->mHDRMetadata->mSmpte2086->displayPrimaryRed.x, 0.708f);
  EXPECT_FLOAT_EQ(data->mHDRMetadata->mSmpte2086->whitePoint.y, 0.3290f);
  ASSERT_TRUE(data->mHDRMetadata->mContentLightLevel.isSome());
  EXPECT_EQ(data->mHDRMetadata->mContentLightLevel->maxContentLightLevel, 1000);
  EXPECT_EQ(data->mHDRMetadata->mContentLightLevel->maxFrameAverageLightLevel,
            400);
}

TEST(VideoData, SetVideoDataToImagePropagatesPQTransferFunction)
{
  TestHDRTransferFunctionPropagation(TransferFunction::PQ);
}

TEST(VideoData, SetVideoDataToImagePropagatesHLGTransferFunction)
{
  TestHDRTransferFunctionPropagation(TransferFunction::HLG);
}

// When VideoInfo has no TransferFunction, the BT709 default is preserved.
TEST(VideoData, SetVideoDataToImagePreservesBT709Default)
{
  const uint32_t w = 64, h = 48;

  nsTArray<uint8_t> storage;
  VideoData::YCbCrBuffer buf{};
  BuildI420Buffer(w, h, storage, buf);

  VideoInfo info;
  info.mDisplay = IntSize(w, h);
  // mTransferFunction = Nothing() — default

  RefPtr<PlanarYCbCrImage> image =
      new RecyclingPlanarYCbCrImage(new BufferRecycleBin());

  MediaResult rv = VideoData::SetVideoDataToImage(image, info, buf,
                                                  IntRect(00, w, h), true);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  const PlanarYCbCrData* data = image->GetData();
  ASSERT_NE(data, nullptr);
  EXPECT_EQ(data->mTransferFunction, TransferFunction::BT709);
  EXPECT_EQ(data->mHDRMetadata, Nothing());
}

TEST(VideoData, StrideOrSizeMismatch)
{
  constexpr int width = 32;
  constexpr int height = 64;
  constexpr int stride = width * 10;
  VideoInfo info(width, height);
  uint8_t buffer[stride * height] = {};
  VideoData::YCbCrBuffer b;
  VideoData::YCbCrBuffer::Plane alpha_plane;

  b.mPlanes[0].mStride = alpha_plane.mStride = stride;
  b.mPlanes[0].mHeight = alpha_plane.mHeight = height;
  b.mPlanes[0].mWidth = alpha_plane.mWidth = width;
  b.mPlanes[0].mSkip = alpha_plane.mSkip = 0;
  b.mPlanes[0].mData = alpha_plane.mData = buffer;

  b.mChromaSubsampling = gfx::ChromaSubsampling::HALF_WIDTH_AND_HEIGHT;
  b.mPlanes[1].mStride = b.mPlanes[2].mStride = stride / 4;
  b.mPlanes[1].mSkip = b.mPlanes[2].mSkip = 0;
  b.mPlanes[1].mHeight = b.mPlanes[2].mHeight = (b.mPlanes[0].mHeight + 1) / 2;
  b.mPlanes[1].mWidth = b.mPlanes[2].mWidth = (b.mPlanes[0].mWidth + 1) / 2;
  // Use tail end of buffer.
  b.mPlanes[1].mData = b.mPlanes[2].mData =
      buffer + stride * height - b.mPlanes[1].mStride * b.mPlanes[1].mHeight;

  b.mYUVColorSpace = gfx::YUVColorSpace::BT601;
  b.mColorRange = gfx::ColorRange::FULL;

  RefPtr imageContainer = new ImageContainer(
      ImageUsageType::VideoFrameContainer, ImageContainer::ASYNCHRONOUS);
  auto CreateVideoData = [&]() {
    Result res = VideoData::CreateAndCopyData(
        info, imageContainer, /*aOffset*/ 0, TimeUnit::Zero(),
        TimeUnit::FromSeconds(1), b, alpha_plane, /*aKeyFrame*/ true,
        TimeUnit::Zero(), info.ImageRect());
    return res.unwrapOr(nullptr);
  };
  // Trigger gfx::GPUProcessManager::EnsureImageBridgeChild()
  // for ImageContainer::CreateSharedRGBImage(),
  // from VideoData::CreateAndCopyData().
  // (ImageContainer::EnsureRecycleAllocatorForRDD() requires
  // XRE_IsRDDProcess().)
  RefPtr widget = nsIWidget::CreateHeadlessWidget();
  widget->CreateCompositor();
  // Check that VideoData can be created successfully from a simple
  // combination of planes.
  RefPtr v = CreateVideoData();
  EXPECT_NE(v.get(), nullptr);

  // Check that non-so-simple combinations do not cause crashes.
  // At the time of writing this test, CreateAndCopyData() returns failure,
  // but these combinations could be supported in the future, if desired.
  {
    // Differing alpha and luma plane strides
    AutoRestore r(alpha_plane.mStride);
    AutoRestore r2(alpha_plane.mData);
    alpha_plane.mStride = width;
    EXPECT_NE(alpha_plane.mStride, b.mPlanes[0].mStride);
    // tail end of buffer
    alpha_plane.mData = buffer + (stride - alpha_plane.mStride) * height;
    v = CreateVideoData();
    // Change to NE if this becomes supported.
    EXPECT_EQ(v.get(), nullptr);
  }
  {
    // Differing alpha and luma plane heights
    AutoRestore r(alpha_plane.mHeight);
    AutoRestore r2(alpha_plane.mData);
    alpha_plane.mHeight = height / 2;
    EXPECT_NE(alpha_plane.mHeight, b.mPlanes[0].mHeight);
    alpha_plane.mData =
        buffer + stride * height - alpha_plane.mStride * alpha_plane.mHeight;
    v = CreateVideoData();
    // Change to NE if this becomes supported.
    EXPECT_EQ(v.get(), nullptr);
  }
  {
    // Differing chroma plane strides
    AutoRestore r(b.mPlanes[2].mStride);
    AutoRestore r2(b.mPlanes[2].mData);
    b.mPlanes[2].mStride = b.mPlanes[2].mWidth;
    EXPECT_NE(b.mPlanes[1].mStride, b.mPlanes[2].mStride);
    b.mPlanes[2].mData =
        buffer + stride * height - b.mPlanes[2].mStride * b.mPlanes[2].mHeight;
    v = CreateVideoData();
    // Change to NE if this becomes supported.
    EXPECT_EQ(v.get(), nullptr);
  }
}

Messung V0.5 in Prozent
C=91 H=95 G=92

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002