diff --git a/test/BUILD.gn b/test/BUILD.gn index de69a1b6f8..c1e6362521 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -616,6 +616,7 @@ rtc_source_set("fake_video_codecs") { "../rtc_base:rtc_task_queue", "../rtc_base:sequenced_task_checker", "../system_wrappers", + "//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/types:optional", ] } diff --git a/test/fake_encoder.cc b/test/fake_encoder.cc index 4adeffb344..67fc839ac0 100644 --- a/test/fake_encoder.cc +++ b/test/fake_encoder.cc @@ -16,6 +16,7 @@ #include #include +#include "absl/memory/memory.h" #include "api/video/video_content_type.h" #include "common_types.h" // NOLINT(build/include) #include "modules/video_coding/codecs/h264/include/h264_globals.h" @@ -80,7 +81,7 @@ int32_t FakeEncoder::InitEncode(const VideoCodec* config, } int32_t FakeEncoder::Encode(const VideoFrame& input_image, - const CodecSpecificInfo* codec_specific_info, + const CodecSpecificInfo* /*codec_specific_info*/, const std::vector* frame_types) { unsigned char max_framerate; unsigned char num_simulcast_streams; @@ -121,16 +122,14 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image, continue; } - CodecSpecificInfo specifics; - specifics.codecType = kVideoCodecGeneric; - std::unique_ptr encoded_buffer( - new uint8_t[frame_info.layers[i].size]); + EncodedImage encoded; + encoded.Allocate(frame_info.layers[i].size); + encoded.set_size(frame_info.layers[i].size); + // Fill the buffer with arbitrary data. Write someting to make Asan happy. - memset(encoded_buffer.get(), 9, frame_info.layers[i].size); + memset(encoded.data(), 9, frame_info.layers[i].size); // Write a counter to the image to make each frame unique. - WriteCounter(encoded_buffer.get() + frame_info.layers[i].size - 4, counter); - EncodedImage encoded(encoded_buffer.get(), frame_info.layers[i].size, - frame_info.layers[i].size); + WriteCounter(encoded.data() + frame_info.layers[i].size - 4, counter); encoded.SetTimestamp(input_image.timestamp()); encoded.capture_time_ms_ = input_image.render_time_ms(); encoded._frameType = @@ -142,14 +141,25 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image, ? VideoContentType::SCREENSHARE : VideoContentType::UNSPECIFIED; encoded.SetSpatialIndex(i); - if (callback->OnEncodedImage(encoded, &specifics, nullptr).error != - EncodedImageCallback::Result::OK) { + CodecSpecificInfo codec_specific; + std::unique_ptr fragmentation = + EncodeHook(&encoded, &codec_specific); + + if (callback->OnEncodedImage(encoded, &codec_specific, fragmentation.get()) + .error != EncodedImageCallback::Result::OK) { return -1; } } return 0; } +std::unique_ptr FakeEncoder::EncodeHook( + EncodedImage* encoded_image, + CodecSpecificInfo* codec_specific) { + codec_specific->codecType = kVideoCodecGeneric; + return nullptr; +} + FakeEncoder::FrameInfo FakeEncoder::NextFrame( const std::vector* frame_types, bool keyframe, @@ -271,77 +281,65 @@ int FakeEncoder::GetConfiguredInputFramerate() const { } FakeH264Encoder::FakeH264Encoder(Clock* clock) - : FakeEncoder(clock), callback_(nullptr), idr_counter_(0) { - FakeEncoder::RegisterEncodeCompleteCallback(this); -} + : FakeEncoder(clock), idr_counter_(0) {} -int32_t FakeH264Encoder::RegisterEncodeCompleteCallback( - EncodedImageCallback* callback) { - rtc::CritScope cs(&local_crit_sect_); - callback_ = callback; - return 0; -} - -EncodedImageCallback::Result FakeH264Encoder::OnEncodedImage( - const EncodedImage& encoded_image, - const CodecSpecificInfo* codec_specific_info, - const RTPFragmentationHeader* fragments) { +std::unique_ptr FakeH264Encoder::EncodeHook( + EncodedImage* encoded_image, + CodecSpecificInfo* codec_specific) { const size_t kSpsSize = 8; const size_t kPpsSize = 11; const int kIdrFrequency = 10; - EncodedImageCallback* callback; int current_idr_counter; { rtc::CritScope cs(&local_crit_sect_); - callback = callback_; current_idr_counter = idr_counter_; ++idr_counter_; } - RTPFragmentationHeader fragmentation; + auto fragmentation = absl::make_unique(); + if (current_idr_counter % kIdrFrequency == 0 && - encoded_image.size() > kSpsSize + kPpsSize + 1) { + encoded_image->size() > kSpsSize + kPpsSize + 1) { const size_t kNumSlices = 3; - fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices); - fragmentation.fragmentationOffset[0] = 0; - fragmentation.fragmentationLength[0] = kSpsSize; - fragmentation.fragmentationOffset[1] = kSpsSize; - fragmentation.fragmentationLength[1] = kPpsSize; - fragmentation.fragmentationOffset[2] = kSpsSize + kPpsSize; - fragmentation.fragmentationLength[2] = - encoded_image.size() - (kSpsSize + kPpsSize); + fragmentation->VerifyAndAllocateFragmentationHeader(kNumSlices); + fragmentation->fragmentationOffset[0] = 0; + fragmentation->fragmentationLength[0] = kSpsSize; + fragmentation->fragmentationOffset[1] = kSpsSize; + fragmentation->fragmentationLength[1] = kPpsSize; + fragmentation->fragmentationOffset[2] = kSpsSize + kPpsSize; + fragmentation->fragmentationLength[2] = + encoded_image->size() - (kSpsSize + kPpsSize); const size_t kSpsNalHeader = 0x67; const size_t kPpsNalHeader = 0x68; const size_t kIdrNalHeader = 0x65; - encoded_image.buffer()[fragmentation.fragmentationOffset[0]] = + encoded_image->data()[fragmentation->fragmentationOffset[0]] = kSpsNalHeader; - encoded_image.buffer()[fragmentation.fragmentationOffset[1]] = + encoded_image->data()[fragmentation->fragmentationOffset[1]] = kPpsNalHeader; - encoded_image.buffer()[fragmentation.fragmentationOffset[2]] = + encoded_image->data()[fragmentation->fragmentationOffset[2]] = kIdrNalHeader; } else { const size_t kNumSlices = 1; - fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices); - fragmentation.fragmentationOffset[0] = 0; - fragmentation.fragmentationLength[0] = encoded_image.size(); + fragmentation->VerifyAndAllocateFragmentationHeader(kNumSlices); + fragmentation->fragmentationOffset[0] = 0; + fragmentation->fragmentationLength[0] = encoded_image->size(); const size_t kNalHeader = 0x41; - encoded_image.buffer()[fragmentation.fragmentationOffset[0]] = kNalHeader; + encoded_image->data()[fragmentation->fragmentationOffset[0]] = kNalHeader; } uint8_t value = 0; int fragment_counter = 0; - for (size_t i = 0; i < encoded_image.size(); ++i) { - if (fragment_counter == fragmentation.fragmentationVectorSize || - i != fragmentation.fragmentationOffset[fragment_counter]) { - encoded_image.buffer()[i] = value++; + for (size_t i = 0; i < encoded_image->size(); ++i) { + if (fragment_counter == fragmentation->fragmentationVectorSize || + i != fragmentation->fragmentationOffset[fragment_counter]) { + encoded_image->data()[i] = value++; } else { ++fragment_counter; } } - CodecSpecificInfo specifics; - specifics.codecType = kVideoCodecH264; - specifics.codecSpecific.H264.packetization_mode = + codec_specific->codecType = kVideoCodecH264; + codec_specific->codecSpecific.H264.packetization_mode = H264PacketizationMode::NonInterleaved; - RTC_DCHECK(callback); - return callback->OnEncodedImage(encoded_image, &specifics, &fragmentation); + + return fragmentation; } DelayedEncoder::DelayedEncoder(Clock* clock, int delay_ms) diff --git a/test/fake_encoder.h b/test/fake_encoder.h index 0760353746..ffd672a63e 100644 --- a/test/fake_encoder.h +++ b/test/fake_encoder.h @@ -79,6 +79,13 @@ class FakeEncoder : public VideoEncoder { SimulcastStream simulcast_streams[kMaxSimulcastStreams], int framerate); + // Called before the frame is passed to callback_->OnEncodedImage, to let + // subclasses fill out codec_specific, possibly modify encodedImage. + // Returns an RTPFragmentationHeader, if needed by the codec. + virtual std::unique_ptr EncodeHook( + EncodedImage* encoded_image, + CodecSpecificInfo* codec_specific); + FrameInfo last_frame_info_ RTC_GUARDED_BY(crit_sect_); Clock* const clock_; @@ -97,20 +104,16 @@ class FakeEncoder : public VideoEncoder { size_t debt_bytes_; }; -class FakeH264Encoder : public FakeEncoder, public EncodedImageCallback { +class FakeH264Encoder : public FakeEncoder { public: explicit FakeH264Encoder(Clock* clock); virtual ~FakeH264Encoder() = default; - int32_t RegisterEncodeCompleteCallback( - EncodedImageCallback* callback) override; - - Result OnEncodedImage(const EncodedImage& encodedImage, - const CodecSpecificInfo* codecSpecificInfo, - const RTPFragmentationHeader* fragments) override; - private: - EncodedImageCallback* callback_ RTC_GUARDED_BY(local_crit_sect_); + std::unique_ptr EncodeHook( + EncodedImage* encoded_image, + CodecSpecificInfo* codec_specific) override; + int idr_counter_ RTC_GUARDED_BY(local_crit_sect_); rtc::CriticalSection local_crit_sect_; }; diff --git a/test/fake_vp8_encoder.cc b/test/fake_vp8_encoder.cc index cb60091d1d..bf7ec68386 100644 --- a/test/fake_vp8_encoder.cc +++ b/test/fake_vp8_encoder.cc @@ -45,19 +45,10 @@ namespace webrtc { namespace test { -FakeVP8Encoder::FakeVP8Encoder(Clock* clock) - : FakeEncoder(clock), callback_(nullptr) { - FakeEncoder::RegisterEncodeCompleteCallback(this); +FakeVP8Encoder::FakeVP8Encoder(Clock* clock) : FakeEncoder(clock) { sequence_checker_.Detach(); } -int32_t FakeVP8Encoder::RegisterEncodeCompleteCallback( - EncodedImageCallback* callback) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); - callback_ = callback; - return 0; -} - int32_t FakeVP8Encoder::InitEncode(const VideoCodec* config, int32_t number_of_cores, size_t max_payload_size) { @@ -112,25 +103,22 @@ void FakeVP8Encoder::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, timestamp, size_bytes, frame_type == kVideoFrameKey, -1, codec_specific); } -EncodedImageCallback::Result FakeVP8Encoder::OnEncodedImage( - const EncodedImage& encoded_image, - const CodecSpecificInfo* codec_specific_info, - const RTPFragmentationHeader* fragments) { +std::unique_ptr FakeVP8Encoder::EncodeHook( + EncodedImage* encoded_image, + CodecSpecificInfo* codec_specific) { RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); - uint8_t stream_idx = encoded_image.SpatialIndex().value_or(0); - CodecSpecificInfo overrided_specific_info; - temporal_layers_[stream_idx]->UpdateLayerConfig(encoded_image.Timestamp()); - PopulateCodecSpecific(&overrided_specific_info, encoded_image.size(), - encoded_image._frameType, stream_idx, - encoded_image.Timestamp()); + uint8_t stream_idx = encoded_image->SpatialIndex().value_or(0); + temporal_layers_[stream_idx]->UpdateLayerConfig(encoded_image->Timestamp()); + PopulateCodecSpecific(codec_specific, encoded_image->size(), + encoded_image->_frameType, stream_idx, + encoded_image->Timestamp()); // Write width and height to the payload the same way as the real encoder // does. - WriteFakeVp8(encoded_image.buffer(), encoded_image._encodedWidth, - encoded_image._encodedHeight, - encoded_image._frameType == kVideoFrameKey); - return callback_->OnEncodedImage(encoded_image, &overrided_specific_info, - fragments); + WriteFakeVp8(encoded_image->data(), encoded_image->_encodedWidth, + encoded_image->_encodedHeight, + encoded_image->_frameType == kVideoFrameKey); + return nullptr; } VideoEncoder::EncoderInfo FakeVP8Encoder::GetEncoderInfo() const { diff --git a/test/fake_vp8_encoder.h b/test/fake_vp8_encoder.h index 590a20474f..9607baf12d 100644 --- a/test/fake_vp8_encoder.h +++ b/test/fake_vp8_encoder.h @@ -31,24 +31,17 @@ namespace webrtc { namespace test { -class FakeVP8Encoder : public FakeEncoder, public EncodedImageCallback { +class FakeVP8Encoder : public FakeEncoder { public: explicit FakeVP8Encoder(Clock* clock); virtual ~FakeVP8Encoder() = default; - int32_t RegisterEncodeCompleteCallback( - EncodedImageCallback* callback) override; - int32_t InitEncode(const VideoCodec* config, int32_t number_of_cores, size_t max_payload_size) override; int32_t Release() override; - Result OnEncodedImage(const EncodedImage& encodedImage, - const CodecSpecificInfo* codecSpecificInfo, - const RTPFragmentationHeader* fragments) override; - EncoderInfo GetEncoderInfo() const override; private: @@ -59,8 +52,11 @@ class FakeVP8Encoder : public FakeEncoder, public EncodedImageCallback { int stream_idx, uint32_t timestamp); + std::unique_ptr EncodeHook( + EncodedImage* encoded_image, + CodecSpecificInfo* codec_specific) override; + rtc::SequencedTaskChecker sequence_checker_; - EncodedImageCallback* callback_ RTC_GUARDED_BY(sequence_checker_); std::vector> temporal_layers_ RTC_GUARDED_BY(sequence_checker_);