libvorbis: segfault при закрытии блока (vorbis_analysis_wrote)
Я пытаюсь закодировать POC для кодирования и декодирования "туда-обратно" аудио в / из vorbis.
Функция кодирования передает 88200 байт (22050 выборок с плавающей запятой между -1.f и 1.f). Они копируются в vorbis_analysis_buffer
максимум 1024 образца за один раз.
Согласно обзору API libvorbis и со ссылкой на файлы примеров и тестов в каталогах /src и /examples источника, vorbis_analysis_wrote
должно быть передано 0 в качестве значения, чтобы сообщить создателю блока, что данные больше не поступают. Это вызывает segfault, и я не могу понять, почему.
Кстати, если я просто опущу вызов 0-значение vorbis_analysis_wrote
во время заполнения буфера данные не выводятся (vorbis_analysis_blockout
возвращает 0 на каждом проходе).
int writeStreamToFile(vorbis_dsp_state *d, vorbis_block *b, ogg_stream_state *s, int samplecount, float *pcmbuffer, char *filename) {
int i, ii, e = 0;
int last = 0;
int t = 0;
FILE *f;
char tmpfile[15] = "/tmp/vbsXXXXXX\0";
ogg_packet op;
int size_vorbis = L_VORBISBUFFERSIZE * L_RESOLUTION_BYTES;
int size_data = samplecount * L_RESOLUTION_BYTES;
mkstemp(tmpfile);
f = fopen(tmpfile, "w");
while (!last) {
int size_units = 0;
int size = size_data - t;
if (size >= size_vorbis) {
size = size_vorbis;
} else {
last = 1;
}
size_units = (int)(size / L_RESOLUTION_BYTES);
float **encoding_buffer = vorbis_analysis_buffer(d, size_units);
fprintf(stderr, "read iter %d pos %d size %d (%d units) / %d, starting at %p\n", i, t, size, size_units, size_data, pcmbuffer + (int)(t / L_RESOLUTION_BYTES));
memcpy(encoding_buffer[0], pcmbuffer + (int)(t / L_RESOLUTION_BYTES), (size_t)size);
if ((e = vorbis_analysis_wrote(d, size_units))) {
return -1;
}
if (last) {
float *src = pcmbuffer + ((t + size) / L_RESOLUTION_BYTES) - L_RESOLUTION_BYTES;
float *dst = *encoding_buffer + (size / L_RESOLUTION_BYTES) - L_RESOLUTION_BYTES;
fprintf(stderr, "last copied byte is src: %f at %p, dst: %f at %p\n", *src, src, *dst, dst);
vorbis_analysis_wrote(d, 0);
}
// remove this when debugging is over
if (memcmp(encoding_buffer[0], pcmbuffer + (int)(t / L_RESOLUTION_BYTES), (size_t)size)) {
return -1;
}
while (vorbis_analysis_blockout(d, b) == 1) {
if ((e = vorbis_analysis(b, NULL))) {
return -1;
}
if ((e = vorbis_bitrate_addblock(b))) {
return -1;
}
vorbis_bitrate_flushpacket(d, &op);
fprintf(stderr, "Packet #%i (%p) got %li bytes\n", ii, op.packet, op.bytes);
fwrite(op.packet, sizeof(char), op.bytes, f);
ii++;
}
t += size;
i++;
}
fclose(f);
strcpy(filename, tmpfile);
return t;
}
Результат пробега:
(gdb) r
Starting program: /home/lash/programming/projects/p2pconference/bin/vorbisroundtrip
ogg stream output 7912 bytes in headerdata
Created 22050 samples of 4 bytes, last sample is -0.248100 at 0x619888
read iter 0 pos 0 size 4096 (1024 units) / 88200, starting at 0x604010
read iter 1 pos 4096 size 4096 (1024 units) / 88200, starting at 0x605010
read iter 2 pos 8192 size 4096 (1024 units) / 88200, starting at 0x606010
read iter 3 pos 12288 size 4096 (1024 units) / 88200, starting at 0x607010
read iter 4 pos 16384 size 4096 (1024 units) / 88200, starting at 0x608010
read iter 5 pos 20480 size 4096 (1024 units) / 88200, starting at 0x609010
read iter 6 pos 24576 size 4096 (1024 units) / 88200, starting at 0x60a010
read iter 7 pos 28672 size 4096 (1024 units) / 88200, starting at 0x60b010
read iter 8 pos 32768 size 4096 (1024 units) / 88200, starting at 0x60c010
read iter 9 pos 36864 size 4096 (1024 units) / 88200, starting at 0x60d010
read iter 10 pos 40960 size 4096 (1024 units) / 88200, starting at 0x60e010
read iter 11 pos 45056 size 4096 (1024 units) / 88200, starting at 0x60f010
read iter 12 pos 49152 size 4096 (1024 units) / 88200, starting at 0x610010
read iter 13 pos 53248 size 4096 (1024 units) / 88200, starting at 0x611010
read iter 14 pos 57344 size 4096 (1024 units) / 88200, starting at 0x612010
read iter 15 pos 61440 size 4096 (1024 units) / 88200, starting at 0x613010
read iter 16 pos 65536 size 4096 (1024 units) / 88200, starting at 0x614010
read iter 17 pos 69632 size 4096 (1024 units) / 88200, starting at 0x615010
read iter 18 pos 73728 size 4096 (1024 units) / 88200, starting at 0x616010
read iter 19 pos 77824 size 4096 (1024 units) / 88200, starting at 0x617010
read iter 20 pos 81920 size 4096 (1024 units) / 88200, starting at 0x618010
read iter 21 pos 86016 size 2184 (546 units) / 88200, starting at 0x619010
last copied byte is src: -0.248100 at 0x619888, dst: -0.248100 at 0x688d18
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff78ad228 in vorbis_lpc_from_data () from /usr/lib/x86_64-linux-gnu/libvorbis.so.0
Карта памяти и дамп стека:
(gdb) bt
#0 0x00007ffff78ad228 in vorbis_lpc_from_data () from /usr/lib/x86_64-linux-gnu/libvorbis.so.0
#1 0x00007ffff78aaa60 in vorbis_analysis_wrote () from /usr/lib/x86_64-linux-gnu/libvorbis.so.0
#2 0x00000000004019b5 in writeStreamToFile (d=0x603840 <vdsp_e>, b=0x603380 <vblk_e>, s=0x6031a0 <os_e>, samplecount=22050, pcmbuffer=0x604010,
filename=0x7fffffffdf60 "0 @") at ./tests/vorbisroundtrip.c:131
#3 0x0000000000401ee3 in main (argc=1, argv=0x7fffffffe068) at ./tests/vorbisroundtrip.c:243
(gdb) info proc map
process 28458
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x403000 0x3000 0x0 /home/lash/programming/projects/p2pconference/bin/vorbisroundtrip
0x602000 0x603000 0x1000 0x2000 /home/lash/programming/projects/p2pconference/bin/vorbisroundtrip
0x603000 0x604000 0x1000 0x3000 /home/lash/programming/projects/p2pconference/bin/vorbisroundtrip
0x604000 0x69d000 0x99000 0x0 [heap]
0x7ffff0000000 0x7ffff0021000 0x21000 0x0
0x7ffff0021000 0x7ffff4000000 0x3fdf000 0x0
0x7ffff7027000 0x7ffff71e6000 0x1bf000 0x0 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff71e6000 0x7ffff73e6000 0x200000 0x1bf000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff73e6000 0x7ffff73ea000 0x4000 0x1bf000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff73ea000 0x7ffff73ec000 0x2000 0x1c3000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff73ec000 0x7ffff73f0000 0x4000 0x0
0x7ffff73f0000 0x7ffff73f7000 0x7000 0x0 /usr/lib/x86_64-linux-gnu/libogg.so.0.8.2
0x7ffff73f7000 0x7ffff75f7000 0x200000 0x7000 /usr/lib/x86_64-linux-gnu/libogg.so.0.8.2
0x7ffff75f7000 0x7ffff75f8000 0x1000 0x7000 /usr/lib/x86_64-linux-gnu/libogg.so.0.8.2
0x7ffff75f8000 0x7ffff75f9000 0x1000 0x8000 /usr/lib/x86_64-linux-gnu/libogg.so.0.8.2
0x7ffff75f9000 0x7ffff7686000 0x8d000 0x0 /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2.0.11
0x7ffff7686000 0x7ffff7885000 0x1ff000 0x8d000 /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2.0.11
0x7ffff7885000 0x7ffff78a1000 0x1c000 0x8c000 /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2.0.11
0x7ffff78a1000 0x7ffff78a2000 0x1000 0xa8000 /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2.0.11
0x7ffff78a2000 0x7ffff78cc000 0x2a000 0x0 /usr/lib/x86_64-linux-gnu/libvorbis.so.0.4.8
0x7ffff78cc000 0x7ffff7acc000 0x200000 0x2a000 /usr/lib/x86_64-linux-gnu/libvorbis.so.0.4.8
0x7ffff7acc000 0x7ffff7acd000 0x1000 0x2a000 /usr/lib/x86_64-linux-gnu/libvorbis.so.0.4.8
0x7ffff7acd000 0x7ffff7ace000 0x1000 0x2b000 /usr/lib/x86_64-linux-gnu/libvorbis.so.0.4.8
0x7ffff7ace000 0x7ffff7bd6000 0x108000 0x0 /lib/x86_64-linux-gnu/libm-2.23.so
0x7ffff7bd6000 0x7ffff7dd5000 0x1ff000 0x108000 /lib/x86_64-linux-gnu/libm-2.23.so
0x7ffff7dd5000 0x7ffff7dd6000 0x1000 0x107000 /lib/x86_64-linux-gnu/libm-2.23.so
0x7ffff7dd6000 0x7ffff7dd7000 0x1000 0x108000 /lib/x86_64-linux-gnu/libm-2.23.so
0x7ffff7dd7000 0x7ffff7dfd000 0x26000 0x0 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7fb5000 0x7ffff7fba000 0x5000 0x0
0x7ffff7ff6000 0x7ffff7ff8000 0x2000 0x0
0x7ffff7ff8000 0x7ffff7ffa000 0x2000 0x0 [vvar]
0x7ffff7ffa000 0x7ffff7ffc000 0x2000 0x0 [vdso]
0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x25000 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7ffd000 0x7ffff7ffe000 0x1000 0x26000 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7ffe000 0x7ffff7fff000 0x1000 0x0
0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack]
0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]
Полный источник незавершенного производства можно посмотреть здесь. аудио данные здесь (необработанные PCM)
С помощью:
- libvorbis 1.3.5
- gcc 5.4.0
- linux 4.4.0-45-generic
LDD:
linux-vdso.so.1 => (0x00007ffe7afa9000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f30a9c70000)
libvorbis.so.0 => /home/lash/src/libvorbis-1.3.5/build/lib/libvorbis.so.0 (0x00007f30a9a37000)
libvorbisenc.so.2 => /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2 (0x00007f30a978d000)
libogg.so.0 => /usr/lib/x86_64-linux-gnu/libogg.so.0 (0x00007f30a9584000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f30a91bb000)
/lib64/ld-linux-x86-64.so.2 (0x0000560df33a6000)