shithub: h264bsd

Download patch

ref: d845fb5e4d7e03cd55f0c627f5c5d81c4599ec8b
parent: 5e5feb8fc8da3889301dabe105f7680488c99caf
author: Sam Leitch <conceptualalchemist@gmail.com>
date: Tue Jul 11 17:30:01 EDT 2017

Updated test Rakefile so that it can build all test data (it requires ffmpeg to work).
Added posix comparison test that compares output to test data.
The comparison test currently fails, so I need to find out why.

--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,4 @@
 posix/lib/
 posix/obj/
 test/output/
+test/raw/
--- a/posix/Rakefile
+++ b/posix/Rakefile
@@ -50,13 +50,18 @@
 end
 
 # Run test application
-task :test_repeatedy => [test_app] do |t|
+task :test_640x360 => [test_app] do |t|
+  sh "#{test_app} ../test/test_640x360.h264"
+end
+
+# Run test application decoding repeatedy until stopped
+task :test_repeat => [test_app] do |t|
   sh "#{test_app} -r ../test/test_1920x1080.h264"
 end
 
-# Run test application
-task :test_output => ["../test/output", test_app] do |t|
-  sh "#{test_app} -o ../test/output ../test/test_1920x1080.h264"
+# Run test application and compare to test/output
+task :test_compare => [test_app] do |t|
+  sh "#{test_app} -c ../test/output/1920x1080 ../test/test_1920x1080.h264"
 end
 
 task :clean do
--- a/posix/test_h264bsd.c
+++ b/posix/test_h264bsd.c
@@ -12,6 +12,7 @@
 #include "../src/h264bsd_util.h"
 
 static char* outputDir = NULL;
+static char* compareDir = NULL;
 static int repeatTest = 0;
 
 void createContentBuffer(char* contentPath, u8** pContentBuffer, size_t* pContentSize) {
@@ -33,7 +34,7 @@
   }
 
   off_t offset = 0;
-  while(offset < contentSize) {
+  while (offset < contentSize) {
     offset += fread(contentBuffer + offset, sizeof(u8), contentSize - offset, input);
   }
 
@@ -40,13 +41,11 @@
   fclose(input);
 }
 
