blob: 3a9751e67f70a65964ffc193552b5c380a63dd3c [file] [log] [blame]
philipel2fee4d62018-03-21 16:52:13 +01001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "video/video_stream_decoder_impl.h"
12
philipel97187112018-03-23 10:43:21 +010013#include "rtc_base/logging.h"
philipel2fee4d62018-03-21 16:52:13 +010014#include "rtc_base/ptr_util.h"
15
16namespace webrtc {
philipel97187112018-03-23 10:43:21 +010017
philipel2fee4d62018-03-21 16:52:13 +010018VideoStreamDecoderImpl::VideoStreamDecoderImpl(
19 VideoStreamDecoder::Callbacks* callbacks,
20 VideoDecoderFactory* decoder_factory,
21 std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings)
22 : callbacks_(callbacks),
23 decoder_factory_(decoder_factory),
philipel97187112018-03-23 10:43:21 +010024 decoder_settings_(std::move(decoder_settings)),
25 bookkeeping_queue_("video_stream_decoder_bookkeeping_queue"),
26 jitter_estimator_(Clock::GetRealTimeClock()),
27 timing_(Clock::GetRealTimeClock()),
28 frame_buffer_(Clock::GetRealTimeClock(),
29 &jitter_estimator_,
30 &timing_,
31 nullptr) {}
philipel2fee4d62018-03-21 16:52:13 +010032
philipel97187112018-03-23 10:43:21 +010033VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
34 frame_buffer_.Stop();
35}
philipel2fee4d62018-03-21 16:52:13 +010036
37void VideoStreamDecoderImpl::OnFrame(
philipel97187112018-03-23 10:43:21 +010038 std::unique_ptr<video_coding::EncodedFrame> frame) {
39 if (!bookkeeping_queue_.IsCurrent()) {
40 struct OnFrameTask : rtc::QueuedTask {
41 OnFrameTask(std::unique_ptr<video_coding::EncodedFrame> frame,
42 VideoStreamDecoderImpl* video_stream_decoder)
43 : frame_(std::move(frame)),
44 video_stream_decoder_(video_stream_decoder) {}
45
Niels Möllerbe682d42018-03-27 08:31:45 +020046 bool Run() override {
philipel97187112018-03-23 10:43:21 +010047 video_stream_decoder_->OnFrame(std::move(frame_));
48 return true;
49 }
50
51 std::unique_ptr<video_coding::EncodedFrame> frame_;
52 VideoStreamDecoderImpl* video_stream_decoder_;
53 };
54
55 bookkeeping_queue_.PostTask(
56 rtc::MakeUnique<OnFrameTask>(std::move(frame), this));
57 return;
58 }
59
60 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
61
62 uint64_t continuous_pid = frame_buffer_.InsertFrame(std::move(frame));
63 video_coding::VideoLayerFrameId continuous_id(continuous_pid, 0);
64 if (last_continuous_id_ < continuous_id) {
65 last_continuous_id_ = continuous_id;
66 callbacks_->OnContinuousUntil(last_continuous_id_);
67 }
68}
69
philipel79aab3f2018-03-26 14:31:23 +020070VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
71 if (current_payload_type_ == payload_type) {
72 RTC_DCHECK(decoder_);
73 return decoder_.get();
74 }
75
76 current_payload_type_.reset();
77 decoder_.reset();
78
79 auto decoder_settings_it = decoder_settings_.find(payload_type);
80 if (decoder_settings_it == decoder_settings_.end()) {
81 RTC_LOG(LS_WARNING) << "Payload type " << payload_type
82 << " not registered.";
83 return nullptr;
84 }
85
86 const SdpVideoFormat& video_format = decoder_settings_it->second.first;
87 std::unique_ptr<VideoDecoder> decoder =
88 decoder_factory_->CreateVideoDecoder(video_format);
89 if (!decoder) {
90 RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
91 << payload_type << ".";
92 return nullptr;
93 }
94
95 int num_cores = decoder_settings_it->second.second;
96 int32_t init_result = decoder->InitDecode(nullptr, num_cores);
97 if (init_result != WEBRTC_VIDEO_CODEC_OK) {
98 RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
99 << payload_type << ".";
100 return nullptr;
101 }
102
103 int32_t register_result = decoder->RegisterDecodeCompleteCallback(this);
104 if (register_result != WEBRTC_VIDEO_CODEC_OK) {
105 RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
106 return nullptr;
107 }
108
109 current_payload_type_.emplace(payload_type);
110 decoder_ = std::move(decoder);
111 return decoder_.get();
112}
113
philipel2fee4d62018-03-21 16:52:13 +0100114} // namespace webrtc