shithub: openh264

Download patch

ref: 4fa810da8b1e6ec63384cacb2d22df6cfee1df96
parent: b51963c009a7c3c55fb4d3418ec983a9b15dae10
author: jwwang <jwwang@mozilla.com>
date: Wed Feb 12 09:52:35 EST 2014

1. support .c in makefile generator. 2. add test to check C interfaces.

--- a/Makefile
+++ b/Makefile
@@ -64,6 +64,7 @@
 #### No user-serviceable parts below this line
 ifneq ($(V),Yes)
     QUIET_CXX = @printf "CXX\t$@\n";
+    QUIET_CC  = @printf "CC\t$@\n";
     QUIET_ASM = @printf "ASM\t$@\n";
     QUIET_AR  = @printf "AR\t$@\n";
     QUIET     = @
--- a/build/mktargets.py
+++ b/build/mktargets.py
@@ -30,6 +30,14 @@
     f.write('\t$(QUIET_CXX)$(CXX) $(CFLAGS) $(CXXFLAGS) $(INCLUDES) $(' + PREFIX + '_CFLAGS) $(' + PREFIX + '_INCLUDES) -c $(CXX_O) $<\n')
     f.write("\n")
 
+def write_c_rule_pattern(f):
+    src = "$(%s_SRCDIR)/%%.c"%(PREFIX)
+    dst = "$(%s_SRCDIR)/%%.o"%(PREFIX)
+
+    f.write("%s: %s\n"%(dst, src))
+    f.write('\t$(QUIET_CC)$(CC) $(CFLAGS) $(INCLUDES) $(' + PREFIX + '_CFLAGS) $(' + PREFIX + '_INCLUDES) -c $(CXX_O) $<\n')
+    f.write("\n")
+
 def write_asm_rule_pattern(f):
     src = "$(%s_SRCDIR)/%%.asm"%(PREFIX)
     dst = "$(%s_SRCDIR)/%%.o"%(PREFIX)
@@ -42,6 +50,7 @@
 def find_sources():
     cpp_files = []
     asm_files = []
+    c_files = []
     print EXCLUDE
     for dir in os.walk("."):
         for file in dir[2]:
@@ -50,7 +59,9 @@
                     cpp_files.append(os.path.join(dir[0].strip('./'), file))
                 if os.path.splitext(file)[1] == '.asm':
                     asm_files.append(os.path.join(dir[0].strip('./'), file))
-    return [cpp_files, asm_files]
+                if os.path.splitext(file)[1] == '.c':
+                    c_files.append(os.path.join(dir[0].strip('./'), file))
+    return [cpp_files, asm_files, c_files]
 
 
 args = parser.parse_args()
@@ -80,7 +91,7 @@
 except:
     sys.exit(1)
 
-(cpp, asm) = find_sources()
+(cpp, asm, cfiles) = find_sources()
 
 
 
@@ -91,8 +102,15 @@
 for c in cpp:
     f.write("\t$(%s_SRCDIR)/%s\\\n"%(PREFIX, c))
 f.write("\n")
-f.write("%s_OBJS += $(%s_CPP_SRCS:%s=.o)\n"%(PREFIX, PREFIX, CPP_SUFFIX))
+f.write("%s_OBJS += $(%s_CPP_SRCS:%s=.o)\n\n"%(PREFIX, PREFIX, CPP_SUFFIX))
 
+if len(cfiles) > 0:
+    f.write("%s_C_SRCS=\\\n"%(PREFIX))
+    for cfile in cfiles:
+        f.write("\t$(%s_SRCDIR)/%s\\\n"%(PREFIX, cfile))
+    f.write("\n")
+    f.write("%s_OBJS += $(%s_C_SRCS:.c=.o)\n\n"%(PREFIX, PREFIX))
+
 if len(asm) > 0:
     f.write("ifeq ($(USE_ASM), Yes)\n")
     f.write("%s_ASM_SRCS=\\\n"%(PREFIX))
@@ -105,6 +123,9 @@
 f.write("OBJS += $(%s_OBJS)\n"%PREFIX)
 
 write_cpp_rule_pattern(f)
+
+if len(cfiles) > 0:
+    write_c_rule_pattern(f)
 
 if len(asm) > 0:
     write_asm_rule_pattern(f)
