blob: daa919d7e477b56e8b77f3d74af2abaf75f955df [file] [log] [blame]
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef TEST_PC_E2E_ANALYZER_VIDEO_QUALITY_ANALYZING_VIDEO_DECODER_H_
#define TEST_PC_E2E_ANALYZER_VIDEO_QUALITY_ANALYZING_VIDEO_DECODER_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/environment/environment.h"
#include "api/test/video_quality_analyzer_interface.h"
#include "api/video/encoded_image.h"
#include "api/video/video_frame.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "rtc_base/synchronization/mutex.h"
#include "test/pc/e2e/analyzer/video/encoded_image_data_injector.h"
namespace webrtc {
namespace webrtc_pc_e2e {
// QualityAnalyzingVideoDecoder is used to wrap origin video decoder and inject
// VideoQualityAnalyzerInterface before and after decoder.
//
// QualityAnalyzingVideoDecoder propagates all calls to the origin decoder.
// It registers its own DecodedImageCallback in the origin decoder and will
// store user specified callback inside itself.
//
// When Decode(...) will be invoked, quality decoder first will extract frame id
// from passed EncodedImage with EncodedImageIdExtracor that was specified in
// constructor, then will call video quality analyzer, with correct
// EncodedImage and only then will pass image to origin decoder.
//
// When origin decoder decodes the image it will call quality decoder's special
// callback, where video analyzer will be called again and then decoded frame
// will be passed to origin callback, provided by user.
//
// Quality decoder registers its own callback in origin decoder, at the same
// time the user registers their callback in quality decoder.
class QualityAnalyzingVideoDecoder : public VideoDecoder {
public:
QualityAnalyzingVideoDecoder(absl::string_view peer_name,
std::unique_ptr<VideoDecoder> delegate,
EncodedImageDataExtractor* extractor,
VideoQualityAnalyzerInterface* analyzer);
~QualityAnalyzingVideoDecoder() override;
// Methods of VideoDecoder interface.
bool Configure(const Settings& settings) override;
int32_t Decode(const EncodedImage& input_image,
int64_t render_time_ms) override;
int32_t RegisterDecodeCompleteCallback(
DecodedImageCallback* callback) override;
int32_t Release() override;
DecoderInfo GetDecoderInfo() const override;
const char* ImplementationName() const override;
private:
class DecoderCallback : public DecodedImageCallback {
public:
explicit DecoderCallback(QualityAnalyzingVideoDecoder* decoder);
~DecoderCallback() override;
void SetDelegateCallback(DecodedImageCallback* delegate);
// Methods of DecodedImageCallback interface.
int32_t Decoded(VideoFrame& decodedImage) override;
int32_t Decoded(VideoFrame& decodedImage, int64_t decode_time_ms) override;
void Decoded(VideoFrame& decodedImage,
absl::optional<int32_t> decode_time_ms,
absl::optional<uint8_t> qp) override;
int32_t IrrelevantSimulcastStreamDecoded(uint16_t frame_id,
uint32_t timestamp_ms);
private:
rtc::scoped_refptr<webrtc::VideoFrameBuffer> GetDummyFrameBuffer();
QualityAnalyzingVideoDecoder* const decoder_;
rtc::scoped_refptr<webrtc::VideoFrameBuffer> dummy_frame_buffer_;
Mutex callback_mutex_;
DecodedImageCallback* delegate_callback_ RTC_GUARDED_BY(callback_mutex_);
};
void OnFrameDecoded(VideoFrame* frame,
absl::optional<int32_t> decode_time_ms,
absl::optional<uint8_t> qp);
const std::string peer_name_;
const std::string implementation_name_;
std::unique_ptr<VideoDecoder> delegate_;
EncodedImageDataExtractor* const extractor_;
VideoQualityAnalyzerInterface* const analyzer_;
std::unique_ptr<DecoderCallback> analyzing_callback_;
// VideoDecoder interface assumes async delivery of decoded video frames.
// This lock is used to protect shared state, that have to be propagated
// from received EncodedImage to resulted VideoFrame.
Mutex mutex_;
// Name of the video codec type used. Ex: VP8, VP9, H264 etc.
std::string codec_name_ RTC_GUARDED_BY(mutex_);
std::map<uint32_t, absl::optional<uint16_t>> timestamp_to_frame_id_
RTC_GUARDED_BY(mutex_);
// Stores currently being decoded images by timestamp. Because
// EncodedImageDataExtractor can create new copy on EncodedImage we need to
// ensure, that this image won't be deleted during async decoding. To do it
// all images are putted into this map and removed from here inside callback.
std::map<uint32_t, EncodedImage> decoding_images_ RTC_GUARDED_BY(mutex_);
};
// Produces QualityAnalyzingVideoDecoder, which hold decoders, produced by
// specified factory as delegates. Forwards all other calls to specified
// factory.
class QualityAnalyzingVideoDecoderFactory : public VideoDecoderFactory {
public:
QualityAnalyzingVideoDecoderFactory(
absl::string_view peer_name,
std::unique_ptr<VideoDecoderFactory> delegate,
EncodedImageDataExtractor* extractor,
VideoQualityAnalyzerInterface* analyzer);
~QualityAnalyzingVideoDecoderFactory() override;
// Methods of VideoDecoderFactory interface.
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
std::unique_ptr<VideoDecoder> Create(const Environment& env,
const SdpVideoFormat& format) override;
private:
const std::string peer_name_;
std::unique_ptr<VideoDecoderFactory> delegate_;
EncodedImageDataExtractor* const extractor_;
VideoQualityAnalyzerInterface* const analyzer_;
};
} // namespace webrtc_pc_e2e
} // namespace webrtc
#endif // TEST_PC_E2E_ANALYZER_VIDEO_QUALITY_ANALYZING_VIDEO_DECODER_H_