Modify video_render/ to allow a single old frame.

This stabilizes tests as a single frame reaches end-to-end, as well as
allowing slow or heavily-loaded systems to see any video updates even if
the frame takes more than 500ms in the pipeline.

R=mflodman@webrtc.org, stefan@webrtc.org
BUG=2724

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5303 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pbos@webrtc.org 2013-12-16 18:24:37 +00:00
parent 5b3c67ef25
commit eb7b7bce3d
2 changed files with 83 additions and 3 deletions

View File

@ -35,12 +35,19 @@ VideoRenderFrames::~VideoRenderFrames() {
int32_t VideoRenderFrames::AddFrame(I420VideoFrame* new_frame) {
const int64_t time_now = TickTime::MillisecondTimestamp();
if (new_frame->render_time_ms() + KOldRenderTimestampMS < time_now) {
WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1,
// Drop old frames only when there are other frames in the queue, otherwise, a
// really slow system never renders any frames.
if (!incoming_frames_.Empty() &&
new_frame->render_time_ms() + KOldRenderTimestampMS < time_now) {
WEBRTC_TRACE(kTraceWarning,
kTraceVideoRenderer,
-1,
"%s: too old frame, timestamp=%u.",
__FUNCTION__, new_frame->timestamp());
__FUNCTION__,
new_frame->timestamp());
return -1;
}
if (new_frame->render_time_ms() > time_now + KFutureRenderTimestampMS) {
WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1,
"%s: frame too long into the future, timestamp=%u.",

View File

@ -23,6 +23,7 @@
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/test/direct_transport.h"
#include "webrtc/test/fake_audio_device.h"
#include "webrtc/test/fake_decoder.h"
@ -298,6 +299,78 @@ TEST_F(CallTest, UsesTraceCallback) {
receiver_call_.reset();
}
TEST_F(CallTest, RendersSingleDelayedFrame) {
static const int kWidth = 320;
static const int kHeight = 240;
// This constant is chosen to be higher than the timeout in the video_render
// module. This makes sure that frames aren't dropped if there are no other
// frames in the queue.
static const int kDelayRenderCallbackMs = 1000;
class Renderer : public VideoRenderer {
public:
Renderer() : event_(EventWrapper::Create()) {}
virtual void RenderFrame(const I420VideoFrame& video_frame,
int /*time_to_render_ms*/) OVERRIDE {
event_->Set();
}
EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
scoped_ptr<EventWrapper> event_;
} renderer;
class TestFrameCallback : public I420FrameCallback {
public:
TestFrameCallback() : event_(EventWrapper::Create()) {}
EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
private:
virtual void FrameCallback(I420VideoFrame* frame) {
SleepMs(kDelayRenderCallbackMs);
event_->Set();
}
scoped_ptr<EventWrapper> event_;
};
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();
TestFrameCallback pre_render_callback;
receive_config_.pre_render_callback = &pre_render_callback;
receive_config_.renderer = &renderer;
CreateStreams();
StartSending();
// Create frames that are smaller than the send width/height, this is done to
// check that the callbacks are done after processing video.
scoped_ptr<test::FrameGenerator> frame_generator(
test::FrameGenerator::Create(kWidth, kHeight));
send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
<< "Timed out while waiting for pre-render callback.";
EXPECT_EQ(kEventSignaled, renderer.Wait())
<< "Timed out while waiting for the frame to render.";
StopSending();
sender_transport.StopSending();
receiver_transport.StopSending();
DestroyStreams();
}
TEST_F(CallTest, TransmitsFirstFrame) {
class Renderer : public VideoRenderer {
public: