Add a clone method to the audio frame transformer API.

This will clone an encoded audio frame into a sender frame.

Bug: webrtc:14949
Change-Id: Ie62d9f5ec457541b335bde8f2f6e9b6d24704cf6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/294560
Commit-Queue: Tove Petersson <tovep@google.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39480}
This commit is contained in:
Tove Petersson 2023-03-05 11:03:06 +00:00 committed by WebRTC LUCI CQ
parent 28db3c6f9f
commit 1e2d951762
8 changed files with 95 additions and 1 deletions

View File

@ -1293,6 +1293,17 @@ if (rtc_include_tests) {
]
}
rtc_source_set("mock_transformable_audio_frame") {
visibility = [ "*" ]
testonly = true
sources = [ "test/mock_transformable_audio_frame.h" ]
deps = [
":frame_transformer_interface",
"../test:test_support",
]
}
rtc_source_set("mock_transformable_video_frame") {
visibility = [ "*" ]
testonly = true
@ -1478,6 +1489,7 @@ if (rtc_include_tests) {
":mock_peerconnectioninterface",
":mock_rtp",
":mock_session_description_interface",
":mock_transformable_audio_frame",
":mock_transformable_video_frame",
":mock_video_bitrate_allocator",
":mock_video_bitrate_allocator_factory",
@ -1548,6 +1560,7 @@ rtc_library("frame_transformer_factory") {
deps = [
":frame_transformer_interface",
":scoped_refptr",
"../audio:audio",
"../modules/rtp_rtcp",
"../rtc_base:refcount",
"video:encoded_frame",

View File

@ -10,6 +10,7 @@
#include "api/frame_transformer_factory.h"
#include "audio/channel_send_frame_transformer_delegate.h"
#include "modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h"
namespace webrtc {
@ -24,6 +25,12 @@ std::unique_ptr<TransformableVideoFrameInterface> CreateVideoReceiverFrame() {
return nullptr;
}
std::unique_ptr<TransformableFrameInterface> CloneAudioFrame(
TransformableAudioFrameInterface* original) {
// At the moment, only making sender frames is supported.
return CloneSenderAudioFrame(original);
}
std::unique_ptr<TransformableVideoFrameInterface> CloneVideoFrame(
TransformableVideoFrameInterface* original) {
// At the moment, only making sender frames from receiver frames is supported.

View File

@ -32,6 +32,8 @@ std::unique_ptr<TransformableVideoFrameInterface> CreateVideoSenderFrame();
std::unique_ptr<TransformableVideoFrameInterface> CreateVideoReceiverFrame();
// Creates a new frame with the same metadata as the original.
// The original can be a sender or receiver frame.
RTC_EXPORT std::unique_ptr<TransformableFrameInterface> CloneAudioFrame(
TransformableAudioFrameInterface* original);
RTC_EXPORT std::unique_ptr<TransformableVideoFrameInterface> CloneVideoFrame(
TransformableVideoFrameInterface* original);
} // namespace webrtc

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 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 API_TEST_MOCK_TRANSFORMABLE_AUDIO_FRAME_H_
#define API_TEST_MOCK_TRANSFORMABLE_AUDIO_FRAME_H_
#include "api/frame_transformer_interface.h"
#include "test/gmock.h"
namespace webrtc {
class MockTransformableAudioFrame : public TransformableAudioFrameInterface {
public:
MOCK_METHOD(rtc::ArrayView<const uint8_t>, GetData, (), (const, override));
MOCK_METHOD(void, SetData, (rtc::ArrayView<const uint8_t>), (override));
MOCK_METHOD(uint8_t, GetPayloadType, (), (const, override));
MOCK_METHOD(uint32_t, GetSsrc, (), (const, override));
MOCK_METHOD(uint32_t, GetTimestamp, (), (const, override));
MOCK_METHOD(RTPHeader&, GetHeader, (), (const override));
MOCK_METHOD(rtc::ArrayView<const uint32_t>,
GetContributingSources,
(),
(const override));
};
} // namespace webrtc
#endif // API_TEST_MOCK_TRANSFORMABLE_AUDIO_FRAME_H_

View File

@ -127,4 +127,19 @@ void ChannelSendFrameTransformerDelegate::SendFrame(
transformed_frame->GetAbsoluteCaptureTimestampMs());
}
std::unique_ptr<TransformableFrameInterface> CloneSenderAudioFrame(
TransformableAudioFrameInterface* original) {
AudioFrameType audio_frame_type =
original->GetHeader().extension.voiceActivity
? AudioFrameType::kAudioFrameSpeech
: AudioFrameType::kAudioFrameCN;
// TODO(crbug.com/webrtc/14949): Ensure the correct timestamps are passed.
return std::make_unique<TransformableOutgoingAudioFrame>(
audio_frame_type, original->GetPayloadType(), original->GetTimestamp(),
/*rtp_start_timestamp=*/0u, original->GetData().data(),
original->GetData().size(), original->GetTimestamp(),
original->GetSsrc());
}
} // namespace webrtc

View File

@ -77,5 +77,9 @@ class ChannelSendFrameTransformerDelegate : public TransformedFrameCallback {
rtc::scoped_refptr<FrameTransformerInterface> frame_transformer_;
rtc::TaskQueue* encoder_queue_ RTC_GUARDED_BY(send_lock_);
};
std::unique_ptr<TransformableFrameInterface> CloneSenderAudioFrame(
TransformableAudioFrameInterface* original);
} // namespace webrtc
#endif // AUDIO_CHANNEL_SEND_FRAME_TRANSFORMER_DELEGATE_H_

View File

@ -709,6 +709,7 @@ if (rtc_include_tests) {
sources = [ "source/frame_transformer_factory_unittest.cc" ]
deps = [
"../../api:frame_transformer_factory",
"../../api:mock_transformable_audio_frame",
"../../api:mock_transformable_video_frame",
"../../api:transport_api",
"../../call:video_stream_api",

View File

@ -17,6 +17,7 @@
#include "absl/memory/memory.h"
#include "api/call/transport.h"
#include "api/test/mock_transformable_audio_frame.h"
#include "api/test/mock_transformable_video_frame.h"
#include "call/video_receive_stream.h"
#include "modules/rtp_rtcp/source/rtp_descriptor_authentication.h"
@ -28,8 +29,24 @@
namespace webrtc {
namespace {
using testing::Each;
using testing::ElementsAreArray;
using testing::NiceMock;
using testing::Return;
using testing::ReturnRef;
TEST(FrameTransformerFactory, CloneAudioFrame) {
NiceMock<MockTransformableAudioFrame> original_frame;
uint8_t data[10];
std::fill_n(data, 10, 5);
rtc::ArrayView<uint8_t> data_view(data);
ON_CALL(original_frame, GetData()).WillByDefault(Return(data_view));
RTPHeader rtp_header;
ON_CALL(original_frame, GetHeader()).WillByDefault(ReturnRef(rtp_header));
auto cloned_frame = CloneAudioFrame(&original_frame);
EXPECT_THAT(cloned_frame->GetData(), ElementsAreArray(data));
}
TEST(FrameTransformerFactory, CloneVideoFrame) {
NiceMock<MockTransformableVideoFrame> original_frame;
@ -46,7 +63,7 @@ TEST(FrameTransformerFactory, CloneVideoFrame) {
auto cloned_frame = CloneVideoFrame(&original_frame);
EXPECT_EQ(cloned_frame->GetData().size(), 10u);
EXPECT_THAT(cloned_frame->GetData(), testing::Each(5u));
EXPECT_THAT(cloned_frame->GetData(), Each(5u));
EXPECT_EQ(cloned_frame->Metadata().GetCsrcs(), csrcs);
}