blob: b5daf937cc9f4d71012df4683b22983e5ffb7757 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_TEST_VIDEO_ENCODER_BITSTREAM_VALIDATOR_H_
#define MEDIA_GPU_TEST_VIDEO_ENCODER_BITSTREAM_VALIDATOR_H_
#include <memory>
#include <utility>
#include <vector>
#include "base/containers/mru_cache.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "base/threading/thread.h"
#include "media/base/bitstream_buffer.h"
#include "media/base/video_decoder.h"
#include "media/gpu/test/bitstream_helpers.h"
#include "media/gpu/test/video_frame_helpers.h"
#include "media/video/video_encode_accelerator.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/size.h"
namespace media {
class MediaLog;
class VideoFrame;
class VideoDecoderConfig;
namespace test {
// BitstreamValidator validates encoded bitstreams by decoding them using a
// software decoder and optionally processes the decoded video frames using one
// or more VideoFrameProcessors (e.g. compute SSIM with the original video frame
// and save them to files).
class BitstreamValidator : public BitstreamProcessor {
public:
// |decoder_config| is used to create a software VideoDecoder.
// |last_frame_index| is the index of the last bitstream in the stream.
static std::unique_ptr<BitstreamValidator> Create(
const VideoDecoderConfig& decoder_config,
size_t last_frame_index,
std::vector<std::unique_ptr<VideoFrameProcessor>> video_frame_processors =
{},
absl::optional<size_t> spatial_layer_index_to_decode_ = absl::nullopt,
absl::optional<size_t> temporal_layer_index_to_decode = absl::nullopt,
const std::vector<gfx::Size>& spatial_layer_resolutions = {});
~BitstreamValidator() override;
// BitstreamProcessor implementation.
void ProcessBitstream(scoped_refptr<BitstreamRef> bitstream,
size_t frame_index) override;
bool WaitUntilDone() override;
private:
BitstreamValidator(
std::unique_ptr<VideoDecoder> decoder,
std::unique_ptr<MediaLog> media_log,
size_t last_frame_index,
const gfx::Rect& decoding_rect,
absl::optional<size_t> spatial_layer_index_to_decode_,
absl::optional<size_t> temporal_layer_index_to_decode,
const std::vector<gfx::Size>& spatial_layer_resolutions,
std::vector<std::unique_ptr<VideoFrameProcessor>> video_frame_processors);
BitstreamValidator(const BitstreamValidator&) = delete;
BitstreamValidator& operator=(const BitstreamValidator&) = delete;
bool Initialize(const VideoDecoderConfig& decoder_config);
void InitializeVideoDecoder(const VideoDecoderConfig& decoder_config,
VideoDecoder::InitCB init_cb);
void ProcessBitstreamTask(scoped_refptr<BitstreamRef> decoder_buffer,
size_t frame_index);
void OutputFrameProcessed();
// Functions for media::VideoDecoder.
void DecodeDone(int64_t timestamp, Status status);
void VerifyOutputFrame(scoped_refptr<VideoFrame> frame);
// Construct the spatial index conversion table |original_spatial_indices_|
// from |spatial_layer_resolutions|.
void ConstructSpatialIndices(
const std::vector<gfx::Size>& spatial_layer_resolutions);
// Validator components touched by validator_thread_ only.
std::unique_ptr<VideoDecoder> decoder_;
const std::unique_ptr<MediaLog> media_log_;
const size_t last_frame_index_;
const gfx::Rect desired_decoding_rect_;
const absl::optional<size_t> spatial_layer_index_to_decode_;
const absl::optional<size_t> temporal_layer_index_to_decode_;
const std::vector<gfx::Size> spatial_layer_resolutions_;
const std::vector<std::unique_ptr<VideoFrameProcessor>>
video_frame_processors_;
// The key is timestamp, and the value is BitstreamRef that is being processed
// by |decoder_| and its frame index.
static constexpr size_t kDecoderBufferMapSize = 32;
base::MRUCache<int64_t, std::pair<size_t, scoped_refptr<BitstreamRef>>>
decoding_buffers_{kDecoderBufferMapSize};
// The conversion table from the current spatial index to the spatial index of
// the initial spatial layers. Constructed in ConstructSpatialIndices().
std::vector<uint8_t> original_spatial_indices_;
base::Thread validator_thread_;
mutable base::ConditionVariable validator_cv_;
mutable base::Lock validator_lock_;
// The number of buffers that are being validated.
size_t num_buffers_validating_ GUARDED_BY(validator_lock_);
// True if |decoder_| detects an error while decoding bitstreams.
bool decode_error_ GUARDED_BY(validator_lock_);
// True if a flush is being processed.
bool waiting_flush_done_ GUARDED_BY(validator_lock_);
SEQUENCE_CHECKER(validator_sequence_checker_);
SEQUENCE_CHECKER(validator_thread_sequence_checker_);
};
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_VIDEO_ENCODER_BITSTREAM_VALIDATOR_H_