Reset frame timestamp epoch for new capturers.
Incoming frames usually have an epoch of time since the capturer was created or similar, not any fixed-time epoch. As such, setting a new capturer resulted in delivering frames with older timestamps which caused these frames to be dropped before encoding. BUG=webrtc:4994 R=stefan@webrtc.org TBR=pthatcher@webrtc.org Review URL: https://codereview.webrtc.org/1345473002 Cr-Commit-Position: refs/heads/master@{#9934}
This commit is contained in:
parent
6304626268
commit
1cb121dea4
@ -133,6 +133,10 @@ class FakeVideoCapturer : public cricket::VideoCapturer {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SignalCapturedFrame(cricket::CapturedFrame* frame) {
|
||||
SignalFrameCaptured(this, frame);
|
||||
}
|
||||
|
||||
sigslot::signal1<FakeVideoCapturer*> SignalDestroyed;
|
||||
|
||||
virtual cricket::CaptureState Start(const cricket::VideoFormat& format) {
|
||||
|
||||
@ -1881,6 +1881,10 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
|
||||
{
|
||||
rtc::CritScope cs(&lock_);
|
||||
|
||||
// Reset timestamps to realign new incoming frames to a webrtc timestamp. A
|
||||
// new capturer may have a different timestamp delta than the previous one.
|
||||
first_frame_timestamp_ms_ = 0;
|
||||
|
||||
if (capturer == NULL) {
|
||||
if (stream_ != NULL) {
|
||||
LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
|
||||
|
||||
@ -440,18 +440,14 @@ TEST_F(WebRtcVideoEngine2Test, PropagatesInputFrameTimestamp) {
|
||||
cricket::FOURCC_I420));
|
||||
channel->SetSend(true);
|
||||
|
||||
FakeCall* call = factory.GetCall();
|
||||
std::vector<FakeVideoSendStream*> streams = call->GetVideoSendStreams();
|
||||
FakeVideoSendStream* stream = streams[0];
|
||||
FakeVideoSendStream* stream = factory.GetCall()->GetVideoSendStreams()[0];
|
||||
|
||||
int64_t timestamp;
|
||||
int64_t last_timestamp;
|
||||
|
||||
EXPECT_TRUE(capturer.CaptureFrame());
|
||||
last_timestamp = stream->GetLastTimestamp();
|
||||
int64_t last_timestamp = stream->GetLastTimestamp();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
EXPECT_TRUE(capturer.CaptureFrame());
|
||||
timestamp = stream->GetLastTimestamp();
|
||||
int64_t timestamp = stream->GetLastTimestamp();
|
||||
int64_t interval = timestamp - last_timestamp;
|
||||
|
||||
// Precision changes from nanosecond to millisecond.
|
||||
@ -469,7 +465,7 @@ TEST_F(WebRtcVideoEngine2Test, PropagatesInputFrameTimestamp) {
|
||||
last_timestamp = stream->GetLastTimestamp();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
EXPECT_TRUE(capturer.CaptureFrame());
|
||||
timestamp = stream->GetLastTimestamp();
|
||||
int64_t timestamp = stream->GetLastTimestamp();
|
||||
int64_t interval = timestamp - last_timestamp;
|
||||
|
||||
// Precision changes from nanosecond to millisecond.
|
||||
@ -483,6 +479,64 @@ TEST_F(WebRtcVideoEngine2Test, PropagatesInputFrameTimestamp) {
|
||||
EXPECT_TRUE(channel->RemoveSendStream(kSsrc));
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test,
|
||||
ProducesIncreasingTimestampsWithResetInputSources) {
|
||||
cricket::FakeWebRtcVideoEncoderFactory encoder_factory;
|
||||
encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
|
||||
std::vector<cricket::VideoCodec> codecs;
|
||||
codecs.push_back(kVp8Codec);
|
||||
|
||||
FakeCallFactory factory;
|
||||
engine_.SetCallFactory(&factory);
|
||||
rtc::scoped_ptr<VideoMediaChannel> channel(
|
||||
SetUpForExternalEncoderFactory(&encoder_factory, codecs));
|
||||
|
||||
EXPECT_TRUE(
|
||||
channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
|
||||
channel->SetSend(true);
|
||||
FakeVideoSendStream* stream = factory.GetCall()->GetVideoSendStreams()[0];
|
||||
|
||||
FakeVideoCapturer capturer1;
|
||||
EXPECT_TRUE(channel->SetCapturer(kSsrc, &capturer1));
|
||||
|
||||
cricket::CapturedFrame frame;
|
||||
frame.width = 1280;
|
||||
frame.height = 720;
|
||||
frame.fourcc = cricket::FOURCC_I420;
|
||||
frame.data_size = static_cast<uint32>(
|
||||
cricket::VideoFrame::SizeOf(frame.width, frame.height));
|
||||
rtc::scoped_ptr<char[]> data(new char[frame.data_size]);
|
||||
frame.data = data.get();
|
||||
memset(frame.data, 1, frame.data_size);
|
||||
frame.elapsed_time = 0;
|
||||
const int kInitialTimestamp = 123456;
|
||||
frame.time_stamp = kInitialTimestamp;
|
||||
|
||||
// Deliver initial frame.
|
||||
capturer1.SignalCapturedFrame(&frame);
|
||||
// Deliver next frame 1 second later.
|
||||
frame.time_stamp += rtc::kNumNanosecsPerSec;
|
||||
rtc::Thread::Current()->SleepMs(1000);
|
||||
capturer1.SignalCapturedFrame(&frame);
|
||||
|
||||
int64_t capturer1_last_timestamp = stream->GetLastTimestamp();
|
||||
// Reset input source, should still be continuous even though input-frame
|
||||
// timestamp is less than before.
|
||||
FakeVideoCapturer capturer2;
|
||||
EXPECT_TRUE(channel->SetCapturer(kSsrc, &capturer2));
|
||||
|
||||
rtc::Thread::Current()->SleepMs(1);
|
||||
// Deliver with a timestamp (10 seconds) before the previous initial one,
|
||||
// these should not be related at all anymore and it should still work fine.
|
||||
frame.time_stamp = kInitialTimestamp - 10000;
|
||||
capturer2.SignalCapturedFrame(&frame);
|
||||
|
||||
// New timestamp should be at least 1ms in the future and not old.
|
||||
EXPECT_GT(stream->GetLastTimestamp(), capturer1_last_timestamp);
|
||||
|
||||
EXPECT_TRUE(channel->RemoveSendStream(kSsrc));
|
||||
}
|
||||
|
||||
VideoMediaChannel* WebRtcVideoEngine2Test::SetUpForExternalEncoderFactory(
|
||||
cricket::WebRtcVideoEncoderFactory* encoder_factory,
|
||||
const std::vector<VideoCodec>& codecs) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user