--- /dev/null
+++ b/test/c_interface_test.c
@@ -1,0 +1,32 @@
+#include "codec_api.h"
+
+// Cast to this function type to ignore other parameters.
+typedef int (*Func)(void*);
+#define CALL(p, m) (((Func)((*p)->m))(p))
+// Check if the function return an expected number.
+#define CHECK(n, p, m) check(n, CALL(p, m), #m)
+
+typedef void(*CheckFunc)(int, int, const char*);
+
+void CheckEncoderInterface(ISVCEncoder* p, CheckFunc check) {
+  CHECK(1, p, Initialize);
+  CHECK(2, p, Initialize2);
+  CHECK(3, p, Uninitialize);
+  CHECK(4, p, EncodeFrame);
+  CHECK(5, p, EncodeFrame2);
+  CHECK(6, p, EncodeParameterSets);
+  CHECK(7, p, PauseFrame);
+  CHECK(8, p, ForceIntraFrame);
+  CHECK(9, p, SetOption);
+  CHECK(10, p, GetOption);
+}
+
+void CheckDecoderInterface(ISVCDecoder* p, CheckFunc check) {
+  CHECK(1, p, Initialize);
+  CHECK(2, p, Uninitialize);
+  CHECK(3, p, DecodeFrame);
+  CHECK(4, p, DecodeFrame2);
+  CHECK(5, p, DecodeFrameEx);
+  CHECK(6, p, SetOption);
+  CHECK(7, p, GetOption);
+}
--- /dev/null
+++ b/test/cpp_interface_test.cpp
@@ -1,0 +1,116 @@
+#include <gtest/gtest.h>
+#include "codec_api.h"
+
+static void CheckFunctionOrder(int expect, int actual, const char* name) {
+  EXPECT_EQ(expect, actual) << "Wrong function order: " << name;
+}
+
+typedef void(*CheckFunc)(int, int, const char*);
+extern "C" void CheckEncoderInterface(ISVCEncoder* p, CheckFunc);
+extern "C" void CheckDecoderInterface(ISVCDecoder* p, CheckFunc);
+
+// Store the 'this' pointer to verify 'this' is received as expected from C code.
+static void* gThis;
+
+/**
+ * Return a unique number for each virtual function so that we are able to
+ * check if the order of functions in the virtual table is as expected.
+ */
+struct SVCEncoderImpl : public ISVCEncoder {
+  virtual ~SVCEncoderImpl() {}
+  virtual int EXTAPI Initialize(SVCEncodingParam* pParam,
+      const INIT_TYPE kiInitType) {
+    EXPECT_TRUE(gThis == this);
+    return 1;
+  }
+  virtual int EXTAPI Initialize2(void* pParam, const INIT_TYPE kiInitType) {
+    EXPECT_TRUE(gThis == this);
+    return 2;
+  }
+  virtual int EXTAPI Uninitialize() {
+    EXPECT_TRUE(gThis == this);
+    return 3;
+  }
+  virtual int EXTAPI EncodeFrame(const unsigned char* kpSrc,
+      SFrameBSInfo* pBsInfo) {
+    EXPECT_TRUE(gThis == this);
+    return 4;
+  }
+  virtual int EXTAPI EncodeFrame2(const SSourcePicture** kppSrcPicList,
+      int nSrcPicNum, SFrameBSInfo* pBsInfo) {
+    EXPECT_TRUE(gThis == this);
+    return 5;
+  }
+  virtual int EXTAPI EncodeParameterSets(SFrameBSInfo* pBsInfo) {
+    EXPECT_TRUE(gThis == this);
+    return 6;
+  }
+  virtual int EXTAPI PauseFrame(const unsigned char* kpSrc,
+      SFrameBSInfo* pBsInfo) {
+    EXPECT_TRUE(gThis == this);
+    return 7;
+  }
+  virtual int EXTAPI ForceIntraFrame(bool bIDR) {
+    EXPECT_TRUE(gThis == this);
+    return 8;
+  }
+  virtual int EXTAPI SetOption(ENCODER_OPTION eOptionId, void* pOption) {
+    EXPECT_TRUE(gThis == this);
+    return 9;
+  }
+  virtual int EXTAPI GetOption(ENCODER_OPTION eOptionId, void* pOption) {
+    EXPECT_TRUE(gThis == this);
+    return 10;
+  }
+};
+
+struct SVCDecoderImpl : public ISVCDecoder {
+  virtual ~SVCDecoderImpl() {}
+  virtual long EXTAPI Initialize(void* pParam, const INIT_TYPE iInitType) {
+    EXPECT_TRUE(gThis == this);
+    return 1;
+  }
+  virtual long EXTAPI Uninitialize() {
+    EXPECT_TRUE(gThis == this);
+    return 2;
+  }
+  virtual DECODING_STATE EXTAPI DecodeFrame(const unsigned char* pSrc,
+      const int iSrcLen, unsigned char** ppDst, int* pStride,
+      int& iWidth, int& iHeight) {
+    EXPECT_TRUE(gThis == this);
+    return static_cast<DECODING_STATE>(3);
+  }
+  virtual DECODING_STATE EXTAPI DecodeFrame2(const unsigned char* pSrc,
+      const int iSrcLen, void** ppDst, SBufferInfo* pDstInfo) {
+    EXPECT_TRUE(gThis == this);
+    return static_cast<DECODING_STATE>(4);
+  }
+  virtual DECODING_STATE EXTAPI DecodeFrameEx(const unsigned char* pSrc,
+      const int iSrcLen, unsigned char* pDst, int iDstStride,
+      int& iDstLen, int& iWidth, int& iHeight, int& iColorFormat) {
+    EXPECT_TRUE(gThis == this);
+    return static_cast<DECODING_STATE>(5);
+  }
+  virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) {
+    EXPECT_TRUE(gThis == this);
+    return 6;
+  }
+  virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) {
+    EXPECT_TRUE(gThis == this);
+    return 7;
+  }
+};
+
+TEST(ISVCEncoderTest, CheckFunctionOrder) {
+  SVCEncoderImpl* p = new SVCEncoderImpl;
+  gThis = p;
+  CheckEncoderInterface(p, CheckFunctionOrder);
+  delete p;
+}
+
+TEST(ISVCDecoderTest, CheckFunctionOrder) {
+  SVCDecoderImpl* p = new SVCDecoderImpl;
+  gThis = p;
+  CheckDecoderInterface(p, CheckFunctionOrder);
+  delete p;
+}
--- a/test/targets.mk
+++ b/test/targets.mk
@@ -6,11 +6,21 @@
 	$(CODEC_UNITTEST_SRCDIR)/decoder_test.cpp\
 	$(CODEC_UNITTEST_SRCDIR)/encoder_test.cpp\
 	$(CODEC_UNITTEST_SRCDIR)/simple_test.cpp\
