diff --git a/test/BaseDecoderTest.cpp b/test/BaseDecoderTest.cpp index 4dfc479d..03c7b4e7 100644 --- a/test/BaseDecoderTest.cpp +++ b/test/BaseDecoderTest.cpp @@ -43,7 +43,8 @@ static void ReadFrame(std::ifstream* file, BufferedData* buf) { } } -BaseDecoderTest::BaseDecoderTest() : decoder_(NULL) {} +BaseDecoderTest::BaseDecoderTest() + : decoder_(NULL), decodeStatus_(OpenFile) {} void BaseDecoderTest::SetUp() { long rv = CreateDecoder(&decoder_); @@ -126,3 +127,41 @@ void BaseDecoderTest::DecodeFile(const char* fileName, Callback* cbk) { // Get pending last frame DecodeFrame(NULL, 0, cbk); } + +bool BaseDecoderTest::Open(const char* fileName) { + if (decodeStatus_ == OpenFile) { + file_.open(fileName); + if (file_.is_open()) { + decodeStatus_ = Decoding; + return true; + } + } + return false; +} + +bool BaseDecoderTest::DecodeNextFrame(Callback* cbk) { + switch (decodeStatus_) { + case Decoding: + ReadFrame(&file_, &buf_); + if (::testing::Test::HasFatalFailure()) { + return false; + } + if (buf_.Length() == 0) { + decodeStatus_ = EndOfStream; + return true; + } + DecodeFrame(buf_.data(), buf_.Length(), cbk); + if (::testing::Test::HasFatalFailure()) { + return false; + } + return true; + case EndOfStream: { + int32_t iEndOfStreamFlag = 1; + decoder_->SetOption(DECODER_OPTION_END_OF_STREAM, &iEndOfStreamFlag); + DecodeFrame(NULL, 0, cbk); + decodeStatus_ = End; + break; + } + } + return false; +} diff --git a/test/BaseDecoderTest.h b/test/BaseDecoderTest.h index 204b41ae..32923a15 100644 --- a/test/BaseDecoderTest.h +++ b/test/BaseDecoderTest.h @@ -3,8 +3,11 @@ #include #include +#include #include "codec_api.h" +#include "utils/BufferedData.h" + class BaseDecoderTest { public: struct Plane { @@ -29,10 +32,21 @@ class BaseDecoderTest { void TearDown(); void DecodeFile(const char* fileName, Callback* cbk); + bool Open(const char* fileName); + bool DecodeNextFrame(Callback* cbk); + private: void DecodeFrame(const uint8_t* src, int sliceSize, Callback* cbk); ISVCDecoder* decoder_; + std::ifstream file_; + BufferedData buf_; + enum { + OpenFile, + Decoding, + EndOfStream, + End + } decodeStatus_; }; #endif //__BASEDECODERTEST_H__ diff --git a/test/BaseEncoderTest.cpp b/test/BaseEncoderTest.cpp index c3b02b2a..64dba91b 100644 --- a/test/BaseEncoderTest.cpp +++ b/test/BaseEncoderTest.cpp @@ -2,6 +2,7 @@ #include #include "codec_def.h" #include "utils/BufferedData.h" +#include "utils/FileInputStream.h" #include "BaseEncoderTest.h" static int InitWithParam(ISVCEncoder* encoder, int width, @@ -50,11 +51,8 @@ void BaseEncoderTest::TearDown() { } } -void BaseEncoderTest::EncodeFile(const char* fileName, int width, int height, +void BaseEncoderTest::EncodeStream(InputStream* in, int width, int height, float frameRate, Callback* cbk) { - std::ifstream file(fileName, std::ios::in | std::ios::binary); - ASSERT_TRUE(file.is_open()); - int rv = InitWithParam(encoder_, width, height, frameRate); ASSERT_TRUE(rv == cmResultSuccess); @@ -64,12 +62,11 @@ void BaseEncoderTest::EncodeFile(const char* fileName, int width, int height, BufferedData buf; buf.SetLength(frameSize); ASSERT_TRUE(buf.Length() == frameSize); - char* data = reinterpret_cast(buf.data()); SFrameBSInfo info; memset(&info, 0, sizeof(SFrameBSInfo)); - while (file.read(data, frameSize), file.gcount() == frameSize) { + while (in->read(buf.data(), frameSize) == frameSize) { rv = encoder_->EncodeFrame(buf.data(), &info); ASSERT_TRUE(rv != videoFrameTypeInvalid); if (rv != videoFrameTypeSkip && cbk != NULL) { @@ -77,3 +74,10 @@ void BaseEncoderTest::EncodeFile(const char* fileName, int width, int height, } } } + +void BaseEncoderTest::EncodeFile(const char* fileName, int width, int height, + float frameRate, Callback* cbk) { + FileInputStream fileStream; + ASSERT_TRUE(fileStream.Open(fileName)); + EncodeStream(&fileStream, width, height, frameRate, cbk); +} diff --git a/test/BaseEncoderTest.h b/test/BaseEncoderTest.h index 29a40e34..3689603b 100644 --- a/test/BaseEncoderTest.h +++ b/test/BaseEncoderTest.h @@ -3,6 +3,7 @@ #include "codec_api.h" #include "codec_app_def.h" +#include "utils/InputStream.h" class BaseEncoderTest { public: @@ -14,6 +15,7 @@ class BaseEncoderTest { void SetUp(); void TearDown(); void EncodeFile(const char* fileName, int width, int height, float frameRate, Callback* cbk); + void EncodeStream(InputStream* in, int width, int height, float frameRate, Callback* cbk); private: ISVCEncoder* encoder_; diff --git a/test/decode_encode_test.cpp b/test/decode_encode_test.cpp index bbfbf150..ee1a0b4e 100644 --- a/test/decode_encode_test.cpp +++ b/test/decode_encode_test.cpp @@ -1,7 +1,8 @@ -#include #include #include "codec_def.h" #include "utils/HashFunctions.h" +#include "utils/BufferedData.h" +#include "utils/InputStream.h" #include "BaseDecoderTest.h" #include "BaseEncoderTest.h" @@ -16,10 +17,12 @@ static void UpdateHashFromFrame(const SFrameBSInfo& info, SHA_CTX* ctx) { } } -static void WritePlaneToFile(FILE* file, const uint8_t* plane, +static void WritePlaneBuffer(BufferedData* buf, const uint8_t* plane, int width, int height, int stride) { for (int i = 0; i < height; i++) { - fwrite(plane, 1, width, file); + if (!buf->Push(plane, width)) { + FAIL() << "unable to allocate memory"; + } plane += stride; } } @@ -34,10 +37,9 @@ struct DecodeEncodeFileParam { class DecodeEncodeTest : public ::testing::TestWithParam, public BaseDecoderTest, public BaseDecoderTest::Callback, - public BaseEncoderTest , public BaseEncoderTest::Callback { + public BaseEncoderTest , public BaseEncoderTest::Callback, + public InputStream { public: - DecodeEncodeTest() : tmpFileName_(NULL), tmpFile_(NULL) {} - virtual void SetUp() { BaseDecoderTest::SetUp(); if (HasFatalFailure()) { @@ -47,11 +49,6 @@ class DecodeEncodeTest : public ::testing::TestWithParam, if (HasFatalFailure()) { return; } - - tmpFileName_ = tmpnam(NULL); - tmpFile_ = fopen(tmpFileName_, "wb"); - ASSERT_TRUE(tmpFile_ != NULL); - SHA1_Init(&ctx_); } @@ -64,40 +61,46 @@ class DecodeEncodeTest : public ::testing::TestWithParam, const Plane& y = frame.y; const Plane& u = frame.u; const Plane& v = frame.v; - WritePlaneToFile(tmpFile_, y.data, y.width, y.height, y.stride); - WritePlaneToFile(tmpFile_, u.data, u.width, u.height, u.stride); - WritePlaneToFile(tmpFile_, v.data, v.width, v.height, v.stride); + WritePlaneBuffer(&buf_, y.data, y.width, y.height, y.stride); + WritePlaneBuffer(&buf_, u.data, u.width, u.height, u.stride); + WritePlaneBuffer(&buf_, v.data, v.width, v.height, v.stride); } virtual void onEncodeFrame(const SFrameBSInfo& frameInfo) { UpdateHashFromFrame(frameInfo, &ctx_); } + virtual int read(void* ptr, size_t len) { + while (buf_.Length() < len) { + bool hasNext = DecodeNextFrame(this); + if (HasFatalFailure()) { + return -1; + } + if (!hasNext) { + if (buf_.Length() == 0) { + return -1; + } + break; + } + } + return buf_.Pop(static_cast(ptr), len); + } + protected: SHA_CTX ctx_; - const char* tmpFileName_; - FILE* tmpFile_; + BufferedData buf_; }; TEST_P(DecodeEncodeTest, CompareOutput) { DecodeEncodeFileParam p = GetParam(); - DecodeFile(p.fileName, this); - if (HasFatalFailure()) { - return; - } - - // force flushing the file - fclose(tmpFile_); - - EncodeFile(tmpFileName_, p.width, p.height, p.frameRate, this); + ASSERT_TRUE(Open(p.fileName)); + EncodeStream(this, p.width, p.height, p.frameRate, this); unsigned char digest[SHA_DIGEST_LENGTH]; SHA1_Final(digest, &ctx_); if (!HasFatalFailure()) { ASSERT_TRUE(CompareHash(digest, p.hashStr)); } - - remove(tmpFileName_); } static const DecodeEncodeFileParam kFileParamArray[] = { diff --git a/test/utils/BufferedData.h b/test/utils/BufferedData.h index 122768a9..6d8dc239 100644 --- a/test/utils/BufferedData.h +++ b/test/utils/BufferedData.h @@ -21,6 +21,23 @@ class BufferedData { return true; } + bool Push(const uint8_t* data, size_t len) { + if (!EnsureCapacity(length_ + len)) { + return false; + } + memcpy(data_ + length_, data, len); + length_ += len; + return true; + } + + size_t Pop(uint8_t* ptr, size_t len) { + len = std::min(length_, len); + memcpy(ptr, data_, len); + memcpy(data_, data_ + len, length_ - len); + SetLength(length_ - len); + return len; + } + void Clear() { length_ = 0; } diff --git a/test/utils/FileInputStream.h b/test/utils/FileInputStream.h new file mode 100644 index 00000000..ef2df62a --- /dev/null +++ b/test/utils/FileInputStream.h @@ -0,0 +1,21 @@ +#ifndef __FILEINPUTSTREAM_H__ +#define __FILEINPUTSTREAM_H__ + +#include +#include "InputStream.h" + +class FileInputStream : public InputStream { + public: + bool Open(const char* fileName) { + file_.open(fileName, std::ios_base::in | std::ios_base::binary); + return file_.is_open(); + } + int read(void* ptr, size_t len) { + file_.read(static_cast(ptr), len); + return file_.eof() ? -1 : file_.gcount(); + } + private: + std::ifstream file_; +}; + +#endif //__FILEINPUTSTREAM_H__ diff --git a/test/utils/InputStream.h b/test/utils/InputStream.h new file mode 100644 index 00000000..ef8decc1 --- /dev/null +++ b/test/utils/InputStream.h @@ -0,0 +1,10 @@ +#ifndef __INPUTSTREAM_H__ +#define __INPUTSTREAM_H__ + +#include + +struct InputStream { + virtual int read(void* ptr, size_t len) = 0; +}; + +#endif //__INPUTSTREAM_H__