mirror of https://github.com/sipwise/rtpengine.git
Fixes AMR transcoding. Some features yet unsupported. Fixes #498 Change-Id: I1075a539a7a7dab9106df9ef49b8bda2484b97ecchanges/55/20655/9
parent
4d4abfabf8
commit
895fa96054
@ -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);
|
||||
}
|
Loading…
Reference in new issue