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 | |||||