Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  TestWebrtcGmpCodec.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 "WebrtcGmpVideoCodec.h"
#include "api/video/i420_buffer.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "media/base/media_constants.h"
#include "mozilla/gtest/WaitFor.h"

using testing::_;
using testing::AtLeast;
using testing::Eq;
using testing::Ge;
using testing::Gt;
using testing::InSequence;
using testing::Property;
using testing::Test;

namespace mozilla {

struct TestWebrtcGmpVideoEncoder : public Test {
  nsCOMPtr<nsIThread> mGmpThread;
  RefPtr<WebrtcGmpVideoEncoder> mEncoder;
  webrtc::VideoCodec mCodecSettings;
  webrtc::VideoEncoder::Settings mSettings = {
      webrtc::VideoEncoder::Capabilities(/*loss_notification=*/true),
      /*number_of_cores=*/1, /*max_payload_size=*/0};

  void SetUp() override {
    mEncoder = MakeRefPtr<WebrtcGmpVideoEncoder>(
        webrtc::SdpVideoFormat(webrtc::kH264CodecName), "dummy");
    mCodecSettings.codecType = webrtc::VideoCodecType::kVideoCodecH264;
    mCodecSettings.numberOfSimulcastStreams = 1;
    mCodecSettings.simulcastStream[0].active = true;
    mCodecSettings.simulcastStream[0].numberOfTemporalLayers = 1;
    mCodecSettings.width = 640;
    mCodecSettings.height = 480;
    mCodecSettings.maxFramerate = 60;
    mCodecSettings.minBitrate = 50;
    mCodecSettings.startBitrate = 200;
    mCodecSettings.maxBitrate = 1000;

    nsCOMPtr<mozIGeckoMediaPluginService> mps =
        do_GetService("@mozilla.org/gecko-media-plugin-service;1");
    ASSERT_TRUE(mps);
    mps->GetThread(getter_AddRefs(mGmpThread));
    ASSERT_TRUE(mGmpThread);
  }

