From 4070935f4fb5b9fb2df246d7073fe0ba7e350791 Mon Sep 17 00:00:00 2001 From: "sprang@webrtc.org" Date: Tue, 26 Nov 2013 11:41:59 +0000 Subject: [PATCH] Implement and test EncodedImageCallback in new ViE API. R=mflodman@webrtc.org, pbos@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/4059004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5179 4adac7df-926f-26a2-2b94-8c16560cd09d --- webrtc/call_tests.cc | 74 +++++++++++++++++++ webrtc/frame_callback.h | 14 +++- .../main/interface/video_coding.h | 6 ++ .../main/source/generic_encoder.cc | 17 ++++- .../main/source/generic_encoder.h | 10 +++ .../main/source/video_coding_impl.cc | 10 +++ .../main/source/video_coding_impl.h | 9 +++ .../main/source/video_receiver.cc | 12 +++ .../video_coding/main/source/video_sender.cc | 6 ++ webrtc/test/fake_encoder.cc | 7 +- .../video/encoded_frame_callback_adapter.cc | 39 ++++++++++ webrtc/video/encoded_frame_callback_adapter.h | 36 +++++++++ webrtc/video/video_receive_stream.cc | 13 +++- webrtc/video/video_receive_stream.h | 2 + webrtc/video/video_send_stream.cc | 6 +- webrtc/video/video_send_stream.h | 2 + webrtc/video/webrtc_video.gypi | 2 + .../video_engine/include/vie_image_process.h | 13 +++- webrtc/video_engine/vie_channel.cc | 6 ++ webrtc/video_engine/vie_channel.h | 5 +- webrtc/video_engine/vie_encoder.cc | 11 +++ webrtc/video_engine/vie_encoder.h | 7 +- webrtc/video_engine/vie_image_process_impl.cc | 30 ++++++++ webrtc/video_engine/vie_image_process_impl.h | 10 +++ webrtc/video_send_stream.h | 4 +- 25 files changed, 337 insertions(+), 14 deletions(-) create mode 100644 webrtc/video/encoded_frame_callback_adapter.cc create mode 100644 webrtc/video/encoded_frame_callback_adapter.h diff --git a/webrtc/call_tests.cc b/webrtc/call_tests.cc index 773886d77..539328617 100644 --- a/webrtc/call_tests.cc +++ b/webrtc/call_tests.cc @@ -18,6 +18,7 @@ #include "webrtc/call.h" #include "webrtc/common_video/test/frame_generator.h" +#include "webrtc/frame_callback.h" #include "webrtc/modules/remote_bitrate_estimator/include/rtp_to_ntp.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" @@ -1040,4 +1041,77 @@ TEST_F(CallTest, PlaysOutAudioAndVideoInSync) { VoiceEngine::Delete(voice_engine); } +TEST_F(CallTest, ObserversEncodedFrames) { + class EncodedFrameTestObserver : public EncodedFrameObserver { + public: + EncodedFrameTestObserver() : length_(0), + frame_type_(kFrameEmpty), + called_(EventWrapper::Create()) {} + virtual ~EncodedFrameTestObserver() {} + + virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) { + frame_type_ = encoded_frame.frame_type_; + length_ = encoded_frame.length_; + buffer_.reset(new uint8_t[length_]); + memcpy(buffer_.get(), encoded_frame.data_, length_); + called_->Set(); + } + + EventTypeWrapper Wait() { + return called_->Wait(kDefaultTimeoutMs); + } + + void ExpectEqualFrames(const EncodedFrameTestObserver& observer) { + ASSERT_EQ(length_, observer.length_) + << "Observed frames are of different lengths."; + EXPECT_EQ(frame_type_, observer.frame_type_) + << "Observed frames have different frame types."; + EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_)) + << "Observed encoded frames have different content."; + } + + private: + scoped_ptr buffer_; + size_t length_; + FrameType frame_type_; + scoped_ptr called_; + }; + + EncodedFrameTestObserver post_encode_observer; + EncodedFrameTestObserver pre_decode_observer; + + test::DirectTransport sender_transport, receiver_transport; + + CreateCalls(Call::Config(&sender_transport), + Call::Config(&receiver_transport)); + + sender_transport.SetReceiver(receiver_call_->Receiver()); + receiver_transport.SetReceiver(sender_call_->Receiver()); + + CreateTestConfigs(); + send_config_.post_encode_callback = &post_encode_observer; + receive_config_.pre_decode_callback = &pre_decode_observer; + + CreateStreams(); + StartSending(); + + scoped_ptr frame_generator(test::FrameGenerator::Create( + send_config_.codec.width, send_config_.codec.height)); + send_stream_->Input()->PutFrame(frame_generator->NextFrame(), 0); + + EXPECT_EQ(kEventSignaled, post_encode_observer.Wait()) + << "Timed out while waiting for send-side encoded-frame callback."; + + EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait()) + << "Timed out while waiting for pre-decode encoded-frame callback."; + + post_encode_observer.ExpectEqualFrames(pre_decode_observer); + + StopSending(); + + sender_transport.StopSending(); + receiver_transport.StopSending(); + + DestroyStreams(); +} } // namespace webrtc diff --git a/webrtc/frame_callback.h b/webrtc/frame_callback.h index 7f542450a..cfb07d8b1 100644 --- a/webrtc/frame_callback.h +++ b/webrtc/frame_callback.h @@ -11,11 +11,22 @@ #ifndef WEBRTC_VIDEO_ENGINE_NEW_INCLUDE_FRAME_CALLBACK_H_ #define WEBRTC_VIDEO_ENGINE_NEW_INCLUDE_FRAME_CALLBACK_H_ +#include "webrtc/common_types.h" + namespace webrtc { class I420VideoFrame; -struct EncodedFrame; +struct EncodedFrame { + public: + EncodedFrame() : data_(NULL), length_(0), frame_type_(kFrameEmpty) {} + EncodedFrame(const uint8_t* data, size_t length, FrameType frame_type) + : data_(data), length_(length), frame_type_(frame_type) {} + + const uint8_t* data_; + const size_t length_; + const FrameType frame_type_; +}; class I420FrameCallback { public: @@ -34,6 +45,7 @@ class EncodedFrameObserver { protected: virtual ~EncodedFrameObserver() {} }; + } // namespace webrtc #endif // WEBRTC_VIDEO_ENGINE_NEW_INCLUDE_FRAME_CALLBACK_H_ diff --git a/webrtc/modules/video_coding/main/interface/video_coding.h b/webrtc/modules/video_coding/main/interface/video_coding.h index 9fb98c365..c0166761e 100644 --- a/webrtc/modules/video_coding/main/interface/video_coding.h +++ b/webrtc/modules/video_coding/main/interface/video_coding.h @@ -21,6 +21,7 @@ namespace webrtc { class Clock; +class EncodedImageCallback; class VideoEncoder; class VideoDecoder; struct CodecSpecificInfo; @@ -600,6 +601,11 @@ public: // Returns true if SuspendBelowMinBitrate is engaged and the video has been // suspended due to bandwidth limitations; otherwise false. virtual bool VideoSuspended() const = 0; + + virtual void RegisterPreDecodeImageCallback( + EncodedImageCallback* observer) = 0; + virtual void RegisterPostEncodeImageCallback( + EncodedImageCallback* post_encode_callback) = 0; }; } // namespace webrtc diff --git a/webrtc/modules/video_coding/main/source/generic_encoder.cc b/webrtc/modules/video_coding/main/source/generic_encoder.cc index c6ab9fbfb..064470b16 100644 --- a/webrtc/modules/video_coding/main/source/generic_encoder.cc +++ b/webrtc/modules/video_coding/main/source/generic_encoder.cc @@ -12,6 +12,7 @@ #include "webrtc/modules/video_coding/main/source/encoded_frame.h" #include "webrtc/modules/video_coding/main/source/generic_encoder.h" #include "webrtc/modules/video_coding/main/source/media_optimization.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" namespace webrtc { @@ -147,7 +148,9 @@ _mediaOpt(NULL), _encodedBytes(0), _payloadType(0), _codecType(kVideoCodecUnknown), -_internalSource(false) +_internalSource(false), +post_encode_callback_lock_(CriticalSectionWrapper::CreateCriticalSection()), +post_encode_callback_(NULL) #ifdef DEBUG_ENCODER_BIT_STREAM , _bitStreamAfterEncoder(NULL) #endif @@ -177,6 +180,12 @@ VCMEncodedFrameCallback::Encoded( const CodecSpecificInfo* codecSpecificInfo, const RTPFragmentationHeader* fragmentationHeader) { + { + CriticalSectionScoped cs(post_encode_callback_lock_.get()); + if (post_encode_callback_) { + post_encode_callback_->Encoded(encodedImage); + } + } FrameType frameType = VCMEncodedFrame::ConvertFrameType(encodedImage._frameType); uint32_t encodedBytes = 0; @@ -271,4 +280,10 @@ void VCMEncodedFrameCallback::CopyCodecSpecific(const CodecSpecificInfo& info, return; } } + +void VCMEncodedFrameCallback::RegisterPostEncodeImageCallback( + EncodedImageCallback* callback) { + CriticalSectionScoped cs(post_encode_callback_lock_.get()); + post_encode_callback_ = callback; +} } // namespace webrtc diff --git a/webrtc/modules/video_coding/main/source/generic_encoder.h b/webrtc/modules/video_coding/main/source/generic_encoder.h index 0c2d287a9..c5cfeabc2 100644 --- a/webrtc/modules/video_coding/main/source/generic_encoder.h +++ b/webrtc/modules/video_coding/main/source/generic_encoder.h @@ -15,9 +15,13 @@ #include +#include "webrtc/system_wrappers/interface/scoped_ptr.h" + namespace webrtc { +class CriticalSectionWrapper; + namespace media_optimization { class MediaOptimization; } // namespace media_optimization @@ -55,6 +59,8 @@ public: void SetCodecType(VideoCodecType codecType) {_codecType = codecType;}; void SetInternalSource(bool internalSource) { _internalSource = internalSource; }; + void RegisterPostEncodeImageCallback(EncodedImageCallback* callback); + private: /* * Map information from info into rtp. If no relevant information is found @@ -69,6 +75,10 @@ private: uint8_t _payloadType; VideoCodecType _codecType; bool _internalSource; + + scoped_ptr post_encode_callback_lock_; + EncodedImageCallback* post_encode_callback_; + #ifdef DEBUG_ENCODER_BIT_STREAM FILE* _bitStreamAfterEncoder; #endif diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.cc b/webrtc/modules/video_coding/main/source/video_coding_impl.cc index 8282edc44..1decc2f11 100644 --- a/webrtc/modules/video_coding/main/source/video_coding_impl.cc +++ b/webrtc/modules/video_coding/main/source/video_coding_impl.cc @@ -319,6 +319,16 @@ class VideoCodingModuleImpl : public VideoCodingModule { return receiver_->SetReceiveChannelParameters(rtt); } + virtual void RegisterPreDecodeImageCallback( + EncodedImageCallback* observer) OVERRIDE { + receiver_->RegisterPreDecodeImageCallback(observer); + } + + virtual void RegisterPostEncodeImageCallback( + EncodedImageCallback* observer) OVERRIDE { + sender_->RegisterPostEncodeImageCallback(observer); + } + private: scoped_ptr sender_; scoped_ptr receiver_; diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.h b/webrtc/modules/video_coding/main/source/video_coding_impl.h index c1d02d94e..d9564c04b 100644 --- a/webrtc/modules/video_coding/main/source/video_coding_impl.h +++ b/webrtc/modules/video_coding/main/source/video_coding_impl.h @@ -27,6 +27,9 @@ #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" namespace webrtc { + +class EncodedFrameObserver; + namespace vcm { class VCMProcessTimer { @@ -98,6 +101,9 @@ class VideoSender { void SuspendBelowMinBitrate(); bool VideoSuspended() const; + void RegisterPostEncodeImageCallback( + EncodedImageCallback* post_encode_callback); + int32_t TimeUntilNextProcess(); int32_t Process(); @@ -173,6 +179,8 @@ class VideoReceiver { int32_t TimeUntilNextProcess(); int32_t Process(); + void RegisterPreDecodeImageCallback(EncodedImageCallback* observer); + protected: int32_t Decode(const webrtc::VCMEncodedFrame& frame); int32_t RequestKeyFrame(); @@ -213,6 +221,7 @@ class VideoReceiver { VCMKeyRequestMode _keyRequestMode; bool _scheduleKeyRequest; size_t max_nack_list_size_; + EncodedImageCallback* pre_decode_image_callback_; VCMCodecDataBase _codecDataBase; VCMProcessTimer _receiveStatsTimer; diff --git a/webrtc/modules/video_coding/main/source/video_receiver.cc b/webrtc/modules/video_coding/main/source/video_receiver.cc index cea8b448d..68668eae7 100644 --- a/webrtc/modules/video_coding/main/source/video_receiver.cc +++ b/webrtc/modules/video_coding/main/source/video_receiver.cc @@ -52,6 +52,7 @@ VideoReceiver::VideoReceiver(const int32_t id, _keyRequestMode(kKeyOnError), _scheduleKeyRequest(false), max_nack_list_size_(0), + pre_decode_image_callback_(NULL), _codecDataBase(id), _receiveStatsTimer(1000, clock_), _retransmissionTimer(10, clock_), @@ -400,6 +401,11 @@ int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { _timing.UpdateCurrentDelay(frame->RenderTimeMs(), clock_->TimeInMilliseconds()); + if (pre_decode_image_callback_) { + EncodedImage encoded_image(frame->EncodedImage()); + pre_decode_image_callback_->Encoded(encoded_image); + } + #ifdef DEBUG_DECODER_BIT_STREAM if (_bitStreamBeforeDecoder != NULL) { // Write bit stream to file for debugging purposes @@ -815,5 +821,11 @@ int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) { return _receiver.SetMinReceiverDelay(desired_delay_ms); } +void VideoReceiver::RegisterPreDecodeImageCallback( + EncodedImageCallback* observer) { + CriticalSectionScoped cs(_receiveCritSect); + pre_decode_image_callback_ = observer; +} + } // namespace vcm } // namespace webrtc diff --git a/webrtc/modules/video_coding/main/source/video_sender.cc b/webrtc/modules/video_coding/main/source/video_sender.cc index 5a9a56303..948218b83 100644 --- a/webrtc/modules/video_coding/main/source/video_sender.cc +++ b/webrtc/modules/video_coding/main/source/video_sender.cc @@ -446,5 +446,11 @@ bool VideoSender::VideoSuspended() const { return _mediaOpt.video_suspended(); } +void VideoSender::RegisterPostEncodeImageCallback( + EncodedImageCallback* observer) { + CriticalSectionScoped cs(_sendCritSect); + _encodedFrameCallback.RegisterPostEncodeImageCallback(observer); +} + } // namespace vcm } // namespace webrtc diff --git a/webrtc/test/fake_encoder.cc b/webrtc/test/fake_encoder.cc index eec75bef5..f4e5227ed 100644 --- a/webrtc/test/fake_encoder.cc +++ b/webrtc/test/fake_encoder.cc @@ -20,13 +20,16 @@ FakeEncoder::FakeEncoder(Clock* clock) callback_(NULL), target_bitrate_kbps_(0), last_encode_time_ms_(0) { - memset(encoded_buffer_, 0, sizeof(encoded_buffer_)); + // Generate some arbitrary not-all-zero data + for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) { + encoded_buffer_[i] = static_cast(i); + } } FakeEncoder::~FakeEncoder() {} void FakeEncoder::SetCodecSettings(VideoCodec* codec, - size_t num_streams) { + size_t num_streams) { assert(num_streams > 0); assert(num_streams <= kMaxSimulcastStreams); diff --git a/webrtc/video/encoded_frame_callback_adapter.cc b/webrtc/video/encoded_frame_callback_adapter.cc new file mode 100644 index 000000000..f5eca7ce4 --- /dev/null +++ b/webrtc/video/encoded_frame_callback_adapter.cc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 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 "webrtc/video/encoded_frame_callback_adapter.h" + +#include "webrtc/modules/video_coding/main/source/encoded_frame.h" + +namespace webrtc { +namespace internal { + +EncodedFrameCallbackAdapter::EncodedFrameCallbackAdapter( + EncodedFrameObserver* observer) : observer_(observer) { +} + +EncodedFrameCallbackAdapter::~EncodedFrameCallbackAdapter() {} + +int32_t EncodedFrameCallbackAdapter::Encoded( + EncodedImage& encodedImage, + const CodecSpecificInfo* codecSpecificInfo, + const RTPFragmentationHeader* fragmentation) { + assert(observer_ != NULL); + FrameType frame_type = + VCMEncodedFrame::ConvertFrameType(encodedImage._frameType); + const EncodedFrame frame(encodedImage._buffer, + encodedImage._length, + frame_type); + observer_->EncodedFrameCallback(frame); + return 0; +} + +} // namespace internal +} // namespace webrtc diff --git a/webrtc/video/encoded_frame_callback_adapter.h b/webrtc/video/encoded_frame_callback_adapter.h new file mode 100644 index 000000000..d3814797a --- /dev/null +++ b/webrtc/video/encoded_frame_callback_adapter.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 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 WEBRTC_VIDEO_ENCODED_FRAME_CALLBACK_ADAPTER_H_ +#define WEBRTC_VIDEO_ENCODED_FRAME_CALLBACK_ADAPTER_H_ + +#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" +#include "webrtc/frame_callback.h" + +namespace webrtc { +namespace internal { + +class EncodedFrameCallbackAdapter : public EncodedImageCallback { + public: + explicit EncodedFrameCallbackAdapter(EncodedFrameObserver* observer); + virtual ~EncodedFrameCallbackAdapter(); + + virtual int32_t Encoded(EncodedImage& encodedImage, + const CodecSpecificInfo* codecSpecificInfo, + const RTPFragmentationHeader* fragmentation); + + private: + EncodedFrameObserver* observer_; +}; + +} // namespace internal +} // namespace webrtc + +#endif // WEBRTC_VIDEO_ENCODED_FRAME_CALLBACK_ADAPTER_H_ diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index d88937941..515723762 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -32,7 +32,10 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, const VideoReceiveStream::Config& config, newapi::Transport* transport, webrtc::VoiceEngine* voice_engine) - : transport_adapter_(transport), config_(config), channel_(-1) { + : transport_adapter_(transport), + encoded_frame_proxy_(config.pre_decode_callback), + config_(config), + channel_(-1) { video_engine_base_ = ViEBase::GetInterface(video_engine); // TODO(mflodman): Use the other CreateChannel method. video_engine_base_->CreateChannel(channel_); @@ -96,6 +99,10 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, } image_process_ = ViEImageProcess::GetInterface(video_engine); + if (config.pre_decode_callback) { + image_process_->RegisterPreDecodeImageCallback(channel_, + &encoded_frame_proxy_); + } image_process_->RegisterPreRenderCallback(channel_, config_.pre_render_callback); @@ -103,7 +110,8 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, } VideoReceiveStream::~VideoReceiveStream() { - image_process_->DeRegisterPreEncodeCallback(channel_); + image_process_->DeRegisterPreRenderCallback(channel_); + image_process_->DeRegisterPreDecodeCallback(channel_); render_->RemoveRenderer(channel_); @@ -161,6 +169,5 @@ int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id, video_frame, video_frame.render_time_ms() - clock_->TimeInMilliseconds()); return 0; } - } // internal } // webrtc diff --git a/webrtc/video/video_receive_stream.h b/webrtc/video/video_receive_stream.h index bf6f9db79..8a23a10e1 100644 --- a/webrtc/video/video_receive_stream.h +++ b/webrtc/video/video_receive_stream.h @@ -16,6 +16,7 @@ #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/modules/video_render/include/video_render_defines.h" #include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/video/encoded_frame_callback_adapter.h" #include "webrtc/video/transport_adapter.h" #include "webrtc/video_engine/include/vie_render.h" #include "webrtc/video_receive_stream.h" @@ -57,6 +58,7 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, private: TransportAdapter transport_adapter_; + EncodedFrameCallbackAdapter encoded_frame_proxy_; VideoReceiveStream::Config config_; Clock* clock_; diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc index 5b8c23c8c..b5fec72d9 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -83,6 +83,7 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, webrtc::VideoEngine* video_engine, const VideoSendStream::Config& config) : transport_adapter_(transport), + encoded_frame_proxy_(config.post_encode_callback), codec_lock_(CriticalSectionWrapper::CreateCriticalSection()), config_(config), external_codec_(NULL) { @@ -199,6 +200,10 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, image_process_ = ViEImageProcess::GetInterface(video_engine); image_process_->RegisterPreEncodeCallback(channel_, config_.pre_encode_callback); + if (config_.post_encode_callback) { + image_process_->RegisterPostEncodeImageCallback(channel_, + &encoded_frame_proxy_); + } if (config.suspend_below_min_bitrate) { codec_->SuspendBelowMinBitrate(channel_); @@ -294,6 +299,5 @@ bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { return network_->ReceivedRTCPPacket( channel_, packet, static_cast(length)) == 0; } - } // namespace internal } // namespace webrtc diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h index d0da69f4d..0881d9181 100644 --- a/webrtc/video/video_send_stream.h +++ b/webrtc/video/video_send_stream.h @@ -14,6 +14,7 @@ #include #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" +#include "webrtc/video/encoded_frame_callback_adapter.h" #include "webrtc/video/transport_adapter.h" #include "webrtc/video_receive_stream.h" #include "webrtc/video_send_stream.h" @@ -62,6 +63,7 @@ class VideoSendStream : public webrtc::VideoSendStream, private: TransportAdapter transport_adapter_; + EncodedFrameCallbackAdapter encoded_frame_proxy_; scoped_ptr codec_lock_; VideoSendStream::Config config_; diff --git a/webrtc/video/webrtc_video.gypi b/webrtc/video/webrtc_video.gypi index e26db0b98..82e17f461 100644 --- a/webrtc/video/webrtc_video.gypi +++ b/webrtc/video/webrtc_video.gypi @@ -11,6 +11,8 @@ '<(webrtc_root)/video_engine/video_engine.gyp:video_engine_core', ], 'webrtc_video_sources': [ + 'video/encoded_frame_callback_adapter.cc', + 'video/encoded_frame_callback_adapter.h', 'video/transport_adapter.cc', 'video/transport_adapter.h', 'video/video_receive_stream.cc', diff --git a/webrtc/video_engine/include/vie_image_process.h b/webrtc/video_engine/include/vie_image_process.h index 9a12748e2..5006eda20 100644 --- a/webrtc/video_engine/include/vie_image_process.h +++ b/webrtc/video_engine/include/vie_image_process.h @@ -18,12 +18,11 @@ #define WEBRTC_VIDEO_ENGINE_INCLUDE_VIE_IMAGE_PROCESS_H_ #include "webrtc/common_types.h" -#include "webrtc/common_video/interface/i420_video_frame.h" namespace webrtc { +class EncodedImageCallback; class I420FrameCallback; - class VideoEngine; // This class declares an abstract interface for a user defined effect filter. @@ -98,6 +97,16 @@ class WEBRTC_DLLEXPORT ViEImageProcess { I420FrameCallback* pre_encode_callback) = 0; virtual void DeRegisterPreEncodeCallback(int video_channel) = 0; + virtual void RegisterPostEncodeImageCallback( + int video_channel, + EncodedImageCallback* post_encode_callback) = 0; + virtual void DeRegisterPostEncodeCallback(int video_channel) {} + + virtual void RegisterPreDecodeImageCallback( + int video_channel, + EncodedImageCallback* pre_decode_callback) = 0; + virtual void DeRegisterPreDecodeCallback(int video_channel) {} + virtual void RegisterPreRenderCallback( int video_channel, I420FrameCallback* pre_render_callback) = 0; diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index aa86673c9..4a85a1858 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -1870,6 +1870,12 @@ void ViEChannel::RegisterPreRenderCallback( pre_render_callback_ = pre_render_callback; } +void ViEChannel::RegisterPreDecodeImageCallback( + EncodedImageCallback* pre_decode_callback) { + CriticalSectionScoped cs(callback_cs_.get()); + vcm_.RegisterPreDecodeImageCallback(pre_decode_callback); +} + void ViEChannel::OnApplicationDataReceived(const int32_t id, const uint8_t sub_type, const uint32_t name, diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h index 3b3714050..f6bc3fc83 100644 --- a/webrtc/video_engine/vie_channel.h +++ b/webrtc/video_engine/vie_channel.h @@ -33,6 +33,7 @@ class CallStatsObserver; class ChannelStatsObserver; class Config; class CriticalSectionWrapper; +class EncodedImageCallback; class Encryption; class I420FrameCallback; class PacedSender; @@ -320,8 +321,10 @@ class ViEChannel int32_t RegisterEffectFilter(ViEEffectFilter* effect_filter); - // New-style callback, used by VideoReceiveStream. + // New-style callbacks, used by VideoReceiveStream. void RegisterPreRenderCallback(I420FrameCallback* pre_render_callback); + void RegisterPreDecodeImageCallback( + EncodedImageCallback* pre_decode_callback); protected: static bool ChannelDecodeThreadFunction(void* obj); diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc index 9733a8984..ce13b1a67 100644 --- a/webrtc/video_engine/vie_encoder.cc +++ b/webrtc/video_engine/vie_encoder.cc @@ -14,6 +14,7 @@ #include +#include "webrtc/common_video/interface/video_image.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/modules/pacing/include/paced_sender.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" @@ -21,6 +22,7 @@ #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" #include "webrtc/modules/video_coding/main/interface/video_coding.h" #include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" +#include "webrtc/modules/video_coding/main/source/encoded_frame.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/system_wrappers/interface/tick_util.h" @@ -1183,6 +1185,15 @@ void ViEEncoder::DeRegisterPreEncodeCallback() { pre_encode_callback_ = NULL; } +void ViEEncoder::RegisterPostEncodeImageCallback( + EncodedImageCallback* post_encode_callback) { + vcm_.RegisterPostEncodeImageCallback(post_encode_callback); +} + +void ViEEncoder::DeRegisterPostEncodeImageCallback() { + vcm_.RegisterPostEncodeImageCallback(NULL); +} + QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm) : vpm_(vpm) { } diff --git a/webrtc/video_engine/vie_encoder.h b/webrtc/video_engine/vie_encoder.h index 73f84af7f..cd8328e82 100644 --- a/webrtc/video_engine/vie_encoder.h +++ b/webrtc/video_engine/vie_encoder.h @@ -29,6 +29,7 @@ namespace webrtc { class Config; class CriticalSectionWrapper; +class EncodedImageCallback; class PacedSender; class ProcessThread; class QMVideoSettingsCallback; @@ -168,11 +169,15 @@ class ViEEncoder // |threshold_bps| + |window_bps|. virtual void SuspendBelowMinBitrate(); - // New-style callback, used by VideoSendStream. + // New-style callbacks, used by VideoSendStream. void RegisterPreEncodeCallback(I420FrameCallback* pre_encode_callback); void DeRegisterPreEncodeCallback(); + void RegisterPostEncodeImageCallback( + EncodedImageCallback* post_encode_callback); + void DeRegisterPostEncodeImageCallback(); int channel_id() const { return channel_id_; } + protected: // Called by BitrateObserver. void OnNetworkChanged(const uint32_t bitrate_bps, diff --git a/webrtc/video_engine/vie_image_process_impl.cc b/webrtc/video_engine/vie_image_process_impl.cc index 92fe69762..b10e774a3 100644 --- a/webrtc/video_engine/vie_image_process_impl.cc +++ b/webrtc/video_engine/vie_image_process_impl.cc @@ -284,6 +284,36 @@ void ViEImageProcessImpl::DeRegisterPreEncodeCallback(int video_channel) { vie_encoder->DeRegisterPreEncodeCallback(); } +void ViEImageProcessImpl::RegisterPostEncodeImageCallback( + int video_channel, + EncodedImageCallback* post_encode_callback) { + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEEncoder* vie_encoder = cs.Encoder(video_channel); + assert(vie_encoder != NULL); + vie_encoder->RegisterPostEncodeImageCallback(post_encode_callback); +} + +void ViEImageProcessImpl::DeRegisterPostEncodeCallback(int video_channel) { + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEEncoder* vie_encoder = cs.Encoder(video_channel); + assert(vie_encoder != NULL); + vie_encoder->DeRegisterPostEncodeImageCallback(); +} + +void ViEImageProcessImpl::RegisterPreDecodeImageCallback( + int video_channel, + EncodedImageCallback* pre_decode_callback) { + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* channel = cs.Channel(video_channel); + channel->RegisterPreDecodeImageCallback(pre_decode_callback); +} + +void ViEImageProcessImpl::DeRegisterPreDecodeCallback(int video_channel) { + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* channel = cs.Channel(video_channel); + channel->RegisterPreDecodeImageCallback(NULL); +} + void ViEImageProcessImpl::RegisterPreRenderCallback( int video_channel, I420FrameCallback* pre_render_callback) { diff --git a/webrtc/video_engine/vie_image_process_impl.h b/webrtc/video_engine/vie_image_process_impl.h index 9b43e7ed0..74a7ff037 100644 --- a/webrtc/video_engine/vie_image_process_impl.h +++ b/webrtc/video_engine/vie_image_process_impl.h @@ -43,6 +43,16 @@ class ViEImageProcessImpl I420FrameCallback* pre_encode_callback) OVERRIDE; virtual void DeRegisterPreEncodeCallback(int video_channel) OVERRIDE; + virtual void RegisterPostEncodeImageCallback( + int video_channel, + EncodedImageCallback* post_encode_callback) OVERRIDE; + virtual void DeRegisterPostEncodeCallback(int video_channel) OVERRIDE; + + virtual void RegisterPreDecodeImageCallback( + int video_channel, + EncodedImageCallback* post_encode_callback) OVERRIDE; + virtual void DeRegisterPreDecodeCallback(int video_channel) OVERRIDE; + virtual void RegisterPreRenderCallback( int video_channel, I420FrameCallback* pre_render_callback) OVERRIDE; diff --git a/webrtc/video_send_stream.h b/webrtc/video_send_stream.h index 85d7519cc..2358042e5 100644 --- a/webrtc/video_send_stream.h +++ b/webrtc/video_send_stream.h @@ -71,7 +71,7 @@ class VideoSendStream { struct Config { Config() : pre_encode_callback(NULL), - encoded_callback(NULL), + post_encode_callback(NULL), local_renderer(NULL), render_delay_ms(0), encoder(NULL), @@ -113,7 +113,7 @@ class VideoSendStream { // Called for each encoded frame, e.g. used for file storage. 'NULL' // disables the callback. - EncodedFrameObserver* encoded_callback; + EncodedFrameObserver* post_encode_callback; // Renderer for local preview. The local renderer will be called even if // sending hasn't started. 'NULL' disables local rendering.