Add support for simulcast streams in QualityAnalyzingVideoDecoder.

In QualityAnalyzingVideoEncoder all encoded images that belongs to
unrelated simulcast streams will be marked as to be discarded. So
to support simulcast streams QualityAnalyzingVideoDecoder have to return
black frames when all encoded images in received concatenated encoded
image are marked as to be discarded. Also QualityAnalyzingVideoDecoder
shouldn't pass such encoded image into VideoQualityAnalyzerInterface.

Bug: webrtc:10138
Change-Id: I0f793a7dc04b5d6b10949479bd074b2db86c5c6f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/125460
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Peter Slatala <psla@webrtc.org>
Reviewed-by: Yves Gerey <yvesg@google.com>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26973}
This commit is contained in:
Artem Titov 2019-03-05 13:26:48 +01:00 committed by Commit Bot
parent 6ec2f547d7
commit d36c08623d
3 changed files with 68 additions and 2 deletions

View File

@ -104,6 +104,7 @@ rtc_source_set("quality_analyzing_video_decoder") {
":id_generator",
"../../../api/video:encoded_image",
"../../../api/video:video_frame",
"../../../api/video:video_frame_i420",
"../../../api/video_codecs:video_codecs_api",
"../../../modules/video_coding:video_codec_interface",
"../../../rtc_base:criticalsection",

View File

@ -16,11 +16,18 @@
#include "absl/memory/memory.h"
#include "absl/types/optional.h"
#include "api/video/i420_buffer.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "rtc_base/logging.h"
namespace webrtc {
namespace test {
namespace {
constexpr size_t kIrrelatedSimulcastStreamFrameWidth = 320;
constexpr size_t kIrrelatedSimulcastStreamFrameHeight = 480;
} // namespace
QualityAnalyzingVideoDecoder::QualityAnalyzingVideoDecoder(
int id,
@ -55,8 +62,24 @@ int32_t QualityAnalyzingVideoDecoder::Decode(
// deleting it.
EncodedImageExtractionResult out = extractor_->ExtractData(input_image, id_);
// TODO(titovartem) add support for simulcast.
RTC_CHECK(!out.discard) << "Simulcast is not supported yet";
if (out.discard) {
// To partly emulate behavior of Selective Forwarding Unit (SFU) in the
// test, on receiver side we will "discard" frames from irrelevant streams.
// When all encoded images were marked to discarded, black frame have to be
// returned. Because simulcast streams will be received by receiver as 3
// different independent streams we don't want that irrelevant streams
// affect video quality metrics and also we don't want to use CPU time to
// decode them to prevent regressions on relevant streams. Also we can't
// just drop frame, because in such case, receiving part will be confused
// with all frames missing and will request a key frame, which will result
// into extra load on network and sender side. Because of it, discarded
// image will be always decoded as black frame and will be passed to
// callback directly without reaching decoder and video quality analyzer.
//
// For more details see QualityAnalyzingVideoEncoder.
return analyzing_callback_->IrrelevantSimulcastStreamDecoded(
out.id, input_image.Timestamp());
}
EncodedImage* origin_image;
{
@ -168,6 +191,38 @@ int32_t QualityAnalyzingVideoDecoder::DecoderCallback::ReceivedDecodedFrame(
return delegate_callback_->ReceivedDecodedFrame(pictureId);
}
int32_t
QualityAnalyzingVideoDecoder::DecoderCallback::IrrelevantSimulcastStreamDecoded(
uint16_t frame_id,
int64_t timestamp_ms) {
webrtc::VideoFrame black_frame =
webrtc::VideoFrame::Builder()
.set_video_frame_buffer(
GetBlackFrameBuffer(kIrrelatedSimulcastStreamFrameWidth,
kIrrelatedSimulcastStreamFrameHeight))
.set_timestamp_ms(timestamp_ms)
.set_id(frame_id)
.build();
rtc::CritScope crit(&callback_lock_);
RTC_DCHECK(delegate_callback_);
return delegate_callback_->Decoded(black_frame);
}
rtc::scoped_refptr<webrtc::VideoFrameBuffer>
QualityAnalyzingVideoDecoder::DecoderCallback::GetBlackFrameBuffer(int width,
int height) {
if (!black_frame_buffer_ || black_frame_buffer_->width() != width ||
black_frame_buffer_->height() != height) {
// Use i420 buffer here as default one and supported by all codecs.
rtc::scoped_refptr<webrtc::I420Buffer> buffer =
webrtc::I420Buffer::Create(width, height);
webrtc::I420Buffer::SetBlack(buffer.get());
black_frame_buffer_ = buffer;
}
return black_frame_buffer_;
}
void QualityAnalyzingVideoDecoder::OnFrameDecoded(
VideoFrame* frame,
absl::optional<int32_t> decode_time_ms,

View File

@ -88,8 +88,18 @@ class QualityAnalyzingVideoDecoder : public VideoDecoder {
int32_t ReceivedDecodedReferenceFrame(uint64_t pictureId) override;
int32_t ReceivedDecodedFrame(uint64_t pictureId) override;
int32_t IrrelevantSimulcastStreamDecoded(uint16_t frame_id,
int64_t timestamp_ms);
private:
rtc::scoped_refptr<webrtc::VideoFrameBuffer> GetBlackFrameBuffer(
int width,
int height);
QualityAnalyzingVideoDecoder* const decoder_;
rtc::scoped_refptr<webrtc::VideoFrameBuffer> black_frame_buffer_;
rtc::CriticalSection callback_lock_;
DecodedImageCallback* delegate_callback_ RTC_GUARDED_BY(callback_lock_);
};