From d29d4e9c08f50e470eaa239957c5859996856d0c Mon Sep 17 00:00:00 2001 From: "pbos@webrtc.org" Date: Wed, 20 Nov 2013 13:19:54 +0000 Subject: [PATCH] Deliver I420VideoFrames from VideoRender module. Performance issue and simplicity, this implementation skips conversion to VideoEngine's frame format and then back again to I420VideoFrame. BUG=2526 R=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/3989004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5140 4adac7df-926f-26a2-2b94-8c16560cd09d --- webrtc/video/video_receive_stream.cc | 55 +++++------------------- webrtc/video/video_receive_stream.h | 15 ++----- webrtc/video_engine/include/vie_render.h | 8 ++++ webrtc/video_engine/vie_render_impl.cc | 31 +++++++++++++ webrtc/video_engine/vie_render_impl.h | 3 ++ webrtc/video_engine/vie_renderer.cc | 5 +++ webrtc/video_engine/vie_renderer.h | 3 ++ 7 files changed, 65 insertions(+), 55 deletions(-) diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index 26a760afac..d88937941b 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -85,10 +85,10 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, } } - render_ = webrtc::ViERender::GetInterface(video_engine); + render_ = ViERender::GetInterface(video_engine); assert(render_ != NULL); - render_->AddRenderer(channel_, kVideoI420, this); + render_->AddRenderCallback(channel_, this); if (voice_engine) { video_engine_base_->SetVoiceEngine(voice_engine); @@ -125,21 +125,17 @@ VideoReceiveStream::~VideoReceiveStream() { } void VideoReceiveStream::StartReceiving() { - if (render_->StartRender(channel_)) { + if (render_->StartRender(channel_) != 0) abort(); - } - if (video_engine_base_->StartReceive(channel_) != 0) { + if (video_engine_base_->StartReceive(channel_) != 0) abort(); - } } void VideoReceiveStream::StopReceiving() { - if (render_->StopRender(channel_)) { + if (render_->StopRender(channel_) != 0) abort(); - } - if (video_engine_base_->StopReceive(channel_) != 0) { + if (video_engine_base_->StopReceive(channel_) != 0) abort(); - } } void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) { @@ -156,44 +152,15 @@ bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) { channel_, packet, static_cast(length)) == 0; } -int VideoReceiveStream::FrameSizeChange(unsigned int width, - unsigned int height, - unsigned int /*number_of_streams*/) { - width_ = width; - height_ = height; - return 0; -} - -int VideoReceiveStream::DeliverFrame(uint8_t* frame, - int buffer_size, - uint32_t timestamp, - int64_t render_time, - void* /*handle*/) { - if (config_.renderer == NULL) { +int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id, + I420VideoFrame& video_frame) { + if (config_.renderer == NULL) return 0; - } - - I420VideoFrame video_frame; - video_frame.CreateEmptyFrame(width_, height_, width_, height_, height_); - ConvertToI420(kI420, - frame, - 0, - 0, - width_, - height_, - buffer_size, - webrtc::kRotateNone, - &video_frame); - video_frame.set_timestamp(timestamp); - video_frame.set_render_time_ms(render_time); - - config_.renderer->RenderFrame(video_frame, - render_time - clock_->TimeInMilliseconds()); + config_.renderer->RenderFrame( + video_frame, video_frame.render_time_ms() - clock_->TimeInMilliseconds()); return 0; } -bool VideoReceiveStream::IsTextureSupported() { return false; } - } // internal } // webrtc diff --git a/webrtc/video/video_receive_stream.h b/webrtc/video/video_receive_stream.h index da4a9a6935..bf6f9db79c 100644 --- a/webrtc/video/video_receive_stream.h +++ b/webrtc/video/video_receive_stream.h @@ -14,6 +14,7 @@ #include #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/transport_adapter.h" #include "webrtc/video_engine/include/vie_render.h" @@ -34,7 +35,7 @@ class VoiceEngine; namespace internal { class VideoReceiveStream : public webrtc::VideoReceiveStream, - public webrtc::ExternalRenderer { + public VideoRenderCallback { public: VideoReceiveStream(webrtc::VideoEngine* video_engine, const VideoReceiveStream::Config& config, @@ -47,12 +48,8 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, virtual void GetCurrentReceiveCodec(VideoCodec* receive_codec) OVERRIDE; - virtual int FrameSizeChange(unsigned int width, unsigned int height, - unsigned int /*number_of_streams*/) OVERRIDE; - virtual int DeliverFrame(uint8_t* frame, int buffer_size, uint32_t timestamp, - int64_t render_time, void* /*handle*/) OVERRIDE; - - virtual bool IsTextureSupported() OVERRIDE; + virtual int32_t RenderFrame(const uint32_t stream_id, + I420VideoFrame& video_frame) OVERRIDE; public: virtual bool DeliverRtcp(const uint8_t* packet, size_t length); @@ -72,10 +69,6 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, ViEImageProcess* image_process_; int channel_; - - // TODO(pbos): Remove VideoReceiveStream can operate on I420 frames directly. - unsigned int height_; - unsigned int width_; }; } // internal } // webrtc diff --git a/webrtc/video_engine/include/vie_render.h b/webrtc/video_engine/include/vie_render.h index 48afc1adbb..ab7cc6c380 100644 --- a/webrtc/video_engine/include/vie_render.h +++ b/webrtc/video_engine/include/vie_render.h @@ -22,6 +22,7 @@ namespace webrtc { class VideoEngine; class VideoRender; +class VideoRenderCallback; // This class declares an abstract interface to be used for external renderers. // The user implemented derived class is registered using AddRenderer(). @@ -111,6 +112,13 @@ class WEBRTC_DLLEXPORT ViERender { RawVideoType video_input_format, ExternalRenderer* renderer) = 0; + // Propagating VideoRenderCallback down to the VideoRender module for new API. + // Contains default-implementation not to break code mocking this interface. + // (Ugly, but temporary.) + virtual int AddRenderCallback(int render_id, VideoRenderCallback* callback) { + return 0; + } + protected: ViERender() {} virtual ~ViERender() {} diff --git a/webrtc/video_engine/vie_render_impl.cc b/webrtc/video_engine/vie_render_impl.cc index 507e05ae35..b7b7c94cde 100644 --- a/webrtc/video_engine/vie_render_impl.cc +++ b/webrtc/video_engine/vie_render_impl.cc @@ -394,4 +394,35 @@ int ViERenderImpl::AddRenderer(const int render_id, } } +int ViERenderImpl::AddRenderCallback(int render_id, + VideoRenderCallback* callback) { + if (render_id < kViEChannelIdBase || render_id > kViEChannelIdMax) + return -1; + // This is a channel. + ViEChannelManagerScoped cm(*(shared_data_->channel_manager())); + ViEFrameProviderBase* frame_provider = cm.Channel(render_id); + if (!frame_provider) { + WEBRTC_TRACE(kTraceError, + kTraceVideo, + ViEId(shared_data_->instance_id()), + "%s: FrameProvider id %d doesn't exist", + __FUNCTION__, + render_id); + shared_data_->SetLastError(kViERenderInvalidRenderId); + return -1; + } + ViERenderer* renderer = shared_data_->render_manager()->AddRenderStream( + render_id, NULL, 0, 0.0f, 0.0f, 1.0f, 1.0f); + if (!renderer) { + shared_data_->SetLastError(kViERenderUnknownError); + return -1; + } + if (renderer->SetVideoRenderCallback(render_id, callback) != 0) { + shared_data_->SetLastError(kViERenderUnknownError); + return -1; + } + + return frame_provider->RegisterFrameCallback(render_id, renderer); +} + } // namespace webrtc diff --git a/webrtc/video_engine/vie_render_impl.h b/webrtc/video_engine/vie_render_impl.h index c41979407d..e8f1587a83 100644 --- a/webrtc/video_engine/vie_render_impl.h +++ b/webrtc/video_engine/vie_render_impl.h @@ -46,6 +46,9 @@ class ViERenderImpl virtual int AddRenderer(const int render_id, RawVideoType video_input_format, ExternalRenderer* renderer); + virtual int AddRenderCallback(int render_id, + VideoRenderCallback* callback) OVERRIDE; + protected: explicit ViERenderImpl(ViESharedData* shared_data); virtual ~ViERenderImpl(); diff --git a/webrtc/video_engine/vie_renderer.cc b/webrtc/video_engine/vie_renderer.cc index 35c68aa933..e18ebe9898 100644 --- a/webrtc/video_engine/vie_renderer.cc +++ b/webrtc/video_engine/vie_renderer.cc @@ -104,6 +104,11 @@ int32_t ViERenderer::SetExternalRenderer( incoming_external_callback_); } +int32_t ViERenderer::SetVideoRenderCallback(int32_t render_id, + VideoRenderCallback* callback) { + return render_module_.AddExternalRenderCallback(render_id, callback); +} + ViERenderer::ViERenderer(const int32_t render_id, const int32_t engine_id, VideoRender& render_module, diff --git a/webrtc/video_engine/vie_renderer.h b/webrtc/video_engine/vie_renderer.h index 4f73e5182d..907735cad7 100644 --- a/webrtc/video_engine/vie_renderer.h +++ b/webrtc/video_engine/vie_renderer.h @@ -86,6 +86,9 @@ class ViERenderer: public ViEFrameCallback { RawVideoType video_input_format, ExternalRenderer* external_renderer); + int32_t SetVideoRenderCallback(const int32_t render_id, + VideoRenderCallback* callback); + private: ViERenderer(const int32_t render_id, const int32_t engine_id, VideoRender& render_module,