mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-26 07:38:09 +00:00
Audio bypass tester is done except for the crash at the end
This commit is contained in:
parent
bbb1f1c647
commit
ad41e4d304
4 changed files with 266 additions and 18 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit e998419b7fd1e43a39974d2cf408ae169888a62b
|
||||
Subproject commit 75fe8bcf69ecb6e08153242d5b5c2b7fa0c36e11
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
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[] = {
|
||||
|
|
|
|||
BIN
tester/sounds/hello44100.wav
Normal file
BIN
tester/sounds/hello44100.wav
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue