shithub: openh264

Download patch

ref: 0c2227e4b15b488a21a1a62f4d337c0bafb00e09
parent: 596be02cc476b8882a39cf318d5faf5505a0814c
author: jwwang <jwwang@mozilla.com>
date: Sat Jan 18 14:31:54 EST 2014

Remove temp files using the iterator pattern

--- a/test/BaseDecoderTest.cpp
+++ b/test/BaseDecoderTest.cpp
@@ -43,7 +43,8 @@
   }
 }
 
-BaseDecoderTest::BaseDecoderTest() : decoder_(NULL) {}
+BaseDecoderTest::BaseDecoderTest()
+  : decoder_(NULL), decodeStatus_(OpenFile) {}
 
 void BaseDecoderTest::SetUp() {
   long rv = CreateDecoder(&decoder_);
@@ -125,4 +126,42 @@
 
   // 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;
 }
--- a/test/BaseDecoderTest.h
+++ b/test/BaseDecoderTest.h
@@ -3,8 +3,11 @@
 
 #include <stdint.h>
 #include <limits.h>
+#include <fstream>
 #include "codec_api.h"
 
+#include "utils/BufferedData.h"
+
 class BaseDecoderTest {
  public:
   struct Plane {
@@ -29,10 +32,21 @@
   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__
--- a/test/BaseEncoderTest.cpp
+++ b/test/BaseEncoderTest.cpp
@@ -2,6 +2,7 @@
 #include <gtest/gtest.h>
 #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::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 @@
   BufferedData buf;
   buf.SetLength(frameSize);
   ASSERT_TRUE(buf.Length() == frameSize);
-  char* data = reinterpret_cast<char*>(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) {
@@ -76,4 +73,11 @@
       cbk->onEncodeFrame(info);
     }
   }
+}
+
+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);
 }
--- 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 @@
   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_;
--- a/test/decode_encode_test.cpp
+++ b/test/decode_encode_test.cpp
@@ -1,7 +1,8 @@
-#include <cstdio>
 #include <gtest/gtest.h>
 #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 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 @@
 
 class DecodeEncodeTest : public ::testing::TestWithParam<DecodeEncodeFileParam>,
     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 @@
     if (HasFatalFailure()) {
       return;
     }
-
-    tmpFileName_ = tmpnam(NULL);
-    tmpFile_ = fopen(tmpFileName_, "wb");
-    ASSERT_TRUE(tmpFile_ != NULL);
-
     SHA1_Init(&ctx_);
   }
 
@@ -64,9 +61,9 @@
     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) {
@@ -73,31 +70,37 @@
     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<uint8_t*>(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[] = {
--- a/test/utils/BufferedData.h
+++ b/test/utils/BufferedData.h
@@ -21,6 +21,23 @@
     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;
   }
--- /dev/null
+++ b/test/utils/FileInputStream.h
@@ -1,0 +1,21 @@
+#ifndef __FILEINPUTSTREAM_H__
+#define __FILEINPUTSTREAM_H__
+
+#include <fstream>
+#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<char*>(ptr), len);
+    return file_.eof() ? -1 : file_.gcount();
+  }
+ private:
+  std::ifstream file_;
+};
+
+#endif //__FILEINPUTSTREAM_H__
--- /dev/null
+++ b/test/utils/InputStream.h
@@ -1,0 +1,10 @@
+#ifndef __INPUTSTREAM_H__
+#define __INPUTSTREAM_H__
+
+#include <cstddef>
+
+struct InputStream {
+  virtual int read(void* ptr, size_t len) = 0;
+};
+
+#endif //__INPUTSTREAM_H__