Commit ad41e4d3 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩
Browse files

Audio bypass tester is done except for the crash at the end

parent bbb1f1c6
mediastreamer2 @ 75fe8bcf
Subproject commit e998419b7fd1e43a39974d2cf408ae169888a62b
Subproject commit 75fe8bcf69ecb6e08153242d5b5c2b7fa0c36e11
TESTER_SOUNDS = sounds/ahbahouaismaisbon.wav \
sounds/hello8000.wav \
sounds/hello44100.wav \
sounds/oldphone.wav \
sounds/sintel_trailer_opus_h264.mkv \
sounds/sintel_trailer_pcmu_h264.mkv \
......
......@@ -19,29 +19,250 @@
#include "liblinphone_tester.h"
#include "private.h"
/**********************************************************************
* This is a (simpler) copy of msfileplay filter in mediastreamer2 *
*********************************************************************/
#include "mediastreamer2/src/audiofilters/waveheader.h"
struct _PlayerData{
int fd;
MSPlayerState state;
int rate;
int nchannels;
int hsize;
int loop_after;
int pause_time;
int count;
int samplesize;
char *mime;
uint32_t ts;
bool_t swap;
bool_t is_raw;
#ifdef HAVE_PCAP
pcap_t *pcap;
struct pcap_pkthdr *pcap_hdr;
const u_char *pcap_data;
bool_t pcap_started;
uint64_t pcap_initial_time;
uint32_t pcap_initial_ts;
uint16_t pcap_seq;
#endif
};
typedef struct _PlayerData PlayerData;
static void audio_bypass_snd_read_init(MSFilter *f) {
PlayerData *d=ms_new0(PlayerData,1);
d->fd=-1;
d->state=MSPlayerClosed;
d->swap=TRUE;
d->rate=44100;
d->nchannels=1;
d->samplesize=2;
d->mime = "L16";
d->hsize=0;
d->loop_after=-1; /*by default, don't loop*/
d->pause_time=0;
d->count=0;
d->ts=0;
d->is_raw=TRUE;
f->data=d;
}
int ms_read_wav_header_from_fd(wave_header_t *header,int fd){
int count;
int skip;
int hsize=0;
riff_t *riff_chunk=&header->riff_chunk;
format_t *format_chunk=&header->format_chunk;
data_t *data_chunk=&header->data_chunk;
unsigned long len=0;
len = read(fd, (char*)riff_chunk, sizeof(riff_t)) ;
if (len != sizeof(riff_t)){
goto not_a_wav;
}
if (0!=strncmp(riff_chunk->riff, "RIFF", 4) || 0!=strncmp(riff_chunk->wave, "WAVE", 4)){
goto not_a_wav;
}
len = read(fd, (char*)format_chunk, sizeof(format_t)) ;
if (len != sizeof(format_t)){
ms_warning("Wrong wav header: cannot read file");
goto not_a_wav;
}
if ((skip=le_uint32(format_chunk->len)-0x10)>0)
{
lseek(fd,skip,SEEK_CUR);
}
hsize=sizeof(wave_header_t)-0x10+le_uint32(format_chunk->len);
count=0;
do{
len = read(fd, data_chunk, sizeof(data_t)) ;
if (len != sizeof(data_t)){
ms_warning("Wrong wav header: cannot read file");
goto not_a_wav;
}
if (strncmp(data_chunk->data, "data", 4)!=0){
ms_warning("skipping chunk=%c%c%c%c len=%i", data_chunk->data[0],data_chunk->data[1],data_chunk->data[2],data_chunk->data[3], data_chunk->len);
lseek(fd,le_uint32(data_chunk->len),SEEK_CUR);
count++;
hsize+=len+le_uint32(data_chunk->len);
}else{
hsize+=len;
break;
}
}while(count<30);
return hsize;
not_a_wav:
/*rewind*/
lseek(fd,0,SEEK_SET);
return -1;
}
static int read_wav_header(PlayerData *d){
wave_header_t header;
format_t *format_chunk=&header.format_chunk;
int ret=ms_read_wav_header_from_fd(&header,d->fd);
d->samplesize=le_uint16(format_chunk->blockalign)/d->nchannels;
d->hsize=ret;
#ifdef WORDS_BIGENDIAN
if (le_uint16(format_chunk->blockalign)==le_uint16(format_chunk->channel) * 2)
d->swap=TRUE;
#endif
d->is_raw=FALSE;
return 0;
}
static void audio_bypass_snd_read_preprocess(MSFilter *f) {
PlayerData *d=(PlayerData*)f->data;
int fd;
const char *file=bc_tester_res("sounds/hello44100.wav");
if ((fd=open(file,O_RDONLY|O_BINARY))==-1){
ms_warning("MSFilePlayer[%p]: failed to open %s: %s",f,file,strerror(errno));
return;
}
d->state=MSPlayerPaused;
d->fd=fd;
d->ts=0;
if (read_wav_header(d)!=0 && strstr(file,".wav")){
ms_warning("File %s has .wav extension but wav header could be found.",file);
}
ms_filter_notify_no_arg(f,MS_FILTER_OUTPUT_FMT_CHANGED);
ms_message("MSFilePlayer[%p]: %s opened: rate=%i,channel=%i",f,file,d->rate,d->nchannels);
if (d->state==MSPlayerPaused)
d->state=MSPlayerPlaying;
return;
}
static void swap_bytes(unsigned char *bytes, int len){
int i;
unsigned char tmp;
for(i=0;i<len;i+=2){
tmp=bytes[i];
bytes[i]=bytes[i+1];
bytes[i+1]=tmp;
}
}
static void audio_bypass_snd_read_process(MSFilter *f) {
mblk_t *m = allocb(10, 0);
memset(m->b_wptr, 0, 10);
m->b_wptr += 10;
ms_queue_put(f->outputs[0], m);
PlayerData *d=(PlayerData*)f->data;
int nsamples=(f->ticker->interval*d->rate*d->nchannels)/1000;
int bytes;
/*send an even number of samples each tick. At 22050Hz the number of samples per 10 ms chunk is odd.
Odd size buffer of samples cause troubles to alsa. Fixing in alsa is difficult, so workaround here.
*/
if (nsamples & 0x1 ) { //odd number of samples
if (d->count & 0x1 )
nsamples++;
else
nsamples--;
}
bytes=nsamples*d->samplesize;
d->count++;
ms_filter_lock(f);
if (d->state==MSPlayerPlaying){
{
int err;
mblk_t *om=allocb(bytes,0);
if (d->pause_time>0){
err=bytes;
memset(om->b_wptr,0,bytes);
d->pause_time-=f->ticker->interval;
}else{
err=read(d->fd,om->b_wptr,bytes);
if (d->swap) swap_bytes(om->b_wptr,bytes);
}
if (err>=0){
if (err!=0){
if (err<bytes)
memset(om->b_wptr+err,0,bytes-err);
om->b_wptr+=bytes;
mblk_set_timestamp_info(om,d->ts);
d->ts+=nsamples;
ms_queue_put(f->outputs[0],om);
}else freemsg(om);
if (err<bytes){
ms_filter_notify_no_arg(f,MS_PLAYER_EOF);
/*for compatibility:*/
lseek(d->fd,d->hsize,SEEK_SET);
/* special value for playing file only once */
if (d->loop_after<0)
{
d->state=MSPlayerPaused;
ms_filter_unlock(f);
return;
}
if (d->loop_after>=0){
d->pause_time=d->loop_after;
}
}
}else{
ms_warning("Fail to read %i bytes: %s",bytes,strerror(errno));
}
}
}
ms_filter_unlock(f);
}
static void audio_bypass_snd_read_postprocess(MSFilter *f) {
PlayerData *d=(PlayerData*)f->data;
ms_filter_lock(f);
if (d->state!=MSPlayerClosed){
d->state=MSPlayerPaused;
lseek(d->fd,d->hsize,SEEK_SET);
}
ms_filter_unlock(f);
if (d->fd!=-1) close(d->fd);
d->fd=-1;
d->state=MSPlayerClosed;
}
static void audio_bypass_snd_read_uninit(MSFilter *f) {
}
static int audio_bypass_snd_read_set_sample_rate(MSFilter *f, void *arg) { // This is to prevent ms2 to put a resampler between this filter and the rtpsend
return 0;
}
static int audio_bypass_snd_read_set_nchannels(MSFilter *f, void *arg) { // This is to prevent ms2 to put a resampler between this filter and the rtpsend
return 0;
}
static int audio_bypass_snd_read_get_sample_rate(MSFilter *f, void *arg) {
int *sample_rate = (int *)arg;
*sample_rate = 44100;
......@@ -61,6 +282,8 @@ static int audio_bypass_snd_read_get_fmt(MSFilter *f, void *arg) {
}
static MSFilterMethod audio_bypass_snd_read_methods[] = {
{ MS_FILTER_SET_SAMPLE_RATE, audio_bypass_snd_read_set_sample_rate },
{ MS_FILTER_SET_NCHANNELS, audio_bypass_snd_read_set_nchannels },
{ MS_FILTER_GET_SAMPLE_RATE, audio_bypass_snd_read_get_sample_rate },
{ MS_FILTER_GET_NCHANNELS, audio_bypass_snd_read_get_nchannels },
{ MS_FILTER_GET_OUTPUT_FMT, audio_bypass_snd_read_get_fmt },
......@@ -92,7 +315,8 @@ static void audio_bypass_snd_write_preprocess(MSFilter *f) {
}
static void audio_bypass_snd_write_process(MSFilter *f) {
ms_queue_get(f->inputs[0]);
mblk_t *m = ms_queue_get(f->inputs[0]);
ms_free(m);
}
static void audio_bypass_snd_write_postprocess(MSFilter *f) {
......@@ -103,6 +327,14 @@ static void audio_bypass_snd_write_uninit(MSFilter *f) {
}
static int audio_bypass_snd_write_set_sample_rate(MSFilter *f, void *arg) { // This is to prevent ms2 to put a resampler between this filter and the rtprecv
return 0;
}
static int audio_bypass_snd_write_set_nchannels(MSFilter *f, void *arg) { // This is to prevent ms2 to put a resampler between this filter and the rtprecv
return 0;
}
static int audio_bypass_snd_write_get_sample_rate(MSFilter *f, void *arg) {
int *sample_rate = (int*)arg;
*sample_rate = 44100;
......@@ -122,6 +354,8 @@ static int audio_bypass_snd_write_get_fmt(MSFilter *f, void *arg) {
}
static MSFilterMethod audio_bypass_snd_write_methods[] = {
{ MS_FILTER_SET_SAMPLE_RATE, audio_bypass_snd_write_set_sample_rate },
{ MS_FILTER_SET_NCHANNELS, audio_bypass_snd_write_set_nchannels },
{ MS_FILTER_GET_SAMPLE_RATE, audio_bypass_snd_write_get_sample_rate },
{ MS_FILTER_GET_NCHANNELS, audio_bypass_snd_write_get_nchannels },
{ MS_FILTER_GET_OUTPUT_FMT, audio_bypass_snd_write_get_fmt },
......@@ -214,6 +448,10 @@ static void audio_bypass(void) {
bool_t call_ok;
MSList *marie_audio_codecs = marie_lc->codecs_conf.audio_codecs;
MSList *pauline_audio_codecs = pauline_lc->codecs_conf.audio_codecs;
char *hellopath = bc_tester_res("sounds/hello44100.wav");
char *recordpath = bc_tester_file("audiobypass-record.wav");
double similar=1;
const double threshold = 0.85;
// Enable L16 audio codec
only_enable_payload(marie_audio_codecs, "L16", 1);
......@@ -222,16 +460,20 @@ static void audio_bypass(void) {
// Add our custom sound card
ms_snd_card_manager_register_desc(marie_sndcard_manager, &audio_bypass_snd_card_desc);
ms_snd_card_manager_register_desc(pauline_sndcard_manager, &audio_bypass_snd_card_desc);
linphone_core_reload_sound_devices(marie->lc);
linphone_core_reload_sound_devices(pauline->lc);
linphone_core_set_playback_device(marie->lc, AUDIO_BYPASS_SOUNDCARD);
linphone_core_set_playback_device(pauline->lc, AUDIO_BYPASS_SOUNDCARD);
linphone_core_set_capture_device(marie->lc, AUDIO_BYPASS_SOUNDCARD);
linphone_core_set_capture_device(pauline->lc, AUDIO_BYPASS_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_capture_device(marie->lc), AUDIO_BYPASS_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_capture_device(pauline->lc), AUDIO_BYPASS_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_playback_device(marie->lc), AUDIO_BYPASS_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_playback_device(pauline->lc), AUDIO_BYPASS_SOUNDCARD);
linphone_core_reload_sound_devices(marie_lc);
linphone_core_reload_sound_devices(pauline_lc);
linphone_core_set_playback_device(marie_lc, AUDIO_BYPASS_SOUNDCARD);
linphone_core_set_playback_device(pauline_lc, AUDIO_BYPASS_SOUNDCARD);
linphone_core_set_capture_device(marie_lc, AUDIO_BYPASS_SOUNDCARD);
linphone_core_set_capture_device(pauline_lc, AUDIO_BYPASS_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_capture_device(marie_lc), AUDIO_BYPASS_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_capture_device(pauline_lc), AUDIO_BYPASS_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_playback_device(marie_lc), AUDIO_BYPASS_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_playback_device(pauline_lc), AUDIO_BYPASS_SOUNDCARD);
linphone_core_use_files(pauline_lc, TRUE);
linphone_core_set_play_file(pauline_lc, NULL);
linphone_core_set_record_file(pauline_lc, recordpath);
call_ok = call(marie, pauline);
BC_ASSERT_TRUE(call_ok);
......@@ -239,12 +481,17 @@ static void audio_bypass(void) {
BC_ASSERT_STRING_EQUAL(linphone_call_params_get_used_audio_codec(linphone_call_get_current_params(linphone_core_get_current_call(marie_lc)))->mime_type, "L16");
wait_for_until(pauline->lc, marie->lc, NULL, 0, 10000);
wait_for_until(pauline_lc, marie_lc, NULL, 0, 22000); //hello44100.wav is 22 seconds long
end_call(marie, pauline);
BC_ASSERT_EQUAL(ms_audio_diff(hellopath, recordpath, &similar, &audio_cmp_params, NULL, NULL), 0, int, "%d");
BC_ASSERT_GREATER(similar, threshold, double, "%g");
BC_ASSERT_LOWER(similar, 1.0, double, "%g");
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
bc_free(recordpath);
}
test_t audio_bypass_tests[] = {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment