| /* |
| * Copyright (c) 2016 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. |
| */ |
| |
| #include "modules/video_coding/rtp_frame_reference_finder.h" |
| |
| #include <utility> |
| |
| #include "absl/types/variant.h" |
| #include "modules/video_coding/frame_object.h" |
| #include "modules/video_coding/rtp_frame_id_only_ref_finder.h" |
| #include "modules/video_coding/rtp_generic_ref_finder.h" |
| #include "modules/video_coding/rtp_seq_num_only_ref_finder.h" |
| #include "modules/video_coding/rtp_vp8_ref_finder.h" |
| #include "modules/video_coding/rtp_vp9_ref_finder.h" |
| |
| namespace webrtc { |
| namespace internal { |
| class RtpFrameReferenceFinderImpl { |
| public: |
| RtpFrameReferenceFinderImpl() = default; |
| |
| RtpFrameReferenceFinder::ReturnVector ManageFrame( |
| std::unique_ptr<RtpFrameObject> frame); |
| RtpFrameReferenceFinder::ReturnVector PaddingReceived(uint16_t seq_num); |
| void ClearTo(uint16_t seq_num); |
| |
| private: |
| using RefFinder = absl::variant<absl::monostate, |
| RtpGenericFrameRefFinder, |
| RtpFrameIdOnlyRefFinder, |
| RtpSeqNumOnlyRefFinder, |
| RtpVp8RefFinder, |
| RtpVp9RefFinder>; |
| |
| template <typename T> |
| T& GetRefFinderAs(); |
| RefFinder ref_finder_; |
| }; |
| |
| RtpFrameReferenceFinder::ReturnVector RtpFrameReferenceFinderImpl::ManageFrame( |
| std::unique_ptr<RtpFrameObject> frame) { |
| const RTPVideoHeader& video_header = frame->GetRtpVideoHeader(); |
| |
| if (video_header.generic.has_value()) { |
| return GetRefFinderAs<RtpGenericFrameRefFinder>().ManageFrame( |
| std::move(frame), *video_header.generic); |
| } |
| |
| switch (frame->codec_type()) { |
| case kVideoCodecVP8: { |
| const RTPVideoHeaderVP8& vp8_header = |
| absl::get<RTPVideoHeaderVP8>(video_header.video_type_header); |
| |
| if (vp8_header.temporalIdx == kNoTemporalIdx || |
| vp8_header.tl0PicIdx == kNoTl0PicIdx) { |
| if (vp8_header.pictureId == kNoPictureId) { |
| return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame( |
| std::move(frame)); |
| } |
| |
| return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame( |
| std::move(frame), vp8_header.pictureId); |
| } |
| |
| return GetRefFinderAs<RtpVp8RefFinder>().ManageFrame(std::move(frame)); |
| } |
| case kVideoCodecVP9: { |
| const RTPVideoHeaderVP9& vp9_header = |
| absl::get<RTPVideoHeaderVP9>(video_header.video_type_header); |
| |
| if (vp9_header.temporal_idx == kNoTemporalIdx) { |
| if (vp9_header.picture_id == kNoPictureId) { |
| return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame( |
| std::move(frame)); |
| } |
| |
| return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame( |
| std::move(frame), vp9_header.picture_id); |
| } |
| |
| return GetRefFinderAs<RtpVp9RefFinder>().ManageFrame(std::move(frame)); |
| } |
| case kVideoCodecGeneric: { |
| if (auto* generic_header = absl::get_if<RTPVideoHeaderLegacyGeneric>( |
| &video_header.video_type_header)) { |
| return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame( |
| std::move(frame), generic_header->picture_id); |
| } |
| |
| return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame( |
| std::move(frame)); |
| } |
| default: { |
| return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame( |
| std::move(frame)); |
| } |
| } |
| } |
| |
| RtpFrameReferenceFinder::ReturnVector |
| RtpFrameReferenceFinderImpl::PaddingReceived(uint16_t seq_num) { |
| if (auto* ref_finder = absl::get_if<RtpSeqNumOnlyRefFinder>(&ref_finder_)) { |
| return ref_finder->PaddingReceived(seq_num); |
| } |
| return {}; |
| } |
| |
| void RtpFrameReferenceFinderImpl::ClearTo(uint16_t seq_num) { |
| struct ClearToVisitor { |
| void operator()(absl::monostate& ref_finder) {} |
| void operator()(RtpGenericFrameRefFinder& ref_finder) {} |
| void operator()(RtpFrameIdOnlyRefFinder& ref_finder) {} |
| void operator()(RtpSeqNumOnlyRefFinder& ref_finder) { |
| ref_finder.ClearTo(seq_num); |
| } |
| void operator()(RtpVp8RefFinder& ref_finder) { |
| ref_finder.ClearTo(seq_num); |
| } |
| void operator()(RtpVp9RefFinder& ref_finder) { |
| ref_finder.ClearTo(seq_num); |
| } |
| uint16_t seq_num; |
| }; |
| |
| absl::visit(ClearToVisitor{seq_num}, ref_finder_); |
| } |
| |
| template <typename T> |
| T& RtpFrameReferenceFinderImpl::GetRefFinderAs() { |
| if (auto* ref_finder = absl::get_if<T>(&ref_finder_)) { |
| return *ref_finder; |
| } |
| return ref_finder_.emplace<T>(); |
| } |
| |
| } // namespace internal |
| |
| RtpFrameReferenceFinder::RtpFrameReferenceFinder( |
| OnCompleteFrameCallback* frame_callback) |
| : RtpFrameReferenceFinder(frame_callback, 0) {} |
| |
| RtpFrameReferenceFinder::RtpFrameReferenceFinder( |
| OnCompleteFrameCallback* frame_callback, |
| int64_t picture_id_offset) |
| : picture_id_offset_(picture_id_offset), |
| frame_callback_(frame_callback), |
| impl_(std::make_unique<internal::RtpFrameReferenceFinderImpl>()) {} |
| |
| RtpFrameReferenceFinder::~RtpFrameReferenceFinder() = default; |
| |
| void RtpFrameReferenceFinder::ManageFrame( |
| std::unique_ptr<RtpFrameObject> frame) { |
| // If we have cleared past this frame, drop it. |
| if (cleared_to_seq_num_ != -1 && |
| AheadOf<uint16_t>(cleared_to_seq_num_, frame->first_seq_num())) { |
| return; |
| } |
| HandOffFrames(impl_->ManageFrame(std::move(frame))); |
| } |
| |
| void RtpFrameReferenceFinder::PaddingReceived(uint16_t seq_num) { |
| HandOffFrames(impl_->PaddingReceived(seq_num)); |
| } |
| |
| void RtpFrameReferenceFinder::ClearTo(uint16_t seq_num) { |
| cleared_to_seq_num_ = seq_num; |
| impl_->ClearTo(seq_num); |
| } |
| |
| void RtpFrameReferenceFinder::HandOffFrames(ReturnVector frames) { |
| for (auto& frame : frames) { |
| frame->SetId(frame->Id() + picture_id_offset_); |
| for (size_t i = 0; i < frame->num_references; ++i) { |
| frame->references[i] += picture_id_offset_; |
| } |
| |
| frame_callback_->OnCompleteFrame(std::move(frame)); |
| } |
| } |
| |
| } // namespace webrtc |