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:
parent
5b3c67ef25
commit
eb7b7bce3d
@ -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.",
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user