
Long term goal is to use the VideoStreamDecoder in the VideoReceiveStream so that we can stop using legacy VideoCodingModule components and classes. This CL is one of several in preparation for that. Bug: webrtc:7408, webrtc:9378 Change-Id: Ifd7e4c3c7d38dbb7c4b0636aaad318c571a29158 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/164525 Reviewed-by: Sebastian Jansson <srte@webrtc.org> Reviewed-by: Åsa Persson <asapersson@webrtc.org> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Commit-Queue: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30211}
126 lines
4.8 KiB
C++
126 lines
4.8 KiB
C++
/*
|
|
* Copyright (c) 2018 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 VIDEO_VIDEO_STREAM_DECODER_IMPL_H_
|
|
#define VIDEO_VIDEO_STREAM_DECODER_IMPL_H_
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "absl/types/optional.h"
|
|
#include "api/video/video_stream_decoder.h"
|
|
#include "modules/video_coding/frame_buffer2.h"
|
|
#include "modules/video_coding/timing.h"
|
|
#include "rtc_base/platform_thread.h"
|
|
#include "rtc_base/task_queue.h"
|
|
#include "rtc_base/thread_checker.h"
|
|
#include "system_wrappers/include/clock.h"
|
|
|
|
namespace webrtc {
|
|
|
|
class VideoStreamDecoderImpl : public VideoStreamDecoderInterface {
|
|
public:
|
|
VideoStreamDecoderImpl(
|
|
VideoStreamDecoderInterface::Callbacks* callbacks,
|
|
VideoDecoderFactory* decoder_factory,
|
|
TaskQueueFactory* task_queue_factory,
|
|
std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings);
|
|
|
|
~VideoStreamDecoderImpl() override;
|
|
|
|
void OnFrame(std::unique_ptr<video_coding::EncodedFrame> frame) override;
|
|
|
|
void SetMinPlayoutDelay(TimeDelta min_delay) override;
|
|
void SetMaxPlayoutDelay(TimeDelta max_delay) override;
|
|
|
|
private:
|
|
class DecodeCallbacks : public DecodedImageCallback {
|
|
public:
|
|
explicit DecodeCallbacks(VideoStreamDecoderImpl* video_stream_decoder_impl);
|
|
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;
|
|
|
|
private:
|
|
VideoStreamDecoderImpl* const video_stream_decoder_impl_;
|
|
};
|
|
|
|
enum DecodeResult {
|
|
kOk,
|
|
kOkRequestKeyframe,
|
|
kDecodeFailure,
|
|
};
|
|
|
|
struct FrameTimestamps {
|
|
int64_t timestamp;
|
|
int64_t decode_start_time_ms;
|
|
int64_t render_time_us;
|
|
};
|
|
|
|
void SaveFrameTimestamps(const video_coding::EncodedFrame& frame)
|
|
RTC_RUN_ON(bookkeeping_queue_);
|
|
FrameTimestamps* GetFrameTimestamps(int64_t timestamp)
|
|
RTC_RUN_ON(bookkeeping_queue_);
|
|
void StartNextDecode() RTC_RUN_ON(bookkeeping_queue_);
|
|
void OnNextFrameCallback(std::unique_ptr<video_coding::EncodedFrame> frame,
|
|
video_coding::FrameBuffer::ReturnReason res)
|
|
RTC_RUN_ON(bookkeeping_queue_);
|
|
void OnDecodedFrameCallback(VideoFrame& decodedImage, // NOLINT
|
|
absl::optional<int32_t> decode_time_ms,
|
|
absl::optional<uint8_t> qp);
|
|
|
|
VideoDecoder* GetDecoder(int payload_type) RTC_RUN_ON(decode_queue_);
|
|
VideoStreamDecoderImpl::DecodeResult DecodeFrame(
|
|
std::unique_ptr<video_coding::EncodedFrame> frame)
|
|
RTC_RUN_ON(decode_queue_);
|
|
|
|
VCMTiming timing_;
|
|
DecodeCallbacks decode_callbacks_;
|
|
|
|
// Some decoders are pipelined so it is not sufficient to save frame info
|
|
// for the last frame only.
|
|
static constexpr int kFrameTimestampsMemory = 8;
|
|
std::array<FrameTimestamps, kFrameTimestampsMemory> frame_timestamps_
|
|
RTC_GUARDED_BY(bookkeeping_queue_);
|
|
int next_frame_timestamps_index_ RTC_GUARDED_BY(bookkeeping_queue_);
|
|
VideoStreamDecoderInterface::Callbacks* const callbacks_
|
|
RTC_PT_GUARDED_BY(bookkeeping_queue_);
|
|
video_coding::VideoLayerFrameId last_continuous_id_
|
|
RTC_GUARDED_BY(bookkeeping_queue_);
|
|
bool keyframe_required_ RTC_GUARDED_BY(bookkeeping_queue_);
|
|
|
|
absl::optional<int> current_payload_type_ RTC_GUARDED_BY(decode_queue_);
|
|
VideoDecoderFactory* const decoder_factory_ RTC_PT_GUARDED_BY(decode_queue_);
|
|
std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings_
|
|
RTC_GUARDED_BY(decode_queue_);
|
|
|
|
// The |bookkeeping_queue_| use the |frame_buffer_| and also posts tasks to
|
|
// the |decode_queue_|. The |decode_queue_| in turn use the |decoder_| to
|
|
// decode frames. When the |decoder_| is done it will post back to the
|
|
// |bookkeeping_queue_| with the decoded frame. During shutdown we start by
|
|
// isolating the |bookkeeping_queue_| from the |decode_queue_|, so now it's
|
|
// safe for the |decode_queue_| to be destructed. After that the |decoder_|
|
|
// can be destructed, and then the |bookkeeping_queue_|. Finally the
|
|
// |frame_buffer_| can be destructed.
|
|
rtc::CriticalSection shut_down_crit_;
|
|
bool shut_down_ RTC_GUARDED_BY(shut_down_crit_);
|
|
video_coding::FrameBuffer frame_buffer_ RTC_GUARDED_BY(bookkeeping_queue_);
|
|
rtc::TaskQueue bookkeeping_queue_;
|
|
std::unique_ptr<VideoDecoder> decoder_ RTC_GUARDED_BY(decode_queue_);
|
|
rtc::TaskQueue decode_queue_;
|
|
};
|
|
|
|
} // namespace webrtc
|
|
|
|
#endif // VIDEO_VIDEO_STREAM_DECODER_IMPL_H_
|