-void saveImage(int picNum, u8* picData, int width, int height) {
-  if(!outputDir) return;
+void saveImage(u8* picData, int width, int height, int picNum) {
+  char picPath[128];
+  sprintf(picPath, "%s/frame_%02d.yuv", outputDir, picNum);
 
-  char outputPath[128];
-  sprintf(outputPath, "%s/frame_%02d.yuv", outputDir, picNum);
-
-  FILE *output = fopen(outputPath, "w");
+  FILE *output = fopen(picPath, "w");
   if (output == NULL) {
     perror("open failed");
     exit(1);
@@ -54,7 +53,7 @@
 
   size_t picSize = width * height * 3 / 2;
   off_t offset = 0;
-  while(offset < picSize) {
+  while (offset < picSize) {
     offset += fwrite(picData + offset, sizeof(u8), picSize - offset, output);
   }
 
@@ -61,12 +60,79 @@
   fclose(output);
 }
 
-void decodeContent(u8* contentBuffer, size_t contentSize) {
+static u8* expectedData = NULL;
+static int totalErrors = 0;
+
+int compareImage(u8* actualData, int width, int height, int picNum) {
+  char expectedPath[128];
+  sprintf(expectedPath, "%s/frame_%02d.yuv", compareDir, picNum);
+
+  FILE *input = fopen(expectedPath, "r");
+  if (input == NULL) {
+    perror("open failed");
+    exit(1);
+  }
+
+  size_t picSize = width * height * 3 / 2;
+  size_t uDataOffset = width * height;
+  size_t vDataOffset = width * height * 5 / 4;
+
+  if (!expectedData) expectedData = (u8*)malloc(picSize);
+
+  off_t offset = 0;
+  while (offset < picSize) {
+    offset += fread(expectedData + offset, sizeof(u8), picSize - offset, input);
+  }
+
+  fclose(input);
+
+  int numErrors = 0;
+
+  size_t yOffset = 0;
+  size_t uvOffset = 0;
+
+  u8* yExpected = expectedData;
+  u8* uExpected = expectedData + uDataOffset;
+  u8* vExpected = expectedData + vDataOffset;
+
+  u8* yActual = actualData;
+  u8* uActual = actualData + uDataOffset;
+  u8* vActual = actualData + vDataOffset;
+
+  for (int y=0; y<height; ++y) {
+    for (int x=0; x<width; ++x) {
+      int ySame = yActual[yOffset] == yExpected[yOffset];
+      int uSame = uActual[uvOffset] == uExpected[uvOffset];
+      int vSame = vActual[uvOffset] == vExpected[uvOffset];
+
+      if(!ySame || !uSame || !vSame) {
+        ++numErrors;
+        if (numErrors <= 5) {
+          printf(
+            "Pixel (%d,%d) is different. Expected (%d,%d,%d) but saw (%d,%d,%d).\n",
+            x, y,
+            yExpected[yOffset], uExpected[uvOffset], vExpected[uvOffset],
+            yActual[yOffset], uActual[uvOffset], vActual[uvOffset]);
+        }
+
+        if (numErrors == 6) printf("...\n");
+      }
+
+      ++yOffset;
+      if(yOffset % 1) ++ uvOffset;
+    }
+  }
+
+  if(numErrors > 0) printf("%d pixels are different on frame %d.\n\n", numErrors, picNum);
+  return numErrors;
+}
+
+void decodeContent (u8* contentBuffer, size_t contentSize) {
   u32 status;
   storage_t dec;
   status = h264bsdInit(&dec, HANTRO_FALSE);
 
-  if(status != HANTRO_OK) {
+  if (status != HANTRO_OK) {
     fprintf(stderr, "h264bsdInit failed\n");
     exit(1);
   }
@@ -78,21 +144,23 @@
   u8* pic;
   u32 picId, isIdrPic, numErrMbs;
   u32 top, left, width, height, croppingFlag;
+  int totalErrors = 0;
 
-  while(len > 0) {
+  while (len > 0) {
     u32 result = h264bsdDecode(&dec, byteStrm, len, 0, &readBytes);
     len -= readBytes;
     byteStrm += readBytes;
 
-    switch(result) {
+    switch (result) {
       case H264BSD_PIC_RDY:
         pic = h264bsdNextOutputPicture(&dec, &picId, &isIdrPic, &numErrMbs);
         ++numPics;
-        saveImage(numPics, pic, width, height);
+        if (outputDir) saveImage(pic, width, height, numPics);
+        if (compareDir) totalErrors += compareImage(pic, width, height, numPics);
         break;
       case H264BSD_HDRS_RDY:
         h264bsdCroppingParams(&dec, &croppingFlag, &left, &width, &top, &height);
-        if(!croppingFlag) {
+        if (!croppingFlag) {
           width = h264bsdPicWidth(&dec) * 16;
           height = h264bsdPicHeight(&dec) * 16;
         }
@@ -111,28 +179,32 @@
     }
   }
 
-  printf("Test file complete. %d pictures decoded.\n", numPics);
   h264bsdShutdown(&dec);
+
+  printf("Test file complete. %d pictures decoded.\n", numPics);
+  if (compareDir) printf("%d errors found.\n", totalErrors);
 }
 
 int main(int argc, char *argv[]) {
-  int c = getopt (argc, argv, "ro:");
-  while (c != -1) {
+  int c;
+  while ((c = getopt (argc, argv, "ro:c:")) != -1) {
     switch (c) {
       case 'o':
         outputDir = optarg;
         break;
+      case 'c':
+        compareDir = optarg;
+        break;
       case 'r':
         repeatTest = 1;
         break;
       default:
-        abort ();
+        abort();
     }
-    c = getopt (argc, argv, "o");
   }
 
   if (argc < 2) {
-    fprintf(stderr, "Usage: %s -r [-o <outputDir>] <test_video.h264>\n", argv[0]);
+    fprintf(stderr, "Usage: %s [-r] [-c <actualDir>] [-o <outputDir>] <test_video.h264>\n", argv[0]);
     exit(1);
   }
 
@@ -142,7 +214,7 @@
   createContentBuffer(contentPath, &contentBuffer, &contentSize);
 
   if (repeatTest) {
-    while(1) {
+    while (1) {
       loadContent(contentPath, contentBuffer, contentSize);
       decodeContent(contentBuffer, contentSize);
     }
--- a/test/Rakefile
+++ b/test/Rakefile
@@ -1,9 +1,62 @@
+require 'open-uri'
 
-desc "Download raw test data"
-task :download_raw do
-    (5208..5280).each do |filenum|
-        url = "http://media.xiph.org/BBB/BBB-360-png/big_buck_bunny_0#{filenum}.png"
-        puts "Grabbing #{url}"
-        system("curl -O #{url}")
-    end
+def output_dir(size)
+  sprintf("output/%s", size)
 end
+
+def raw_dir(size)
+  sprintf("raw/%s", size)
+end
+
+def raw_files(size)
+  (5208..5280).collect {|n| sprintf("raw/%s/big_buck_bunny_%05d.png", size, n)}
+end
+
+# 640x360
+directory raw_dir("640x360")
+
+rule %r(raw/640x360/big_buck_bunny_[0-9]+\.png) => raw_dir("640x360") do |t|
+  url = sprintf("http://media.xiph.org/BBB/BBB-360-png/%s", t.name.pathmap("%f"))
+  puts "Grabbing #{url}"
+  open(url) do |s|
+    IO.copy_stream(s, t.name)
+  end
+end
+
+file "test_640x360.h264" => raw_files("640x360") do |f|
+  sh "ffmpeg -y -start_number 5208 -i raw/640x360/big_buck_bunny_%05d.png -pix_fmt yuv420p -c:v libx264 -x264-params keyint=40 -profile:v baseline -f rawvideo test_640x360.h264"
+end
+
+# 1920x1080
+directory raw_dir("1920x1080")
+
+rule %r(raw/1920x1080/big_buck_bunny_[0-9]+\.png) => raw_dir("1920x1080") do |t|
+  url = sprintf("http://media.xiph.org/BBB/BBB-1080-png/%s", t.name.pathmap("%f"))
+  puts "Grabbing #{url}"
+  open(url) do |s|
+    IO.copy_stream(s, t.name)
+  end
+end
+
+file "test_1920x1080.h264" => raw_files("1920x1080") do |f|
+  sh "ffmpeg -y -start_number 5208 -i raw/1920x1080/big_buck_bunny_%05d.png -pix_fmt yuv420p -c:v libx264 -x264-params keyint=40 -profile:v baseline -f rawvideo test_1920x1080.h264"
+end
+
+task :generate_test_data => ["test_640x360.h264", "test_1920x1080.h264"]
+
+directory output_dir("640x360")
+directory output_dir("1920x1080")
+
+task :generate_output_data => ["test_640x360.h264", "test_1920x1080.h264", output_dir("640x360"), output_dir("1920x1080")] do
+  sh "ffmpeg -y -i test_640x360.h264 -c:v rawvideo -f image2 -pix_fmt yuv420p output/640x360/frame_%02d.yuv"
+  sh "ffmpeg -y -i test_1920x1080.h264 -c:v rawvideo -f image2 -pix_fmt yuv420p output/1920x1080/frame_%02d.yuv"
+end
+
+task :clean do
+  FileUtils.rm_rf "raw"
+  FileUtils.rm_rf "output"
+  FileUtils.rm_f "test_640x360.h264"
+  FileUtils.rm_f "test_1920x1080.h264"
+end
+
+task :default => [:generate_test_data]
binary files a/test/test_1920x1080.h264 b/test/test_1920x1080.h264 differ
binary files a/test/test_640x360.h264 b/test/test_640x360.h264 differ