Switching to I420VideoFrame

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2983 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mikhal@webrtc.org
2012-10-24 18:33:04 +00:00
parent 6392657643
commit 9fedff7c17
152 changed files with 2076 additions and 1862 deletions

View File

@ -47,7 +47,7 @@ public:
//
// Return value : WEBRTC_VIDEO_CODEC_OK if OK.
// <0 - Error
virtual int Encode(const VideoFrame& inputImage,
virtual int Encode(const I420VideoFrame& inputImage,
const CodecSpecificInfo* /*codecSpecificInfo*/,
const std::vector<VideoFrameType>* /*frame_types*/);
@ -138,7 +138,7 @@ public:
private:
VideoFrame _decodedImage;
I420VideoFrame _decodedImage;
int _width;
int _height;
bool _inited;

View File

@ -14,7 +14,6 @@
#include "common_video/libyuv/include/webrtc_libyuv.h"
namespace webrtc
{
@ -76,9 +75,9 @@ int I420Encoder::InitEncode(const VideoCodec* codecSettings,
int I420Encoder::Encode(const VideoFrame& inputImage,
const CodecSpecificInfo* /*codecSpecificInfo*/,
const std::vector<VideoFrameType>* /*frame_types*/) {
int I420Encoder::Encode(const I420VideoFrame& inputImage,
const CodecSpecificInfo* /*codecSpecificInfo*/,
const std::vector<VideoFrameType>* /*frame_types*/) {
if (!_inited) {
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
@ -87,29 +86,32 @@ int I420Encoder::Encode(const VideoFrame& inputImage,
}
_encodedImage._frameType = kKeyFrame; // No coding.
_encodedImage._timeStamp = inputImage.TimeStamp();
_encodedImage._encodedHeight = inputImage.Height();
_encodedImage._encodedWidth = inputImage.Width();
if (inputImage.Length() > _encodedImage._size) {
_encodedImage._timeStamp = inputImage.timestamp();
_encodedImage._encodedHeight = inputImage.height();
_encodedImage._encodedWidth = inputImage.width();
int req_length = CalcBufferSize(kI420, inputImage.width(),
inputImage.height());
if (_encodedImage._size > static_cast<unsigned int>(req_length)) {
// Allocating encoded memory.
if (_encodedImage._buffer != NULL) {
delete [] _encodedImage._buffer;
_encodedImage._buffer = NULL;
_encodedImage._size = 0;
}
const uint32_t newSize = CalcBufferSize(kI420,
_encodedImage._encodedWidth,
_encodedImage._encodedHeight);
uint8_t* newBuffer = new uint8_t[newSize];
uint8_t* newBuffer = new uint8_t[req_length];
if (newBuffer == NULL) {
return WEBRTC_VIDEO_CODEC_MEMORY;
}
_encodedImage._size = newSize;
_encodedImage._size = req_length;
_encodedImage._buffer = newBuffer;
}
memcpy(_encodedImage._buffer, inputImage.Buffer(), inputImage.Length());
_encodedImage._length = inputImage.Length();
int ret_length = ExtractBuffer(inputImage, req_length, _encodedImage._buffer);
if (ret_length < 0)
return WEBRTC_VIDEO_CODEC_MEMORY;
_encodedImage._length = ret_length;
_encodedCompleteCallback->Encoded(_encodedImage);
return WEBRTC_VIDEO_CODEC_OK;
}
@ -174,12 +176,24 @@ I420Decoder::Decode(const EncodedImage& inputImage,
}
// Set decoded image parameters.
if (_decodedImage.CopyFrame(inputImage._length, inputImage._buffer) < 0) {
int half_width = (_width + 1) / 2;
int half_height = (_height + 1) / 2;
int size_y = _width * _height;
int size_uv = half_width * half_height;
const uint8_t* buffer_y = inputImage._buffer;
const uint8_t* buffer_u = buffer_y + size_y;
const uint8_t* buffer_v = buffer_u + size_uv;
// TODO(mikhal): Do we need an align stride?
int ret = _decodedImage.CreateFrame(size_y, buffer_y,
size_uv, buffer_u,
size_uv, buffer_v,
_width, _height,
_width, half_width, half_width);
if (ret < 0) {
return WEBRTC_VIDEO_CODEC_MEMORY;
}
_decodedImage.SetHeight(_height);
_decodedImage.SetWidth(_width);
_decodedImage.SetTimeStamp(inputImage._timeStamp);
_decodedImage.set_timestamp(inputImage._timeStamp);
_decodeCompleteCallback->Decoded(_decodedImage);
return WEBRTC_VIDEO_CODEC_OK;
@ -193,7 +207,6 @@ I420Decoder::RegisterDecodeCompleteCallback(DecodedImageCallback* callback) {
int
I420Decoder::Release() {
_decodedImage.Free();
_inited = false;
return WEBRTC_VIDEO_CODEC_OK;
}

View File

@ -37,7 +37,7 @@ class MockVideoEncoder : public VideoEncoder {
WebRtc_Word32 numberOfCores,
WebRtc_UWord32 maxPayloadSize));
MOCK_METHOD3(Encode,
WebRtc_Word32(const VideoFrame& inputImage,
WebRtc_Word32(const I420VideoFrame& inputImage,
const CodecSpecificInfo* codecSpecificInfo,
const std::vector<VideoFrameType>* frame_types));
MOCK_METHOD1(RegisterEncodeCompleteCallback,
@ -57,7 +57,7 @@ class MockVideoEncoder : public VideoEncoder {
class MockDecodedImageCallback : public DecodedImageCallback {
public:
MOCK_METHOD1(Decoded,
WebRtc_Word32(VideoFrame& decodedImage));
WebRtc_Word32(I420VideoFrame& decodedImage));
MOCK_METHOD1(ReceivedDecodedReferenceFrame,
WebRtc_Word32(const WebRtc_UWord64 pictureId));
MOCK_METHOD1(ReceivedDecodedFrame,

View File

@ -14,9 +14,11 @@
#include <vector>
#include "common_types.h"
#include "common_video/interface/i420_video_frame.h"
#include "modules/interface/module_common_types.h"
#include "modules/video_coding/codecs/interface/video_error_codes.h"
#include "common_video/interface/video_image.h"
#include "typedefs.h"
namespace webrtc
@ -102,7 +104,7 @@ public:
// Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0
// otherwise.
virtual WebRtc_Word32 Encode(
const VideoFrame& inputImage,
const I420VideoFrame& inputImage,
const CodecSpecificInfo* codecSpecificInfo,
const std::vector<VideoFrameType>* frame_types) = 0;
@ -167,7 +169,7 @@ public:
// - decodedImage : The decoded image.
//
// Return value : 0 if OK, < 0 otherwise.
virtual WebRtc_Word32 Decoded(VideoFrame& decodedImage) = 0;
virtual WebRtc_Word32 Decoded(I420VideoFrame& decodedImage) = 0;
virtual WebRtc_Word32 ReceivedDecodedReferenceFrame(const WebRtc_UWord64 pictureId) {return -1;}

View File

@ -58,18 +58,11 @@ bool VideoProcessorImpl::Init() {
// Calculate a factor used for bit rate calculations:
bit_rate_factor_ = config_.codec_settings->maxFramerate * 0.001 * 8; // bits
int frame_length_in_bytes = frame_reader_->FrameLength();
// Initialize data structures used by the encoder/decoder APIs
int frame_length_in_bytes = frame_reader_->FrameLength();
source_buffer_ = new WebRtc_UWord8[frame_length_in_bytes];
last_successful_frame_buffer_ = new WebRtc_UWord8[frame_length_in_bytes];
// Set fixed properties common for all frames:
source_frame_.SetWidth(config_.codec_settings->width);
source_frame_.SetHeight(config_.codec_settings->height);
source_frame_.VerifyAndAllocate(frame_length_in_bytes);
source_frame_.SetLength(frame_length_in_bytes);
// Set fixed properties common for all frames.
// To keep track of spatial resize actions by encoder.
last_encoder_frame_width_ = config_.codec_settings->width;
last_encoder_frame_height_ = config_.codec_settings->height;
@ -169,15 +162,24 @@ bool VideoProcessorImpl::ProcessFrame(int frame_number) {
}
if (frame_reader_->ReadFrame(source_buffer_)) {
// Copy the source frame to the newly read frame data.
// Length is common for all frames.
source_frame_.CopyFrame(source_frame_.Length(), source_buffer_);
int size_y = config_.codec_settings->width * config_.codec_settings->height;
int half_width = (config_.codec_settings->width + 1) / 2;
int half_height = (config_.codec_settings->height + 1) / 2;
int size_uv = half_width * half_height;
source_frame_.CreateFrame(size_y, source_buffer_,
size_uv, source_buffer_ + size_y,
size_uv, source_buffer_ + size_y + size_uv,
config_.codec_settings->width,
config_.codec_settings->height,
config_.codec_settings->width,
half_width, half_width);
// Ensure we have a new statistics data object we can fill:
FrameStatistic& stat = stats_->NewFrame(frame_number);
encode_start_ = TickTime::Now();
// Use the frame number as "timestamp" to identify frames
source_frame_.SetTimeStamp(frame_number);
source_frame_.set_timestamp(frame_number);
// Decide if we're going to force a keyframe:
std::vector<VideoFrameType> frame_types(1, kDeltaFrame);
@ -273,9 +275,9 @@ void VideoProcessorImpl::FrameEncoded(EncodedImage* encoded_image) {
last_frame_missing_ = encoded_image->_length == 0;
}
void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) {
void VideoProcessorImpl::FrameDecoded(const I420VideoFrame& image) {
TickTime decode_stop = TickTime::Now();
int frame_number = image.TimeStamp();
int frame_number = image.timestamp();
// Report stats
FrameStatistic& stat = stats_->stats_[frame_number];
stat.decode_time_in_us = GetElapsedTimeMicroseconds(decode_start_,
@ -283,18 +285,18 @@ void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) {
stat.decoding_successful = true;
// Check for resize action (either down or up):
if (static_cast<int>(image.Width()) != last_encoder_frame_width_ ||
static_cast<int>(image.Height()) != last_encoder_frame_height_ ) {
if (static_cast<int>(image.width()) != last_encoder_frame_width_ ||
static_cast<int>(image.height()) != last_encoder_frame_height_ ) {
++num_spatial_resizes_;
last_encoder_frame_width_ = image.Width();
last_encoder_frame_height_ = image.Height();
last_encoder_frame_width_ = image.width();
last_encoder_frame_height_ = image.height();
}
// Check if codec size is different from native/original size, and if so,
// upsample back to original size: needed for PSNR and SSIM computations.
if (image.Width() != config_.codec_settings->width ||
image.Height() != config_.codec_settings->height) {
VideoFrame up_image;
int ret_val = scaler_.Set(image.Width(), image.Height(),
if (image.width() != config_.codec_settings->width ||
image.height() != config_.codec_settings->height) {
I420VideoFrame up_image;
int ret_val = scaler_.Set(image.width(), image.height(),
config_.codec_settings->width,
config_.codec_settings->height,
kI420, kI420, kScaleBilinear);
@ -309,20 +311,27 @@ void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) {
fprintf(stderr, "Failed to scale frame: %d, return code: %d\n",
frame_number, ret_val);
}
// TODO(mikhal): Extracting the buffer for now - need to update test.
int length = CalcBufferSize(kI420, up_image.width(), up_image.height());
scoped_array<uint8_t> image_buffer(new uint8_t[length]);
length = ExtractBuffer(up_image, length, image_buffer.get());
// Update our copy of the last successful frame:
memcpy(last_successful_frame_buffer_, up_image.Buffer(), up_image.Length());
bool write_success = frame_writer_->WriteFrame(up_image.Buffer());
memcpy(last_successful_frame_buffer_, image_buffer.get(), length);
bool write_success = frame_writer_->WriteFrame(image_buffer.get());
assert(write_success);
if (!write_success) {
fprintf(stderr, "Failed to write frame %d to disk!", frame_number);
}
up_image.Free();
} else { // No resize.
// Update our copy of the last successful frame:
memcpy(last_successful_frame_buffer_, image.Buffer(), image.Length());
// TODO(mikhal): Add as a member function, so won't be allocated per frame.
int length = CalcBufferSize(kI420,image.width(), image.height());
scoped_array<uint8_t> image_buffer(new uint8_t[length]);
length = ExtractBuffer(image, length, image_buffer.get());
assert(length > 0);
memcpy(last_successful_frame_buffer_, image_buffer.get(), length);
bool write_success = frame_writer_->WriteFrame(image.Buffer());
bool write_success = frame_writer_->WriteFrame(image_buffer.get());
assert(write_success);
if (!write_success) {
fprintf(stderr, "Failed to write frame %d to disk!", frame_number);
@ -379,7 +388,7 @@ VideoProcessorImpl::VideoProcessorEncodeCompleteCallback::Encoded(
}
WebRtc_Word32
VideoProcessorImpl::VideoProcessorDecodeCompleteCallback::Decoded(
VideoFrame& image) {
I420VideoFrame& image) {
video_processor_->FrameDecoded(image); // forward to parent class
return 0;
}

View File

@ -15,7 +15,7 @@
#include "common_video/libyuv/include/webrtc_libyuv.h"
#include "common_video/libyuv/include/scaler.h"
#include "modules/interface/module_common_types.h"
#include "common_video/interface/i420_video_frame.h"
#include "modules/video_coding/codecs/interface/video_codec_interface.h"
#include "modules/video_coding/codecs/test/packet_manipulator.h"
#include "modules/video_coding/codecs/test/stats.h"
@ -175,7 +175,7 @@ class VideoProcessorImpl : public VideoProcessor {
// Invoked by the callback when a frame has completed encoding.
void FrameEncoded(webrtc::EncodedImage* encodedImage);
// Invoked by the callback when a frame has completed decoding.
void FrameDecoded(const webrtc::VideoFrame& image);
void FrameDecoded(const webrtc::I420VideoFrame& image);
// Used for getting a 32-bit integer representing time
// (checks the size is within signed 32-bit bounds before casting it)
int GetElapsedTimeMicroseconds(const webrtc::TickTime& start,
@ -204,7 +204,7 @@ class VideoProcessorImpl : public VideoProcessor {
// Keep track of the last successful frame, since we need to write that
// when decoding fails:
WebRtc_UWord8* last_successful_frame_buffer_;
webrtc::VideoFrame source_frame_;
webrtc::I420VideoFrame source_frame_;
// To keep track of if we have excluded the first key frame from packet loss:
bool first_key_frame_has_been_excluded_;
// To tell the decoder previous frame have been dropped due to packet loss:
@ -247,7 +247,7 @@ class VideoProcessorImpl : public VideoProcessor {
explicit VideoProcessorDecodeCompleteCallback(VideoProcessorImpl* vp)
: video_processor_(vp) {
}
WebRtc_Word32 Decoded(webrtc::VideoFrame& image);
WebRtc_Word32 Decoded(webrtc::I420VideoFrame& image);
private:
VideoProcessorImpl* video_processor_;

View File

@ -156,7 +156,8 @@ class VideoProcessorIntegrationTest: public testing::Test {
webrtc::test::ResourcePath("foreman_cif", "yuv");
config_.output_filename = webrtc::test::OutputPath() +
"foreman_cif_short_video_codecs_test_framework_integrationtests.yuv";
config_.frame_length_in_bytes = 3 * kCIFWidth * kCIFHeight / 2;
config_.frame_length_in_bytes = CalcBufferSize(kI420,
kCIFWidth, kCIFHeight);
config_.verbose = false;
// Only allow encoder/decoder to use single core, for predictability.
config_.use_single_core = true;

View File

@ -64,7 +64,7 @@ class VideoProcessorTest: public testing::Test {
EXPECT_CALL(frame_reader_mock_, NumberOfFrames())
.WillOnce(Return(1));
EXPECT_CALL(frame_reader_mock_, FrameLength())
.WillOnce(Return(150000));
.WillOnce(Return(152064));
}
};

View File

@ -230,9 +230,6 @@ Benchmark::PerformNormalTest()
CodecSettings(_target->GetWidth(), _target->GetHeight(), _target->GetFrameRate(), _bitRate);
Setup();
EventWrapper* waitEvent = EventWrapper::Create();
_inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_encoder->InitEncode(&_inst, 4, 1440);
CodecSpecific_InitBitrate();
_decoder->InitDecode(&_inst,1);
@ -282,9 +279,7 @@ Benchmark::PerformNormalTest()
waitEvent->Wait(5);
}
_inputVideoBuffer.Free();
_encodedVideoBuffer.Free();
_decodedVideoBuffer.Free();
_encoder->Release();
_decoder->Release();

View File

@ -16,6 +16,7 @@
#include <sstream>
#include <vector>
#include "common_video/libyuv/include/webrtc_libyuv.h"
#include "gtest/gtest.h"
#include "tick_util.h"
#include "testsupport/fileutils.h"
@ -262,16 +263,13 @@ WebRtc_UWord32 VideoDecodeCompleteCallback::DecodedBytes()
}
WebRtc_Word32
VideoDecodeCompleteCallback::Decoded(VideoFrame& image)
VideoDecodeCompleteCallback::Decoded(I420VideoFrame& image)
{
_test.Decoded(image);
_decodedBytes += image.Length();
_decodedBytes += CalcBufferSize(kI420, image.width(), image.height());
if (_decodedFile != NULL)
{
if (fwrite(image.Buffer(), 1, image.Length(),
_decodedFile) != image.Length()) {
return -1;
}
return PrintI420VideoFrame(image, _decodedFile);
}
return 0;
}
@ -300,14 +298,14 @@ NormalAsyncTest::Encoded(const EncodedImage& encodedImage)
}
void
NormalAsyncTest::Decoded(const VideoFrame& decodedImage)
NormalAsyncTest::Decoded(const I420VideoFrame& decodedImage)
{
_decodeCompleteTime = tGetTime();
_decFrameCnt++;
_totalDecodePipeTime += _decodeCompleteTime -
_decodeTimes[decodedImage.TimeStamp()];
_decodedWidth = decodedImage.Width();
_decodedHeight = decodedImage.Height();
_decodeTimes[decodedImage.timestamp()];
_decodedWidth = decodedImage.width();
_decodedHeight = decodedImage.height();
}
void
@ -316,8 +314,6 @@ NormalAsyncTest::Perform()
_inname = webrtc::test::ProjectRootPath() + "resources/foreman_cif.yuv";
CodecSettings(352, 288, 30, _bitRate);
Setup();
_inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
if(_encoder->InitEncode(&_inst, 1, 1440) < 0)
{
exit(EXIT_FAILURE);
@ -410,17 +406,19 @@ NormalAsyncTest::Encode()
{
_lengthEncFrame = 0;
EXPECT_GT(fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile), 0u);
_inputVideoBuffer.CopyFrame(_lengthSourceFrame, _sourceBuffer);
_inputVideoBuffer.SetTimeStamp((unsigned int)
_inputVideoBuffer.CreateFrame(_sizeY, _sourceBuffer,
_sizeUv, _sourceBuffer + _sizeY,
_sizeUv, _sourceBuffer + _sizeY + _sizeUv,
_width, _height,
_width, _halfWidth, _halfWidth);
_inputVideoBuffer.set_timestamp((unsigned int)
(_encFrameCnt * 9e4 / _inst.maxFramerate));
_inputVideoBuffer.SetWidth(_inst.width);
_inputVideoBuffer.SetHeight(_inst.height);
if (feof(_sourceFile) != 0)
{
return true;
}
_encodeCompleteTime = 0;
_encodeTimes[_inputVideoBuffer.TimeStamp()] = tGetTime();
_encodeTimes[_inputVideoBuffer.timestamp()] = tGetTime();
std::vector<VideoFrameType> frame_types(1, kDeltaFrame);
// check SLI queue
@ -474,12 +472,12 @@ NormalAsyncTest::Encode()
if (_encodeCompleteTime > 0)
{
_totalEncodeTime += _encodeCompleteTime -
_encodeTimes[_inputVideoBuffer.TimeStamp()];
_encodeTimes[_inputVideoBuffer.timestamp()];
}
else
{
_totalEncodeTime += tGetTime() -
_encodeTimes[_inputVideoBuffer.TimeStamp()];
_encodeTimes[_inputVideoBuffer.timestamp()];
}
assert(ret >= 0);
return false;

View File

@ -80,7 +80,7 @@ public:
virtual ~NormalAsyncTest() {};
virtual void Perform();
virtual void Encoded(const webrtc::EncodedImage& encodedImage);
virtual void Decoded(const webrtc::VideoFrame& decodedImage);
virtual void Decoded(const webrtc::I420VideoFrame& decodedImage);
virtual webrtc::CodecSpecificInfo*
CopyCodecSpecificInfo(
const webrtc::CodecSpecificInfo* codecSpecificInfo) const;
@ -172,7 +172,7 @@ public:
_decodedBytes(0)
{}
virtual WebRtc_Word32 Decoded(webrtc::VideoFrame& decodedImage);
virtual WebRtc_Word32 Decoded(webrtc::I420VideoFrame& decodedImage);
virtual WebRtc_Word32
ReceivedDecodedReferenceFrame(const WebRtc_UWord64 pictureId);
virtual WebRtc_Word32 ReceivedDecodedFrame(const WebRtc_UWord64 pictureId);

View File

@ -14,6 +14,7 @@
#include <sstream>
#include <string.h>
#include "common_video/libyuv/include/webrtc_libyuv.h"
#include "gtest/gtest.h"
#include "testsupport/fileutils.h"
@ -22,7 +23,13 @@ NormalTest::NormalTest()
CodecTest("Normal Test 1", "A test of normal execution of the codec"),
_testNo(1),
_lengthEncFrame(0),
_appendNext(false)
_appendNext(false),
_width(0),
_halfWidth(0),
_height(0),
_halfHeight(0),
_sizeY(0),
_sizeUv(0)
{
}
@ -33,7 +40,13 @@ CodecTest(name, description),
_requestKeyFrame(false),
_testNo(testNo),
_lengthEncFrame(0),
_appendNext(false)
_appendNext(false),
_width(0),
_halfWidth(0),
_height(0),
_halfHeight(0),
_sizeY(0),
_sizeUv(0)
{
}
@ -108,12 +121,22 @@ NormalTest::Teardown()
void
NormalTest::Perform()
{
_width = 352;
_halfWidth = (_width + 1) / 2;
_height = 288;
_halfHeight = (_height + 1) / 2;
_sizeY = _width * _height;
_sizeUv = _halfWidth * _halfHeight;
_inname = webrtc::test::ProjectRootPath() + "resources/foreman_cif.yuv";
CodecSettings(352, 288, 30, _bitRate);
CodecSettings(_width, _height, 30, _bitRate);
Setup();
_inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_inputVideoBuffer.CreateEmptyFrame(_width, _height,
_width, _halfWidth, _halfWidth);
_inputVideoBuffer.CreateEmptyFrame(_width, _height,
_width, _halfWidth, _halfWidth);
_decodedVideoBuffer.CreateEmptyFrame(_width, _height,
_width, _halfWidth, _halfWidth);
_encodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_encoder->InitEncode(&_inst, 1, 1460);
@ -140,8 +163,7 @@ NormalTest::Perform()
fprintf(stderr,"\n\nError in decoder: %d\n\n", decodeLength);
exit(EXIT_FAILURE);
}
if (fwrite(_decodedVideoBuffer.Buffer(), 1, decodeLength,
_decodedFile) != static_cast<unsigned int>(decodeLength)) {
if (PrintI420VideoFrame(_decodedVideoBuffer, _decodedFile) < 0) {
return;
}
CodecSpecific_InitBitrate();
@ -157,8 +179,7 @@ NormalTest::Perform()
fprintf(stderr,"\n\nError in decoder: %d\n\n", decodeLength);
exit(EXIT_FAILURE);
}
if (fwrite(_decodedVideoBuffer.Buffer(), 1, decodeLength,
_decodedFile) != static_cast<unsigned int>(decodeLength)) {
if (PrintI420VideoFrame(_decodedVideoBuffer, _decodedFile) < 0) {
return;
}
}
@ -173,8 +194,6 @@ NormalTest::Perform()
(*_log) << "Average encode time: " << avgEncTime << " s" << std::endl;
(*_log) << "Average decode time: " << avgDecTime << " s" << std::endl;
_inputVideoBuffer.Free();
_encoder->Release();
_decoder->Release();
@ -190,8 +209,13 @@ NormalTest::Encode()
{
return true;
}
_inputVideoBuffer.CopyFrame(_lengthSourceFrame, _sourceBuffer);
_inputVideoBuffer.SetTimeStamp(_framecnt);
_inputVideoBuffer.CreateFrame(_sizeY, _sourceBuffer,
_sizeUv, _sourceBuffer + _sizeY,
_sizeUv, _sourceBuffer + _sizeY +
_sizeUv,
_width, _height,
_width, _halfWidth, _halfWidth);
_inputVideoBuffer.set_timestamp(_framecnt);
// This multiple attempt ridiculousness is to accomodate VP7:
// 1. The wrapper can unilaterally reduce the framerate for low bitrates.
@ -204,8 +228,8 @@ NormalTest::Encode()
{
starttime = clock()/(double)CLOCKS_PER_SEC;
_inputVideoBuffer.SetWidth(_inst.width);
_inputVideoBuffer.SetHeight(_inst.height);
_inputVideoBuffer.set_width(_inst.width);
_inputVideoBuffer.set_height(_inst.height);
//_lengthEncFrame = _encoder->Encode(_inputVideoBuffer, _encodedVideoBuffer, _frameInfo,
// _inst.frameRate, _requestKeyFrame && !(_framecnt%50));

View File

@ -40,6 +40,12 @@ protected:
unsigned int _testNo;
int _lengthEncFrame;
bool _appendNext;
int _width;
int _halfWidth;
int _height;
int _halfHeight;
int _sizeY;
int _sizeUv;
};
#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_FRAMEWORK_NORMAL_TEST_H_

View File

@ -64,11 +64,11 @@ PacketLossTest::Encoded(const EncodedImage& encodedImage)
}
void
PacketLossTest::Decoded(const VideoFrame& decodedImage)
PacketLossTest::Decoded(const I420VideoFrame& decodedImage)
{
// check the frame queue if any frames have gone missing
assert(!_frameQueue.empty()); // decoded frame is not in the queue
while(_frameQueue.front() < decodedImage.TimeStamp())
while(_frameQueue.front() < decodedImage.timestamp())
{
// this frame is missing
// write previous decoded frame again (frame freeze)
@ -84,20 +84,23 @@ PacketLossTest::Decoded(const VideoFrame& decodedImage)
_frameQueue.pop_front();
}
// Decoded frame is not in the queue.
assert(_frameQueue.front() == decodedImage.TimeStamp());
assert(_frameQueue.front() == decodedImage.timestamp());
// pop the current frame
_frameQueue.pop_front();
// save image for future freeze-frame
if (_lastFrameLength < decodedImage.Length())
unsigned int length = CalcBufferSize(kI420, decodedImage.width(),
decodedImage.height());
if (_lastFrameLength < length)
{
if (_lastFrame) delete [] _lastFrame;
_lastFrame = new WebRtc_UWord8[decodedImage.Length()];
_lastFrame = new WebRtc_UWord8[length];
}
memcpy(_lastFrame, decodedImage.Buffer(), decodedImage.Length());
_lastFrameLength = decodedImage.Length();
// TODO(mikhal): Can't the last frame be a I420VideoFrame?
ExtractBuffer(decodedImage, length, _lastFrame);
_lastFrameLength = length;
NormalAsyncTest::Decoded(decodedImage);
}

View File

@ -21,7 +21,7 @@ public:
PacketLossTest();
virtual ~PacketLossTest() {if(_lastFrame) {delete [] _lastFrame; _lastFrame = NULL;}}
virtual void Encoded(const webrtc::EncodedImage& encodedImage);
virtual void Decoded(const webrtc::VideoFrame& decodedImage);
virtual void Decoded(const webrtc::I420VideoFrame& decodedImage);
protected:
PacketLossTest(std::string name, std::string description);
PacketLossTest(std::string name,

View File

@ -49,11 +49,11 @@ protected:
WebRtc_UWord32 _bitRate;
unsigned int _lengthSourceFrame;
unsigned char* _sourceBuffer;
webrtc::VideoFrame _inputVideoBuffer;
webrtc::I420VideoFrame _inputVideoBuffer;
// TODO(mikhal): For now using VideoFrame for encodedBuffer, should use a
// designated class.
webrtc::VideoFrame _encodedVideoBuffer;
webrtc::VideoFrame _decodedVideoBuffer;
webrtc::I420VideoFrame _decodedVideoBuffer;
webrtc::VideoCodec _inst;
std::fstream* _log;
std::string _inname;

View File

@ -98,7 +98,8 @@ UnitTestEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
_encodedVideoBuffer->VerifyAndAllocate(encodedImage._size);
_encodedVideoBuffer->CopyFrame(encodedImage._size, encodedImage._buffer);
_encodedVideoBuffer->SetLength(encodedImage._length);
// _encodedVideoBuffer->SetFrameType(encodedImage._frameType);
// TODO(mikhal): Update frame type API.
// _encodedVideoBuffer->SetFrameType(encodedImage._frameType);
_encodedVideoBuffer->SetWidth(
(WebRtc_UWord16)encodedImage._encodedWidth);
_encodedVideoBuffer->SetHeight(
@ -109,12 +110,9 @@ UnitTestEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
return 0;
}
WebRtc_Word32 UnitTestDecodeCompleteCallback::Decoded(VideoFrame& image)
WebRtc_Word32 UnitTestDecodeCompleteCallback::Decoded(I420VideoFrame& image)
{
_decodedVideoBuffer->CopyFrame(image.Length(), image.Buffer());
_decodedVideoBuffer->SetWidth(image.Width());
_decodedVideoBuffer->SetHeight(image.Height());
_decodedVideoBuffer->SetTimeStamp(image.TimeStamp());
_decodedVideoBuffer->CopyFrame(image);
_decodeComplete = true;
return 0;
}
@ -155,7 +153,7 @@ UnitTest::WaitForEncodedFrame() const
{
if (_encodeCompleteCallback->EncodeComplete())
{
return _encodedVideoBuffer.Length();
return _encodedVideoBuffer.Length();
}
}
return 0;
@ -169,7 +167,8 @@ UnitTest::WaitForDecodedFrame() const
{
if (_decodeCompleteCallback->DecodeComplete())
{
return _decodedVideoBuffer.Length();
return webrtc::CalcBufferSize(kI420, _decodedVideoBuffer.width(),
_decodedVideoBuffer.height());
}
}
return 0;
@ -224,12 +223,16 @@ UnitTest::Setup()
_inst.codecSpecific.VP8.denoisingOn = true;
// Get input frame.
_inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
ASSERT_TRUE(fread(_refFrame, 1, _lengthSourceFrame, _sourceFile)
== _lengthSourceFrame);
_inputVideoBuffer.CopyFrame(_lengthSourceFrame, _refFrame);
_inputVideoBuffer.SetWidth(_source->GetWidth());
_inputVideoBuffer.SetHeight(_source->GetHeight());
int size_y = _inst.width * _inst.height;
int size_uv = ((_inst.width + 1) / 2) * ((_inst.height + 1) / 2);
_inputVideoBuffer.CreateFrame(size_y, _refFrame,
size_uv, _refFrame + size_y,
size_uv, _refFrame + size_y + size_uv,
_inst.width, _inst.height,
_inst.width,
(_inst.width + 1) / 2, (_inst.width + 1) / 2);
rewind(_sourceFile);
// Get a reference encoded frame.
@ -244,7 +247,9 @@ UnitTest::Setup()
memcpy(_refEncFrame, _encodedVideoBuffer.Buffer(), _refEncFrameLength);
// Get a reference decoded frame.
_decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_decodedVideoBuffer.CreateEmptyFrame(_inst.width, _inst.height, _inst.width,
(_inst.width + 1) / 2,
(_inst.width + 1) / 2);
EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
@ -255,12 +260,15 @@ UnitTest::Setup()
if (i > 0)
{
// Insert yet another frame
_inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
ASSERT_TRUE(fread(_refFrame, 1, _lengthSourceFrame,
_sourceFile) == _lengthSourceFrame);
_inputVideoBuffer.CopyFrame(_lengthSourceFrame, _refFrame);
_inputVideoBuffer.SetWidth(_source->GetWidth());
_inputVideoBuffer.SetHeight(_source->GetHeight());
_inputVideoBuffer.CreateFrame(size_y, _refFrame,
size_uv, _refFrame + size_y,
size_uv, _refFrame + size_y + size_uv,
_inst.width, _inst.height,
_inst.width,
(_inst.width + 1) / 2,
(_inst.width + 1) / 2);
_encoder->Encode(_inputVideoBuffer, NULL, NULL);
ASSERT_TRUE(WaitForEncodedFrame() > 0);
}
@ -274,7 +282,7 @@ UnitTest::Setup()
}
rewind(_sourceFile);
EXPECT_TRUE(frameLength == _lengthSourceFrame);
memcpy(_refDecFrame, _decodedVideoBuffer.Buffer(), _lengthSourceFrame);
ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame, _refDecFrame);
}
void
@ -342,7 +350,7 @@ UnitTest::Perform()
{
UnitTest::Setup();
int frameLength;
VideoFrame inputImage;
I420VideoFrame inputImage;
EncodedImage encodedImage;
//----- Encoder parameter tests -----
@ -409,17 +417,20 @@ UnitTest::Perform()
EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
//-- Encode() errors --
// inputVideoBuffer unallocated.
_inputVideoBuffer.Free();
inputImage.Free();
inputImage.ResetSize();
EXPECT_TRUE(_encoder->Encode(inputImage, NULL, NULL) ==
WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
_inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_inputVideoBuffer.CopyFrame(_lengthSourceFrame, _refFrame);
_inputVideoBuffer.SetWidth(_source->GetWidth());
_inputVideoBuffer.SetHeight(_source->GetHeight());
int width = _source->GetWidth();
int half_width = (width + 1) / 2;
int height = _source->GetHeight();
int half_height = (height + 1) / 2;
int size_y = width * height;
int size_uv = half_width * half_height;
_inputVideoBuffer.CreateFrame(size_y, _refFrame,
size_uv, _refFrame + size_y,
size_uv, _refFrame + size_y + size_uv,
width, height,
width, half_width, half_width);
//----- Encoder stress tests -----
// Vary frame rate and I-frame request.
@ -539,8 +550,12 @@ UnitTest::Perform()
_decoder->Decode(encodedImage, false, NULL);
frameLength = WaitForDecodedFrame();
}
EXPECT_TRUE(CheckIfBitExact(_decodedVideoBuffer.Buffer(), frameLength,
_refDecFrame, _lengthSourceFrame) == true);
unsigned int length = CalcBufferSize(kI420, width, height);
scoped_array<uint8_t> decoded_buffer(new uint8_t[length]);
ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame,
decoded_buffer.get());
EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength, _refDecFrame,
_lengthSourceFrame) == true);
// Reset then decode.
EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
@ -551,8 +566,10 @@ UnitTest::Perform()
_decoder->Decode(encodedImage, false, NULL);
frameLength = WaitForDecodedFrame();
}
EXPECT_TRUE(CheckIfBitExact(_decodedVideoBuffer.Buffer(), frameLength,
_refDecFrame, _lengthSourceFrame) == true);
ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame,
decoded_buffer.get());
EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength,
_refDecFrame, _lengthSourceFrame) == true);
// Decode with other size, reset, then decode with original size again
// to verify that decoder is reset to a "fresh" state upon Reset().
@ -565,20 +582,25 @@ UnitTest::Perform()
memcpy(&tempInst, &_inst, sizeof(VideoCodec));
tempInst.width /= 2;
tempInst.height /= 2;
int tmpHalfWidth = (tempInst.width + 1) / 2;
int tmpHalfHeight = (tempInst.height + 1) / 2;
int tmpSizeY = tempInst.width * tempInst.height;
int tmpSizeUv = tmpHalfWidth * tmpHalfHeight;
// Encode reduced (quarter) frame size.
EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
EXPECT_TRUE(_encoder->InitEncode(&tempInst, 1, 1440) ==
WEBRTC_VIDEO_CODEC_OK);
VideoFrame tempInput;
unsigned int tmpLength = _inputVideoBuffer.Length() / 4;
tempInput.CopyFrame(tmpLength, _inputVideoBuffer.Buffer());
tempInput.SetWidth(tempInst.width);
tempInput.SetHeight(tempInst.height);
webrtc::I420VideoFrame tempInput;
tempInput.CreateFrame(tmpSizeY, _inputVideoBuffer.buffer(kYPlane),
tmpSizeUv, _inputVideoBuffer.buffer(kUPlane),
tmpSizeUv, _inputVideoBuffer.buffer(kVPlane),
tempInst.width, tempInst.height,
tempInst.width, tmpHalfWidth, tmpHalfWidth);
_encoder->Encode(tempInput, NULL, NULL);
frameLength = WaitForEncodedFrame();
EXPECT_TRUE(frameLength > 0);
tempInput.Free();
// Reset then decode.
EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
frameLength = 0;
@ -608,9 +630,11 @@ UnitTest::Perform()
}
// check that decoded frame matches with reference
EXPECT_TRUE(CheckIfBitExact(_decodedVideoBuffer.Buffer(), frameLength,
_refDecFrame, _lengthSourceFrame) == true);
unsigned int length = CalcBufferSize(kI420, width, height);
scoped_array<uint8_t> decoded_buffer(new uint8_t[length]);
ExtractBuffer(_decodedVideoBuffer, length, decoded_buffer.get());
EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), length,
_refDecFrame, _lengthSourceFrame) == true);
}
// Release then decode.
@ -624,8 +648,9 @@ UnitTest::Perform()
_decoder->Decode(encodedImage, false, NULL);
frameLength = WaitForDecodedFrame();
}
EXPECT_TRUE(CheckIfBitExact(_decodedVideoBuffer.Buffer(), frameLength,
_refDecFrame, _lengthSourceFrame) == true);
ExtractBuffer(_decodedVideoBuffer, length, decoded_buffer.get());
EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength,
_refDecFrame, _lengthSourceFrame) == true);
_encodedVideoBuffer.SetLength(0);
delete [] tmpBuf;
@ -644,19 +669,24 @@ UnitTest::Perform()
frames = 0;
int frameDelay = 0;
int encTimeStamp;
_decodedVideoBuffer.SetTimeStamp(0);
_decodedVideoBuffer.set_timestamp(0);
while (fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile) ==
_lengthSourceFrame)
{
_inputVideoBuffer.CopyFrame(_lengthSourceFrame, _sourceBuffer);
_inputVideoBuffer.SetTimeStamp(frames);
_inputVideoBuffer.CreateFrame(size_y, _sourceBuffer,
size_uv, _sourceBuffer + size_y,
size_uv, _sourceBuffer + size_y + size_uv,
width, height,
width, half_width, half_width);
_inputVideoBuffer.set_timestamp(frames);
ASSERT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
WEBRTC_VIDEO_CODEC_OK);
frameLength = WaitForEncodedFrame();
//ASSERT_TRUE(frameLength);
EXPECT_TRUE(frameLength > 0);
encTimeStamp = _encodedVideoBuffer.TimeStamp();
EXPECT_TRUE(_inputVideoBuffer.TimeStamp() ==
EXPECT_TRUE(_inputVideoBuffer.timestamp() ==
static_cast<unsigned>(encTimeStamp));
frameLength = Decode();
@ -670,7 +700,7 @@ UnitTest::Perform()
{
encTimeStamp = 0;
}
EXPECT_TRUE(_decodedVideoBuffer.TimeStamp() ==
EXPECT_TRUE(_decodedVideoBuffer.timestamp() ==
static_cast<unsigned>(encTimeStamp));
frames++;
}
@ -678,7 +708,6 @@ UnitTest::Perform()
rewind(_sourceFile);
RateControlTests();
inputImage.Free();
Teardown();
}
@ -719,13 +748,22 @@ UnitTest::RateControlTests()
{
CodecSpecific_SetBitrate(_bitRate, _inst.maxFramerate);
}
int width = _source->GetWidth();
int half_width = (width + 1) / 2;
int height = _source->GetHeight();
int half_height = (height + 1) / 2;
int size_y = width * height;
int size_uv = half_width * half_height;
while (fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile) ==
_lengthSourceFrame)
{
_inputVideoBuffer.CopyFrame(_lengthSourceFrame, _sourceBuffer);
_inputVideoBuffer.SetTimeStamp(_inputVideoBuffer.TimeStamp() +
static_cast<WebRtc_UWord32>(9e4 /
_inputVideoBuffer.CreateFrame(size_y, _sourceBuffer,
size_uv, _sourceBuffer + size_y,
size_uv, _sourceBuffer + size_y +
size_uv,
width, height,
width, half_width, half_width);
_inputVideoBuffer.set_timestamp(static_cast<WebRtc_UWord32>(9e4 /
static_cast<float>(_inst.maxFramerate)));
ASSERT_EQ(_encoder->Encode(_inputVideoBuffer, NULL, NULL),
WEBRTC_VIDEO_CODEC_OK);

View File

@ -94,12 +94,12 @@ private:
class UnitTestDecodeCompleteCallback : public webrtc::DecodedImageCallback
{
public:
UnitTestDecodeCompleteCallback(webrtc::VideoFrame* buffer) :
UnitTestDecodeCompleteCallback(webrtc::I420VideoFrame* buffer) :
_decodedVideoBuffer(buffer), _decodeComplete(false) {}
WebRtc_Word32 Decoded(webrtc::VideoFrame& image);
WebRtc_Word32 Decoded(webrtc::I420VideoFrame& image);
bool DecodeComplete();
private:
webrtc::VideoFrame* _decodedVideoBuffer;
webrtc::I420VideoFrame* _decodedVideoBuffer;
bool _decodeComplete;
};

View File

@ -36,8 +36,6 @@ VP8DualDecoderTest::~VP8DualDecoderTest()
_decoder2->Release();
delete _decoder2;
}
_decodedVideoBuffer2.Free();
}
void
@ -46,9 +44,6 @@ VP8DualDecoderTest::Perform()
_inname = webrtc::test::ProjectRootPath() + "resources/foreman_cif.yuv";
CodecSettings(352, 288, 30, _bitRate);
Setup();
_inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_decodedVideoBuffer2.VerifyAndAllocate(_lengthSourceFrame);
if(_encoder->InitEncode(&_inst, 4, 1460) < 0)
{
exit(EXIT_FAILURE);
@ -171,9 +166,7 @@ VP8DualDecoderTest::Decode(int lossValue)
}
// compare decoded images
if (!CheckIfBitExact(_decodedVideoBuffer.Buffer(),
_decodedVideoBuffer.Length(),
_decodedVideoBuffer2.Buffer(), _decodedVideoBuffer.Length()))
if (!CheckIfBitExactFrames(_decodedVideoBuffer, _decodedVideoBuffer2))
{
fprintf(stderr,"\n\nClone output different from master.\n\n");
exit(EXIT_FAILURE);
@ -185,26 +178,10 @@ VP8DualDecoderTest::Decode(int lossValue)
return ret;
}
bool
VP8DualDecoderTest::CheckIfBitExact(const void* ptrA, unsigned int aLengthBytes,
const void* ptrB, unsigned int bLengthBytes)
WebRtc_Word32 DualDecoderCompleteCallback::Decoded(webrtc::I420VideoFrame&
image)
{
if (aLengthBytes != bLengthBytes)
{
return false;
}
return memcmp(ptrA, ptrB, aLengthBytes) == 0;
}
WebRtc_Word32 DualDecoderCompleteCallback::Decoded(webrtc::VideoFrame& image)
{
_decodedVideoBuffer->VerifyAndAllocate(image.Length());
_decodedVideoBuffer->CopyFrame(image.Length(), image.Buffer());
_decodedVideoBuffer->SetWidth(image.Width());
_decodedVideoBuffer->SetHeight(image.Height());
_decodedVideoBuffer->SetTimeStamp(image.TimeStamp());
_decodedVideoBuffer->CopyFrame(image);
_decodeComplete = true;
return 0;
}
@ -219,3 +196,20 @@ bool DualDecoderCompleteCallback::DecodeComplete()
return false;
}
bool
VP8DualDecoderTest::CheckIfBitExactFrames(const webrtc::I420VideoFrame& frame1,
const webrtc::I420VideoFrame& frame2) {
for (int plane = 0; plane < webrtc::kNumOfPlanes; plane ++) {
webrtc::PlaneType plane_type = static_cast<webrtc::PlaneType>(plane);
int allocated_size1 = frame1.allocated_size(plane_type);
int allocated_size2 = frame2.allocated_size(plane_type);
if (allocated_size1 != allocated_size2)
return false;
const uint8_t* plane_buffer1 = frame1.buffer(plane_type);
const uint8_t* plane_buffer2 = frame2.buffer(plane_type);
if (memcmp(plane_buffer1, plane_buffer2, allocated_size1) != 0)
return false;
}
return true;
}

View File

@ -30,21 +30,21 @@ protected:
virtual int Decode(int lossValue = 0);
webrtc::VP8Decoder* _decoder2;
webrtc::VideoFrame _decodedVideoBuffer2;
static bool CheckIfBitExact(const void *ptrA, unsigned int aLengthBytes,
const void *ptrB, unsigned int bLengthBytes);
webrtc::I420VideoFrame _decodedVideoBuffer2;
static bool CheckIfBitExactFrames(const webrtc::I420VideoFrame& frame1,
const webrtc::I420VideoFrame& frame2);
private:
};
class DualDecoderCompleteCallback : public webrtc::DecodedImageCallback
{
public:
DualDecoderCompleteCallback(webrtc::VideoFrame* buffer)
DualDecoderCompleteCallback(webrtc::I420VideoFrame* buffer)
: _decodedVideoBuffer(buffer), _decodeComplete(false) {}
WebRtc_Word32 Decoded(webrtc::VideoFrame& decodedImage);
WebRtc_Word32 Decoded(webrtc::I420VideoFrame& decodedImage);
bool DecodeComplete();
private:
webrtc::VideoFrame* _decodedVideoBuffer;
webrtc::I420VideoFrame* _decodedVideoBuffer;
bool _decodeComplete;
};

View File

@ -34,16 +34,12 @@ VP8RpsTest::~VP8RpsTest() {
decoder2_->Release();
delete decoder2_;
}
decoded_frame2_.Free();
}
void VP8RpsTest::Perform() {
_inname = "test/testFiles/foreman_cif.yuv";
CodecSettings(352, 288, 30, _bitRate);
Setup();
_inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
_decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
decoded_frame2_.VerifyAndAllocate(_lengthSourceFrame);
// Enable RPS functionality
_inst.codecSpecific.VP8.pictureLossIndicationOn = true;
@ -137,16 +133,22 @@ bool VP8RpsTest::EncodeRps(RpsDecodeCompleteCallback* decodeCallback) {
size_t bytes_read = fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile);
if (bytes_read < _lengthSourceFrame)
return true;
_inputVideoBuffer.CopyFrame(_lengthSourceFrame, _sourceBuffer);
_inputVideoBuffer.SetTimeStamp((unsigned int)
(_encFrameCnt * 9e4 / _inst.maxFramerate));
_inputVideoBuffer.SetWidth(_inst.width);
_inputVideoBuffer.SetHeight(_inst.height);
int half_width = (_inst.width + 1) / 2;
int half_height = (_inst.height + 1) / 2;
int size_y = _inst.width * _inst.height;
int size_uv = half_width * half_height;
_inputVideoBuffer.CreateFrame(size_y, _sourceBuffer,
size_uv, _sourceBuffer + size_y,
size_uv, _sourceBuffer + size_y + size_uv,
_inst.width, _inst.height,
_inst.width, half_width, half_width);
_inputVideoBuffer.set_timestamp((unsigned int)
(_encFrameCnt * 9e4 / _inst.maxFramerate));
if (feof(_sourceFile) != 0) {
return true;
}
_encodeCompleteTime = 0;
_encodeTimes[_inputVideoBuffer.TimeStamp()] = tGetTime();
_encodeTimes[_inputVideoBuffer.timestamp()] = tGetTime();
webrtc::CodecSpecificInfo* codecSpecificInfo = CreateEncoderSpecificInfo();
codecSpecificInfo->codecSpecific.VP8.pictureIdRPSI =
@ -169,11 +171,11 @@ bool VP8RpsTest::EncodeRps(RpsDecodeCompleteCallback* decodeCallback) {
}
if (_encodeCompleteTime > 0) {
_totalEncodeTime += _encodeCompleteTime -
_encodeTimes[_inputVideoBuffer.TimeStamp()];
_encodeTimes[_inputVideoBuffer.timestamp()];
}
else {
_totalEncodeTime += tGetTime() -
_encodeTimes[_inputVideoBuffer.TimeStamp()];
_encodeTimes[_inputVideoBuffer.timestamp()];
}
return false;
}
@ -219,9 +221,8 @@ int VP8RpsTest::Decode(int lossValue) {
// compare decoded images
#if FRAME_LOSS
if (!_missingFrames) {
if (!CheckIfBitExact(_decodedVideoBuffer.GetBuffer(),
_decodedVideoBuffer.GetLength(),
decoded_frame2_.GetBuffer(), _decodedVideoBuffer.GetLength())) {
if (!CheckIfBitExactFrames(_decodedVideoBuffer,
decoded_frame2_)) {
fprintf(stderr,"\n\nRPS decoder different from master: %u\n\n",
_framecnt);
return -1;
@ -229,9 +230,7 @@ int VP8RpsTest::Decode(int lossValue) {
}
#else
if (_framecnt > 0 && _framecnt % 10 != 0) {
if (!CheckIfBitExact(_decodedVideoBuffer.Buffer(),
_decodedVideoBuffer.Length(),
decoded_frame2_.Buffer(), _decodedVideoBuffer.Length())) {
if (!CheckIfBitExactFrames(_decodedVideoBuffer, decoded_frame2_)) {
fprintf(stderr,"\n\nRPS decoder different from master: %u\n\n",
_framecnt);
return -1;
@ -247,24 +246,30 @@ int VP8RpsTest::Decode(int lossValue) {
return 0;
}
bool
VP8RpsTest::CheckIfBitExact(const void* ptrA, unsigned int aLengthBytes,
const void* ptrB, unsigned int bLengthBytes) {
if (aLengthBytes != bLengthBytes)
return false;
return memcmp(ptrA, ptrB, aLengthBytes) == 0;
VP8RpsTest::CheckIfBitExactFrames(const webrtc::I420VideoFrame& frame1,
const webrtc::I420VideoFrame& frame2) {
for (int plane = 0; plane < webrtc::kNumOfPlanes; plane ++) {
webrtc::PlaneType plane_type = static_cast<webrtc::PlaneType>(plane);
int allocated_size1 = frame1.allocated_size(plane_type);
int allocated_size2 = frame2.allocated_size(plane_type);
if (allocated_size1 != allocated_size2)
return false;
const uint8_t* plane_buffer1 = frame1.buffer(plane_type);
const uint8_t* plane_buffer2 = frame2.buffer(plane_type);
if (memcmp(plane_buffer1, plane_buffer2, allocated_size1) != 0)
return false;
}
return true;
}
RpsDecodeCompleteCallback::RpsDecodeCompleteCallback(webrtc::VideoFrame* buffer)
RpsDecodeCompleteCallback::RpsDecodeCompleteCallback(webrtc::I420VideoFrame*
buffer)
: decoded_frame_(buffer),
decode_complete_(false),
last_decoded_picture_id_(0),
last_decoded_ref_picture_id_(0),
updated_ref_picture_id_(false) {
}
decode_complete_(false) {}
WebRtc_Word32 RpsDecodeCompleteCallback::Decoded(webrtc::VideoFrame& image) {
WebRtc_Word32 RpsDecodeCompleteCallback::Decoded(webrtc::I420VideoFrame&
image) {
return decoded_frame_->CopyFrame(image);
decode_complete_ = true;
}

View File

@ -11,6 +11,7 @@
#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_RPS_TEST_H_
#define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_RPS_TEST_H_
#include "common_video/interface/i420_video_frame.h"
#include "vp8.h"
#include "normal_async_test.h"
@ -28,18 +29,18 @@ class VP8RpsTest : public VP8NormalAsyncTest {
virtual bool EncodeRps(RpsDecodeCompleteCallback* decodeCallback);
virtual int Decode(int lossValue = 0);
static bool CheckIfBitExact(const void *ptrA, unsigned int aLengthBytes,
const void *ptrB, unsigned int bLengthBytes);
static bool CheckIfBitExactFrames(const webrtc::I420VideoFrame& frame1,
const webrtc::I420VideoFrame& frame2);
webrtc::VP8Decoder* decoder2_;
webrtc::VideoFrame decoded_frame2_;
webrtc::I420VideoFrame decoded_frame2_;
bool sli_;
};
class RpsDecodeCompleteCallback : public webrtc::DecodedImageCallback {
public:
RpsDecodeCompleteCallback(webrtc::VideoFrame* buffer);
WebRtc_Word32 Decoded(webrtc::VideoFrame& decodedImage);
RpsDecodeCompleteCallback(webrtc::I420VideoFrame* buffer);
WebRtc_Word32 Decoded(webrtc::I420VideoFrame& decodedImage);
bool DecodeComplete();
WebRtc_Word32 ReceivedDecodedReferenceFrame(const WebRtc_UWord64 picture_id);
WebRtc_Word32 ReceivedDecodedFrame(const WebRtc_UWord64 picture_id);
@ -47,7 +48,7 @@ class RpsDecodeCompleteCallback : public webrtc::DecodedImageCallback {
WebRtc_UWord64 LastDecodedRefPictureId(bool *updated);
private:
webrtc::VideoFrame* decoded_frame_;
webrtc::I420VideoFrame* decoded_frame_;
bool decode_complete_;
WebRtc_UWord64 last_decoded_picture_id_;
WebRtc_UWord64 last_decoded_ref_picture_id_;

View File

@ -324,13 +324,13 @@ uint32_t VP8EncoderImpl::MaxIntraTarget(uint32_t optimalBuffersize) {
return (targetPct < minIntraTh) ? minIntraTh: targetPct;
}
int VP8EncoderImpl::Encode(const VideoFrame& input_image,
int VP8EncoderImpl::Encode(const I420VideoFrame& input_image,
const CodecSpecificInfo* codec_specific_info,
const std::vector<VideoFrameType>* frame_types) {
if (!inited_) {
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
if (input_image.Buffer() == NULL) {
if (input_image.IsZeroSize()) {
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
}
if (encoded_complete_callback_ == NULL) {
@ -344,20 +344,18 @@ int VP8EncoderImpl::Encode(const VideoFrame& input_image,
}
// Check for change in frame size.
if (input_image.Width() != codec_.width ||
input_image.Height() != codec_.height) {
int ret = UpdateCodecFrameSize(input_image.Width(), input_image.Height());
if (input_image.width() != codec_.width ||
input_image.height() != codec_.height) {
int ret = UpdateCodecFrameSize(input_image.width(), input_image.height());
if (ret < 0) {
return ret;
}
}
// Image in vpx_image_t format.
uint8_t* buffer = input_image.Buffer();
uint32_t v_plane_loc = codec_.height * codec_.width +
((codec_.width + 1) >> 1) * ((codec_.height + 1) >> 1);
raw_->planes[PLANE_Y] = buffer;
raw_->planes[PLANE_U] = &buffer[codec_.width * codec_.height];
raw_->planes[PLANE_V] = &buffer[v_plane_loc];
// Input image is const. VP8's raw image is not defined as const.
raw_->planes[PLANE_Y] = const_cast<uint8_t*>(input_image.buffer(kYPlane));
raw_->planes[PLANE_U] = const_cast<uint8_t*>(input_image.buffer(kUPlane));
raw_->planes[PLANE_V] = const_cast<uint8_t*>(input_image.buffer(kVPlane));
int flags = 0;
#if WEBRTC_LIBVPX_VERSION >= 971
@ -379,11 +377,11 @@ int VP8EncoderImpl::Encode(const VideoFrame& input_image,
codec_specific_info->codecSpecific.VP8.pictureIdRPSI);
}
if (codec_specific_info->codecSpecific.VP8.hasReceivedSLI) {
sendRefresh = rps_->ReceivedSLI(input_image.TimeStamp());
sendRefresh = rps_->ReceivedSLI(input_image.timestamp());
}
}
flags = rps_->EncodeFlags(picture_id_, sendRefresh,
input_image.TimeStamp());
input_image.timestamp());
}
// TODO(holmer): Ideally the duration should be the timestamp diff of this
@ -456,7 +454,7 @@ void VP8EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
picture_id_ = (picture_id_ + 1) & 0x7FFF; // prepare next
}
int VP8EncoderImpl::GetEncodedFrame(const VideoFrame& input_image) {
int VP8EncoderImpl::GetEncodedFrame(const I420VideoFrame& input_image) {
vpx_codec_iter_t iter = NULL;
encoded_image_._frameType = kDeltaFrame;
const vpx_codec_cx_pkt_t *pkt= vpx_codec_get_cx_data(encoder_, &iter);
@ -469,7 +467,7 @@ int VP8EncoderImpl::GetEncodedFrame(const VideoFrame& input_image) {
}
} else if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
CodecSpecificInfo codecSpecific;
PopulateCodecSpecific(&codecSpecific, *pkt, input_image.TimeStamp());
PopulateCodecSpecific(&codecSpecific, *pkt, input_image.timestamp());
assert(pkt->data.frame.sz <= encoded_image_._size);
memcpy(encoded_image_._buffer, pkt->data.frame.buf, pkt->data.frame.sz);
@ -484,9 +482,9 @@ int VP8EncoderImpl::GetEncodedFrame(const VideoFrame& input_image) {
}
if (encoded_image_._length > 0) {
encoded_image_._timeStamp = input_image.TimeStamp();
encoded_image_._timeStamp = input_image.timestamp();
// TODO(mikhal): Resolve confusion in terms.
encoded_image_.capture_time_ms_ = input_image.RenderTimeMs();
encoded_image_.capture_time_ms_ = input_image.render_time_ms();
// Figure out where partition boundaries are located.
RTPFragmentationHeader fragInfo;
@ -518,7 +516,7 @@ int VP8EncoderImpl::GetEncodedFrame(const VideoFrame& input_image) {
}
#if WEBRTC_LIBVPX_VERSION >= 971
int VP8EncoderImpl::GetEncodedPartitions(const VideoFrame& input_image) {
int VP8EncoderImpl::GetEncodedPartitions(const I420VideoFrame& input_image) {
vpx_codec_iter_t iter = NULL;
int part_idx = 0;
encoded_image_._length = 0;
@ -554,13 +552,13 @@ int VP8EncoderImpl::GetEncodedPartitions(const VideoFrame& input_image) {
encoded_image_._frameType = kKeyFrame;
rps_->EncodedKeyFrame(picture_id_);
}
PopulateCodecSpecific(&codec_specific, *pkt, input_image.TimeStamp());
PopulateCodecSpecific(&codec_specific, *pkt, input_image.timestamp());
break;
}
}
if (encoded_image_._length > 0) {
encoded_image_._timeStamp = input_image.TimeStamp();
encoded_image_.capture_time_ms_ = input_image.RenderTimeMs();
encoded_image_._timeStamp = input_image.timestamp();
encoded_image_.capture_time_ms_ = input_image.render_time_ms();
encoded_image_._encodedHeight = raw_->h;
encoded_image_._encodedWidth = raw_->w;
encoded_complete_callback_->Encoded(encoded_image_, &codec_specific,
@ -873,30 +871,18 @@ int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, uint32_t timestamp) {
// Decoder OK and NULL image => No show frame
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
}
uint32_t required_size = CalcBufferSize(kI420, img->d_w, img->d_h);
decoded_image_.VerifyAndAllocate(required_size);
uint8_t* buf;
uint32_t pos = 0;
uint32_t plane, y;
uint8_t* buffer = decoded_image_.Buffer();
for (plane = 0; plane < 3; plane++) {
unsigned int width = (plane ? (img->d_w + 1) >> 1 : img->d_w);
unsigned int height = (plane ? (img->d_h + 1) >> 1 : img->d_h);
buf = img->planes[plane];
for (y = 0; y < height; y++) {
memcpy(&buffer[pos], buf, width);
pos += width;
buf += img->stride[plane];
}
}
// Set decoded image parameters.
decoded_image_.SetHeight(img->d_h);
decoded_image_.SetWidth(img->d_w);
decoded_image_.SetLength(CalcBufferSize(kI420, img->d_w, img->d_h));
decoded_image_.SetTimeStamp(timestamp);
int size_y = img->stride[VPX_PLANE_Y] * img->d_h;
int size_u = img->stride[VPX_PLANE_U] * ((img->d_h + 1) / 2);
int size_v = img->stride[VPX_PLANE_V] * ((img->d_h + 1) / 2);
// TODO(mikhal): This does a copy - need to SwapBuffers.
decoded_image_.CreateFrame(size_y, img->planes[VPX_PLANE_Y],
size_u, img->planes[VPX_PLANE_U],
size_v, img->planes[VPX_PLANE_V],
img->d_w, img->d_h,
img->stride[VPX_PLANE_Y],
img->stride[VPX_PLANE_U],
img->stride[VPX_PLANE_V]);
decoded_image_.set_timestamp(timestamp);
int ret = decode_complete_callback_->Decoded(decoded_image_);
if (ret != 0)
return ret;
@ -913,7 +899,6 @@ int VP8DecoderImpl::RegisterDecodeCompleteCallback(
}
int VP8DecoderImpl::Release() {
decoded_image_.Free();
if (last_keyframe_._buffer != NULL) {
delete [] last_keyframe_._buffer;
last_keyframe_._buffer = NULL;
@ -941,7 +926,7 @@ VideoDecoder* VP8DecoderImpl::Copy() {
assert(false);
return NULL;
}
if (decoded_image_.Buffer() == NULL) {
if (decoded_image_.IsZeroSize()) {
// Nothing has been decoded before; cannot clone.
return NULL;
}
@ -964,13 +949,13 @@ VideoDecoder* VP8DecoderImpl::Copy() {
return NULL;
}
// Allocate memory for reference image copy
assert(decoded_image_.Width() > 0);
assert(decoded_image_.Height() > 0);
assert(decoded_image_.width() > 0);
assert(decoded_image_.height() > 0);
assert(image_format_ > VPX_IMG_FMT_NONE);
// Check if frame format has changed.
if (ref_frame_ &&
(decoded_image_.Width() != ref_frame_->img.d_w ||
decoded_image_.Height() != ref_frame_->img.d_h ||
(decoded_image_.width() != static_cast<int>(ref_frame_->img.d_w) ||
decoded_image_.height() != static_cast<int>(ref_frame_->img.d_h) ||
image_format_ != ref_frame_->img.fmt)) {
vpx_img_free(&ref_frame_->img);
delete ref_frame_;
@ -982,12 +967,12 @@ VideoDecoder* VP8DecoderImpl::Copy() {
ref_frame_ = new vpx_ref_frame_t;
unsigned int align = 1;
if (decoded_image_.Width() % 32 == 0) {
if (decoded_image_.width() % 32 == 0) {
align = 32;
}
if (!vpx_img_alloc(&ref_frame_->img,
static_cast<vpx_img_fmt_t>(image_format_),
decoded_image_.Width(), decoded_image_.Height(),
decoded_image_.width(), decoded_image_.height(),
align)) {
assert(false);
delete copy;

View File

@ -72,7 +72,7 @@ class VP8EncoderImpl : public VP8Encoder {
// WEBRTC_VIDEO_CODEC_ERROR
// WEBRTC_VIDEO_CODEC_TIMEOUT
virtual int Encode(const VideoFrame& input_image,
virtual int Encode(const I420VideoFrame& input_image,
const CodecSpecificInfo* codec_specific_info,
const std::vector<VideoFrameType>* frame_types);
@ -115,9 +115,9 @@ class VP8EncoderImpl : public VP8Encoder {
const vpx_codec_cx_pkt& pkt,
uint32_t timestamp);
int GetEncodedFrame(const VideoFrame& input_image);
int GetEncodedFrame(const I420VideoFrame& input_image);
int GetEncodedPartitions(const VideoFrame& input_image);
int GetEncodedPartitions(const I420VideoFrame& input_image);
// Determine maximum target for Intra frames
//
@ -219,7 +219,7 @@ class VP8DecoderImpl : public VP8Decoder {
int ReturnFrame(const vpx_image_t* img, uint32_t timeStamp);
VideoFrame decoded_image_;
I420VideoFrame decoded_image_;
DecodedImageCallback* decode_complete_callback_;
bool inited_;
bool feedback_mode_;