summaryrefslogtreecommitdiff
path: root/test/test_multiplexer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_multiplexer.cc')
-rw-r--r--test/test_multiplexer.cc316
1 files changed, 316 insertions, 0 deletions
diff --git a/test/test_multiplexer.cc b/test/test_multiplexer.cc
new file mode 100644
index 0000000..d431707
--- /dev/null
+++ b/test/test_multiplexer.cc
@@ -0,0 +1,316 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * test_multiplexer.cc
+ *
+ * Wed May 7 08:37:33 CEST 2014
+ * Copyright 2005 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of MIaV.
+ *
+ * MIaV is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MIaV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIaV; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "../src/multiplexer.cc"
+#include "../src/multicast.cc"
+#include "../src/frame.cc"
+#include "../src/miav_config.cc"
+#include "../src/file.cc"
+#include "../src/info_console.cc"
+#include "../src/info.cc"
+#include "../src/threadsafe_queue_priority.cc"
+#include "../src/mutex.cc"
+#include "../src/semaphore.cc"
+#include "../src/util.cc"
+
+// Class used to set config variables from string.
+class MiavConfigString : public MiavConfig {
+public:
+ MiavConfigString(const char *configstring) : MiavConfig() {
+ configs = parse((char*)configstring);
+ }
+};
+
+class StringFile : public File {
+public:
+ StringFile(Info *info) : File(info) {}
+ int Write(void* data, int size) {
+ str.append((const char*)data, (size_t)size);
+ return size;
+ }
+
+ std::string str;
+};
+
+std::string bin2str(uint64_t i)
+{
+ char test[32];
+ i = htonll(i);
+ sprintf(test, "%016llX", i);
+ return test;
+}
+
+std::string bin2str(uint32_t i)
+{
+ char test[32];
+ sprintf(test, "%08X", htonl(i));
+ return test;
+}
+
+std::string bin2str24(uint32_t i)
+{
+ char test[32];
+ sprintf(test, "%06X", (htonl(i) >> 8) & 0xffffff);
+ return test;
+}
+
+std::string bin2str(uint16_t i)
+{
+ char test[32];
+ sprintf(test, "%04X", htons(i));
+ return test;
+}
+
+std::string bin2str(uint8_t i)
+{
+ char test[32];
+ sprintf(test, "%02X", i);
+ return test;
+}
+
+class MultiplexerTest : public Multiplexer {
+public:
+ MultiplexerTest(File *f, Multicast *m, Info *i, volatile bool *r,
+ ThreadSafeQueuePriority *video_q,
+ ThreadSafeQueuePriority *audio_q)
+ : Multiplexer(f, m, i, r, video_q, audio_q) {}
+ void system_header() { Multiplexer::system_header(); }
+ void pack_header(uint32_t SCR) {
+ Multiplexer::SCR = SCR; Multiplexer::pack_header();
+ }
+};
+
+// Originally declared in artefact.cc but we cannot include that since main
+// resides there...
+class test_multiplexer : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_multiplexer);
+ CPPUNIT_TEST(test_SCR);
+ CPPUNIT_TEST(test_Rmux);
+ CPPUNIT_TEST(test_pack);
+ CPPUNIT_TEST(test_system_header);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ InfoConsole *info;
+ MiavConfigString *cfg;
+ volatile bool r;
+
+ void setUp() {
+ cfg = new MiavConfigString(
+ "server_log_file=\"/tmp/miav_unit_test.log\"\n"
+ "server_trash=\"\"\n"
+ "server_later=\"\"\n");
+ config = cfg; // Global. Declared as extern in miav_config.h
+ info = new InfoConsole(cfg);
+ }
+
+ void tearDown() {
+ delete cfg;
+ delete info;
+ }
+
+ void test_SCR() {
+ uint32_t scr = 0xD2345678;
+
+ printf("%x\n", TIMECODE32_30(scr));
+ CPPUNIT_ASSERT(TIMECODE32_30(scr) == 0x3);
+
+ printf("%x\n", TIMECODE29_15(scr));
+ CPPUNIT_ASSERT(TIMECODE29_15(scr) == 0x2468);
+
+ printf("%x\n", TIMECODE14_0(scr));
+ CPPUNIT_ASSERT(TIMECODE14_0(scr) == 0x5678);
+ }
+
+ void test_Rmux() {
+ /**
+ * Calculates Rmux according to subclause A.6.4
+ * mux stands for multiplexing and R for Rate,
+ * so Rmux is the rate of the multiplexing.
+ * IMPORTANT: The formula is wrong...
+ * See
+ * https://www.iso.org/obp/ui/#iso:std:iso-iec:11172:-1:ed-1:v1:cor:2:v1:en
+ * for the correct formula:
+ * Rmux = (video_data_rate + audio_data_rate) *
+ * packet_header_size + pack_header_size / packets_per_pack
+ * ( 1 + ---------------------------------------------------------- )
+ * packet_data_size
+ */
+
+ // Values taken from iso document example.
+ double video_data_rate = 150000;
+ double audio_data_rate = 24000;
+ double packet_header_size = 20;
+ double pack_header_size = 12;
+ double packets_per_pack = 3;
+ double packet_data_size = 2028;
+
+ uint32_t m = ISO11172_1::Rmux(video_data_rate,
+ audio_data_rate,
+ packet_header_size,
+ pack_header_size,
+ packets_per_pack,
+ packet_data_size);
+ CPPUNIT_ASSERT(m == 176059); // Ref value taken from iso document.
+ }
+
+ void test_pack() {
+ StringFile file(info);
+ MultiplexerTest mp(&file, NULL, info, &r, NULL, NULL);
+ mp.pack_header(0xD2345678);
+
+ printf("pack_header:\n ");
+ for(size_t i = 0; i < file.str.length(); i++) {
+ printf("%s ", bin2str(*((uint8_t*)(file.str.data() + i))).c_str());
+ }
+ printf("\n");
+
+ std::string test;
+
+ /*
+ pack_start_code (32 bit) 000001BA in hex.
+ */
+ test = bin2str(*((uint32_t*)(file.str.data() + 0)));
+ printf("system_header_start_code: %s\n", test.c_str());
+ CPPUNIT_ASSERT(test == "000001BA");
+
+ /*
+ system_clock:
+ marker (4 bits): 0b0010
+ sys_clk_ref_32-30 (3 bits): 0x3
+ marker bit(1 bit): 1
+ sys_clk_ref_29-15 (15 bits): 0x2468
+ marker bit(1 bit): 1
+ sys_clk_ref_14-0 (15 bits): 0x5678
+ marker bit(1 bit): 1
+ marker bit(1 bit): 1
+ mux_rate (22 bits): 0x12B667
+ marker bit(1 bit): 1
+ 64 bits total as hex: 2748D1ACF1A56CCF
+ */
+
+ /* // Calculate mux rate
+ uint32_t rmux =
+ ISO11172_1::Rmux(112000, // if no audio frame exists
+ 1100000, // if no video frame exists
+ 20, // packet_header_size,
+ 12, // pack_header_size,
+ PACKETS_PER_PACK, // packets_per_pack,
+ PACKET_SIZE);
+ printf("Rmux: %8X\n", rmux);
+ */
+
+ test = bin2str(*((uint64_t*)(file.str.data() + 4)));
+ CPPUNIT_ASSERT(test == "2748D1ACF1A56CCF");
+ }
+
+ void test_system_header() {
+ StringFile file(info);
+ MultiplexerTest mp(&file, NULL, info, &r, NULL, NULL);
+ mp.system_header();
+
+ printf("system_header:\n ");
+ for(size_t i = 0; i < file.str.length(); i++) {
+ printf("%s ", bin2str(*((uint8_t*)(file.str.data() + i))).c_str());
+ }
+ printf("\n");
+
+ std::string test;
+
+ /*
+ system_header_start_code (32 bit) 000001BB in hex.
+ */
+ test = bin2str(*((uint32_t*)(file.str.data() + 0)));
+ printf("system_header_start_code: %s\n", test.c_str());
+ CPPUNIT_ASSERT(test == "000001BB");
+
+ /*
+ header_length (16 bit) not counting start code and header_length itself.
+ We run with precisely one video stream and one audio stream.
+ 48 bits in fixed header.
+ 24 bits in each of the streamid chunks (of which we have 2)
+ 96 bits in total = 12 bytes (000C in hex)
+ */
+ test = bin2str(*((uint16_t*)(file.str.data() + 4)));
+ printf("header length: %s\n", test.c_str());
+ CPPUNIT_ASSERT(test == "000C");
+
+ /*
+ marker_bit (1 bit) set to 1
+ rate_bound (22 bits) with integer value 3521
+ marker_bit (1 bit) set to 1
+ 24 bits in total with the value 801B83 in hex.
+ */
+ test = bin2str24(*((uint32_t*)(file.str.data() + 6)));
+ printf("rate_bound: %s\n", test.c_str());
+ CPPUNIT_ASSERT(test == "801B83");
+
+ /*
+ header.bits.marker_bit = 1;
+ header.bits.audio_bound = 1; // Only 1 audio stream
+ header.bits.fixed_flag = 1; // Fixed bitrate (0 indicates vbr)
+ header.bits.CSPS_flag = 1; // Standarts compliant?
+ header.bits.system_audio_clock_flag = 1; // FIXME: What excactly is this??
+ header.bits.system_video_clock_flag = 1; // FIXME: What excactly is this??
+ header.bits.video_bound = 1; // Only 1 video stream
+ header.bits.reserved_byte = 0xFF; // Must be 0xFF
+ 24 bits in total with the value 07E1FF in hex.
+ */
+ test = bin2str24(*((uint32_t*)(file.str.data() + 9)));
+ printf("the rest(tm): %s\n", test.c_str());
+ CPPUNIT_ASSERT(test == "07E1FF");
+
+ /*
+ audio stream descriptor:
+ stream_id (8 bits) 0xC0
+ marking bits (2 bits): 0b11
+ STD_buffer_bound_scale (1 bit) : 0
+ STD_buffer_size_bound (13 bits) : 32
+ Total of 24 bits with the value C0E020
+ */
+ test = bin2str24(*((uint32_t*)(file.str.data() + 12)));
+ printf("audio stream descriptor: %s\n", test.c_str());
+ CPPUNIT_ASSERT(test == "C0C020");
+
+ /*
+ video stream descriptor:
+ stream_id (8 bits) 0xE3
+ marking bits (2 bits): 0b11
+ STD_buffer_bound_scale (1 bit) : 1
+ STD_buffer_size_bound (13 bits) : 46
+ Total of 24 bits with the value E3E02E
+ */
+ test = bin2str24(*((uint32_t*)(file.str.data() + 15)));
+ printf("video stream descriptor: %s\n", test.c_str());
+ CPPUNIT_ASSERT(test == "E3E02E");
+ }
+};
+
+// Registers the fixture into the 'registry'
+CPPUNIT_TEST_SUITE_REGISTRATION(test_multiplexer);