+	$(CODEC_UNITTEST_SRCDIR)/./cpp_interface_test.cpp\
 
 CODEC_UNITTEST_OBJS += $(CODEC_UNITTEST_CPP_SRCS:.cpp=.o)
+
+CODEC_UNITTEST_C_SRCS=\
+	$(CODEC_UNITTEST_SRCDIR)/./c_interface_test.c\
+
+CODEC_UNITTEST_OBJS += $(CODEC_UNITTEST_C_SRCS:.c=.o)
+
 OBJS += $(CODEC_UNITTEST_OBJS)
 $(CODEC_UNITTEST_SRCDIR)/%.o: $(CODEC_UNITTEST_SRCDIR)/%.cpp
 	$(QUIET_CXX)$(CXX) $(CFLAGS) $(CXXFLAGS) $(INCLUDES) $(CODEC_UNITTEST_CFLAGS) $(CODEC_UNITTEST_INCLUDES) -c $(CXX_O) $<
+
+$(CODEC_UNITTEST_SRCDIR)/%.o: $(CODEC_UNITTEST_SRCDIR)/%.c
+	$(QUIET_CXX)$(CC) $(CFLAGS) $(INCLUDES) $(CODEC_UNITTEST_CFLAGS) $(CODEC_UNITTEST_INCLUDES) -c $(CXX_O) $<
 
 codec_unittest$(EXEEXT): $(CODEC_UNITTEST_OBJS) $(LIBS) $(CODEC_UNITTEST_LIBS) $(CODEC_UNITTEST_DEPS)
 	$(QUIET_CXX)$(CXX) $(CXX_LINK_O) $(CODEC_UNITTEST_OBJS) $(CODEC_UNITTEST_LDFLAGS) $(CODEC_UNITTEST_LIBS) $(LDFLAGS) $(LIBS)