Report encoded frame size in VideoSendStream.
Implements reporting transmitted frame size in WebRtcVideoEngine2. R=mflodman@webrtc.org, stefan@webrtc.org BUG=4033 Review URL: https://webrtc-codereview.appspot.com/33399004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7772 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
1db20a4180
commit
273a414b0e
@ -724,6 +724,8 @@ class FakeWebRtcVideoEngine
|
||||
}
|
||||
WEBRTC_STUB(GetVersion, (char version[1024]));
|
||||
WEBRTC_STUB(LastError, ());
|
||||
WEBRTC_VOID_STUB(RegisterSendStatisticsProxy,
|
||||
(int, webrtc::SendStatisticsProxy*));
|
||||
|
||||
// webrtc::ViECodec
|
||||
WEBRTC_FUNC_CONST(NumberOfCodecs, ()) {
|
||||
|
@ -1836,6 +1836,8 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
|
||||
info.framerate_input = stats.input_frame_rate;
|
||||
info.framerate_sent = stats.encode_frame_rate;
|
||||
|
||||
info.send_frame_width = 0;
|
||||
info.send_frame_height = 0;
|
||||
for (std::map<uint32_t, webrtc::SsrcStats>::iterator it =
|
||||
stats.substreams.begin();
|
||||
it != stats.substreams.end();
|
||||
@ -1847,6 +1849,10 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
|
||||
stream_stats.rtp_stats.padding_bytes;
|
||||
info.packets_sent += stream_stats.rtp_stats.packets;
|
||||
info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
|
||||
if (stream_stats.sent_width > info.send_frame_width)
|
||||
info.send_frame_width = stream_stats.sent_width;
|
||||
if (stream_stats.sent_height > info.send_frame_height)
|
||||
info.send_frame_height = stream_stats.sent_height;
|
||||
}
|
||||
|
||||
if (!stats.substreams.empty()) {
|
||||
@ -1865,10 +1871,6 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
|
||||
&last_captured_frame_format);
|
||||
info.input_frame_width = last_captured_frame_format.width;
|
||||
info.input_frame_height = last_captured_frame_format.height;
|
||||
info.send_frame_width =
|
||||
static_cast<int>(parameters_.encoder_config.streams.front().width);
|
||||
info.send_frame_height =
|
||||
static_cast<int>(parameters_.encoder_config.streams.front().height);
|
||||
}
|
||||
|
||||
// TODO(pbos): Support or remove the following stats.
|
||||
|
@ -122,8 +122,14 @@ void FakeVideoSendStream::SwapFrame(webrtc::I420VideoFrame* frame) {
|
||||
++num_swapped_frames_;
|
||||
last_frame_.SwapFrame(frame);
|
||||
}
|
||||
webrtc::VideoSendStream::Stats FakeVideoSendStream::GetStats() const {
|
||||
return webrtc::VideoSendStream::Stats();
|
||||
|
||||
void FakeVideoSendStream::SetStats(
|
||||
const webrtc::VideoSendStream::Stats& stats) {
|
||||
stats_ = stats;
|
||||
}
|
||||
|
||||
webrtc::VideoSendStream::Stats FakeVideoSendStream::GetStats() {
|
||||
return stats_;
|
||||
}
|
||||
|
||||
bool FakeVideoSendStream::ReconfigureVideoEncoder(
|
||||
@ -1873,4 +1879,22 @@ TEST_F(WebRtcVideoChannel2Test, OnReadyToSendSignalsNetworkState) {
|
||||
EXPECT_EQ(webrtc::Call::kNetworkUp, fake_call_->GetNetworkState());
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, GetStatsReportsUpperResolution) {
|
||||
FakeVideoSendStream* stream = AddSendStream();
|
||||
webrtc::VideoSendStream::Stats stats;
|
||||
stats.substreams[17].sent_width = 123;
|
||||
stats.substreams[17].sent_height = 40;
|
||||
stats.substreams[42].sent_width = 80;
|
||||
stats.substreams[42].sent_height = 31;
|
||||
stats.substreams[11].sent_width = 20;
|
||||
stats.substreams[11].sent_height = 90;
|
||||
stream->SetStats(stats);
|
||||
|
||||
cricket::VideoMediaInfo info;
|
||||
ASSERT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info));
|
||||
ASSERT_EQ(1u, info.senders.size());
|
||||
EXPECT_EQ(123, info.senders[0].send_frame_width);
|
||||
EXPECT_EQ(90, info.senders[0].send_frame_height);
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
|
@ -51,10 +51,11 @@ class FakeVideoSendStream : public webrtc::VideoSendStream,
|
||||
int GetNumberOfSwappedFrames() const;
|
||||
int GetLastWidth() const;
|
||||
int GetLastHeight() const;
|
||||
void SetStats(const webrtc::VideoSendStream::Stats& stats);
|
||||
|
||||
private:
|
||||
virtual void SwapFrame(webrtc::I420VideoFrame* frame) OVERRIDE;
|
||||
virtual webrtc::VideoSendStream::Stats GetStats() const OVERRIDE;
|
||||
virtual webrtc::VideoSendStream::Stats GetStats() OVERRIDE;
|
||||
|
||||
virtual bool ReconfigureVideoEncoder(
|
||||
const webrtc::VideoEncoderConfig& config) OVERRIDE;
|
||||
@ -71,6 +72,7 @@ class FakeVideoSendStream : public webrtc::VideoSendStream,
|
||||
webrtc::VideoCodecVP8 vp8_settings_;
|
||||
int num_swapped_frames_;
|
||||
webrtc::I420VideoFrame last_frame_;
|
||||
webrtc::VideoSendStream::Stats stats_;
|
||||
};
|
||||
|
||||
class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
|
||||
|
@ -25,12 +25,16 @@ struct SsrcStats {
|
||||
SsrcStats()
|
||||
: key_frames(0),
|
||||
delta_frames(0),
|
||||
sent_width(0),
|
||||
sent_height(0),
|
||||
total_bitrate_bps(0),
|
||||
retransmit_bitrate_bps(0),
|
||||
avg_delay_ms(0),
|
||||
max_delay_ms(0) {}
|
||||
uint32_t key_frames;
|
||||
uint32_t delta_frames;
|
||||
int sent_width;
|
||||
int sent_height;
|
||||
// TODO(holmer): Move bitrate_bps out to the webrtc::Call layer.
|
||||
int total_bitrate_bps;
|
||||
int retransmit_bitrate_bps;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifdef WEBRTC_MODULE_UTILITY_VIDEO
|
||||
|
||||
#include "webrtc/modules/utility/source/video_coder.h"
|
||||
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
|
||||
|
||||
namespace webrtc {
|
||||
VideoCoder::VideoCoder() : _vcm(VideoCodingModule::Create()), _decodedVideo(0) {
|
||||
@ -108,25 +109,22 @@ int32_t VideoCoder::FrameToRender(I420VideoFrame& videoFrame)
|
||||
}
|
||||
|
||||
int32_t VideoCoder::SendData(
|
||||
const FrameType frameType,
|
||||
const uint8_t payloadType,
|
||||
const uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const uint8_t payloadType,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& fragmentationHeader,
|
||||
const RTPVideoHeader* /*rtpVideoHdr*/)
|
||||
{
|
||||
// Store the data in _videoEncodedData which is a pointer to videoFrame in
|
||||
// Encode(..)
|
||||
_videoEncodedData->VerifyAndAllocate(payloadSize);
|
||||
_videoEncodedData->frameType = frameType;
|
||||
_videoEncodedData->VerifyAndAllocate(encoded_image._length);
|
||||
_videoEncodedData->frameType =
|
||||
VCMEncodedFrame::ConvertFrameType(encoded_image._frameType);
|
||||
_videoEncodedData->payloadType = payloadType;
|
||||
_videoEncodedData->timeStamp = timeStamp;
|
||||
_videoEncodedData->timeStamp = encoded_image._timeStamp;
|
||||
_videoEncodedData->fragmentationHeader.CopyFrom(fragmentationHeader);
|
||||
memcpy(_videoEncodedData->payloadData, payloadData,
|
||||
sizeof(uint8_t) * payloadSize);
|
||||
_videoEncodedData->payloadSize = payloadSize;
|
||||
memcpy(_videoEncodedData->payloadData, encoded_image._buffer,
|
||||
sizeof(uint8_t) * encoded_image._length);
|
||||
_videoEncodedData->payloadSize = encoded_image._length;
|
||||
return 0;
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
@ -48,12 +48,8 @@ private:
|
||||
// VCMPacketizationCallback function.
|
||||
// Note: called by VideoCodingModule when encoding finished.
|
||||
virtual int32_t SendData(
|
||||
FrameType /*frameType*/,
|
||||
uint8_t /*payloadType*/,
|
||||
uint32_t /*timeStamp*/,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& /* fragmentationHeader*/,
|
||||
const RTPVideoHeader* rtpTypeHdr) OVERRIDE;
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace webrtc {
|
||||
|
||||
class MockEncodedImageCallback : public EncodedImageCallback {
|
||||
public:
|
||||
MOCK_METHOD3(Encoded, int32_t(EncodedImage& encodedImage,
|
||||
MOCK_METHOD3(Encoded, int32_t(const EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const RTPFragmentationHeader* fragmentation));
|
||||
};
|
||||
|
@ -36,7 +36,6 @@ PacketManipulatorImpl::~PacketManipulatorImpl() {
|
||||
|
||||
int PacketManipulatorImpl::ManipulatePackets(
|
||||
webrtc::EncodedImage* encoded_image) {
|
||||
assert(encoded_image);
|
||||
int nbr_packets_dropped = 0;
|
||||
// There's no need to build a copy of the image data since viewing an
|
||||
// EncodedImage object, setting the length to a new lower value represents
|
||||
|
@ -82,8 +82,7 @@ class PacketManipulator {
|
||||
// If packets are dropped from frame data, the completedFrame field will be
|
||||
// set to false.
|
||||
// Returns the number of packets being dropped.
|
||||
virtual int
|
||||
ManipulatePackets(webrtc::EncodedImage* encoded_image) = 0;
|
||||
virtual int ManipulatePackets(webrtc::EncodedImage* encoded_image) = 0;
|
||||
};
|
||||
|
||||
class PacketManipulatorImpl : public PacketManipulator {
|
||||
|
@ -223,12 +223,12 @@ bool VideoProcessorImpl::ProcessFrame(int frame_number) {
|
||||
}
|
||||
}
|
||||
|
||||
void VideoProcessorImpl::FrameEncoded(EncodedImage* encoded_image) {
|
||||
void VideoProcessorImpl::FrameEncoded(const EncodedImage& encoded_image) {
|
||||
// Timestamp is frame number, so this gives us #dropped frames.
|
||||
int num_dropped_from_prev_encode = encoded_image->_timeStamp -
|
||||
int num_dropped_from_prev_encode = encoded_image._timeStamp -
|
||||
prev_time_stamp_ - 1;
|
||||
num_dropped_frames_ += num_dropped_from_prev_encode;
|
||||
prev_time_stamp_ = encoded_image->_timeStamp;
|
||||
prev_time_stamp_ = encoded_image._timeStamp;
|
||||
if (num_dropped_from_prev_encode > 0) {
|
||||
// For dropped frames, we write out the last decoded frame to avoid getting
|
||||
// out of sync for the computation of PSNR and SSIM.
|
||||
@ -238,25 +238,25 @@ void VideoProcessorImpl::FrameEncoded(EncodedImage* encoded_image) {
|
||||
}
|
||||
// Frame is not dropped, so update the encoded frame size
|
||||
// (encoder callback is only called for non-zero length frames).
|
||||
encoded_frame_size_ = encoded_image->_length;
|
||||
encoded_frame_size_ = encoded_image._length;
|
||||
|
||||
TickTime encode_stop = TickTime::Now();
|
||||
int frame_number = encoded_image->_timeStamp;
|
||||
int frame_number = encoded_image._timeStamp;
|
||||
FrameStatistic& stat = stats_->stats_[frame_number];
|
||||
stat.encode_time_in_us = GetElapsedTimeMicroseconds(encode_start_,
|
||||
encode_stop);
|
||||
stat.encoding_successful = true;
|
||||
stat.encoded_frame_length_in_bytes = encoded_image->_length;
|
||||
stat.frame_number = encoded_image->_timeStamp;
|
||||
stat.frame_type = encoded_image->_frameType;
|
||||
stat.bit_rate_in_kbps = encoded_image->_length * bit_rate_factor_;
|
||||
stat.total_packets = encoded_image->_length /
|
||||
stat.encoded_frame_length_in_bytes = encoded_image._length;
|
||||
stat.frame_number = encoded_image._timeStamp;
|
||||
stat.frame_type = encoded_image._frameType;
|
||||
stat.bit_rate_in_kbps = encoded_image._length * bit_rate_factor_;
|
||||
stat.total_packets = encoded_image._length /
|
||||
config_.networking_config.packet_size_in_bytes + 1;
|
||||
|
||||
// Perform packet loss if criteria is fullfilled:
|
||||
bool exclude_this_frame = false;
|
||||
// Only keyframes can be excluded
|
||||
if (encoded_image->_frameType == kKeyFrame) {
|
||||
if (encoded_image._frameType == kKeyFrame) {
|
||||
switch (config_.exclude_frame_types) {
|
||||
case kExcludeOnlyFirstKeyFrame:
|
||||
if (!first_key_frame_has_been_excluded_) {
|
||||
@ -271,9 +271,15 @@ void VideoProcessorImpl::FrameEncoded(EncodedImage* encoded_image) {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
scoped_ptr<uint8_t[]> copied_buffer(new uint8_t[encoded_image._length]);
|
||||
memcpy(copied_buffer.get(), encoded_image._buffer, encoded_image._length);
|
||||
EncodedImage copied_image;
|
||||
memcpy(&copied_image, &encoded_image, sizeof(copied_image));
|
||||
copied_image._size = copied_image._length;
|
||||
copied_image._buffer = copied_buffer.get();
|
||||
if (!exclude_this_frame) {
|
||||
stat.packets_dropped =
|
||||
packet_manipulator_->ManipulatePackets(encoded_image);
|
||||
packet_manipulator_->ManipulatePackets(&copied_image);
|
||||
}
|
||||
|
||||
// Keep track of if frames are lost due to packet loss so we can tell
|
||||
@ -281,8 +287,8 @@ void VideoProcessorImpl::FrameEncoded(EncodedImage* encoded_image) {
|
||||
decode_start_ = TickTime::Now();
|
||||
// TODO(kjellander): Pass fragmentation header to the decoder when
|
||||
// CL 172001 has been submitted and PacketManipulator supports this.
|
||||
int32_t decode_result = decoder_->Decode(*encoded_image, last_frame_missing_,
|
||||
NULL);
|
||||
int32_t decode_result =
|
||||
decoder_->Decode(copied_image, last_frame_missing_, NULL);
|
||||
stat.decode_return_code = decode_result;
|
||||
if (decode_result != WEBRTC_VIDEO_CODEC_OK) {
|
||||
// Write the last successful frame the output file to avoid getting it out
|
||||
@ -290,7 +296,7 @@ void VideoProcessorImpl::FrameEncoded(EncodedImage* encoded_image) {
|
||||
frame_writer_->WriteFrame(last_successful_frame_buffer_);
|
||||
}
|
||||
// save status for losses so we can inform the decoder for the next frame:
|
||||
last_frame_missing_ = encoded_image->_length == 0;
|
||||
last_frame_missing_ = copied_image._length == 0;
|
||||
}
|
||||
|
||||
void VideoProcessorImpl::FrameDecoded(const I420VideoFrame& image) {
|
||||
@ -399,10 +405,10 @@ const char* VideoCodecTypeToStr(webrtc::VideoCodecType e) {
|
||||
// Callbacks
|
||||
int32_t
|
||||
VideoProcessorImpl::VideoProcessorEncodeCompleteCallback::Encoded(
|
||||
EncodedImage& encoded_image,
|
||||
const EncodedImage& encoded_image,
|
||||
const webrtc::CodecSpecificInfo* codec_specific_info,
|
||||
const webrtc::RTPFragmentationHeader* fragmentation) {
|
||||
video_processor_->FrameEncoded(&encoded_image); // Forward to parent class.
|
||||
video_processor_->FrameEncoded(encoded_image); // Forward to parent class.
|
||||
return 0;
|
||||
}
|
||||
int32_t
|
||||
|
@ -168,7 +168,7 @@ class VideoProcessorImpl : public VideoProcessor {
|
||||
|
||||
private:
|
||||
// Invoked by the callback when a frame has completed encoding.
|
||||
void FrameEncoded(webrtc::EncodedImage* encodedImage);
|
||||
void FrameEncoded(const webrtc::EncodedImage& encodedImage);
|
||||
// Invoked by the callback when a frame has completed decoding.
|
||||
void FrameDecoded(const webrtc::I420VideoFrame& image);
|
||||
// Used for getting a 32-bit integer representing time
|
||||
@ -226,9 +226,9 @@ class VideoProcessorImpl : public VideoProcessor {
|
||||
explicit VideoProcessorEncodeCompleteCallback(VideoProcessorImpl* vp)
|
||||
: video_processor_(vp) {}
|
||||
virtual int32_t Encoded(
|
||||
webrtc::EncodedImage& encoded_image,
|
||||
const webrtc::CodecSpecificInfo* codec_specific_info = NULL,
|
||||
const webrtc::RTPFragmentationHeader* fragmentation = NULL) OVERRIDE;
|
||||
const webrtc::EncodedImage& encoded_image,
|
||||
const webrtc::CodecSpecificInfo* codec_specific_info,
|
||||
const webrtc::RTPFragmentationHeader* fragmentation) OVERRIDE;
|
||||
|
||||
private:
|
||||
VideoProcessorImpl* video_processor_;
|
||||
|
@ -223,12 +223,10 @@ size_t VideoEncodeCompleteCallback::EncodedBytes()
|
||||
return _encodedBytes;
|
||||
}
|
||||
|
||||
int32_t
|
||||
VideoEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const webrtc::RTPFragmentationHeader*
|
||||
fragmentation)
|
||||
{
|
||||
int32_t VideoEncodeCompleteCallback::Encoded(
|
||||
const EncodedImage& encodedImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const webrtc::RTPFragmentationHeader* fragmentation) {
|
||||
_test.Encoded(encodedImage);
|
||||
VideoFrame *newBuffer = new VideoFrame();
|
||||
newBuffer->VerifyAndAllocate(encodedImage._size);
|
||||
@ -564,7 +562,7 @@ void NormalAsyncTest::CodecSpecific_InitBitrate()
|
||||
}
|
||||
|
||||
void NormalAsyncTest::CopyEncodedImage(VideoFrame& dest,
|
||||
EncodedImage& src,
|
||||
const EncodedImage& src,
|
||||
void* /*codecSpecificInfo*/) const
|
||||
{
|
||||
dest.CopyFrame(src._length, src._buffer);
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
CopyCodecSpecificInfo(
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo) const;
|
||||
virtual void CopyEncodedImage(webrtc::VideoFrame& dest,
|
||||
webrtc::EncodedImage& src,
|
||||
const webrtc::EncodedImage& src,
|
||||
void* /*codecSpecificInfo*/) const;
|
||||
virtual webrtc::CodecSpecificInfo* CreateEncoderSpecificInfo() const
|
||||
{
|
||||
@ -149,10 +149,9 @@ public:
|
||||
_encodedBytes(0)
|
||||
{}
|
||||
|
||||
int32_t
|
||||
Encoded(webrtc::EncodedImage& encodedImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL,
|
||||
const webrtc::RTPFragmentationHeader* fragmentation = NULL);
|
||||
int32_t Encoded(const webrtc::EncodedImage& encodedImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const webrtc::RTPFragmentationHeader* fragmentation);
|
||||
size_t EncodedBytes();
|
||||
private:
|
||||
FILE* _encodedFile;
|
||||
|
@ -91,7 +91,7 @@ UnitTest::~UnitTest()
|
||||
}
|
||||
|
||||
int32_t
|
||||
UnitTestEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
|
||||
UnitTestEncodeCompleteCallback::Encoded(const EncodedImage& encodedImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const webrtc::RTPFragmentationHeader*
|
||||
fragmentation)
|
||||
|
@ -79,9 +79,9 @@ public:
|
||||
void* decoderSpecificInfo = NULL) :
|
||||
_encodedVideoBuffer(buffer),
|
||||
_encodeComplete(false) {}
|
||||
int32_t Encoded(webrtc::EncodedImage& encodedImage,
|
||||
int32_t Encoded(const webrtc::EncodedImage& encodedImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const webrtc::RTPFragmentationHeader* fragmentation = NULL);
|
||||
const webrtc::RTPFragmentationHeader* fragmentation);
|
||||
bool EncodeComplete();
|
||||
// Note that this only makes sense if an encode has been completed
|
||||
webrtc::VideoFrameType EncodedFrameType() const;
|
||||
|
@ -33,7 +33,7 @@ class Vp8UnitTestEncodeCompleteCallback : public webrtc::EncodedImageCallback {
|
||||
void* decoderSpecificInfo)
|
||||
: encoded_video_frame_(frame),
|
||||
encode_complete_(false) {}
|
||||
int Encoded(EncodedImage& encodedImage,
|
||||
int Encoded(const EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const RTPFragmentationHeader*);
|
||||
bool EncodeComplete();
|
||||
@ -46,7 +46,7 @@ class Vp8UnitTestEncodeCompleteCallback : public webrtc::EncodedImageCallback {
|
||||
VideoFrameType encoded_frame_type_;
|
||||
};
|
||||
|
||||
int Vp8UnitTestEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
|
||||
int Vp8UnitTestEncodeCompleteCallback::Encoded(const EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const RTPFragmentationHeader* fragmentation) {
|
||||
encoded_video_frame_->VerifyAndAllocate(encodedImage._size);
|
||||
|
@ -25,7 +25,7 @@ class Vp8SequenceCoderEncodeCallback : public webrtc::EncodedImageCallback {
|
||||
: encoded_file_(encoded_file),
|
||||
encoded_bytes_(0) {}
|
||||
~Vp8SequenceCoderEncodeCallback();
|
||||
int Encoded(webrtc::EncodedImage& encoded_image,
|
||||
int Encoded(const webrtc::EncodedImage& encoded_image,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const webrtc::RTPFragmentationHeader*);
|
||||
// Returns the encoded image.
|
||||
@ -42,7 +42,7 @@ Vp8SequenceCoderEncodeCallback::~Vp8SequenceCoderEncodeCallback() {
|
||||
encoded_image_._buffer = NULL;
|
||||
}
|
||||
int Vp8SequenceCoderEncodeCallback::Encoded(
|
||||
webrtc::EncodedImage& encoded_image,
|
||||
const webrtc::EncodedImage& encoded_image,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const webrtc::RTPFragmentationHeader* fragmentation) {
|
||||
if (encoded_image_._size < encoded_image._size) {
|
||||
|
@ -68,15 +68,11 @@ struct VCMFrameCount {
|
||||
// Callback class used for sending data ready to be packetized
|
||||
class VCMPacketizationCallback {
|
||||
public:
|
||||
virtual int32_t SendData(
|
||||
FrameType frameType,
|
||||
uint8_t payloadType,
|
||||
uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const RTPFragmentationHeader& fragmentationHeader,
|
||||
const RTPVideoHeader* rtpVideoHdr) = 0;
|
||||
virtual int32_t SendData(uint8_t payloadType,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& fragmentationHeader,
|
||||
const RTPVideoHeader* rtpVideoHdr) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~VCMPacketizationCallback() {
|
||||
}
|
||||
|
@ -210,19 +210,14 @@ VCMEncodedFrameCallback::SetTransportCallback(VCMPacketizationCallback* transpor
|
||||
|
||||
int32_t
|
||||
VCMEncodedFrameCallback::Encoded(
|
||||
EncodedImage &encodedImage,
|
||||
const EncodedImage &encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const RTPFragmentationHeader* fragmentationHeader)
|
||||
{
|
||||
post_encode_callback_->Encoded(encodedImage);
|
||||
|
||||
FrameType frameType = VCMEncodedFrame::ConvertFrameType(encodedImage._frameType);
|
||||
|
||||
size_t encodedBytes = 0;
|
||||
if (_sendCallback != NULL)
|
||||
{
|
||||
encodedBytes = encodedImage._length;
|
||||
|
||||
#ifdef DEBUG_ENCODER_BIT_STREAM
|
||||
if (_bitStreamAfterEncoder != NULL)
|
||||
{
|
||||
@ -235,12 +230,8 @@ VCMEncodedFrameCallback::Encoded(
|
||||
CopyCodecSpecific(codecSpecificInfo, &rtpVideoHeaderPtr);
|
||||
|
||||
int32_t callbackReturn = _sendCallback->SendData(
|
||||
frameType,
|
||||
_payloadType,
|
||||
encodedImage._timeStamp,
|
||||
encodedImage.capture_time_ms_,
|
||||
encodedImage._buffer,
|
||||
encodedBytes,
|
||||
encodedImage,
|
||||
*fragmentationHeader,
|
||||
rtpVideoHeaderPtr);
|
||||
if (callbackReturn < 0)
|
||||
@ -253,12 +244,9 @@ VCMEncodedFrameCallback::Encoded(
|
||||
return VCM_UNINITIALIZED;
|
||||
}
|
||||
if (_mediaOpt != NULL) {
|
||||
_mediaOpt->UpdateWithEncodedData(encodedBytes, encodedImage._timeStamp,
|
||||
frameType);
|
||||
_mediaOpt->UpdateWithEncodedData(encodedImage);
|
||||
if (_internalSource)
|
||||
{
|
||||
return _mediaOpt->DropFrame(); // Signal to encoder to drop next frame
|
||||
}
|
||||
return _mediaOpt->DropFrame(); // Signal to encoder to drop next frame.
|
||||
}
|
||||
return VCM_OK;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
* Callback implementation - codec encode complete
|
||||
*/
|
||||
int32_t Encoded(
|
||||
EncodedImage& encodedImage,
|
||||
const EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo = NULL,
|
||||
const RTPFragmentationHeader* fragmentationHeader = NULL);
|
||||
/*
|
||||
|
@ -369,9 +369,10 @@ VCMFrameCount MediaOptimization::SentFrameCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t MediaOptimization::UpdateWithEncodedData(size_t encoded_length,
|
||||
uint32_t timestamp,
|
||||
FrameType encoded_frame_type) {
|
||||
int32_t MediaOptimization::UpdateWithEncodedData(
|
||||
const EncodedImage& encoded_image) {
|
||||
size_t encoded_length = encoded_image._length;
|
||||
uint32_t timestamp = encoded_image._timeStamp;
|
||||
CriticalSectionScoped lock(crit_sect_.get());
|
||||
const int64_t now_ms = clock_->TimeInMilliseconds();
|
||||
PurgeOldFrameSamples(now_ms);
|
||||
@ -389,7 +390,7 @@ int32_t MediaOptimization::UpdateWithEncodedData(size_t encoded_length,
|
||||
UpdateSentBitrate(now_ms);
|
||||
UpdateSentFramerate();
|
||||
if (encoded_length > 0) {
|
||||
const bool delta_frame = (encoded_frame_type != kVideoFrameKey);
|
||||
const bool delta_frame = encoded_image._frameType != kKeyFrame;
|
||||
|
||||
frame_dropper_->Fill(encoded_length, delta_frame);
|
||||
if (max_payload_size_ > 0 && encoded_length > 0) {
|
||||
@ -405,7 +406,7 @@ int32_t MediaOptimization::UpdateWithEncodedData(size_t encoded_length,
|
||||
|
||||
if (enable_qm_) {
|
||||
// Update quality select with encoded length.
|
||||
qm_resolution_->UpdateEncodedSize(encoded_length, encoded_frame_type);
|
||||
qm_resolution_->UpdateEncodedSize(encoded_length);
|
||||
}
|
||||
}
|
||||
if (!delta_frame && encoded_length > 0) {
|
||||
|
@ -76,10 +76,8 @@ class MediaOptimization {
|
||||
|
||||
void UpdateContentData(const VideoContentMetrics* content_metrics);
|
||||
|
||||
// Informs Media Optimization of encoding output: Length and frame type.
|
||||
int32_t UpdateWithEncodedData(size_t encoded_length,
|
||||
uint32_t timestamp,
|
||||
FrameType encoded_frame_type);
|
||||
// Informs Media Optimization of encoded output.
|
||||
int32_t UpdateWithEncodedData(const EncodedImage& encoded_image);
|
||||
|
||||
uint32_t InputFrameRate();
|
||||
uint32_t SentFrameRate();
|
||||
|
@ -35,8 +35,11 @@ class TestMediaOptimization : public ::testing::Test {
|
||||
EXPECT_EQ(expect_frame_drop, frame_dropped);
|
||||
if (!frame_dropped) {
|
||||
size_t bytes_per_frame = bitrate_bps * frame_time_ms_ / (8 * 1000);
|
||||
ASSERT_EQ(VCM_OK, media_opt_.UpdateWithEncodedData(
|
||||
bytes_per_frame, next_timestamp_, kVideoFrameDelta));
|
||||
EncodedImage encoded_image;
|
||||
encoded_image._length = bytes_per_frame;
|
||||
encoded_image._timeStamp = next_timestamp_;
|
||||
encoded_image._frameType = kKeyFrame;
|
||||
ASSERT_EQ(VCM_OK, media_opt_.UpdateWithEncodedData(encoded_image));
|
||||
}
|
||||
next_timestamp_ += frame_time_ms_ * kSampleRate / 1000;
|
||||
clock_.AdvanceTimeMilliseconds(frame_time_ms_);
|
||||
|
@ -239,8 +239,7 @@ void VCMQmResolution::UpdateCodecParameters(float frame_rate, uint16_t width,
|
||||
}
|
||||
|
||||
// Update rate data after every encoded frame.
|
||||
void VCMQmResolution::UpdateEncodedSize(size_t encoded_size,
|
||||
FrameType encoded_frame_type) {
|
||||
void VCMQmResolution::UpdateEncodedSize(size_t encoded_size) {
|
||||
frame_cnt_++;
|
||||
// Convert to Kbps.
|
||||
float encoded_size_kbits = 8.0f * static_cast<float>(encoded_size) / 1000.0f;
|
||||
|
@ -216,8 +216,7 @@ class VCMQmResolution : public VCMQmMethod {
|
||||
|
||||
// Update with actual bit rate (size of the latest encoded frame)
|
||||
// and frame type, after every encoded frame.
|
||||
void UpdateEncodedSize(size_t encoded_size,
|
||||
FrameType encoded_frame_type);
|
||||
void UpdateEncodedSize(size_t encoded_size);
|
||||
|
||||
// Update with new target bitrate, actual encoder sent rate, frame_rate,
|
||||
// loss rate: every ~1 sec from SetTargetRates in media_opt.
|
||||
|
@ -1264,11 +1264,10 @@ void QmSelectTest::UpdateQmContentData(float motion_metric,
|
||||
|
||||
void QmSelectTest::UpdateQmEncodedFrame(size_t* encoded_size,
|
||||
size_t num_updates) {
|
||||
FrameType frame_type = kVideoFrameDelta;
|
||||
for (size_t i = 0; i < num_updates; ++i) {
|
||||
// Convert to bytes.
|
||||
size_t encoded_size_update = 1000 * encoded_size[i] / 8;
|
||||
qm_resolution_->UpdateEncodedSize(encoded_size_update, frame_type);
|
||||
qm_resolution_->UpdateEncodedSize(encoded_size_update);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ class EncodedImageCallbackWrapper : public EncodedImageCallback {
|
||||
}
|
||||
|
||||
// TODO(andresp): Change to void as return value is ignored.
|
||||
virtual int32_t Encoded(EncodedImage& encoded_image,
|
||||
virtual int32_t Encoded(const EncodedImage& encoded_image,
|
||||
const CodecSpecificInfo* codec_specific_info,
|
||||
const RTPFragmentationHeader* fragmentation) {
|
||||
CriticalSectionScoped cs(cs_.get());
|
||||
|
@ -86,16 +86,12 @@ class PacketizationCallback : public VCMPacketizationCallback {
|
||||
|
||||
virtual ~PacketizationCallback() {}
|
||||
|
||||
virtual int32_t SendData(FrameType frame_type,
|
||||
uint8_t payload_type,
|
||||
uint32_t timestamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payload_data,
|
||||
size_t payload_size,
|
||||
virtual int32_t SendData(uint8_t payload_type,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& fragmentation_header,
|
||||
const RTPVideoHeader* rtp_video_header) OVERRIDE {
|
||||
assert(rtp_video_header);
|
||||
frame_data_.push_back(FrameData(payload_size, *rtp_video_header));
|
||||
frame_data_.push_back(FrameData(encoded_image._length, *rtp_video_header));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -532,17 +532,11 @@ RTPSendCallback_SizeTest::AveragePayloadSize() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
VCMEncComplete_KeyReqTest::SendData(
|
||||
FrameType frameType,
|
||||
uint8_t payloadType,
|
||||
uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const RTPFragmentationHeader& /*fragmentationHeader*/,
|
||||
const webrtc::RTPVideoHeader* /*videoHdr*/)
|
||||
{
|
||||
int32_t VCMEncComplete_KeyReqTest::SendData(
|
||||
uint8_t payloadType,
|
||||
const webrtc::EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& /*fragmentationHeader*/,
|
||||
const webrtc::RTPVideoHeader* /*videoHdr*/) {
|
||||
WebRtcRTPHeader rtpInfo;
|
||||
rtpInfo.header.markerBit = true; // end of frame
|
||||
rtpInfo.type.Video.codecHeader.VP8.InitRTPVideoHeaderVP8();
|
||||
@ -555,5 +549,6 @@ VCMEncComplete_KeyReqTest::SendData(
|
||||
_timeStamp += 3000;
|
||||
rtpInfo.type.Video.isFirstPacket = false;
|
||||
rtpInfo.frameType = kVideoFrameKey;
|
||||
return _vcm.IncomingPacket(payloadData, payloadSize, rtpInfo);
|
||||
return _vcm.IncomingPacket(encoded_image._buffer, encoded_image._length,
|
||||
rtpInfo);
|
||||
}
|
||||
|
@ -95,14 +95,11 @@ class VCMEncComplete_KeyReqTest : public webrtc::VCMPacketizationCallback
|
||||
public:
|
||||
VCMEncComplete_KeyReqTest(webrtc::VideoCodingModule &vcm) : _vcm(vcm), _seqNo(0), _timeStamp(0) {}
|
||||
virtual int32_t SendData(
|
||||
webrtc::FrameType frameType,
|
||||
uint8_t payloadType,
|
||||
uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const webrtc::EncodedImage& encoded_image,
|
||||
const webrtc::RTPFragmentationHeader& fragmentationHeader,
|
||||
const webrtc::RTPVideoHeader* videoHdr) OVERRIDE;
|
||||
|
||||
private:
|
||||
webrtc::VideoCodingModule& _vcm;
|
||||
uint16_t _seqNo;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
|
||||
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
|
||||
#include "webrtc/modules/video_coding/main/test/test_callbacks.h"
|
||||
#include "webrtc/modules/video_coding/main/test/test_macros.h"
|
||||
#include "webrtc/modules/video_coding/main/test/test_util.h"
|
||||
@ -69,22 +70,17 @@ void VCMNTEncodeCompleteCallback::RegisterTransportCallback(
|
||||
{
|
||||
}
|
||||
|
||||
int32_t
|
||||
VCMNTEncodeCompleteCallback::SendData(
|
||||
FrameType frameType,
|
||||
uint8_t payloadType,
|
||||
uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const RTPFragmentationHeader& /*fragmentationHeader*/,
|
||||
const webrtc::RTPVideoHeader* videoHdr)
|
||||
|
||||
int32_t VCMNTEncodeCompleteCallback::SendData(
|
||||
uint8_t payloadType,
|
||||
const webrtc::EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& /*fragmentationHeader*/,
|
||||
const webrtc::RTPVideoHeader* videoHdr)
|
||||
{
|
||||
// will call the VCMReceiver input packet
|
||||
_frameType = frameType;
|
||||
_frameType = VCMEncodedFrame::ConvertFrameType(encoded_image._frameType);
|
||||
// writing encodedData into file
|
||||
if (fwrite(payloadData, 1, payloadSize, _encodedFile) != payloadSize) {
|
||||
if (fwrite(encoded_image._buffer, 1, encoded_image._length, _encodedFile) !=
|
||||
encoded_image._length) {
|
||||
return -1;
|
||||
}
|
||||
WebRtcRTPHeader rtpInfo;
|
||||
@ -111,18 +107,19 @@ VCMNTEncodeCompleteCallback::SendData(
|
||||
rtpInfo.header.payloadType = payloadType;
|
||||
rtpInfo.header.sequenceNumber = _seqNo++;
|
||||
rtpInfo.header.ssrc = 0;
|
||||
rtpInfo.header.timestamp = timeStamp;
|
||||
rtpInfo.frameType = frameType;
|
||||
rtpInfo.header.timestamp = encoded_image._timeStamp;
|
||||
rtpInfo.frameType = _frameType;
|
||||
rtpInfo.type.Video.isFirstPacket = true;
|
||||
// Size should also be received from that table, since the payload type
|
||||
// defines the size.
|
||||
|
||||
_encodedBytes += payloadSize;
|
||||
if (payloadSize < 20)
|
||||
_encodedBytes += encoded_image._length;
|
||||
if (encoded_image._length < 20)
|
||||
{
|
||||
_skipCnt++;
|
||||
}
|
||||
_VCMReceiver->IncomingPacket(payloadData, payloadSize, rtpInfo);
|
||||
_VCMReceiver->IncomingPacket(
|
||||
encoded_image._buffer, encoded_image._length, rtpInfo);
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
|
@ -33,12 +33,8 @@ class VCMNTEncodeCompleteCallback : public webrtc::VCMPacketizationCallback
|
||||
// process encoded data received from the encoder,
|
||||
// pass stream to the VCMReceiver module
|
||||
virtual int32_t SendData(
|
||||
webrtc::FrameType frameType,
|
||||
uint8_t payloadType,
|
||||
uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const webrtc::EncodedImage& encoded_image,
|
||||
const webrtc::RTPFragmentationHeader& fragmentationHeader,
|
||||
const webrtc::RTPVideoHeader* videoHdr) OVERRIDE;
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
|
||||
#include "webrtc/modules/utility/interface/rtp_dump.h"
|
||||
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
|
||||
#include "webrtc/modules/video_coding/main/test/test_macros.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
|
||||
@ -44,27 +45,22 @@ VCMEncodeCompleteCallback::~VCMEncodeCompleteCallback()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VCMEncodeCompleteCallback::RegisterTransportCallback(
|
||||
VCMPacketizationCallback* transport)
|
||||
{
|
||||
void VCMEncodeCompleteCallback::RegisterTransportCallback(
|
||||
VCMPacketizationCallback* transport) {
|
||||
}
|
||||
|
||||
int32_t
|
||||
VCMEncodeCompleteCallback::SendData(
|
||||
const FrameType frameType,
|
||||
const uint8_t payloadType,
|
||||
const uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
const size_t payloadSize,
|
||||
const uint8_t payloadType,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& fragmentationHeader,
|
||||
const RTPVideoHeader* videoHdr)
|
||||
{
|
||||
// will call the VCMReceiver input packet
|
||||
_frameType = frameType;
|
||||
_frameType = VCMEncodedFrame::ConvertFrameType(encoded_image._frameType);
|
||||
// writing encodedData into file
|
||||
if (fwrite(payloadData, 1, payloadSize, _encodedFile) != payloadSize) {
|
||||
if (fwrite(encoded_image._buffer, 1, encoded_image._length, _encodedFile) !=
|
||||
encoded_image._length) {
|
||||
return -1;
|
||||
}
|
||||
WebRtcRTPHeader rtpInfo;
|
||||
@ -93,14 +89,15 @@ VCMEncodeCompleteCallback::SendData(
|
||||
rtpInfo.header.payloadType = payloadType;
|
||||
rtpInfo.header.sequenceNumber = _seqNo++;
|
||||
rtpInfo.header.ssrc = 0;
|
||||
rtpInfo.header.timestamp = timeStamp;
|
||||
rtpInfo.frameType = frameType;
|
||||
rtpInfo.header.timestamp = encoded_image._timeStamp;
|
||||
rtpInfo.frameType = _frameType;
|
||||
// Size should also be received from that table, since the payload type
|
||||
// defines the size.
|
||||
|
||||
_encodedBytes += payloadSize;
|
||||
_encodedBytes += encoded_image._length;
|
||||
// directly to receiver
|
||||
int ret = _VCMReceiver->IncomingPacket(payloadData, payloadSize, rtpInfo);
|
||||
int ret = _VCMReceiver->IncomingPacket(encoded_image._buffer,
|
||||
encoded_image._length, rtpInfo);
|
||||
_encodeComplete = true;
|
||||
|
||||
return ret;
|
||||
@ -147,24 +144,20 @@ VCMEncodeCompleteCallback::ResetByteCount()
|
||||
|
||||
int32_t
|
||||
VCMRTPEncodeCompleteCallback::SendData(
|
||||
FrameType frameType,
|
||||
uint8_t payloadType,
|
||||
uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
uint8_t payloadType,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& fragmentationHeader,
|
||||
const RTPVideoHeader* videoHdr)
|
||||
{
|
||||
_frameType = frameType;
|
||||
_encodedBytes+= payloadSize;
|
||||
_frameType = VCMEncodedFrame::ConvertFrameType(encoded_image._frameType);
|
||||
_encodedBytes+= encoded_image._length;
|
||||
_encodeComplete = true;
|
||||
return _RTPModule->SendOutgoingData(frameType,
|
||||
return _RTPModule->SendOutgoingData(_frameType,
|
||||
payloadType,
|
||||
timeStamp,
|
||||
capture_time_ms,
|
||||
payloadData,
|
||||
payloadSize,
|
||||
encoded_image._timeStamp,
|
||||
encoded_image.capture_time_ms_,
|
||||
encoded_image._buffer,
|
||||
encoded_image._length,
|
||||
&fragmentationHeader,
|
||||
videoHdr);
|
||||
}
|
||||
|
@ -44,12 +44,8 @@ public:
|
||||
void RegisterTransportCallback(VCMPacketizationCallback* transport);
|
||||
// Process encoded data received from the encoder, pass stream to the
|
||||
// VCMReceiver module
|
||||
virtual int32_t SendData(FrameType frameType,
|
||||
uint8_t payloadType,
|
||||
uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
virtual int32_t SendData(uint8_t payloadType,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& fragmentationHeader,
|
||||
const RTPVideoHeader* videoHdr) OVERRIDE;
|
||||
// Register exisitng VCM. Currently - encode and decode under same module.
|
||||
@ -101,12 +97,8 @@ public:
|
||||
virtual ~VCMRTPEncodeCompleteCallback() {}
|
||||
// Process encoded data received from the encoder, pass stream to the
|
||||
// RTP module
|
||||
virtual int32_t SendData(FrameType frameType,
|
||||
uint8_t payloadType,
|
||||
uint32_t timeStamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
virtual int32_t SendData(uint8_t payloadType,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& fragmentationHeader,
|
||||
const RTPVideoHeader* videoHdr) OVERRIDE;
|
||||
// Return size of last encoded frame. Value good for one call
|
||||
|
@ -139,7 +139,7 @@ int32_t FakeH264Encoder::RegisterEncodeCompleteCallback(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t FakeH264Encoder::Encoded(EncodedImage& encoded_image,
|
||||
int32_t FakeH264Encoder::Encoded(const EncodedImage& encoded_image,
|
||||
const CodecSpecificInfo* codec_specific_info,
|
||||
const RTPFragmentationHeader* fragments) {
|
||||
const size_t kSpsSize = 8;
|
||||
|
@ -42,7 +42,7 @@ class FakeEncoder : public VideoEncoder {
|
||||
virtual int32_t SetRates(uint32_t new_target_bitrate,
|
||||
uint32_t framerate) OVERRIDE;
|
||||
|
||||
private:
|
||||
protected:
|
||||
Clock* const clock_;
|
||||
VideoCodec config_;
|
||||
EncodedImageCallback* callback_;
|
||||
@ -61,9 +61,9 @@ class FakeH264Encoder : public FakeEncoder, public EncodedImageCallback {
|
||||
EncodedImageCallback* callback) OVERRIDE;
|
||||
|
||||
virtual int32_t Encoded(
|
||||
EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo = NULL,
|
||||
const RTPFragmentationHeader* fragments = NULL) OVERRIDE;
|
||||
const EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const RTPFragmentationHeader* fragments) OVERRIDE;
|
||||
|
||||
private:
|
||||
EncodedImageCallback* callback_;
|
||||
|
@ -22,7 +22,7 @@ EncodedFrameCallbackAdapter::EncodedFrameCallbackAdapter(
|
||||
EncodedFrameCallbackAdapter::~EncodedFrameCallbackAdapter() {}
|
||||
|
||||
int32_t EncodedFrameCallbackAdapter::Encoded(
|
||||
EncodedImage& encodedImage,
|
||||
const EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const RTPFragmentationHeader* fragmentation) {
|
||||
assert(observer_ != NULL);
|
||||
|
@ -22,7 +22,7 @@ class EncodedFrameCallbackAdapter : public EncodedImageCallback {
|
||||
explicit EncodedFrameCallbackAdapter(EncodedFrameObserver* observer);
|
||||
virtual ~EncodedFrameCallbackAdapter();
|
||||
|
||||
virtual int32_t Encoded(EncodedImage& encodedImage,
|
||||
virtual int32_t Encoded(const EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const RTPFragmentationHeader* fragmentation);
|
||||
|
||||
|
@ -226,7 +226,7 @@ LowRateStreamObserver::LowRateStreamObserver(
|
||||
test::DirectTransport::SetReceiver(this);
|
||||
}
|
||||
|
||||
void LowRateStreamObserver::SetSendStream(const VideoSendStream* send_stream) {
|
||||
void LowRateStreamObserver::SetSendStream(VideoSendStream* send_stream) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
send_stream_ = send_stream;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class LowRateStreamObserver : public test::DirectTransport,
|
||||
size_t number_of_streams,
|
||||
bool rtx_used);
|
||||
|
||||
virtual void SetSendStream(const VideoSendStream* send_stream);
|
||||
virtual void SetSendStream(VideoSendStream* send_stream);
|
||||
|
||||
virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
|
||||
unsigned int bitrate);
|
||||
@ -135,7 +135,7 @@ class LowRateStreamObserver : public test::DirectTransport,
|
||||
scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
|
||||
|
||||
scoped_ptr<CriticalSectionWrapper> crit_;
|
||||
const VideoSendStream* send_stream_ GUARDED_BY(crit_);
|
||||
VideoSendStream* send_stream_ GUARDED_BY(crit_);
|
||||
FakeNetworkPipe::Config forward_transport_config_ GUARDED_BY(crit_);
|
||||
TestStates test_state_ GUARDED_BY(crit_);
|
||||
int64_t state_start_ms_ GUARDED_BY(crit_);
|
||||
|
@ -13,12 +13,16 @@
|
||||
#include <map>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
SendStatisticsProxy::SendStatisticsProxy(
|
||||
const VideoSendStream::Config& config)
|
||||
: config_(config),
|
||||
const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
|
||||
|
||||
SendStatisticsProxy::SendStatisticsProxy(Clock* clock,
|
||||
const VideoSendStream::Config& config)
|
||||
: clock_(clock),
|
||||
config_(config),
|
||||
crit_(CriticalSectionWrapper::CreateCriticalSection()) {
|
||||
}
|
||||
|
||||
@ -43,11 +47,26 @@ void SendStatisticsProxy::CapturedFrameRate(const int capture_id,
|
||||
stats_.input_frame_rate = frame_rate;
|
||||
}
|
||||
|
||||
VideoSendStream::Stats SendStatisticsProxy::GetStats() const {
|
||||
VideoSendStream::Stats SendStatisticsProxy::GetStats() {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
PurgeOldStats();
|
||||
return stats_;
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::PurgeOldStats() {
|
||||
int64_t current_time_ms = clock_->TimeInMilliseconds();
|
||||
for (std::map<uint32_t, SsrcStats>::iterator it = stats_.substreams.begin();
|
||||
it != stats_.substreams.end(); ++it) {
|
||||
uint32_t ssrc = it->first;
|
||||
if (update_times_[ssrc].resolution_update_ms + kStatsTimeoutMs >
|
||||
current_time_ms)
|
||||
continue;
|
||||
|
||||
it->second.sent_width = 0;
|
||||
it->second.sent_height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SsrcStats* SendStatisticsProxy::GetStatsEntry(uint32_t ssrc) {
|
||||
std::map<uint32_t, SsrcStats>::iterator it = stats_.substreams.find(ssrc);
|
||||
if (it != stats_.substreams.end())
|
||||
@ -64,6 +83,28 @@ SsrcStats* SendStatisticsProxy::GetStatsEntry(uint32_t ssrc) {
|
||||
return &stats_.substreams[ssrc]; // Insert new entry and return ptr.
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::OnSendEncodedImage(
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPVideoHeader* rtp_video_header) {
|
||||
size_t simulcast_idx =
|
||||
rtp_video_header != NULL ? rtp_video_header->simulcastIdx : 0;
|
||||
if (simulcast_idx >= config_.rtp.ssrcs.size()) {
|
||||
LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx
|
||||
<< " >= " << config_.rtp.ssrcs.size() << ").";
|
||||
return;
|
||||
}
|
||||
uint32_t ssrc = config_.rtp.ssrcs[simulcast_idx];
|
||||
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
SsrcStats* stats = GetStatsEntry(ssrc);
|
||||
if (stats == NULL)
|
||||
return;
|
||||
|
||||
stats->sent_width = encoded_image._encodedWidth;
|
||||
stats->sent_height = encoded_image._encodedHeight;
|
||||
update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
|
||||
uint32_t ssrc) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
|
@ -15,10 +15,12 @@
|
||||
|
||||
#include "webrtc/base/thread_annotations.h"
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
#include "webrtc/video_send_stream.h"
|
||||
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_send_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -32,10 +34,15 @@ class SendStatisticsProxy : public RtcpStatisticsCallback,
|
||||
public ViECaptureObserver,
|
||||
public SendSideDelayObserver {
|
||||
public:
|
||||
explicit SendStatisticsProxy(const VideoSendStream::Config& config);
|
||||
static const int kStatsTimeoutMs;
|
||||
|
||||
SendStatisticsProxy(Clock* clock, const VideoSendStream::Config& config);
|
||||
virtual ~SendStatisticsProxy();
|
||||
|
||||
VideoSendStream::Stats GetStats() const;
|
||||
VideoSendStream::Stats GetStats();
|
||||
|
||||
virtual void OnSendEncodedImage(const EncodedImage& encoded_image,
|
||||
const RTPVideoHeader* rtp_video_header);
|
||||
|
||||
protected:
|
||||
// From RtcpStatisticsCallback.
|
||||
@ -77,11 +84,18 @@ class SendStatisticsProxy : public RtcpStatisticsCallback,
|
||||
uint32_t ssrc) OVERRIDE;
|
||||
|
||||
private:
|
||||
struct StatsUpdateTimes {
|
||||
StatsUpdateTimes() : resolution_update_ms(0) {}
|
||||
int64_t resolution_update_ms;
|
||||
};
|
||||
void PurgeOldStats() EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
SsrcStats* GetStatsEntry(uint32_t ssrc) EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
|
||||
Clock* const clock_;
|
||||
const VideoSendStream::Config config_;
|
||||
scoped_ptr<CriticalSectionWrapper> crit_;
|
||||
VideoSendStream::Stats stats_ GUARDED_BY(crit_);
|
||||
std::map<uint32_t, StatsUpdateTimes> update_times_ GUARDED_BY(crit_);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -21,13 +21,14 @@ namespace webrtc {
|
||||
|
||||
class SendStatisticsProxyTest : public ::testing::Test {
|
||||
public:
|
||||
SendStatisticsProxyTest() : avg_delay_ms_(0), max_delay_ms_(0) {}
|
||||
SendStatisticsProxyTest()
|
||||
: fake_clock_(1234), avg_delay_ms_(0), max_delay_ms_(0) {}
|
||||
virtual ~SendStatisticsProxyTest() {}
|
||||
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
statistics_proxy_.reset(
|
||||
new SendStatisticsProxy(GetTestConfig()));
|
||||
new SendStatisticsProxy(&fake_clock_, GetTestConfig()));
|
||||
config_ = GetTestConfig();
|
||||
expected_ = VideoSendStream::Stats();
|
||||
}
|
||||
@ -81,6 +82,7 @@ class SendStatisticsProxyTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
scoped_ptr<SendStatisticsProxy> statistics_proxy_;
|
||||
SimulatedClock fake_clock_;
|
||||
VideoSendStream::Config config_;
|
||||
int avg_delay_ms_;
|
||||
int max_delay_ms_;
|
||||
@ -322,4 +324,51 @@ TEST_F(SendStatisticsProxyTest, NoSubstreams) {
|
||||
EXPECT_TRUE(stats.substreams.empty());
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
|
||||
static const int kEncodedWidth = 123;
|
||||
static const int kEncodedHeight = 81;
|
||||
EncodedImage encoded_image;
|
||||
encoded_image._encodedWidth = kEncodedWidth;
|
||||
encoded_image._encodedHeight = kEncodedHeight;
|
||||
|
||||
RTPVideoHeader rtp_video_header;
|
||||
|
||||
rtp_video_header.simulcastIdx = 0;
|
||||
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
|
||||
rtp_video_header.simulcastIdx = 1;
|
||||
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
|
||||
|
||||
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
|
||||
EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].sent_width);
|
||||
EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].sent_height);
|
||||
EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].sent_width);
|
||||
EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].sent_height);
|
||||
|
||||
// Forward almost to timeout, this should not have removed stats.
|
||||
fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
|
||||
stats = statistics_proxy_->GetStats();
|
||||
EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].sent_width);
|
||||
EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].sent_height);
|
||||
|
||||
// Update the first SSRC with bogus RTCP stats to make sure that encoded
|
||||
// resolution still times out (no global timeout for all stats).
|
||||
RtcpStatistics rtcp_statistics;
|
||||
RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
|
||||
rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
|
||||
|
||||
// Report stats for second SSRC to make sure it's not outdated along with the
|
||||
// first SSRC.
|
||||
rtp_video_header.simulcastIdx = 1;
|
||||
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
|
||||
|
||||
// Forward 1 ms, reach timeout, substream 0 should have no resolution
|
||||
// reported, but substream 1 should.
|
||||
fake_clock_.AdvanceTimeMilliseconds(1);
|
||||
stats = statistics_proxy_->GetStats();
|
||||
EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].sent_width);
|
||||
EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].sent_height);
|
||||
EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].sent_width);
|
||||
EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].sent_height);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -124,7 +124,7 @@ VideoSendStream::VideoSendStream(
|
||||
external_codec_(NULL),
|
||||
channel_(-1),
|
||||
use_config_bitrate_(true),
|
||||
stats_proxy_(config) {
|
||||
stats_proxy_(Clock::GetRealTimeClock(), config) {
|
||||
// Duplicate assert checking of bitrate config. These should be checked in
|
||||
// Call but are added here for verbosity.
|
||||
assert(bitrate_config.min_bitrate_bps >= 0);
|
||||
@ -218,6 +218,7 @@ VideoSendStream::VideoSendStream(
|
||||
video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer);
|
||||
|
||||
video_engine_base_->RegisterSendSideDelayObserver(channel_, &stats_proxy_);
|
||||
video_engine_base_->RegisterSendStatisticsProxy(channel_, &stats_proxy_);
|
||||
|
||||
image_process_ = ViEImageProcess::GetInterface(video_engine);
|
||||
image_process_->RegisterPreEncodeCallback(channel_,
|
||||
@ -442,7 +443,7 @@ bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
|
||||
return network_->ReceivedRTCPPacket(channel_, packet, length) == 0;
|
||||
}
|
||||
|
||||
VideoSendStream::Stats VideoSendStream::GetStats() const {
|
||||
VideoSendStream::Stats VideoSendStream::GetStats() {
|
||||
return stats_proxy_.GetStats();
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
virtual bool ReconfigureVideoEncoder(
|
||||
const VideoEncoderConfig& config) OVERRIDE;
|
||||
|
||||
virtual Stats GetStats() const OVERRIDE;
|
||||
virtual Stats GetStats() OVERRIDE;
|
||||
|
||||
bool DeliverRtcp(const uint8_t* packet, size_t length);
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "webrtc/test/configurable_frame_size_encoder.h"
|
||||
#include "webrtc/test/null_transport.h"
|
||||
#include "webrtc/test/testsupport/perf_test.h"
|
||||
#include "webrtc/video/send_statistics_proxy.h"
|
||||
#include "webrtc/video/transport_adapter.h"
|
||||
#include "webrtc/video_send_stream.h"
|
||||
|
||||
@ -1683,4 +1684,84 @@ TEST_F(VideoSendStreamTest, UsesCallStreamBitratesAndCanReconfigureBitrates) {
|
||||
|
||||
RunBaseTest(&test);
|
||||
}
|
||||
|
||||
TEST_F(VideoSendStreamTest, ReportsSentResolution) {
|
||||
static const size_t kNumStreams = 3;
|
||||
// Unusual resolutions to make sure that they are the ones being reported.
|
||||
static const struct {
|
||||
int width;
|
||||
int height;
|
||||
} kEncodedResolution[kNumStreams] = {
|
||||
{241, 181}, {300, 121}, {121, 221}};
|
||||
class ScreencastTargetBitrateTest : public test::SendTest,
|
||||
public test::FakeEncoder {
|
||||
public:
|
||||
ScreencastTargetBitrateTest()
|
||||
: SendTest(kDefaultTimeoutMs),
|
||||
test::FakeEncoder(Clock::GetRealTimeClock()) {}
|
||||
|
||||
private:
|
||||
virtual int32_t Encode(
|
||||
const I420VideoFrame& input_image,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const std::vector<VideoFrameType>* frame_types) OVERRIDE {
|
||||
CodecSpecificInfo specifics;
|
||||
memset(&specifics, 0, sizeof(specifics));
|
||||
specifics.codecType = kVideoCodecGeneric;
|
||||
|
||||
uint8_t buffer[16] = {0};
|
||||
EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
|
||||
encoded._timeStamp = input_image.timestamp();
|
||||
encoded.capture_time_ms_ = input_image.render_time_ms();
|
||||
|
||||
for (size_t i = 0; i < kNumStreams; ++i) {
|
||||
specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
|
||||
encoded._frameType = (*frame_types)[i];
|
||||
encoded._encodedWidth = kEncodedResolution[i].width;
|
||||
encoded._encodedHeight = kEncodedResolution[i].height;
|
||||
assert(callback_ != NULL);
|
||||
if (callback_->Encoded(encoded, &specifics, NULL) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
observation_complete_->Set();
|
||||
return 0;
|
||||
}
|
||||
virtual void ModifyConfigs(
|
||||
VideoSendStream::Config* send_config,
|
||||
std::vector<VideoReceiveStream::Config>* receive_configs,
|
||||
VideoEncoderConfig* encoder_config) OVERRIDE {
|
||||
send_config->encoder_settings.encoder = this;
|
||||
EXPECT_EQ(kNumStreams, encoder_config->streams.size());
|
||||
}
|
||||
|
||||
virtual size_t GetNumStreams() const OVERRIDE { return kNumStreams; }
|
||||
|
||||
virtual void PerformTest() OVERRIDE {
|
||||
EXPECT_EQ(kEventSignaled, Wait())
|
||||
<< "Timed out while waiting for the encoder to send one frame.";
|
||||
VideoSendStream::Stats stats = send_stream_->GetStats();
|
||||
|
||||
for (size_t i = 0; i < kNumStreams; ++i) {
|
||||
ASSERT_TRUE(stats.substreams.find(kSendSsrcs[i]) !=
|
||||
stats.substreams.end())
|
||||
<< "No stats for SSRC: " << kSendSsrcs[i]
|
||||
<< ", stats should exist as soon as frames have been encoded.";
|
||||
SsrcStats ssrc_stats = stats.substreams[kSendSsrcs[i]];
|
||||
EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.sent_width);
|
||||
EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.sent_height);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnStreamsCreated(
|
||||
VideoSendStream* send_stream,
|
||||
const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
|
||||
send_stream_ = send_stream;
|
||||
}
|
||||
|
||||
VideoSendStream* send_stream_;
|
||||
} test;
|
||||
|
||||
RunBaseTest(&test);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
@ -29,9 +29,9 @@ class EncodedImageCallback {
|
||||
virtual ~EncodedImageCallback() {}
|
||||
|
||||
// Callback function which is called when an image has been encoded.
|
||||
// TODO(pbos): Make encoded_image const or pointer. Remove default arguments.
|
||||
// TODO(pbos): Remove default arguments.
|
||||
virtual int32_t Encoded(
|
||||
EncodedImage& encoded_image,
|
||||
const EncodedImage& encoded_image,
|
||||
const CodecSpecificInfo* codec_specific_info = NULL,
|
||||
const RTPFragmentationHeader* fragmentation = NULL) = 0;
|
||||
};
|
||||
|
@ -25,6 +25,7 @@ namespace webrtc {
|
||||
|
||||
class Config;
|
||||
class VoiceEngine;
|
||||
class SendStatisticsProxy;
|
||||
|
||||
// CpuOveruseObserver is called when a system overuse is detected and
|
||||
// VideoEngine cannot keep up the encoding frequency.
|
||||
@ -238,6 +239,10 @@ class WEBRTC_DLLEXPORT ViEBase {
|
||||
// Returns the last VideoEngine error code.
|
||||
virtual int LastError() = 0;
|
||||
|
||||
virtual void RegisterSendStatisticsProxy(
|
||||
int channel,
|
||||
SendStatisticsProxy* send_statistics_proxy) = 0;
|
||||
|
||||
protected:
|
||||
ViEBase() {}
|
||||
virtual ~ViEBase() {}
|
||||
|
@ -358,4 +358,19 @@ int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ViEBaseImpl::RegisterSendStatisticsProxy(
|
||||
int channel,
|
||||
SendStatisticsProxy* send_statistics_proxy) {
|
||||
LOG_F(LS_VERBOSE) << "RegisterSendStatisticsProxy on channel " << channel;
|
||||
ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
|
||||
ViEChannel* vie_channel = cs.Channel(channel);
|
||||
if (!vie_channel) {
|
||||
shared_data_.SetLastError(kViEBaseInvalidChannelId);
|
||||
return;
|
||||
}
|
||||
ViEEncoder* vie_encoder = cs.Encoder(channel);
|
||||
assert(vie_encoder);
|
||||
|
||||
vie_encoder->RegisterSendStatisticsProxy(send_statistics_proxy);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
@ -67,6 +67,9 @@ class ViEBaseImpl
|
||||
int CreateChannel(int& video_channel, int original_channel, // NOLINT
|
||||
bool sender);
|
||||
|
||||
virtual void RegisterSendStatisticsProxy(
|
||||
int channel,
|
||||
SendStatisticsProxy* send_statistics_proxy) OVERRIDE;
|
||||
// ViEBaseImpl owns ViESharedData used by all interface implementations.
|
||||
ViESharedData shared_data_;
|
||||
};
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "webrtc/common_video/interface/video_image.h"
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/frame_callback.h"
|
||||
#include "webrtc/modules/pacing/include/paced_sender.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
|
||||
#include "webrtc/modules/utility/interface/process_thread.h"
|
||||
@ -29,9 +30,9 @@
|
||||
#include "webrtc/system_wrappers/interface/metrics.h"
|
||||
#include "webrtc/system_wrappers/interface/tick_util.h"
|
||||
#include "webrtc/system_wrappers/interface/trace_event.h"
|
||||
#include "webrtc/video/send_statistics_proxy.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_image_process.h"
|
||||
#include "webrtc/frame_callback.h"
|
||||
#include "webrtc/video_engine/vie_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -158,7 +159,8 @@ ViEEncoder::ViEEncoder(int32_t engine_id,
|
||||
qm_callback_(NULL),
|
||||
video_suspended_(false),
|
||||
pre_encode_callback_(NULL),
|
||||
start_ms_(Clock::GetRealTimeClock()->TimeInMilliseconds()) {
|
||||
start_ms_(Clock::GetRealTimeClock()->TimeInMilliseconds()),
|
||||
send_statistics_proxy_(NULL) {
|
||||
RtpRtcp::Configuration configuration;
|
||||
configuration.id = ViEModuleId(engine_id_, channel_id_);
|
||||
configuration.audio = false; // Video.
|
||||
@ -724,23 +726,19 @@ void ViEEncoder::SetSenderBufferingMode(int target_delay_ms) {
|
||||
}
|
||||
|
||||
int32_t ViEEncoder::SendData(
|
||||
const FrameType frame_type,
|
||||
const uint8_t payload_type,
|
||||
const uint32_t time_stamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payload_data,
|
||||
const size_t payload_size,
|
||||
const EncodedImage& encoded_image,
|
||||
const webrtc::RTPFragmentationHeader& fragmentation_header,
|
||||
const RTPVideoHeader* rtp_video_hdr) {
|
||||
if (send_statistics_proxy_ != NULL) {
|
||||
send_statistics_proxy_->OnSendEncodedImage(encoded_image, rtp_video_hdr);
|
||||
}
|
||||
// New encoded data, hand over to the rtp module.
|
||||
return default_rtp_rtcp_->SendOutgoingData(frame_type,
|
||||
payload_type,
|
||||
time_stamp,
|
||||
capture_time_ms,
|
||||
payload_data,
|
||||
payload_size,
|
||||
&fragmentation_header,
|
||||
rtp_video_hdr);
|
||||
return default_rtp_rtcp_->SendOutgoingData(
|
||||
VCMEncodedFrame::ConvertFrameType(encoded_image._frameType), payload_type,
|
||||
encoded_image._timeStamp, encoded_image.capture_time_ms_,
|
||||
encoded_image._buffer, encoded_image._length, &fragmentation_header,
|
||||
rtp_video_hdr);
|
||||
}
|
||||
|
||||
int32_t ViEEncoder::ProtectionRequest(
|
||||
@ -987,6 +985,11 @@ void ViEEncoder::DeRegisterPostEncodeImageCallback() {
|
||||
vcm_.RegisterPostEncodeImageCallback(NULL);
|
||||
}
|
||||
|
||||
void ViEEncoder::RegisterSendStatisticsProxy(
|
||||
SendStatisticsProxy* send_statistics_proxy) {
|
||||
send_statistics_proxy_ = send_statistics_proxy;
|
||||
}
|
||||
|
||||
QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm)
|
||||
: vpm_(vpm) {
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class PacedSender;
|
||||
class ProcessThread;
|
||||
class QMVideoSettingsCallback;
|
||||
class RtpRtcp;
|
||||
class SendStatisticsProxy;
|
||||
class ViEBitrateObserver;
|
||||
class ViEEffectFilter;
|
||||
class ViEEncoderObserver;
|
||||
@ -120,15 +121,10 @@ class ViEEncoder
|
||||
void SetSenderBufferingMode(int target_delay_ms);
|
||||
|
||||
// Implements VCMPacketizationCallback.
|
||||
virtual int32_t SendData(
|
||||
FrameType frame_type,
|
||||
uint8_t payload_type,
|
||||
uint32_t time_stamp,
|
||||
int64_t capture_time_ms,
|
||||
const uint8_t* payload_data,
|
||||
size_t payload_size,
|
||||
const RTPFragmentationHeader& fragmentation_header,
|
||||
const RTPVideoHeader* rtp_video_hdr) OVERRIDE;
|
||||
virtual int32_t SendData(uint8_t payload_type,
|
||||
const EncodedImage& encoded_image,
|
||||
const RTPFragmentationHeader& fragmentation_header,
|
||||
const RTPVideoHeader* rtp_video_hdr) OVERRIDE;
|
||||
|
||||
// Implements VideoProtectionCallback.
|
||||
virtual int ProtectionRequest(
|
||||
@ -177,6 +173,8 @@ class ViEEncoder
|
||||
EncodedImageCallback* post_encode_callback);
|
||||
void DeRegisterPostEncodeImageCallback();
|
||||
|
||||
void RegisterSendStatisticsProxy(SendStatisticsProxy* send_statistics_proxy);
|
||||
|
||||
int channel_id() const { return channel_id_; }
|
||||
|
||||
protected:
|
||||
@ -239,6 +237,8 @@ class ViEEncoder
|
||||
bool video_suspended_ GUARDED_BY(data_cs_);
|
||||
I420FrameCallback* pre_encode_callback_ GUARDED_BY(callback_cs_);
|
||||
const int64_t start_ms_;
|
||||
|
||||
SendStatisticsProxy* send_statistics_proxy_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -207,6 +207,7 @@ class EncodedImage {
|
||||
// NTP time of the capture time in local timebase in milliseconds.
|
||||
int64_t ntp_time_ms_;
|
||||
int64_t capture_time_ms_;
|
||||
// TODO(pbos): Use webrtc::FrameType directly (and remove VideoFrameType).
|
||||
VideoFrameType _frameType;
|
||||
uint8_t* _buffer;
|
||||
size_t _length;
|
||||
|
@ -151,7 +151,7 @@ class VideoSendStream {
|
||||
// with the VideoStream settings.
|
||||
virtual bool ReconfigureVideoEncoder(const VideoEncoderConfig& config) = 0;
|
||||
|
||||
virtual Stats GetStats() const = 0;
|
||||
virtual Stats GetStats() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~VideoSendStream() {}
|
||||
|
Loading…
Reference in New Issue
Block a user