diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 9 | ||||
-rw-r--r-- | test/test.cc | 33 | ||||
-rw-r--r-- | test/test_multiplexer.cc | 316 |
3 files changed, 358 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..c58c537 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,9 @@ +TESTS = multiplexer +# pseudoclass + +check_PROGRAMS = $(TESTS) + +multiplexer_CXXFLAGS = $(CPPUNIT_CFLAGS) -DOUTPUT=\"multiplexer\" \ + -I.. -I../../lib $(PQ_CFLAGS) -I$(top_srcdir)/hugin +multiplexer_LDFLAGS = $(CPPUNIT_LIBS) $(PTHREAD_LIBS) +multiplexer_SOURCES = test.cc test_multiplexer.cc diff --git a/test/test.cc b/test/test.cc new file mode 100644 index 0000000..211cce6 --- /dev/null +++ b/test/test.cc @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +//#include <cppunit/CompilerOutputter.h> +#include <cppunit/XmlOutputter.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TestRunner.h> + +#include <fstream> + +int main(int argc, char* argv[]) +{ + // Get the top level suite from the registry + CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + + // Adds the test to the list of test to run + CppUnit::TextUi::TestRunner runner; + runner.addTest( suite ); + + // Change the default outputter to a compiler error format outputter + // runner.setOutputter(new CppUnit::CompilerOutputter(&runner.result(), std::cerr)); + + std::ofstream myfile; + myfile.open("result_"OUTPUT".xml"); + runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), myfile)); + + // Run the tests. + bool wasSucessful = runner.run(); + + myfile.close(); + + // Return error code 1 if the one of test failed. + return wasSucessful ? 0 : 1; +} 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); |