  void TearDown() override { mEncoder = nullptr; }
};

struct MockEncodedImageCallback : public webrtc::EncodedImageCallback {
  MOCK_METHOD(Result, OnEncodedImage,
              (const webrtc::EncodedImage&, const webrtc::CodecSpecificInfo*),
              (override));
  MOCK_METHOD(void, OnDroppedFrame, (DropReason), (override));
};

auto CreateBlackFrame(int width, int height) {
  auto buffer = webrtc::I420Buffer::Create(width, height);
  webrtc::I420Buffer::SetBlack(buffer.get());
  return buffer;
}

TEST_F(TestWebrtcGmpVideoEncoder, EmptyLifecycle) {}

TEST_F(TestWebrtcGmpVideoEncoder, InitEncode) {
  mEncoder->InitEncode(&mCodecSettings, mSettings);
  WaitFor(*mEncoder->InitPluginEvent());
}

TEST_F(TestWebrtcGmpVideoEncoder, Encode) {
  using Result = webrtc::EncodedImageCallback::Result;
  mEncoder->InitEncode(&mCodecSettings, mSettings);
  WaitFor(*mEncoder->InitPluginEvent());

  MozPromiseHolder<GenericPromise> doneHolder;
  RefPtr donePromise = doneHolder.Ensure(__func__);
  MockEncodedImageCallback callback;
  constexpr uint32_t rtp_time = 55;
  EXPECT_CALL(
      callback,
      OnEncodedImage(
          Property(&webrtc::EncodedImage::RtpTimestamp, Eq(rtp_time)), _))
      .WillOnce([&] {
        doneHolder.Resolve(true, "TestWebrtcGmpVideoEncoder::Encode");
        return Result(Result::OK);
      });
  mEncoder->RegisterEncodeCompleteCallback(&callback);
  std::vector<webrtc::VideoFrameType> types = {
      webrtc::VideoFrameType::kVideoFrameKey};
  EXPECT_EQ(
      mEncoder->Encode(webrtc::VideoFrame::Builder()
                           .set_rtp_timestamp(rtp_time)
                           .set_video_frame_buffer(CreateBlackFrame(
                               mCodecSettings.width, mCodecSettings.height))
                           .build(),
                       &types),
      WEBRTC_VIDEO_CODEC_OK);
  EXPECT_EQ(WaitForResolve(donePromise), true);
}

TEST_F(TestWebrtcGmpVideoEncoder, BackPressure) {
  using Result = webrtc::EncodedImageCallback::Result;
  mEncoder->InitEncode(&mCodecSettings, mSettings);
  WaitFor(*mEncoder->InitPluginEvent());

  MozPromiseHolder<GenericPromise> doneHolder;
  RefPtr donePromise = doneHolder.Ensure(__func__);
  MockEncodedImageCallback callback;
  constexpr uint32_t rtpTime = 55;
  constexpr size_t iterations = 1000;
  Atomic<uint32_t> lastRtpTime{};
  Atomic<size_t> eventCount{};
  const auto countIteration = [&] {
    size_t c = ++eventCount;
    EXPECT_LE(c, iterations);
    if (c == iterations) {
      doneHolder.Resolve(true, "TestWebrtcGmpVideoEncoder::BackPressure");
    }
  };
  EXPECT_CALL(
      callback,
      OnEncodedImage(
          Property(&webrtc::EncodedImage::RtpTimestamp,
                   testing::AllOf(Ge(rtpTime), Gt<uint32_t>(lastRtpTime))),
          _))
      .Times(AtLeast(1))
      .WillRepeatedly([&](const auto& aImage, const auto*) {
        lastRtpTime = aImage.RtpTimestamp();
        countIteration();
        return Result(Result::OK);
      });
  EXPECT_CALL(
      callback,
      OnDroppedFrame(MockEncodedImageCallback::DropReason::kDroppedByEncoder))
      .Times(AtLeast(iterations / 10))
      .WillRepeatedly(countIteration);
  mEncoder->RegisterEncodeCompleteCallback(&callback);
  std::vector<webrtc::VideoFrameType> types = {
      webrtc::VideoFrameType::kVideoFrameKey};
  EXPECT_EQ(
      mEncoder->Encode(webrtc::VideoFrame::Builder()
                           .set_rtp_timestamp(rtpTime)
                           .set_video_frame_buffer(CreateBlackFrame(
                               mCodecSettings.width, mCodecSettings.height))
                           .build(),
                       &types),
      WEBRTC_VIDEO_CODEC_OK);
  for (size_t i = 1; i < iterations; ++i) {
    mEncoder->Encode(webrtc::VideoFrame::Builder()
                         .set_rtp_timestamp(rtpTime + i)
                         .set_video_frame_buffer(CreateBlackFrame(
                             mCodecSettings.width, mCodecSettings.height))
                         .build(),
                     &types);
  }
  EXPECT_EQ(WaitForResolve(donePromise), true);
  EXPECT_EQ(eventCount, iterations);
}

TEST_F(TestWebrtcGmpVideoEncoder, ReUse) {
  using Result = webrtc::EncodedImageCallback::Result;
  mEncoder->InitEncode(&mCodecSettings, mSettings);
  WaitFor(*mEncoder->InitPluginEvent());

  MozPromiseHolder<GenericPromise> doneHolder;
  RefPtr donePromise = doneHolder.Ensure(__func__);
  MockEncodedImageCallback callback;
  constexpr uint32_t rtpTime = 55;
  constexpr uint32_t rtpTime2 = rtpTime * 2;
  EXPECT_CALL(callback,
              OnEncodedImage(
                  Property(&webrtc::EncodedImage::RtpTimestamp, rtpTime2), _))
      .WillOnce([&] {
        doneHolder.Resolve(true, "TestWebrtcGmpVideoEncoder::ReUse");
        return Result(Result::OK);
      });
  mEncoder->RegisterEncodeCompleteCallback(&callback);

  // Block the GMP thread until after Shutdown() as to avoid racing between the
  // first encoded callback and the Shutdown() call.
  Monitor mon(__func__);
  bool block = true;
  MOZ_ALWAYS_SUCCEEDS(
      mGmpThread->Dispatch(NS_NewRunnableFunction(__func__, [&] {
        MonitorAutoLock lock(mon);
        while (block) {
          lock.Wait();
        }
      })));
  std::vector<webrtc::VideoFrameType> types = {
      webrtc::VideoFrameType::kVideoFrameKey};
  EXPECT_EQ(
      mEncoder->Encode(webrtc::VideoFrame::Builder()
                           .set_rtp_timestamp(rtpTime)
                           .set_video_frame_buffer(CreateBlackFrame(
                               mCodecSettings.width, mCodecSettings.height))
                           .build(),
                       &types),
      WEBRTC_VIDEO_CODEC_OK);

  // Shutdown mid-encode, then re-init and encode again.
  mEncoder->Shutdown();
  {
    MonitorAutoLock lock(mon);
    block = false;
    lock.Notify();
  }
  mEncoder->InitEncode(&mCodecSettings, mSettings);
  WaitFor(*mEncoder->InitPluginEvent());
  mEncoder->RegisterEncodeCompleteCallback(&callback);

  EXPECT_EQ(
      mEncoder->Encode(webrtc::VideoFrame::Builder()
                           .set_rtp_timestamp(rtpTime2)
                           .set_video_frame_buffer(CreateBlackFrame(
                               mCodecSettings.width, mCodecSettings.height))
                           .build(),
                       &types),
      WEBRTC_VIDEO_CODEC_OK);
  EXPECT_EQ(WaitForResolve(donePromise), true);
}

TEST_F(TestWebrtcGmpVideoEncoder, TrackedFrameDrops) {
  using Result = webrtc::EncodedImageCallback::Result;
  // Tell the fakeopenh264 plugin to drop some allocated input frames without
  // telling us. It will drop every fifth input frame. This shall get tracked
  // as frame drops.
  mCodecSettings.SetFrameDropEnabled(true);
  mEncoder->InitEncode(&mCodecSettings, mSettings);
  WaitFor(*mEncoder->InitPluginEvent());

  Monitor m(__func__);
  size_t numEvents = 0;
  const auto handleEvent = ([&] {
    MonitorAutoLock lock(m);
    ++numEvents;
    lock.Notify();
  });
  MockEncodedImageCallback callback;
  {
    InSequence s;
    EXPECT_CALL(callback, OnEncodedImage(_, _)).Times(4).WillRepeatedly([&] {
      handleEvent();
      return Result(Result::OK);
    });
    EXPECT_CALL(
        callback,
        OnDroppedFrame(MockEncodedImageCallback::DropReason::kDroppedByEncoder))
        .WillOnce(handleEvent);
  }
  mEncoder->RegisterEncodeCompleteCallback(&callback);

  constexpr uint32_t ntpTime = 55;
  std::vector<webrtc::VideoFrameType> types = {
      webrtc::VideoFrameType::kVideoFrameKey};
  for (uint8_t i = 0; i < 5; ++i) {
    EXPECT_EQ(
        mEncoder->Encode(webrtc::VideoFrame::Builder()
                             .set_ntp_time_ms(ntpTime * (i + 1))
                             .set_video_frame_buffer(CreateBlackFrame(
                                 mCodecSettings.width, mCodecSettings.height))
                             .build(),
                         &types),
        WEBRTC_VIDEO_CODEC_OK);
    MonitorAutoLock lock(m);
    while (numEvents <= i) {
      lock.Wait();
    }
  }
}
}  // namespace mozilla

Messung V0.5 in Prozent
C=90 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