Propagate capture ntp timestamp from rtp to renderer.
Mostly the interface changes, the real implementation of ntp timestamp will come in a follow up cl. TEST=new tests and try bots BUG=3111 R=niklas.enbom@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/11469004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5911 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -22,6 +22,8 @@ namespace webrtc {
|
||||
enum { kMaxWaitEncTimeMs = 100 };
|
||||
enum { kMaxWaitDecTimeMs = 25 };
|
||||
|
||||
static const uint32_t kTestTimestamp = 123;
|
||||
static const int64_t kTestNtpTimeMs = 456;
|
||||
|
||||
// TODO(mikhal): Replace these with mocks.
|
||||
class Vp8UnitTestEncodeCompleteCallback : public webrtc::EncodedImageCallback {
|
||||
@ -128,6 +130,7 @@ class TestVp8Impl : public ::testing::Test {
|
||||
|
||||
input_frame_.CreateEmptyFrame(codec_inst_.width, codec_inst_.height,
|
||||
stride_y, stride_uv, stride_uv);
|
||||
input_frame_.set_timestamp(kTestTimestamp);
|
||||
// Using ConvertToI420 to add stride to the image.
|
||||
EXPECT_EQ(0, ConvertToI420(kI420, source_buffer_.get(), 0, 0,
|
||||
codec_inst_.width, codec_inst_.height,
|
||||
@ -235,10 +238,13 @@ TEST_F(TestVp8Impl, DISABLED_ON_ANDROID(AlignedStrideEncodeDecode)) {
|
||||
VideoFrameToEncodedImage(encoded_video_frame_, encodedImage);
|
||||
// First frame should be a key frame.
|
||||
encodedImage._frameType = kKeyFrame;
|
||||
encodedImage.ntp_time_ms_ = kTestNtpTimeMs;
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Decode(encodedImage, false, NULL));
|
||||
EXPECT_GT(WaitForDecodedFrame(), 0);
|
||||
// Compute PSNR on all planes (faster than SSIM).
|
||||
EXPECT_GT(I420PSNR(&input_frame_, &decoded_video_frame_), 36);
|
||||
EXPECT_EQ(kTestTimestamp, decoded_video_frame_.timestamp());
|
||||
EXPECT_EQ(kTestNtpTimeMs, decoded_video_frame_.ntp_time_ms());
|
||||
}
|
||||
|
||||
TEST_F(TestVp8Impl, DISABLED_ON_ANDROID(DecodeWithACompleteKeyFrame)) {
|
||||
|
||||
@ -710,7 +710,7 @@ int VP8DecoderImpl::Decode(const EncodedImage& input_image,
|
||||
}
|
||||
|
||||
img = vpx_codec_get_frame(decoder_, &iter);
|
||||
ret = ReturnFrame(img, input_image._timeStamp);
|
||||
ret = ReturnFrame(img, input_image._timeStamp, input_image.ntp_time_ms_);
|
||||
if (ret != 0) {
|
||||
// Reset to avoid requesting key frames too often.
|
||||
if (ret < 0 && propagation_cnt_ > 0)
|
||||
@ -790,7 +790,9 @@ int VP8DecoderImpl::DecodePartitions(
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, uint32_t timestamp) {
|
||||
int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img,
|
||||
uint32_t timestamp,
|
||||
int64_t ntp_time_ms) {
|
||||
if (img == NULL) {
|
||||
// Decoder OK and NULL image => No show frame
|
||||
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
|
||||
@ -808,6 +810,7 @@ int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, uint32_t timestamp) {
|
||||
img->stride[VPX_PLANE_U],
|
||||
img->stride[VPX_PLANE_V]);
|
||||
decoded_image_.set_timestamp(timestamp);
|
||||
decoded_image_.set_ntp_time_ms(ntp_time_ms);
|
||||
int ret = decode_complete_callback_->Decoded(decoded_image_);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
@ -214,7 +214,9 @@ class VP8DecoderImpl : public VP8Decoder {
|
||||
int DecodePartitions(const EncodedImage& input_image,
|
||||
const RTPFragmentationHeader* fragmentation);
|
||||
|
||||
int ReturnFrame(const vpx_image_t* img, uint32_t timeStamp);
|
||||
int ReturnFrame(const vpx_image_t* img,
|
||||
uint32_t timeStamp,
|
||||
int64_t ntp_time_ms);
|
||||
|
||||
I420VideoFrame decoded_image_;
|
||||
DecodedImageCallback* decode_complete_callback_;
|
||||
|
||||
@ -96,6 +96,8 @@ VCMFrameBuffer::InsertPacket(const VCMPacket& packet,
|
||||
// First packet (empty and/or media) inserted into this frame.
|
||||
// store some info and set some initial values.
|
||||
_timeStamp = packet.timestamp;
|
||||
// We only take the ntp timestamp of the first packet of a frame.
|
||||
ntp_time_ms_ = packet.ntp_time_ms_;
|
||||
_codec = packet.codec;
|
||||
if (packet.frameType != kFrameEmpty) {
|
||||
// first media packet
|
||||
|
||||
@ -19,6 +19,7 @@ VCMPacket::VCMPacket()
|
||||
:
|
||||
payloadType(0),
|
||||
timestamp(0),
|
||||
ntp_time_ms_(0),
|
||||
seqNum(0),
|
||||
dataPtr(NULL),
|
||||
sizeBytes(0),
|
||||
@ -38,6 +39,7 @@ VCMPacket::VCMPacket(const uint8_t* ptr,
|
||||
const WebRtcRTPHeader& rtpHeader) :
|
||||
payloadType(rtpHeader.header.payloadType),
|
||||
timestamp(rtpHeader.header.timestamp),
|
||||
ntp_time_ms_(rtpHeader.ntp_time_ms),
|
||||
seqNum(rtpHeader.header.sequenceNumber),
|
||||
dataPtr(ptr),
|
||||
sizeBytes(size),
|
||||
@ -58,6 +60,7 @@ VCMPacket::VCMPacket(const uint8_t* ptr,
|
||||
VCMPacket::VCMPacket(const uint8_t* ptr, uint32_t size, uint16_t seq, uint32_t ts, bool mBit) :
|
||||
payloadType(0),
|
||||
timestamp(ts),
|
||||
ntp_time_ms_(0),
|
||||
seqNum(seq),
|
||||
dataPtr(ptr),
|
||||
sizeBytes(size),
|
||||
@ -76,6 +79,7 @@ VCMPacket::VCMPacket(const uint8_t* ptr, uint32_t size, uint16_t seq, uint32_t t
|
||||
void VCMPacket::Reset() {
|
||||
payloadType = 0;
|
||||
timestamp = 0;
|
||||
ntp_time_ms_ = 0;
|
||||
seqNum = 0;
|
||||
dataPtr = NULL;
|
||||
sizeBytes = 0;
|
||||
|
||||
@ -33,6 +33,8 @@ public:
|
||||
|
||||
uint8_t payloadType;
|
||||
uint32_t timestamp;
|
||||
// NTP time of the capture time in local timebase in milliseconds.
|
||||
int64_t ntp_time_ms_;
|
||||
uint16_t seqNum;
|
||||
const uint8_t* dataPtr;
|
||||
uint32_t sizeBytes;
|
||||
|
||||
Reference in New Issue
Block a user