From 46b37c0b6a69ab22df69eb54bebd4a9e45ff8dac Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Tue, 17 Jan 2017 15:39:52 +0100 Subject: [PATCH 1/3] tool/dump_pklg: report offset in case of invalid frame/error --- tool/dump_pklg.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tool/dump_pklg.py b/tool/dump_pklg.py index 770a63bc9..b07dcab01 100755 --- a/tool/dump_pklg.py +++ b/tool/dump_pklg.py @@ -41,6 +41,7 @@ if len(sys.argv) == 1: infile = sys.argv[1] with open (infile, 'rb') as fin: + pos = 0 try: while True: len = read_net_32(fin) @@ -48,7 +49,11 @@ with open (infile, 'rb') as fin: ts_usec = read_net_32(fin) type = ord(fin.read(1)) packet_len = len - 9; + if (packet_len > 66000): + print ("Error parsing pklg at offset %u (%x)." % (pos, pos)) + break packet = fin.read(packet_len) + pos = pos + 4 + len time = "[%s.%03u]" % (datetime.datetime.fromtimestamp(ts_sec).strftime("%Y-%m-%d %H:%M:%S"), ts_usec / 1000) if type == 0xfc: print time, "LOG", packet @@ -56,5 +61,5 @@ with open (infile, 'rb') as fin: if type <= 0x03: print time, packet_types[type], as_hex(packet) except TypeError: - exit(0) + print ("Error parsing pklg at offset %u (%x)." % (pos, pos)) From 1d3c697462f1587032ebcafb68431c96319ee3b1 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Tue, 17 Jan 2017 15:41:30 +0100 Subject: [PATCH 2/3] avdtp_test: sort code, use 300 ms pre-buffer, fix pause/resume playback --- test/avdtp/avdtp_test.c | 156 +++++++++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 59 deletions(-) diff --git a/test/avdtp/avdtp_test.c b/test/avdtp/avdtp_test.c index 400f616c2..f5fd41d95 100644 --- a/test/avdtp/avdtp_test.c +++ b/test/avdtp/avdtp_test.c @@ -35,7 +35,6 @@ * */ -#include "btstack_config.h" #include #include @@ -43,6 +42,8 @@ #include #include +#include "btstack_config.h" +#include "btstack_debug.h" #include "btstack_event.h" #include "btstack_memory.h" #include "btstack_run_loop.h" @@ -58,10 +59,6 @@ #include "wav_util.h" #include "avdtp_util.h" -#define NUM_CHANNELS 2 -#define SAMPLE_RATE 44100 -//#define SMG_BI - #ifdef HAVE_PORTAUDIO #include #include "btstack_ring_buffer.h" @@ -72,68 +69,38 @@ #define STORE_SBC_TO_WAV_FILE #endif +#if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE) +#define DECODE_SBC +#endif + +#define NUM_CHANNELS 2 +#define SAMPLE_RATE 44100 + +// SBC Decoder for WAV file or PortAudio +#ifdef DECODE_SBC +static btstack_sbc_decoder_state_t state; +static btstack_sbc_mode_t mode = SBC_MODE_STANDARD; +static int total_num_samples = 0; +#endif + +// PortAdudio - live playback #ifdef HAVE_PORTAUDIO #define PA_SAMPLE_TYPE paInt16 #define FRAMES_PER_BUFFER 128 #define BYTES_PER_FRAME (2*NUM_CHANNELS) -#define PREBUFFER_MS 150 +#define PREBUFFER_MS 300 #define PREBUFFER_BYTES (PREBUFFER_MS*SAMPLE_RATE/1000*BYTES_PER_FRAME) - static uint8_t ring_buffer_storage[2*PREBUFFER_BYTES]; static btstack_ring_buffer_t ring_buffer; - static PaStream * stream; -static uint8_t pa_stream_started = 0; - -static int patestCallback( const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void *userData ) { - (void) timeInfo; /* Prevent unused variable warnings. */ - (void) statusFlags; - (void) inputBuffer; - - uint32_t bytes_read = 0; - int bytes_per_buffer = framesPerBuffer * BYTES_PER_FRAME; - - if (btstack_ring_buffer_bytes_available(&ring_buffer) >= bytes_per_buffer){ - btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_per_buffer, &bytes_read); - } else { - memset(outputBuffer, 0, bytes_per_buffer); - } - // printf("bytes avail after read: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer)); - return 0; -} +static int pa_stream_started = 0; +static int pa_stream_paused = 0; #endif +// WAV File #ifdef STORE_SBC_TO_WAV_FILE -// store sbc as wav: -static btstack_sbc_decoder_state_t state; -static int total_num_samples = 0; static int frame_count = 0; static char * wav_filename = "avdtp_sink.wav"; -static btstack_sbc_mode_t mode = SBC_MODE_STANDARD; - -static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ - wav_writer_write_int16(num_samples*num_channels, data); - total_num_samples+=num_samples*num_channels; - frame_count++; - -#ifdef HAVE_PORTAUDIO - if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= PREBUFFER_BYTES){ - /* -- start stream -- */ - PaError err = Pa_StartStream(stream); - if (err != paNoError){ - printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); - return; - } - pa_stream_started = 1; - } - btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2); - // printf("bytes avail after write: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer)); -#endif -} #endif #ifdef STORE_SBC_TO_SBC_FILE @@ -141,7 +108,6 @@ static FILE * sbc_file; static char * sbc_filename = "avdtp_sink.sbc"; #endif - typedef struct { // bitmaps uint8_t sampling_frequency_bitmap; @@ -201,12 +167,81 @@ static btstack_packet_callback_registration_t hci_event_callback_registration; static int media_initialized = 0; + + +#ifdef HAVE_PORTAUDIO +static int patestCallback( const void *inputBuffer, void *outputBuffer, + unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *userData ) { + + /** patestCallback is called from different thread, don't use hci_dump / log_info here without additional checks */ + + (void) timeInfo; /* Prevent unused variable warnings. */ + (void) statusFlags; + (void) inputBuffer; + + int bytes_to_copy = framesPerBuffer * BYTES_PER_FRAME; + + // fill with silence while paused + if (pa_stream_paused){ + + if (btstack_ring_buffer_bytes_available(&ring_buffer) < PREBUFFER_BYTES){ + // printf("PA: silence\n"); + memset(outputBuffer, 0, bytes_to_copy); + return 0; + } else { + // resume playback + pa_stream_paused = 0; + } + } + + // get data from ringbuffer + uint32_t bytes_read = 0; + btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_to_copy, &bytes_read); + bytes_to_copy -= bytes_read; + + // fill with 0 if not enough + if (bytes_to_copy){ + memset(outputBuffer + bytes_read, 0, bytes_to_copy); + pa_stream_paused = 1; + } + return 0; +} +#endif + +#ifdef DECODE_SBC +static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ + wav_writer_write_int16(num_samples*num_channels, data); + total_num_samples+=num_samples*num_channels; + frame_count++; + +#ifdef HAVE_PORTAUDIO + if (!pa_stream_started){ + /* -- start stream -- */ + PaError err = Pa_StartStream(stream); + if (err != paNoError){ + printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); + return; + } + pa_stream_started = 1; + pa_stream_paused = 1; + } + btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2); +#endif +} +#endif + static int init_media_processing(avdtp_media_codec_configuration_sbc_t configuration){ int num_channels = configuration.num_channels; int sample_rate = configuration.sampling_frequency; -#ifdef STORE_SBC_TO_WAV_FILE +#ifdef DECODE_SBC btstack_sbc_decoder_init(&state, mode, handle_pcm_data, NULL); +#endif + +#ifdef STORE_SBC_TO_WAV_FILE wav_writer_open(wav_filename, num_channels, sample_rate); #endif @@ -215,7 +250,7 @@ static int init_media_processing(avdtp_media_codec_configuration_sbc_t configura #endif #ifdef HAVE_PORTAUDIO - int frames_per_buffer = configuration.frames_per_buffer; + // int frames_per_buffer = configuration.frames_per_buffer; PaError err; PaStreamParameters outputParameters; @@ -237,7 +272,7 @@ static int init_media_processing(avdtp_media_codec_configuration_sbc_t configura NULL, /* &inputParameters */ &outputParameters, sample_rate, - frames_per_buffer, + 0, paClipOff, /* we won't output out of range samples so don't bother clipping them */ patestCallback, /* use callback */ NULL ); @@ -335,13 +370,16 @@ static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endp // printf("SBC HEADER: num_frames %u, fragmented %u, start %u, stop %u\n", sbc_header.num_frames, sbc_header.fragmentation, sbc_header.starting_packet, sbc_header.last_packet); // printf_hexdump( packet+pos, size-pos ); -#ifdef STORE_SBC_TO_WAV_FILE +#ifdef DECODE_SBC btstack_sbc_decoder_process_data(&state, 0, packet+pos, size-pos); #endif #ifdef STORE_SBC_TO_SBC_FILE fwrite(packet+pos, size-pos, 1, sbc_file); #endif +#ifdef HAVE_PORTAUDIO + log_info("PA: bytes avail after recv: %d", btstack_ring_buffer_bytes_available(&ring_buffer)); +#endif } static void dump_sbc_capability(adtvp_media_codec_information_sbc_t media_codec_sbc){ From 98e071b73ba99fcb6f0ca94572478c5927778726 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Tue, 17 Jan 2017 17:16:07 +0100 Subject: [PATCH 3/3] avdtp_test: fix unused warnings --- test/avdtp/avdtp_test.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/test/avdtp/avdtp_test.c b/test/avdtp/avdtp_test.c index f5fd41d95..25a0c7d0e 100644 --- a/test/avdtp/avdtp_test.c +++ b/test/avdtp/avdtp_test.c @@ -213,9 +213,15 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, #ifdef DECODE_SBC static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ + UNUSED(sample_rate); + UNUSED(context); + +#ifdef STORE_SBC_TO_WAV_FILE wav_writer_write_int16(num_samples*num_channels, data); - total_num_samples+=num_samples*num_channels; frame_count++; +#endif + + total_num_samples+=num_samples*num_channels; #ifdef HAVE_PORTAUDIO if (!pa_stream_started){ @@ -326,6 +332,9 @@ static void close_media_processing(void){ } static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size){ + + UNUSED(stream_endpoint); + int pos = 0; avdtp_media_packet_header_t media_header; @@ -405,6 +414,10 @@ static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configu static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ + + UNUSED(channel); + UNUSED(size); + bd_addr_t event_addr; switch (packet_type) { @@ -596,6 +609,9 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ + UNUSED(argc); + (void)argv; + /* Register for HCI events */ hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration);