Fixes AMR transcoding. Some features yet unsupported. Fixes #498 Change-Id: I1075a539a7a7dab9106df9ef49b8bda2484b97ecchanges/55/20655/9
| @ -0,0 +1,79 @@ | |||
| #ifndef _BITSTR_H_ | |||
| #define _BITSTR_H_ | |||
| #include "str.h" | |||
| #include <assert.h> | |||
| struct bitstr_s { | |||
| str s; | |||
| unsigned int bit_offset; // leading consumed bits | |||
| }; | |||
| typedef struct bitstr_s bitstr; | |||
| INLINE void bitstr_init(bitstr *b, const str *s) { | |||
| b->s = *s; | |||
| b->bit_offset = 0; | |||
| } | |||
| INLINE int bitstr_shift_ret(bitstr *b, unsigned int bits, str *ret) { | |||
| if (!bits) | |||
| return 0; | |||
| // check if we have enough | |||
| if (bits > b->s.len * 8 - b->bit_offset) | |||
| return -1; | |||
| unsigned int to_copy = (bits + b->bit_offset + 7) / 8; | |||
| if (ret) { | |||
| assert(ret->len >= to_copy); | |||
| ret->len = to_copy; | |||
| memcpy(ret->s, b->s.s, to_copy); | |||
| unsigned char *ret_s = (unsigned char *) ret->s; // avoid bitshifts on signed chars | |||
| // we have to bit-shift the entire string if there was a leading offset | |||
| if (b->bit_offset) { | |||
| unsigned int left = bits; | |||
| unsigned int c = 0; | |||
| while (b->bit_offset + left > 8) { | |||
| // enough to fill one output byte from two consecutive input bytes | |||
| ret_s[c] <<= b->bit_offset; | |||
| ret_s[c] |= ret_s[c + 1] >> (8 - b->bit_offset); | |||
| if (left <= 8) { | |||
| // final trailing bits overlapping bytes: truncate | |||
| ret_s[c] &= 0xff << (8 - left); | |||
| left = 0; | |||
| ret->len--; | |||
| } | |||
| else | |||
| left -= 8; | |||
| c++; | |||
| } | |||
| if (left) { | |||
| // last byte has the remainder | |||
| ret_s[c] <<= b->bit_offset; | |||
| ret_s[c] &= 0xff << (8 - left); | |||
| } | |||
| } | |||
| else { | |||
| // truncate last byte if needed | |||
| unsigned int bits_left = bits % 8; | |||
| if (bits_left) | |||
| ret_s[to_copy - 1] &= 0xff << (8 - bits_left); | |||
| } | |||
| } | |||
| b->bit_offset += bits; | |||
| unsigned int int_bytes = b->bit_offset / 8; | |||
| int shift_ret = str_shift(&b->s, int_bytes); | |||
| assert(shift_ret == 0); | |||
| b->bit_offset -= int_bytes * 8; | |||
| return 0; | |||
| } | |||
| INLINE int bitstr_shift(bitstr *b, unsigned int bits) { | |||
| return bitstr_shift_ret(b, bits, NULL); | |||
| } | |||
| #endif | |||
| @ -0,0 +1,13 @@ | |||
| *.o | |||
| bitstr-test | |||
| amr-encode-test | |||
| amr-decode-test | |||
| core | |||
| .depend | |||
| auxlib.c | |||
| codeclib.c | |||
| fix_frame_channel_layout.h | |||
| loglib.c | |||
| resample.c | |||
| rtplib.c | |||
| str.c | |||
| @ -0,0 +1,111 @@ | |||
| import os | |||
| import ycm_core | |||
| from clang_helpers import PrepareClangFlags | |||
| # Set this to the absolute path to the folder (NOT the file!) containing the | |||
| # compile_commands.json file to use that instead of 'flags'. See here for | |||
| # more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html | |||
| # Most projects will NOT need to set this to anything; you can just change the | |||
| # 'flags' list of compilation flags. Notice that YCM itself uses that approach. | |||
| compilation_database_folder = '' | |||
| # These are the compilation flags that will be used in case there's no | |||
| # compilation database set. | |||
| flags = [ | |||
| '-g', | |||
| '-Wall', | |||
| '-pthread', | |||
| '-fno-strict-aliasing', | |||
| '-I/usr/include/glib-2.0', | |||
| '-I/usr/lib/x86_64-linux-gnu/glib-2.0/include', | |||
| '-I/usr/include/json-glib-1.0', | |||
| '-pthread', | |||
| '-I../kernel-module/', | |||
| '-I../lib/', | |||
| '-D_GNU_SOURCE', | |||
| '-D__DEBUG=1', | |||
| '-D__YCM=1', | |||
| '-DRTPENGINE_VERSION="dummy"', | |||
| '-DRE_PLUGIN_DIR="/usr/lib/rtpengine"', | |||
| '-DWITH_IPTABLES_OPTION', | |||
| '-DWITH_TRANSCODING', | |||
| '-DHAVE_BCG729', | |||
| '-O2', | |||
| '-fstack-protector', | |||
| '--param=ssp-buffer-size=4', | |||
| '-Wformat', | |||
| '-Werror=format-security', | |||
| '-D_FORTIFY_SOURCE=2', | |||
| # THIS IS IMPORTANT! Without a "-std=<something>" flag, clang won't | |||
| # know which language to use when compiling headers. So it will guess. | |||
| # Badly. So C++ headers will be compiled as C headers. | |||
| # You don't want that so ALWAYS specify | |||
| # a "-std=<something>". | |||
| # For a C project, you would set this to something like 'c99' instead of | |||
| # 'c++11'. | |||
| '-std=c99', | |||
| # ...and the same thing goes for the magic -x option which specifies the | |||
| # language that the files to be compiled are written in. This is mostly | |||
| # relevant for c++ headers. | |||
| # For a C project, you would set this to 'c' instead of 'c++'. | |||
| '-x', | |||
| 'c', | |||
| ] | |||
| if compilation_database_folder: | |||
| database = ycm_core.CompilationDatabase(compilation_database_folder) | |||
| else: | |||
| database = None | |||
| def DirectoryOfThisScript(): | |||
| return os.path.dirname(os.path.abspath(__file__)) | |||
| def MakeRelativePathsInFlagsAbsolute(flags, working_directory): | |||
| if not working_directory: | |||
| return flags | |||
| new_flags = [] | |||
| make_next_absolute = False | |||
| path_flags = ['-isystem', '-I', '-iquote', '--sysroot='] | |||
| for flag in flags: | |||
| new_flag = flag | |||
| if make_next_absolute: | |||
| make_next_absolute = False | |||
| if not flag.startswith('/'): | |||
| new_flag = os.path.join(working_directory, flag) | |||
| for path_flag in path_flags: | |||
| if flag == path_flag: | |||
| make_next_absolute = True | |||
| break | |||
| if flag.startswith(path_flag): | |||
| path = flag[len(path_flag):] | |||
| new_flag = path_flag + os.path.join(working_directory, path) | |||
| break | |||
| if new_flag: | |||
| new_flags.append(new_flag) | |||
| return new_flags | |||
| def FlagsForFile(filename): | |||
| if database: | |||
| # Bear in mind that compilation_info.compiler_flags_ does NOT return a | |||
| # python list, but a "list-like" StringVec object | |||
| compilation_info = database.GetCompilationInfoForFile(filename) | |||
| final_flags = PrepareClangFlags( | |||
| MakeRelativePathsInFlagsAbsolute( | |||
| compilation_info.compiler_flags_, | |||
| compilation_info.compiler_working_dir_), | |||
| filename) | |||
| else: | |||
| relative_to = DirectoryOfThisScript() | |||
| final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to) | |||
| return { | |||
| 'flags': final_flags, | |||
| 'do_cache': True | |||
| } | |||
| @ -0,0 +1,62 @@ | |||
| TARGET= unit-tests | |||
| with_transcoding ?= yes | |||
| CFLAGS= -g -Wall -pthread -fno-strict-aliasing | |||
| CFLAGS+= -std=c99 | |||
| CFLAGS+= $(shell pkg-config --cflags glib-2.0) | |||
| CFLAGS+= $(shell pkg-config --cflags gthread-2.0) | |||
| CFLAGS+= $(shell pkg-config --cflags openssl) | |||
| CFLAGS+= -I. -I../lib/ | |||
| CFLAGS+= -D_GNU_SOURCE | |||
| ifeq ($(with_transcoding),yes) | |||
| CFLAGS+= $(shell pkg-config --cflags libavcodec) | |||
| CFLAGS+= $(shell pkg-config --cflags libavformat) | |||
| CFLAGS+= $(shell pkg-config --cflags libavutil) | |||
| CFLAGS+= $(shell pkg-config --cflags libswresample) | |||
| CFLAGS+= $(shell pkg-config --cflags libavfilter) | |||
| CFLAGS+= -DWITH_TRANSCODING | |||
| else | |||
| CFLAGS+= -DWITHOUT_CODECLIB | |||
| endif | |||
| LDFLAGS+= $(shell pkg-config --libs glib-2.0) | |||
| LDFLAGS+= $(shell pkg-config --libs gthread-2.0) | |||
| LDFLAGS+= $(shell pkg-config --libs libcrypto) | |||
| LDFLAGS+= $(shell pkg-config --libs openssl) | |||
| ifeq ($(with_transcoding),yes) | |||
| LDFLAGS+= $(shell pkg-config --libs libavcodec) | |||
| LDFLAGS+= $(shell pkg-config --libs libavformat) | |||
| LDFLAGS+= $(shell pkg-config --libs libavutil) | |||
| LDFLAGS+= $(shell pkg-config --libs libswresample) | |||
| LDFLAGS+= $(shell pkg-config --libs libavfilter) | |||
| endif | |||
| SRCS= bitstr-test.c amr-decode-test.c amr-encode-test.c | |||
| LIBSRCS= loglib.c auxlib.c str.c rtplib.c | |||
| ifeq ($(with_transcoding),yes) | |||
| LIBSRCS+= codeclib.c resample.c | |||
| endif | |||
| OBJS= $(SRCS:.c=.o) $(LIBSRCS:.c=.o) | |||
| include ../lib/common.Makefile | |||
| include .depend | |||
| .PHONY: unit-tests | |||
| TESTS= bitstr-test | |||
| ifeq ($(with_transcoding),yes) | |||
| TESTS+= amr-decode-test amr-encode-test | |||
| endif | |||
| ADD_CLEAN= $(TESTS) | |||
| unit-tests: $(TESTS) | |||
| for x in $(TESTS); do echo testing: $$x; ./$$x || exit 1; done | |||
| bitstr-test: bitstr-test.o | |||
| amr-decode-test: amr-decode-test.o codeclib.o str.o auxlib.o resample.o rtplib.o loglib.o | |||
| amr-encode-test: amr-encode-test.o codeclib.o str.o auxlib.o resample.o rtplib.o loglib.o | |||
| @ -0,0 +1,106 @@ | |||
| #include "codeclib.h" | |||
| #include "str.h" | |||
| #include <assert.h> | |||
| static void hexdump(const unsigned char *buf, int len) { | |||
| for (int i = 0; i < len; i++) | |||
| printf("%02x", buf[i]); | |||
| printf("\n"); | |||
| } | |||
| static int frame_cb(decoder_t *dec, AVFrame *frame, void *u1, void *u2) { | |||
| char **expect = u1; | |||
| int *expect_len = u2; | |||
| assert(expect); | |||
| assert(expect_len); | |||
| assert(*expect); | |||
| if (*expect_len != frame->linesize[0] | |||
| || memcmp(frame->data[0], *expect, *expect_len)) | |||
| { | |||
| printf( | |||
| "packet content mismatch\n" | |||
| "expected %i bytes, received %i bytes\n" | |||
| "expected:\n", | |||
| *expect_len, frame->linesize[0]); | |||
| hexdump((unsigned char *) *expect, *expect_len); | |||
| printf("received:\n"); | |||
| hexdump((unsigned char *) frame->data[0], frame->linesize[0]); | |||
| exit(1); | |||
| } | |||
| *expect = NULL; | |||
| *expect_len = 0; | |||
| return 0; | |||
| } | |||
| static void do_test_amr_xx(const char *file, int line, | |||
| char *fmtp_s, char *data_s, int data_len, char *expect_s, int expect_len, | |||
| char *codec, int clockrate) | |||
| { | |||
| printf("running test %s:%i\n", file, line); | |||
| str codec_name; | |||
| str_init(&codec_name, codec); | |||
| const codec_def_t *def = codec_find(&codec_name, MT_AUDIO); | |||
| assert(def); | |||
| if (!def->support_encoding || !def->support_decoding) { | |||
| printf("AMR not fully supported - skipping test\n"); | |||
| exit(0); | |||
| } | |||
| const format_t fmt = { .clockrate = clockrate, .channels = 1, .format = AV_SAMPLE_FMT_S16}; | |||
| str fmtp_str, *fmtp = NULL; | |||
| if (fmtp_s) { | |||
| str_init(&fmtp_str, fmtp_s); | |||
| fmtp = &fmtp_str; | |||
| } | |||
| decoder_t *d = decoder_new_fmtp(def, clockrate, 1, &fmt, fmtp); | |||
| assert(d); | |||
| const str data = { data_s, data_len }; | |||
| int ret = decoder_input_data(d, &data, 1, frame_cb, &expect_s, &expect_len); | |||
| assert(!ret); | |||
| assert(expect_s == NULL); | |||
| decoder_close(d); | |||
| printf("test ok: %s:%i\n", file, line); | |||
| } | |||
| static void do_test_amr_wb(const char *file, int line, | |||
| char *fmtp_s, char *data_s, int data_len, char *expect_s, int expect_len) | |||
| { | |||
| do_test_amr_xx(file, line, fmtp_s, data_s, data_len, expect_s, expect_len, | |||
| "AMR-WB", 16000); | |||
| } | |||
| static void do_test_amr_nb(const char *file, int line, | |||
| char *fmtp_s, char *data_s, int data_len, char *expect_s, int expect_len) | |||
| { | |||
| do_test_amr_xx(file, line, fmtp_s, data_s, data_len, expect_s, expect_len, | |||
| "AMR", 8000); | |||
| } | |||
| #define do_test_wb(in, out, fmt) \ | |||
| do_test_amr_wb(__FILE__, __LINE__, fmt, in, sizeof(in)-1, out, sizeof(out)-1) | |||
| #define do_test_nb(in, out, fmt) \ | |||
| do_test_amr_nb(__FILE__, __LINE__, fmt, in, sizeof(in)-1, out, sizeof(out)-1) | |||
| int main() { | |||
| codeclib_init(0); | |||
| do_test_wb( | |||
| "\xf0\x44\xf1\x46\x18\x1d\xd1\x57\x23\x13\x42\xf0\x00\x0c\x50\x33\xdd\xff\x0b\x99\x89\x2c\x68\x52\xf8\xf8\xd9\x59\x16\xd7\x45\xe7\x01\xec\x1f\xfe\x5b\xc6\xf9\x01\xa4\xb5\xe0\x6c\x91\x41\xfe\x52\x2c\xce\x44\xbb\x5a\xdf\x76\x29\xf8\xdb\xca\x18\xd6\x50", | |||
| "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\xff\xff\x02\x00\xff\xff\xff\xff\x02\x00\xfd\xff\x03\x00\x00\x00\xfd\xff\x04\x00\xfc\xff\x02\x00\x01\x00\xfd\xff\x03\x00\xfe\xff\x01\x00\x01\x00\xff\xff\x01\x00\xff\xff\x01\x00\xff\xff\x00\x00\x01\x00\xff\xff\x00\x00\x00\x00\xff\xff\x00\x00\x01\x00\xfe\xff\x02\x00\xff\xff\xff\xff\x03\x00\xfd\xff\x03\x00\xff\xff\xff\xff\x03\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x02\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x02\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x04\x00\xfe\xff\xfd\xff\x00\x00\x02\x00\xfe\xff\xf8\xff\x01\x00\x04\x00\xff\xff\xff\xff\xfc\xff\x06\x00\x00\x00\xf8\xff\x11\x00\x09\x00\x06\x00\x3f\x00\x37\x00\xf9\xff\x11\x00\x4e\x00\x34\x00\xf4\xff\x17\x00\x5d\x00\x31\x00\xe0\xff\x0b\x00\x71\x00\x42\x00\xd3\xff\x09\x00\x74\x00\x3c\x00\xc8\xff\x03\x00\x78\x00\x35\x00\xbc\xff\xff\xff\x7a\x00\x2e\x00\xb0\xff\x00\x00\x77\x00\x26\x00\xaa\xff\xfc\xff\x78\x00\x1c\x00\xa3\xff\xfe\xff\x72\x00\x14\x00\xa0\xff\xfc\xff\x6f\x00\x09\x00\x8e\xff\xfc\xff\x72\x00\xff\xff\x89\xff\xff\xff\x7e\x00\xfe\xff\x7b\xff\x19\x00\xa9\x00\xfa\xff\x62\xff\x14\x00\xae\x00\xf5\xff\x54\xff\x16\x00\xb6\x00\xe8\xff\x3f\xff\x0b\x00\xb9\x00\xee\xff\x34\xff\xfd\xff\xb8\x00\xe9\xff\x2d\xff\x00\x00\xb8\x00\xe4\xff\x2c\xff\xff\xff\xb9\x00\xdf\xff\x25\xff\xff\xff\xb2\x00\xda\xff\x28\xff\xfc\xff\xae\x00\xd6\xff\x2a\xff\xff\xff\xa5\x00\xd8\xff\x30\xff\xfc\xff\xa1\x00\xd5\xff\x35\xff\xf9\xff\x97\x00\xd4\xff\x37\xff\xfa\xff\x92\x00\xcd\xff\x38\xff\xfe\xff\x8e\x00\xcb\xff\x3e\xff\xfe\xff\x88\x00\xcc\xff\x40\xff\xfa\xff\x89\x00\xcf\xff\x41\xff\xfa\xff\x87\x00\xd0\xff\x44\xff\xfa\xff\x89\x00\xd6\xff\x48\xff\xf9\xff\x88\x00\xdd\xff\x4d\xff\xf2\xff\x81\x00\xde\xff\x54\xff\xf4\xff\x7b\x00\xde\xff\x5c\xff\xf6\xff\x73\x00\xe0\xff\x65\xff\xf6\xff\x6d\x00\xe0\xff\x6f\xff\xf7\xff\x63\x00\xe0\xff\x78\xff\xf7\xff\x5d\x00\xde\xff\x76\xff\xf9\xff\x60\x00\xdf\xff\x7f\xff\xfb\xff\x5c\x00\xe8\xff\x85\xff\xfb\xff\x60\x00\xea\xff\x87\xff\xfe\xff\x63\x00\xee\xff\x8b\xff\x00\x00\x64\x00\xf3\xff\x8d\xff\xfe\xff\x66\x00\xf7\xff\x8f\xff\xfd\xff\x68\x00\xf9\xff\x8c\xff\xfd\xff\x6d\x00\xfc\xff\x8c\xff\xfd\xff\x71\x00\xff\xff\x89\xff\xfe\xff\x75\x00\x02\x00\x88\xff\xfc\xff\x78\x00\x03\x00\x87\xff\xfd\xff\x7b\x00\x03\x00\x86\xff\x00\x00\x7e\x00\x03\x00\x84\xff\xfe\xff\x81\x00\x07\x00\x82\xff\x01\x00\x84\x00\x03\x00\x82\xff\x05\x00\x88\x00\x05\x00\x81\xff\x04\x00\x88\x00\x05\x00\x80\xff\x05\x00\x8a\x00\x05\x00", | |||
| "octet-align=1"); | |||
| do_test_wb( | |||
| "\xf4\x7c\x51\x86\x07\x74\x55\xc8\xc4\xd0\xbc\x00\x03\x14\x0c\xf7\x7f\xc2\xe6\x62\x4b\x1a\x14\xbe\x3e\x36\x56\x45\xb5\xd1\x79\xc0\x7b\x07\xff\x96\xf1\xbe\x40\x69\x2d\x78\x1b\x24\x50\x7f\x94\x8b\x33\x91\x2e\xd6\xb7\xdd\x8a\x7e\x36\xf2\x86\x35\x94", | |||
| "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\xff\xff\x02\x00\xff\xff\xff\xff\x02\x00\xfd\xff\x03\x00\x00\x00\xfd\xff\x04\x00\xfc\xff\x02\x00\x01\x00\xfd\xff\x03\x00\xfe\xff\x01\x00\x01\x00\xff\xff\x01\x00\xff\xff\x01\x00\xff\xff\x00\x00\x01\x00\xff\xff\x00\x00\x00\x00\xff\xff\x00\x00\x01\x00\xfe\xff\x02\x00\xff\xff\xff\xff\x03\x00\xfd\xff\x03\x00\xff\xff\xff\xff\x03\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x02\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x02\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x04\x00\xfe\xff\xfd\xff\x00\x00\x02\x00\xfe\xff\xf8\xff\x01\x00\x04\x00\xff\xff\xff\xff\xfc\xff\x06\x00\x00\x00\xf8\xff\x11\x00\x09\x00\x06\x00\x3f\x00\x37\x00\xf9\xff\x11\x00\x4e\x00\x34\x00\xf4\xff\x17\x00\x5d\x00\x31\x00\xe0\xff\x0b\x00\x71\x00\x42\x00\xd3\xff\x09\x00\x74\x00\x3c\x00\xc8\xff\x03\x00\x78\x00\x35\x00\xbc\xff\xff\xff\x7a\x00\x2e\x00\xb0\xff\x00\x00\x77\x00\x26\x00\xaa\xff\xfc\xff\x78\x00\x1c\x00\xa3\xff\xfe\xff\x72\x00\x14\x00\xa0\xff\xfc\xff\x6f\x00\x09\x00\x8e\xff\xfc\xff\x72\x00\xff\xff\x89\xff\xff\xff\x7e\x00\xfe\xff\x7b\xff\x19\x00\xa9\x00\xfa\xff\x62\xff\x14\x00\xae\x00\xf5\xff\x54\xff\x16\x00\xb6\x00\xe8\xff\x3f\xff\x0b\x00\xb9\x00\xee\xff\x34\xff\xfd\xff\xb8\x00\xe9\xff\x2d\xff\x00\x00\xb8\x00\xe4\xff\x2c\xff\xff\xff\xb9\x00\xdf\xff\x25\xff\xff\xff\xb2\x00\xda\xff\x28\xff\xfc\xff\xae\x00\xd6\xff\x2a\xff\xff\xff\xa5\x00\xd8\xff\x30\xff\xfc\xff\xa1\x00\xd5\xff\x35\xff\xf9\xff\x97\x00\xd4\xff\x37\xff\xfa\xff\x92\x00\xcd\xff\x38\xff\xfe\xff\x8e\x00\xcb\xff\x3e\xff\xfe\xff\x88\x00\xcc\xff\x40\xff\xfa\xff\x89\x00\xcf\xff\x41\xff\xfa\xff\x87\x00\xd0\xff\x44\xff\xfa\xff\x89\x00\xd6\xff\x48\xff\xf9\xff\x88\x00\xdd\xff\x4d\xff\xf2\xff\x81\x00\xde\xff\x54\xff\xf4\xff\x7b\x00\xde\xff\x5c\xff\xf6\xff\x73\x00\xe0\xff\x65\xff\xf6\xff\x6d\x00\xe0\xff\x6f\xff\xf7\xff\x63\x00\xe0\xff\x78\xff\xf7\xff\x5d\x00\xde\xff\x76\xff\xf9\xff\x60\x00\xdf\xff\x7f\xff\xfb\xff\x5c\x00\xe8\xff\x85\xff\xfb\xff\x60\x00\xea\xff\x87\xff\xfe\xff\x63\x00\xee\xff\x8b\xff\x00\x00\x64\x00\xf3\xff\x8d\xff\xfe\xff\x66\x00\xf7\xff\x8f\xff\xfd\xff\x68\x00\xf9\xff\x8c\xff\xfd\xff\x6d\x00\xfc\xff\x8c\xff\xfd\xff\x71\x00\xff\xff\x89\xff\xfe\xff\x75\x00\x02\x00\x88\xff\xfc\xff\x78\x00\x03\x00\x87\xff\xfd\xff\x7b\x00\x03\x00\x86\xff\x00\x00\x7e\x00\x03\x00\x84\xff\xfe\xff\x81\x00\x07\x00\x82\xff\x01\x00\x84\x00\x03\x00\x82\xff\x05\x00\x88\x00\x05\x00\x81\xff\x04\x00\x88\x00\x05\x00\x80\xff\x05\x00\x8a\x00\x05\x00", | |||
| NULL); | |||
| do_test_wb( | |||
| "\xf4\x7c\x51\x86\x07\x74\x55\xc8\xc4\xd0\xbc\x00\x03\x14\x0c\xf7\x7f\xc2\xe6\x62\x4b\x1a\x14\xbe\x3e\x36\x56\x45\xb5\xd1\x79\xc0\x7b\x07\xff\x96\xf1\xbe\x40\x69\x2d\x78\x1b\x24\x50\x7f\x94\x8b\x33\x91\x2e\xd6\xb7\xdd\x8a\x7e\x36\xf2\x86\x35\x94", | |||
| "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\xff\xff\x02\x00\xff\xff\xff\xff\x02\x00\xfd\xff\x03\x00\x00\x00\xfd\xff\x04\x00\xfc\xff\x02\x00\x01\x00\xfd\xff\x03\x00\xfe\xff\x01\x00\x01\x00\xff\xff\x01\x00\xff\xff\x01\x00\xff\xff\x00\x00\x01\x00\xff\xff\x00\x00\x00\x00\xff\xff\x00\x00\x01\x00\xfe\xff\x02\x00\xff\xff\xff\xff\x03\x00\xfd\xff\x03\x00\xff\xff\xff\xff\x03\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x02\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x02\x00\xfe\xff\x01\x00\x00\x00\xff\xff\x04\x00\xfe\xff\xfd\xff\x00\x00\x02\x00\xfe\xff\xf8\xff\x01\x00\x04\x00\xff\xff\xff\xff\xfc\xff\x06\x00\x00\x00\xf8\xff\x11\x00\x09\x00\x06\x00\x3f\x00\x37\x00\xf9\xff\x11\x00\x4e\x00\x34\x00\xf4\xff\x17\x00\x5d\x00\x31\x00\xe0\xff\x0b\x00\x71\x00\x42\x00\xd3\xff\x09\x00\x74\x00\x3c\x00\xc8\xff\x03\x00\x78\x00\x35\x00\xbc\xff\xff\xff\x7a\x00\x2e\x00\xb0\xff\x00\x00\x77\x00\x26\x00\xaa\xff\xfc\xff\x78\x00\x1c\x00\xa3\xff\xfe\xff\x72\x00\x14\x00\xa0\xff\xfc\xff\x6f\x00\x09\x00\x8e\xff\xfc\xff\x72\x00\xff\xff\x89\xff\xff\xff\x7e\x00\xfe\xff\x7b\xff\x19\x00\xa9\x00\xfa\xff\x62\xff\x14\x00\xae\x00\xf5\xff\x54\xff\x16\x00\xb6\x00\xe8\xff\x3f\xff\x0b\x00\xb9\x00\xee\xff\x34\xff\xfd\xff\xb8\x00\xe9\xff\x2d\xff\x00\x00\xb8\x00\xe4\xff\x2c\xff\xff\xff\xb9\x00\xdf\xff\x25\xff\xff\xff\xb2\x00\xda\xff\x28\xff\xfc\xff\xae\x00\xd6\xff\x2a\xff\xff\xff\xa5\x00\xd8\xff\x30\xff\xfc\xff\xa1\x00\xd5\xff\x35\xff\xf9\xff\x97\x00\xd4\xff\x37\xff\xfa\xff\x92\x00\xcd\xff\x38\xff\xfe\xff\x8e\x00\xcb\xff\x3e\xff\xfe\xff\x88\x00\xcc\xff\x40\xff\xfa\xff\x89\x00\xcf\xff\x41\xff\xfa\xff\x87\x00\xd0\xff\x44\xff\xfa\xff\x89\x00\xd6\xff\x48\xff\xf9\xff\x88\x00\xdd\xff\x4d\xff\xf2\xff\x81\x00\xde\xff\x54\xff\xf4\xff\x7b\x00\xde\xff\x5c\xff\xf6\xff\x73\x00\xe0\xff\x65\xff\xf6\xff\x6d\x00\xe0\xff\x6f\xff\xf7\xff\x63\x00\xe0\xff\x78\xff\xf7\xff\x5d\x00\xde\xff\x76\xff\xf9\xff\x60\x00\xdf\xff\x7f\xff\xfb\xff\x5c\x00\xe8\xff\x85\xff\xfb\xff\x60\x00\xea\xff\x87\xff\xfe\xff\x63\x00\xee\xff\x8b\xff\x00\x00\x64\x00\xf3\xff\x8d\xff\xfe\xff\x66\x00\xf7\xff\x8f\xff\xfd\xff\x68\x00\xf9\xff\x8c\xff\xfd\xff\x6d\x00\xfc\xff\x8c\xff\xfd\xff\x71\x00\xff\xff\x89\xff\xfe\xff\x75\x00\x02\x00\x88\xff\xfc\xff\x78\x00\x03\x00\x87\xff\xfd\xff\x7b\x00\x03\x00\x86\xff\x00\x00\x7e\x00\x03\x00\x84\xff\xfe\xff\x81\x00\x07\x00\x82\xff\x01\x00\x84\x00\x03\x00\x82\xff\x05\x00\x88\x00\x05\x00\x81\xff\x04\x00\x88\x00\x05\x00\x80\xff\x05\x00\x8a\x00\x05\x00", | |||
| ""); | |||
| do_test_nb( | |||
| "\xf0\x3c\x53\xff\x3a\xe8\x30\x41\xa5\xa8\xa4\x1d\x2f\xf2\x03\x60\x35\xc0\x00\x07\xc5\x53\xf4\xbc\x98\x00\x01\x14\x2f\xf0\x00\x0f\x70", | |||
| "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\xff\xf8\xff\x10\x00\x00\x00\xe8\xff\xf8\xff\x28\x00\x00\x00\xc8\xff\x00\x00\x38\x00\xf8\xff\xb0\xff\x08\x00\x48\x00\xf0\xff\xa8\xff\x08\x00\x60\x00\xf8\xff\x98\xff\x08\x00\x88\x00\xf0\xff\x88\xff\x10\x00\x88\x00\xe8\xff\x70\xff\x18\x00\x80\x00\xd8\xff\x70\xff\x08\x00\x78\x00\xd8\xff\x88\xff\x08\x00\x78\x00\xe8\xff\x90\xff\x10\x00\x70\x00\xe0\xff\x90\xff\x08\x00\x68\x00\xf8\xff\x88\xff\x00\x00\x80\x00\xf8\xff\x88\xff\x00\x00\x80\x00\xf8\xff\x78\xff\x08\x00\x80\x00\xe8\xff\x78\xff\x08\x00\x78\x00\xe0\xff\x88\xff\x10\x00\x70\x00\xe8\xff\x90\xff\x10\x00\x68\x00\xe0\xff\x98\xff\x08\x00\x70\x00\xe8\xff\xa8\xff\xf8\xff\x70\x00\xf0\xff\x98\xff\xf8\xff\x68\x00\x00\x00\x80\xff\xf8\xff\x68\x00\xf8\xff\x90\xff\x00\x00\x70\x00\xf8\xff\x90\xff\x00\x00\x78\x00\xf0\xff\x88\xff\x00\x00\x80\x00\xf8\xff\x80\xff\x00\x00\x88\x00\xf8\xff\x80\xff\xf8\xff\x88\x00\xf8\xff\x70\xff\x00\x00\x80\x00\xf0\xff\x80\xff\xf8\xff\x80\x00\xe8\xff\x80\xff\xf0\xff\x88\x00", | |||
| "octet-align=1"); | |||
| return 0; | |||
| } | |||
| @ -0,0 +1,147 @@ | |||
| #include "codeclib.h" | |||
| #include "str.h" | |||
| #include <assert.h> | |||
| static void hexdump(const unsigned char *buf, int len) { | |||
| for (int i = 0; i < len; i++) | |||
| printf("%02x", buf[i]); | |||
| printf("\n"); | |||
| } | |||
| static int dec_cb(encoder_t *e, void *u1, void *u2) { | |||
| char **expect = u1; | |||
| int *expect_len = u2; | |||
| assert(expect); | |||
| assert(expect_len); | |||
| assert(*expect); | |||
| GString *buf = g_string_new(""); | |||
| int plen = 256; | |||
| char payload[plen]; | |||
| str inout = { payload, plen }; | |||
| e->def->packetizer(&e->avpkt, buf, &inout, e); | |||
| if (inout.len != *expect_len | |||
| || memcmp(inout.s, *expect, *expect_len)) | |||
| { | |||
| printf( | |||
| "packet content mismatch\n" | |||
| "expected %i bytes, received %i bytes\n" | |||
| "expected:\n", | |||
| *expect_len, inout.len); | |||
| hexdump((unsigned char *) *expect, *expect_len); | |||
| printf("received:\n"); | |||
| hexdump((unsigned char *) inout.s, inout.len); | |||
| exit(1); | |||
| } | |||
| *expect = NULL; | |||
| *expect_len = 0; | |||
| g_string_free(buf, TRUE); | |||
| return 0; | |||
| } | |||
| static void do_test_amr_xx(const char *file, int line, | |||
| char *fmtp_s, char *data_s, int data_len, char *expect_s, int expect_len, | |||
| int bitrate, char *codec, int clockrate) | |||
| { | |||
| printf("running test %s:%i\n", file, line); | |||
| str codec_name; | |||
| str_init(&codec_name, codec); | |||
| const codec_def_t *def = codec_find(&codec_name, MT_AUDIO); | |||
| assert(def); | |||
| if (!def->support_encoding || !def->support_decoding) { | |||
| printf("AMR not fully supported - skipping test\n"); | |||
| exit(0); | |||
| } | |||
| const format_t fmt = { .clockrate = clockrate, .channels = 1, .format = 0 }; | |||
| str fmtp_str, *fmtp = NULL; | |||
| char *fmtp_buf = NULL; | |||
| if (fmtp_s) { | |||
| fmtp_buf = strdup(fmtp_s); | |||
| str_init(&fmtp_str, fmtp_buf); | |||
| fmtp = &fmtp_str; | |||
| } | |||
| encoder_t *e = encoder_new(); | |||
| assert(e); | |||
| format_t actual_fmt; | |||
| int ret = encoder_config_fmtp(e, def, bitrate, 20, &fmt, &actual_fmt, fmtp); | |||
| assert(actual_fmt.clockrate == clockrate); | |||
| assert(actual_fmt.channels == 1); | |||
| assert(actual_fmt.format == AV_SAMPLE_FMT_S16); | |||
| AVFrame *frame = av_frame_alloc(); | |||
| assert(frame); | |||
| frame->nb_samples = 20 * clockrate / 1000; | |||
| frame->format = actual_fmt.format; | |||
| frame->sample_rate = actual_fmt.clockrate; | |||
| frame->channel_layout = av_get_default_channel_layout(actual_fmt.channels); | |||
| ret = av_frame_get_buffer(frame, 0); | |||
| assert(ret >= 0); | |||
| assert(data_len == frame->nb_samples * 2); | |||
| memcpy(frame->data[0], data_s, data_len); | |||
| ret = encoder_input_data(e, frame, dec_cb, &expect_s, &expect_len); | |||
| assert(!ret); | |||
| assert(expect_s == NULL); | |||
| encoder_free(e); | |||
| free(fmtp_buf); | |||
| printf("test ok: %s:%i\n", file, line); | |||
| } | |||
| static void do_test_amr_wb(const char *file, int line, | |||
| char *fmtp_s, char *data_s, int data_len, char *expect_s, int expect_len, | |||
| int bitrate) | |||
| { | |||
| do_test_amr_xx(file, line, fmtp_s, data_s, data_len, expect_s, expect_len, bitrate, | |||
| "AMR-WB", 16000); | |||
| } | |||
| static void do_test_amr_nb(const char *file, int line, | |||
| char *fmtp_s, char *data_s, int data_len, char *expect_s, int expect_len, | |||
| int bitrate) | |||
| { | |||
| do_test_amr_xx(file, line, fmtp_s, data_s, data_len, expect_s, expect_len, bitrate, | |||
| "AMR", 8000); | |||
| } | |||
| #define do_test_wb(in, out, fmt, bitrate) \ | |||
| do_test_amr_wb(__FILE__, __LINE__, fmt, in, sizeof(in)-1, out, sizeof(out)-1, bitrate) | |||
| #define do_test_nb(in, out, fmt, bitrate) \ | |||
| do_test_amr_nb(__FILE__, __LINE__, fmt, in, sizeof(in)-1, out, sizeof(out)-1, bitrate) | |||
| #define test_320_samples_16_bits \ | |||
| "\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01" | |||
| #define test_160_samples_16_bits \ | |||
| "\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01\x00\x00\x01\x00\x01\x00\x01\x01" | |||
| int main() { | |||
| codeclib_init(0); | |||
| do_test_wb( | |||
| test_320_samples_16_bits, | |||
| "\xf0\x44\xf1\x46\x18\x1d\xd1\x57\x23\x13\x42\xf0\x00\x0c\x50\x33\xdd\xff\x0b\x99\x89\x2c\x68\x52\xf8\xf8\xd9\x59\x16\xd7\x45\xe7\x01\xec\x1f\xfe\x5b\xc6\xf9\x01\xa4\xb5\xe0\x6c\x91\x41\xfe\x52\x2c\xce\x44\xbb\x5a\xdf\x76\x29\xf8\xdb\xca\x18\xd6\x50", | |||
| "octet-align=1", | |||
| 23850); | |||
| do_test_wb( | |||
| test_320_samples_16_bits, | |||
| "\xf0\x00\x44\xf1\x46\x18\x1d\xd1\x57\x23\x13\x42\xf0\x00\x0c\x50\x33\xdd\xff\x0b\x99\x89\x2c\x68\x52\xf8\xf8\xd9\x59\x16\xd7\x45\xe7\x01\xec\x1f\xfe\x5b\xc6\xf9\x01\xa4\xb5\xe0\x6c\x91\x41\xfe\x52\x2c\xce\x44\xbb\x5a\xdf\x76\x29\xf8\xdb\xca\x18\xd6\x50", | |||
| "octet-align=1;interleaving=4", | |||
| 23850); | |||
| do_test_wb( | |||
| test_320_samples_16_bits, | |||
| "\xf4\x7c\x51\x86\x07\x74\x55\xc8\xc4\xd0\xbc\x00\x03\x14\x0c\xf7\x7f\xc2\xe6\x62\x4b\x1a\x14\xbe\x3e\x36\x56\x45\xb5\xd1\x79\xc0\x7b\x07\xff\x96\xf1\xbe\x40\x69\x2d\x78\x1b\x24\x50\x7f\x94\x8b\x33\x91\x2e\xd6\xb7\xdd\x8a\x7e\x36\xf2\x86\x35\x94", | |||
| NULL, | |||
| 23850); | |||
| do_test_nb( | |||
| test_160_samples_16_bits, | |||
| "\xf0\x3c\x53\xff\x3a\xe8\x30\x41\xa5\xa8\xa4\x1d\x2f\xf2\x03\x60\x35\xc0\x00\x07\xc5\x53\xf4\xbc\x98\x00\x01\x14\x2f\xf0\x00\x0f\x70", | |||
| "octet-align=1", | |||
| 12200); | |||
| return 0; | |||
| } | |||
| @ -0,0 +1,204 @@ | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #include <stdlib.h> | |||
| #include <stdarg.h> | |||
| #include "bitstr.h" | |||
| #include "str.h" | |||
| #define do_test_ret(retval, args...) do { \ | |||
| int r = do_test(args); \ | |||
| if (r != retval) \ | |||
| err("didn't run all tests!\n"); \ | |||
| } while (0) | |||
| #define test1(input, shift_len, output, result) \ | |||
| do_test_ret(1, input, sizeof(input)-1, __FILE__, __LINE__, shift_len, output, sizeof(output)-1, \ | |||
| result, 0) | |||
| #define test2(input, shift_len1, output1, result1, shift_len2, output2, result2) \ | |||
| do_test_ret(2, input, sizeof(input)-1, __FILE__, __LINE__, \ | |||
| shift_len1, output1, sizeof(output1)-1, result1, \ | |||
| shift_len2, output2, sizeof(output2)-1, result2, \ | |||
| 0) | |||
| #define test3(input, \ | |||
| shift_len1, output1, result1, \ | |||
| shift_len2, output2, result2, \ | |||
| shift_len3, output3, result3) \ | |||
| do_test_ret(3, input, sizeof(input)-1, __FILE__, __LINE__, \ | |||
| shift_len1, output1, sizeof(output1)-1, result1, \ | |||
| shift_len2, output2, sizeof(output2)-1, result2, \ | |||
| shift_len3, output3, sizeof(output3)-1, result3, \ | |||
| 0) | |||
| #define err(fmt...) do { \ | |||
| fprintf(stderr, fmt); \ | |||
| exit(1); \ | |||
| } while (0) | |||
| int do_test(const char *input, unsigned int input_len, | |||
| const char *file, unsigned int line, | |||
| ...) | |||
| { | |||
| char in_buf[input_len]; | |||
| memcpy(in_buf, input, input_len); | |||
| str inp; | |||
| str_init_len(&inp, in_buf, input_len); | |||
| bitstr inp_bs; | |||
| bitstr_init(&inp_bs, &inp); | |||
| va_list ap; | |||
| va_start(ap, line); | |||
| int argc = 0; | |||
| while (1) { | |||
| unsigned int shift_len = va_arg(ap, unsigned int); | |||
| if (!shift_len) | |||
| break; | |||
| const char *output = va_arg(ap, const char *); | |||
| unsigned int output_len = va_arg(ap, unsigned int); | |||
| int result = va_arg(ap, int); | |||
| char out_buf[output_len+1]; | |||
| str outp = STR_CONST_INIT_BUF(out_buf); | |||
| int ret; | |||
| if (output) | |||
| ret = bitstr_shift_ret(&inp_bs, shift_len, &outp); | |||
| else | |||
| ret = bitstr_shift(&inp_bs, shift_len); | |||
| if (ret != result) | |||
| err("ERROR return %i instead of %i (%s:%i arg %i)\n", | |||
| ret, result, file, line, argc); | |||
| if (ret == 0 && output) { | |||
| if (outp.len != output_len) | |||
| err("ERROR output len %i instead of %i (%s:%i arg %i)\n", | |||
| outp.len, output_len, file, line, argc); | |||
| if (memcmp(outp.s, output, output_len)) | |||
| err("ERROR output string mismatch (%s:%i arg %i)\n", | |||
| file, line, argc); | |||
| } | |||
| // if (inp.len != remainder_len) | |||
| // err("ERROR remainder len %i instead of %i (%s:%i arg %i)\n", | |||
| // inp.len, remainder_len, file, line, argc); | |||
| printf("test ok: %s:%i arg %i\n", file, line, argc); | |||
| argc++; | |||
| } | |||
| return argc; | |||
| } | |||
| int main() { | |||
| test1("\x81", 8, "\x81", 0); | |||
| test2("\x81", 8, "\x81", 0, 1, "", -1); | |||
| test2("\x81", 8, "\x81", 0, 1, NULL, -1); | |||
| test1("\x81", 7, "\x80", 0); | |||
| test2("\x81", 7, "\x80", 0, 1, "\x80", 0); | |||
| test3("\x81", 7, "\x80", 0, 1, "\x80", 0, 1, "", -1); | |||
| test3("\x81", 7, "\x80", 0, 1, NULL, 0, 1, "", -1); | |||
| test3("\x81", 7, "\x80", 0, 1, "\x80", 0, 1, NULL, -1); | |||
| test3("\x81", 7, "\x80", 0, 1, NULL, 0, 1, NULL, -1); | |||
| test2("\x81", 7, "\x80", 0, 2, "", -1); | |||
| test2("\x81", 7, "\x80", 0, 2, NULL, -1); | |||
| test1("\x82", 7, "\x82", 0); | |||
| test2("\x82", 7, "\x82", 0, 1, "\x00", 0); | |||
| test2("\x82", 7, NULL, 0, 1, "\x00", 0); | |||
| test3("\x82", 7, "\x82", 0, 1, "\x00", 0, 1, "", -1); | |||
| test3("\x82", 7, "\x82", 0, 1, NULL, 0, 1, "", -1); | |||
| test3("\x82", 7, "\x82", 0, 1, "\x00", 0, 1, NULL, -1); | |||
| test3("\x82", 7, "\x82", 0, 1, NULL, 0, 1, NULL, -1); | |||
| test2("\x82", 7, "\x82", 0, 2, "", -1); | |||
| test2("\x82", 7, "\x82", 0, 2, NULL, -1); | |||
| test1("\x83", 7, "\x82", 0); | |||
| test2("\x83", 7, "\x82", 0, 1, "\x80", 0); | |||
| test2("\x83", 7, NULL, 0, 1, "\x80", 0); | |||
| test3("\x83", 7, "\x82", 0, 1, "\x80", 0, 1, "", -1); | |||
| test3("\x83", 7, "\x82", 0, 1, NULL, 0, 1, "", -1); | |||
| test2("\x83", 7, "\x82", 0, 2, "", -1); | |||
| test1("\x81", 1, "\x80", 0); | |||
| test2("\x81", 1, "\x80", 0, 7, "\x02", 0); | |||
| test3("\x81", 1, "\x80", 0, 7, "\x02", 0, 1, "", -1); | |||
| test3("\x81", 1, NULL, 0, 7, "\x02", 0, 1, "", -1); | |||
| test3("\x81", 1, "\x80", 0, 7, NULL, 0, 1, "", -1); | |||
| test3("\x81", 1, NULL, 0, 7, NULL, 0, 1, "", -1); | |||
| test1("\xff", 1, "\x80", 0); | |||
| test2("\xff", 1, "\x80", 0, 5, "\xf8", 0); | |||
| test3("\xff", 1, "\x80", 0, 5, "\xf8", 0, 2, "\xc0", 0); | |||
| test3("\xff", 1, NULL, 0, 5, "\xf8", 0, 2, "\xc0", 0); | |||
| test3("\xff", 1, "\x80", 0, 5, NULL, 0, 2, "\xc0", 0); | |||
| test3("\xff", 1, NULL, 0, 5, NULL, 0, 2, "\xc0", 0); | |||
| test3("\xff", 1, "\x80", 0, 5, "\xf8", 0, 3, "", -1); | |||
| test2("\xff", 1, "\x80", 0, 7, "\xfe", 0); | |||
| test3("\xff", 1, "\x80", 0, 7, "\xfe", 0, 1, "", -1); | |||
| test3("\xff", 1, NULL, 0, 7, "\xfe", 0, 1, "", -1); | |||
| test3("\xff", 1, "\x80", 0, 7, NULL, 0, 1, "", -1); | |||
| test3("\xff", 1, NULL, 0, 7, NULL, 0, 1, "", -1); | |||
| test1("J76x", 8, "J", 0); | |||
| test2("J76x", 8, "J", 0, 8, "7", 0); | |||
| test3("J76x", 8, "J", 0, 8, "7", 0, 7, "6", 0); | |||
| test3("J76x", 8, "J", 0, 8, "7", 0, 14, "6x", 0); | |||
| test3("J76x", 8, "J", 0, 8, "7", 0, 16, "6x", 0); | |||
| test3("J76x", 8, "J", 0, 8, "7", 0, 17, "", -1); | |||
| test2("J76x", 8, "J", 0, 12, "70", 0); | |||
| test3("J76x", 8, "J", 0, 12, "70", 0, 3, "`", 0); | |||
| test3("J76x", 8, "J", 0, 12, "70", 0, 6, "d", 0); | |||
| test3("J76x", 8, "J", 0, 12, "70", 0, 8, "g", 0); | |||
| test3("J76x", 8, "J", 0, 12, "70", 0, 12, "g\x80", 0); | |||
| test3("J76x", 8, NULL, 0, 12, "70", 0, 12, "g\x80", 0); | |||
| test3("J76x", 8, "J", 0, 12, NULL, 0, 12, "g\x80", 0); | |||
| test3("J76x", 8, NULL, 0, 12, NULL, 0, 12, "g\x80", 0); | |||
| test3("J76x", 8, "J", 0, 12, "70", 0, 13, "", -1); | |||
| test2("J76x", 8, "J", 0, 14, "74", 0); | |||
| test3("J76x", 8, "J", 0, 14, "74", 0, 5, "\x98", 0); | |||
| test3("J76x", 8, NULL, 0, 14, "74", 0, 5, "\x98", 0); | |||
| test3("J76x", 8, "J", 0, 14, NULL, 0, 5, "\x98", 0); | |||
| test3("J76x", 8, NULL, 0, 14, NULL, 0, 5, "\x98", 0); | |||
| test3("J76x", 8, "J", 0, 14, "74", 0, 8, "\x9e", 0); | |||
| test3("J76x", 8, NULL, 0, 14, "74", 0, 8, "\x9e", 0); | |||
| test3("J76x", 8, "J", 0, 14, NULL, 0, 8, "\x9e", 0); | |||
| test3("J76x", 8, NULL, 0, 14, NULL, 0, 8, "\x9e", 0); | |||
| test1("J76x", 12, "J0", 0); | |||
| test2("J76x", 12, "J0", 0, 3, "`", 0); | |||
| test3("J76x", 12, "J0", 0, 3, "`", 0, 3, "\x80", 0); | |||
| test3("J76x", 12, "J0", 0, 3, "`", 0, 6, "\x98", 0); | |||
| test2("J76x", 12, "J0", 0, 4, "p", 0); | |||
| test2("J76x", 12, "J0", 0, 4, "p", 0); | |||
| test3("J76x", 12, "J0", 0, 4, "p", 0, 3, "\x20", 0); | |||
| test3("J76x", 12, "J0", 0, 4, "p", 0, 6, "\x34", 0); | |||
| test2("J76x", 12, "J0", 0, 6, "p", 0); | |||
| test2("J76x", 12, "J0", 0, 6, "p", 0); | |||
| test3("J76x", 12, "J0", 0, 6, "p", 0, 3, "\xc0", 0); | |||
| test3("J76x", 12, "J0", 0, 6, "p", 0, 6, "\xd8", 0); | |||
| test2("J76x", 12, "J0", 0, 8, "s", 0); | |||
| test2("J76x", 12, "J0", 0, 8, "s", 0); | |||
| test3("J76x", 12, "J0", 0, 8, "s", 0, 3, "\x60", 0); | |||
| test3("J76x", 12, "J0", 0, 8, "s", 0, 6, "\x64", 0); | |||
| test2("J76x", 12, "J0", 0, 11, "s`", 0); | |||
| test2("J76x", 12, "J0", 0, 11, "s`", 0); | |||
| test3("J76x", 12, "J0", 0, 11, "s`", 0, 3, "\x20", 0); | |||
| test3("J76x", 12, "J0", 0, 11, "s`", 0, 6, "\x3c", 0); | |||
| test2("J76x", 12, "J0", 0, 18, "sg\x80", 0); | |||
| test2("J76x", 12, "J0", 0, 18, "sg\x80", 0); | |||
| test3("J76x", 12, "J0", 0, 18, "sg\x80", 0, 2, "\x00", 0); | |||
| test3("J76x", 12, "J0", 0, 18, NULL, 0, 2, "\x00", 0); | |||
| test3("J76x", 12, NULL, 0, 18, "sg\x80", 0, 2, "\x00", 0); | |||
| test3("J76x", 12, NULL, 0, 18, NULL, 0, 2, "\x00", 0); | |||
| test3("J76x", 12, "J0", 0, 18, "sg\x80", 0, 3, NULL, -1); | |||
| // non octet aligned AMR | |||
| test3("\xf0\xde\xc0\x81\xc0\x08\xa9\xbc\x06\x33\x53\x14\x69\xdd\x3d\x2e\xa9\x8f\x81\xee\x2e\x09\x08\x80\xca\x05\x1e\x91\x00\x10\x00\x00\xca\x05\x20\x91\x00\x10\x00\x00\xca\x05\x22\x91\x00\x10\x00\x00\xca\x05\x24\x91\x00\x10\x00\x00\xca\x05\x26\x91\x00\x10", 4, "\xf0", 0, 6, "\x0c", 0, 177, "\x7b\x02\x07\x00\x22\xa6\xf0\x18\xcd\x4c\x51\xa7\x74\xf4\xba\xa6\x3e\x07\xb8\xb8\x24\x22\x00", 0); | |||
| } | |||
| @ -0,0 +1,7 @@ | |||
| #ifndef __LOG_H__ | |||
| #define __LOG_H__ | |||
| #include "loglib.h" | |||
| #define __ilog(prio, fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) | |||
| #endif | |||