VideoStreamDecoderImpl implementation, part 3.

This CL implements the functions related to decoding.

Bug: webrtc:8909
Change-Id: Iefa3c1565a9b9ae93f14992b4a1cca141b7c5193
Reviewed-on: https://webrtc-review.googlesource.com/66403
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22747}
This commit is contained in:
philipel
2018-04-05 11:02:54 +02:00
committed by Commit Bot
parent 498644e645
commit 844876d050
2 changed files with 121 additions and 1 deletions

View File

@ -11,6 +11,7 @@
#include "video/video_stream_decoder_impl.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/mod_ops.h"
#include "rtc_base/ptr_util.h"
namespace webrtc {
@ -23,15 +24,24 @@ VideoStreamDecoderImpl::VideoStreamDecoderImpl(
decoder_factory_(decoder_factory),
decoder_settings_(std::move(decoder_settings)),
bookkeeping_queue_("video_stream_decoder_bookkeeping_queue"),
decode_thread_(&DecodeLoop,
this,
"video_stream_decoder_decode_thread",
rtc::kHighestPriority),
jitter_estimator_(Clock::GetRealTimeClock()),
timing_(Clock::GetRealTimeClock()),
frame_buffer_(Clock::GetRealTimeClock(),
&jitter_estimator_,
&timing_,
nullptr) {}
nullptr),
next_start_time_index_(0) {
decode_start_time_.fill({-1, 0});
decode_thread_.Start();
}
VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
frame_buffer_.Stop();
decode_thread_.Stop();
}
void VideoStreamDecoderImpl::OnFrame(
@ -111,4 +121,94 @@ VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
return decoder_.get();
}
// static
void VideoStreamDecoderImpl::DecodeLoop(void* ptr) {
// TODO(philipel): Remove this and use rtc::Event::kForever when it's
// supported by the |frame_buffer_|.
static constexpr int kForever = 100000000;
int max_wait_time_ms = kForever;
bool keyframe_required = true;
auto* vs_decoder = static_cast<VideoStreamDecoderImpl*>(ptr);
while (true) {
DecodeResult decode_result =
vs_decoder->DecodeNextFrame(max_wait_time_ms, keyframe_required);
switch (decode_result) {
case kOk: {
max_wait_time_ms = kForever;
keyframe_required = false;
break;
}
case kDecodeFailure: {
max_wait_time_ms = 0;
keyframe_required = true;
break;
}
case kNoFrame: {
max_wait_time_ms = kForever;
// If we end up here it means that we got a decoding error and there is
// no keyframe available in the |frame_buffer_|.
vs_decoder->bookkeeping_queue_.PostTask([vs_decoder]() {
RTC_DCHECK_RUN_ON(&vs_decoder->bookkeeping_queue_);
vs_decoder->callbacks_->OnNonDecodableState();
});
break;
}
case kNoDecoder: {
max_wait_time_ms = kForever;
break;
}
case kShutdown: {
return;
}
}
}
}
VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeNextFrame(
int max_wait_time_ms,
bool keyframe_required) {
std::unique_ptr<video_coding::EncodedFrame> frame;
video_coding::FrameBuffer::ReturnReason res =
frame_buffer_.NextFrame(max_wait_time_ms, &frame, keyframe_required);
if (res == video_coding::FrameBuffer::ReturnReason::kStopped)
return kShutdown;
if (frame) {
VideoDecoder* decoder = GetDecoder(frame->PayloadType());
if (!decoder) {
RTC_LOG(LS_WARNING) << "Failed to get decoder, dropping frame ("
<< frame->id.picture_id << ":"
<< frame->id.spatial_layer << ").";
return kNoDecoder;
}
int64_t decode_start_time_ms = rtc::TimeMillis();
uint32_t frame_timestamp = frame->timestamp;
bookkeeping_queue_.PostTask(
[this, decode_start_time_ms, frame_timestamp]() {
RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
// Saving decode start time this way wont work if we decode spatial
// layers sequentially.
decode_start_time_[next_start_time_index_] = {frame_timestamp,
decode_start_time_ms};
next_start_time_index_ =
Add<kDecodeTimeMemory>(next_start_time_index_, 1);
});
int32_t decode_result =
decoder->Decode(frame->EncodedImage(),
false, // missing_frame
nullptr, // rtp fragmentation header
nullptr, // codec specific info
frame->RenderTimeMs());
return decode_result == WEBRTC_VIDEO_CODEC_OK ? kOk : kDecodeFailure;
}
return kNoFrame;
}
} // namespace webrtc