OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2017 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 "modules/video_coding/codecs/stereo/include/stereo_decoder_adapter.h" |
| 12 |
| 13 #include "api/video/i420_buffer.h" |
| 14 #include "common_video/include/video_frame.h" |
| 15 #include "common_video/include/video_frame_buffer.h" |
| 16 #include "common_video/libyuv/include/webrtc_libyuv.h" |
| 17 #include "media/engine/scopedvideodecoder.h" |
| 18 #include "rtc_base/keep_ref_until_done.h" |
| 19 #include "rtc_base/logging.h" |
| 20 |
| 21 namespace webrtc { |
| 22 |
| 23 class StereoDecoderAdapter::AdapterDecodedImageCallback |
| 24 : public webrtc::DecodedImageCallback { |
| 25 public: |
| 26 AdapterDecodedImageCallback(webrtc::StereoDecoderAdapter* adapter, |
| 27 StereoCodecStream stream_idx) |
| 28 : adapter_(adapter), stream_idx_(stream_idx) {} |
| 29 |
| 30 void Decoded(VideoFrame& decodedImage, |
| 31 rtc::Optional<int32_t> decode_time_ms, |
| 32 rtc::Optional<uint8_t> qp) override { |
| 33 if (!adapter_) |
| 34 return; |
| 35 adapter_->Decoded(stream_idx_, decodedImage, decode_time_ms, qp); |
| 36 } |
| 37 int32_t Decoded(VideoFrame& decodedImage) override { |
| 38 RTC_NOTREACHED(); |
| 39 return WEBRTC_VIDEO_CODEC_OK; |
| 40 } |
| 41 int32_t Decoded(VideoFrame& decodedImage, int64_t decode_time_ms) override { |
| 42 RTC_NOTREACHED(); |
| 43 return WEBRTC_VIDEO_CODEC_OK; |
| 44 } |
| 45 |
| 46 private: |
| 47 StereoDecoderAdapter* adapter_; |
| 48 const StereoCodecStream stream_idx_; |
| 49 }; |
| 50 |
| 51 struct StereoDecoderAdapter::DecodedImageData { |
| 52 explicit DecodedImageData(StereoCodecStream stream_idx) |
| 53 : stream_idx_(stream_idx), |
| 54 decodedImage_(I420Buffer::Create(1 /* width */, 1 /* height */), |
| 55 0, |
| 56 0, |
| 57 kVideoRotation_0) { |
| 58 RTC_DCHECK_EQ(kAXXStream, stream_idx); |
| 59 } |
| 60 DecodedImageData(StereoCodecStream stream_idx, |
| 61 const VideoFrame& decodedImage, |
| 62 const rtc::Optional<int32_t>& decode_time_ms, |
| 63 const rtc::Optional<uint8_t>& qp) |
| 64 : stream_idx_(stream_idx), |
| 65 decodedImage_(decodedImage), |
| 66 decode_time_ms_(decode_time_ms), |
| 67 qp_(qp) {} |
| 68 const StereoCodecStream stream_idx_; |
| 69 VideoFrame decodedImage_; |
| 70 const rtc::Optional<int32_t> decode_time_ms_; |
| 71 const rtc::Optional<uint8_t> qp_; |
| 72 |
| 73 private: |
| 74 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DecodedImageData); |
| 75 }; |
| 76 |
| 77 StereoDecoderAdapter::StereoDecoderAdapter( |
| 78 cricket::WebRtcVideoDecoderFactory* factory) |
| 79 : factory_(factory) {} |
| 80 |
| 81 StereoDecoderAdapter::~StereoDecoderAdapter() { |
| 82 Release(); |
| 83 } |
| 84 |
| 85 int32_t StereoDecoderAdapter::InitDecode(const VideoCodec* codec_settings, |
| 86 int32_t number_of_cores) { |
| 87 VideoCodec settings = *codec_settings; |
| 88 settings.codecType = kVideoCodecVP9; |
| 89 for (size_t i = 0; i < kStereoCodecStreams; ++i) { |
| 90 std::unique_ptr<VideoDecoder> decoder = CreateScopedVideoDecoder( |
| 91 factory_, cricket::VideoCodec("VP9"), cricket::VideoDecoderParams()); |
| 92 const int32_t rv = decoder->InitDecode(&settings, number_of_cores); |
| 93 if (rv) |
| 94 return rv; |
| 95 adapter_callbacks_.emplace_back( |
| 96 new StereoDecoderAdapter::AdapterDecodedImageCallback( |
| 97 this, static_cast<StereoCodecStream>(i))); |
| 98 decoder->RegisterDecodeCompleteCallback(adapter_callbacks_.back().get()); |
| 99 decoders_.emplace_back(std::move(decoder)); |
| 100 } |
| 101 return WEBRTC_VIDEO_CODEC_OK; |
| 102 } |
| 103 |
| 104 int32_t StereoDecoderAdapter::Decode( |
| 105 const EncodedImage& input_image, |
| 106 bool missing_frames, |
| 107 const RTPFragmentationHeader* /*fragmentation*/, |
| 108 const CodecSpecificInfo* codec_specific_info, |
| 109 int64_t render_time_ms) { |
| 110 LOG(LS_ERROR) << __func__; |
| 111 LOG(LS_ERROR) << __func__ |
| 112 << static_cast<int>(codec_specific_info->stereoInfo.frameIndex); |
| 113 LOG(LS_ERROR) << __func__ |
| 114 << static_cast<int>(codec_specific_info->stereoInfo.frameCount); |
| 115 LOG(LS_ERROR) << __func__ |
| 116 << static_cast<int>( |
| 117 codec_specific_info->stereoInfo.pictureIndex); |
| 118 if (codec_specific_info->stereoInfo.frameCount == 1) { |
| 119 RTC_DCHECK(decoded_data_.find(input_image._timeStamp) == |
| 120 decoded_data_.end()); |
| 121 decoded_data_.emplace(std::piecewise_construct, |
| 122 std::forward_as_tuple(input_image._timeStamp), |
| 123 std::forward_as_tuple(kAXXStream)); |
| 124 } |
| 125 |
| 126 int32_t rv = decoders_[codec_specific_info->stereoInfo.frameIndex]->Decode( |
| 127 input_image, missing_frames, nullptr, codec_specific_info, |
| 128 render_time_ms); |
| 129 return rv; |
| 130 } |
| 131 |
| 132 int32_t StereoDecoderAdapter::RegisterDecodeCompleteCallback( |
| 133 DecodedImageCallback* callback) { |
| 134 decoded_complete_callback_ = callback; |
| 135 return WEBRTC_VIDEO_CODEC_OK; |
| 136 } |
| 137 |
| 138 int32_t StereoDecoderAdapter::Release() { |
| 139 for (auto& decoder : decoders_) { |
| 140 const int32_t rv = decoder->Release(); |
| 141 if (rv) |
| 142 return rv; |
| 143 // factory_->Destroy(decoder); |
| 144 } |
| 145 decoders_.clear(); |
| 146 adapter_callbacks_.clear(); |
| 147 return WEBRTC_VIDEO_CODEC_OK; |
| 148 } |
| 149 |
| 150 void StereoDecoderAdapter::Decoded(StereoCodecStream stream_idx, |
| 151 VideoFrame& decoded_image, |
| 152 rtc::Optional<int32_t> decode_time_ms, |
| 153 rtc::Optional<uint8_t> qp) { |
| 154 const auto& other_decoded_data_it = |
| 155 decoded_data_.find(decoded_image.timestamp()); |
| 156 if (other_decoded_data_it != decoded_data_.end()) { |
| 157 auto& other_image_data = other_decoded_data_it->second; |
| 158 if (stream_idx == kYUVStream) { |
| 159 RTC_DCHECK_EQ(kAXXStream, other_image_data.stream_idx_); |
| 160 MergeDecodedImages( |
| 161 decoded_image, decode_time_ms, qp, other_image_data.decodedImage_, |
| 162 other_image_data.decode_time_ms_, other_image_data.qp_); |
| 163 } else { |
| 164 RTC_DCHECK_EQ(kYUVStream, other_image_data.stream_idx_); |
| 165 RTC_DCHECK_EQ(kAXXStream, stream_idx); |
| 166 MergeDecodedImages(other_image_data.decodedImage_, |
| 167 other_image_data.decode_time_ms_, other_image_data.qp_, |
| 168 decoded_image, decode_time_ms, qp); |
| 169 } |
| 170 decoded_data_.erase(decoded_data_.begin(), other_decoded_data_it); |
| 171 return; |
| 172 } |
| 173 RTC_DCHECK(decoded_data_.find(decoded_image.timestamp()) == |
| 174 decoded_data_.end()); |
| 175 decoded_data_.emplace( |
| 176 std::piecewise_construct, |
| 177 std::forward_as_tuple(decoded_image.timestamp()), |
| 178 std::forward_as_tuple(stream_idx, decoded_image, decode_time_ms, qp)); |
| 179 } |
| 180 |
| 181 void StereoDecoderAdapter::MergeDecodedImages( |
| 182 VideoFrame& decodedImage, |
| 183 const rtc::Optional<int32_t>& decode_time_ms, |
| 184 const rtc::Optional<uint8_t>& qp, |
| 185 VideoFrame& alpha_decodedImage, |
| 186 const rtc::Optional<int32_t>& stereo_decode_time_ms, |
| 187 const rtc::Optional<uint8_t>& stereo_qp) { |
| 188 if (!alpha_decodedImage.timestamp()) { |
| 189 decoded_complete_callback_->Decoded(decodedImage, decode_time_ms, qp); |
| 190 return; |
| 191 } |
| 192 rtc::scoped_refptr<webrtc::I420BufferInterface> alpha_buffer = |
| 193 alpha_decodedImage.video_frame_buffer()->ToI420(); |
| 194 rtc::scoped_refptr<WrappedI420ABuffer> wrapped_buffer( |
| 195 new rtc::RefCountedObject<webrtc::WrappedI420ABuffer>( |
| 196 decodedImage.video_frame_buffer(), alpha_buffer->DataY(), |
| 197 alpha_buffer->StrideY(), |
| 198 rtc::KeepRefUntilDone(alpha_decodedImage.video_frame_buffer()))); |
| 199 VideoFrame wrapped_image(wrapped_buffer, decodedImage.timestamp(), |
| 200 0 /* render_time_ms */, decodedImage.rotation()); |
| 201 decoded_complete_callback_->Decoded(wrapped_image, decode_time_ms, qp); |
| 202 } |
| 203 |
| 204 } // namespace webrtc |
OLD | NEW |