Added API to set expected render delay.

BUG=905
TEST=API test added and manual delay tests.

Review URL: https://webrtc-codereview.appspot.com/810005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2841 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mflodman@webrtc.org 2012-09-28 11:27:35 +00:00
parent a30eb31729
commit f4f2145c6e
12 changed files with 126 additions and 4 deletions

View File

@ -236,6 +236,13 @@ public:
/*
* re-configure renderer
*/
// Set the expected time needed by the graphics card or external renderer,
// i.e. frames will be released for rendering |delay_ms| before set render
// time in the video frame.
virtual WebRtc_Word32 SetExpectedRenderDelay(WebRtc_UWord32 stream_id,
WebRtc_Word32 delay_ms) = 0;
virtual WebRtc_Word32 ConfigureRenderer(const WebRtc_UWord32 streamId,
const unsigned int zOrder,
const float left, const float top,

View File

@ -175,6 +175,18 @@ WebRtc_Word32 IncomingVideoStream::EnableMirroring(const bool enable,
return 0;
}
WebRtc_Word32 IncomingVideoStream::SetExpectedRenderDelay(
WebRtc_Word32 delay_ms) {
CriticalSectionScoped csS(&stream_critsect_);
if (running_) {
WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
"%s(%d) for stream %d", __FUNCTION__, delay_ms, stream_id_);
return -1;
}
CriticalSectionScoped cs(buffer_critsect_);
return render_buffers_.SetRenderDelay(delay_ms);
}
WebRtc_Word32 IncomingVideoStream::SetExternalCallback(
VideoRenderCallback* external_callback) {
CriticalSectionScoped cs(&stream_critsect_);

View File

@ -68,6 +68,8 @@ class IncomingVideoStream : public VideoRenderCallback {
const bool mirror_xaxis,
const bool mirror_yaxis);
WebRtc_Word32 SetExpectedRenderDelay(WebRtc_Word32 delay_ms);
protected:
static bool IncomingVideoStreamThreadFun(void* obj);
bool IncomingVideoStreamProcess();

View File

@ -18,7 +18,9 @@
namespace webrtc {
WebRtc_Word32 KEventMaxWaitTimeMs = 200;
const WebRtc_Word32 KEventMaxWaitTimeMs = 200;
const WebRtc_Word32 kMinRenderDelayMs = 10;
const WebRtc_Word32 kMaxRenderDelayMs= 500;
VideoRenderFrames::VideoRenderFrames()
: incoming_frames_(),
@ -167,6 +169,14 @@ WebRtc_UWord32 VideoRenderFrames::TimeToNextFrameRelease() {
WebRtc_Word32 VideoRenderFrames::SetRenderDelay(
const WebRtc_UWord32 render_delay) {
if (render_delay < kMinRenderDelayMs ||
render_delay > kMaxRenderDelayMs) {
WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer,
-1, "%s(%d): Invalid argument.", __FUNCTION__,
render_delay);
return -1;
}
render_delay_ms_ = render_delay;
return 0;
}

View File

@ -845,6 +845,37 @@ WebRtc_Word32 ModuleVideoRenderImpl::GetLastRenderedFrame(
return incomingStream->GetLastRenderedFrame(frame);
}
WebRtc_Word32 ModuleVideoRenderImpl::SetExpectedRenderDelay(
WebRtc_UWord32 stream_id, WebRtc_Word32 delay_ms) {
CriticalSectionScoped cs(_moduleCrit);
if (!_ptrRenderer) {
WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
"%s: No renderer", __FUNCTION__);
return false;
}
MapItem *item = _streamRenderMap.Find(stream_id);
if (item == NULL) {
// This stream doesn't exist
WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
"%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id,
delay_ms);
return -1;
}
IncomingVideoStream* incoming_stream =
static_cast<IncomingVideoStream*> (item->GetItem());
if (incoming_stream == NULL) {
// This should never happen
assert(false);
_streamRenderMap.Erase(item);
return 0;
}
return incoming_stream->SetExpectedRenderDelay(delay_ms);
}
WebRtc_Word32 ModuleVideoRenderImpl::ConfigureRenderer(
const WebRtc_UWord32 streamId,
const unsigned int zOrder,

View File

@ -119,6 +119,9 @@ public:
virtual WebRtc_Word32 GetLastRenderedFrame(const WebRtc_UWord32 streamId,
VideoFrame &frame) const;
virtual WebRtc_Word32 SetExpectedRenderDelay(WebRtc_UWord32 stream_id,
WebRtc_Word32 delay_ms);
/**************************************************************************
*
* Start/Stop

View File

@ -81,6 +81,11 @@ class WEBRTC_DLLEXPORT ViERender {
// Stops rendering a render stream.
virtual int StopRender(const int render_id) = 0;
// Set expected render time needed by graphics card or external renderer, i.e.
// the number of ms a frame will be sent to rendering before the actual render
// time.
virtual int SetExpectedRenderDelay(int render_id, int render_delay) = 0;
// Configures an already added render stream.
virtual int ConfigureRender(int render_id,
const unsigned int z_order,

View File

@ -289,7 +289,31 @@ void ViEAutoTest::ViERenderExtendedTest()
tbCapture.Disconnect(tbChannel.videoChannel);
}
void ViEAutoTest::ViERenderAPITest()
{
// TODO(unknown): add the real tests cases
void ViEAutoTest::ViERenderAPITest() {
TbInterfaces ViE("ViERenderAPITest");
TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecVP8);
TbCaptureDevice tbCapture(ViE);
tbCapture.ConnectTo(tbChannel.videoChannel);
tbChannel.StartReceive();
tbChannel.StartSend();
EXPECT_EQ(0, ViE.render->AddRenderer(
tbCapture.captureId, _window1, 0, 0.0, 0.0, 1.0, 1.0));
EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId));
EXPECT_EQ(0, ViE.render->AddRenderer(
tbChannel.videoChannel, _window2, 1, 0.0, 0.0, 1.0, 1.0));
EXPECT_EQ(0, ViE.render->StartRender(tbChannel.videoChannel));
// Test setting HW render delay.
// Already started.
EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 50));
EXPECT_EQ(0, ViE.render->StopRender(tbChannel.videoChannel));
// Invalid values.
EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 9));
EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel,
501));
// Valid values.
EXPECT_EQ(0, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 11));
EXPECT_EQ(0, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 499));
}

View File

@ -262,6 +262,27 @@ int ViERenderImpl::StopRender(const int render_id) {
return 0;
}
int ViERenderImpl::SetExpectedRenderDelay(int render_id, int render_delay) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
ViEId(shared_data_->instance_id(), render_id),
"%s(channel: %d)", __FUNCTION__, render_id);
ViERenderManagerScoped rs(*(shared_data_->render_manager()));
ViERenderer* renderer = rs.Renderer(render_id);
if (!renderer) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), render_id),
"%s: No renderer with render_id %d exist.", __FUNCTION__,
render_id);
shared_data_->SetLastError(kViERenderInvalidRenderId);
return -1;
}
if (renderer->SetExpectedRenderDelay(render_delay) != 0) {
shared_data_->SetLastError(kViERenderUnknownError);
return -1;
}
return 0;
}
int ViERenderImpl::ConfigureRender(int render_id, const unsigned int z_order,
const float left, const float top,
const float right, const float bottom) {

View File

@ -36,6 +36,7 @@ class ViERenderImpl
virtual int RemoveRenderer(const int render_id);
virtual int StartRender(const int render_id);
virtual int StopRender(const int render_id);
virtual int SetExpectedRenderDelay(int render_id, int render_delay);
virtual int ConfigureRender(int render_id, const unsigned int z_order,
const float left, const float top,
const float right, const float bottom);

View File

@ -55,6 +55,10 @@ WebRtc_Word32 ViERenderer::GetLastRenderedFrame(const WebRtc_Word32 renderID,
return render_module_.GetLastRenderedFrame(renderID, video_frame);
}
int ViERenderer::SetExpectedRenderDelay(int render_delay) {
return render_module_.SetExpectedRenderDelay(render_id_, render_delay);
}
WebRtc_Word32 ViERenderer::ConfigureRenderer(const unsigned int z_order,
const float left,
const float top,

View File

@ -62,6 +62,8 @@ class ViERenderer: public ViEFrameCallback {
WebRtc_Word32 GetLastRenderedFrame(const WebRtc_Word32 renderID,
VideoFrame& video_frame);
int SetExpectedRenderDelay(int render_delay);
WebRtc_Word32 ConfigureRenderer(const unsigned int z_order,
const float left,
const float top,