Beispiel #1
0
static void a2dp_source_setup_media_header(uint8_t * media_packet, int size, int *offset, uint8_t marker, uint16_t sequence_number){
    if (size < AVDTP_MEDIA_PAYLOAD_HEADER_SIZE){
        log_error("small outgoing buffer");
        return;
    }

    uint8_t  rtp_version = 2;
    uint8_t  padding = 0;
    uint8_t  extension = 0;
    uint8_t  csrc_count = 0;
    uint8_t  payload_type = 0x60;
    // uint16_t sequence_number = stream_endpoint->sequence_number;
    uint32_t timestamp = btstack_run_loop_get_time_ms();
    uint32_t ssrc = 0x11223344;

    // rtp header (min size 12B)
    int pos = 0;
    // int mtu = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);

    media_packet[pos++] = (rtp_version << 6) | (padding << 5) | (extension << 4) | csrc_count;
    media_packet[pos++] = (marker << 1) | payload_type;
    big_endian_store_16(media_packet, pos, sequence_number);
    pos += 2;
    big_endian_store_32(media_packet, pos, timestamp);
    pos += 4;
    big_endian_store_32(media_packet, pos, ssrc); // only used for multicast
    pos += 4;
    *offset = pos;
}
Beispiel #2
0
static void hal_audio_dma_process(btstack_data_source_t * ds, btstack_data_source_callback_type_t callback_type){
    UNUSED(ds);
    UNUSED(callback_type);

    if (!media_initialized) return;

    int trigger_resume = 0;
    if (audio_stream_paused) {
        if (sbc_frame_size && btstack_ring_buffer_bytes_available(&ring_buffer) >= OPTIMAL_FRAMES_MIN * sbc_frame_size){
            trigger_resume = 1;
            // reset buffers
            playback_buffer = NUM_AUDIO_BUFFERS - 1;
            write_buffer = 0;
        } else {
            return;
        }
    }

    while (playback_buffer != write_buffer && btstack_ring_buffer_bytes_available(&ring_buffer) >= sbc_frame_size ){
        uint8_t frame[MAX_SBC_FRAME_SIZE];
        uint32_t bytes_read = 0;
        btstack_ring_buffer_read(&ring_buffer, frame, sbc_frame_size, &bytes_read);
        btstack_sbc_decoder_process_data(&state, 0, frame, sbc_frame_size);
    }

    if (trigger_resume){
        printf("%6u - resume\n", (int) btstack_run_loop_get_time_ms());
        audio_stream_paused = 0;
    }
}
Beispiel #3
0
static void test_track_sent(int bytes_sent){
    test_data_sent += test_data_len;
    // evaluate
    uint32_t now = btstack_run_loop_get_time_ms();
    uint32_t time_passed = now - test_data_start;
    if (time_passed < REPORT_INTERVAL_MS) return;
    // print speed
    int bytes_per_second = test_data_sent * 1000 / time_passed;
    printf("%u bytes sent-> %u.%03u kB/s\n", (int) test_data_sent, (int) bytes_per_second / 1000, bytes_per_second % 1000);

    // restart
    test_data_start = now;
    test_data_sent  = 0;
}
static void test_track_data(le_streamer_connection_t * context, int bytes_sent){
    context->test_data_sent += bytes_sent;
    // evaluate
    uint32_t now = btstack_run_loop_get_time_ms();
    uint32_t time_passed = now - context->test_data_start;
    if (time_passed < REPORT_INTERVAL_MS) return;
    // print speed
    int bytes_per_second = context->test_data_sent * 1000 / time_passed;
    printf("%c: %"PRIu32" bytes -> %u.%03u kB/s\n", context->name, context->test_data_sent, bytes_per_second / 1000, bytes_per_second % 1000);

    // restart
    context->test_data_start = now;
    context->test_data_sent  = 0;
}
Beispiel #5
0
static void avdtp_audio_timeout_handler(btstack_timer_source_t * timer){
    a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer);
    btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 
    btstack_run_loop_add_timer(&context->audio_timer);
    uint32_t now = btstack_run_loop_get_time_ms();

    uint32_t update_period_ms = AUDIO_TIMEOUT_MS;
    if (context->time_audio_data_sent > 0){
        update_period_ms = now - context->time_audio_data_sent;
    } 

    uint32_t num_samples = (update_period_ms * a2dp_sample_rate()) / 1000;
    context->acc_num_missed_samples += (update_period_ms * a2dp_sample_rate()) % 1000;
    
    while (context->acc_num_missed_samples >= 1000){
        num_samples++;
        context->acc_num_missed_samples -= 1000;
    }
    context->time_audio_data_sent = now;
    context->samples_ready += num_samples;

    if (context->sbc_ready_to_send) return;

    fill_sbc_audio_buffer(context);

    if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){
        // schedule sending
        context->sbc_ready_to_send = 1;

        // a2dp_source_stream_endpoint_request_can_send_now(context->local_seid);
        avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(context->local_seid, &a2dp_source_context);
        if (!stream_endpoint) {
            printf("no stream_endpoint for seid %d\n", context->local_seid);
            return;
        }
        stream_endpoint->send_stream = 1;
        if (stream_endpoint->connection){
            avdtp_request_can_send_now_initiator(stream_endpoint->connection, stream_endpoint->l2cap_media_cid);
        }
    }
}
Beispiel #6
0
static void handle_l2cap_media_data_packet(uint8_t seid, uint8_t *packet, uint16_t size){
    UNUSED(seid);
    int pos = 0;
    
    avdtp_media_packet_header_t media_header;
    if (!read_media_data_header(packet, size, &pos, &media_header)) return;
    
    avdtp_sbc_codec_header_t sbc_header;
    if (!read_sbc_header(packet, size, &pos, &sbc_header)) return;

#ifdef HAVE_AUDIO_DMA
    // store sbc frame size for buffer management
    sbc_frame_size = (size-pos)/ sbc_header.num_frames;
#endif
    
#if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE)
    btstack_sbc_decoder_process_data(&state, 0, packet+pos, size-pos);
#endif

#ifdef HAVE_AUDIO_DMA
    btstack_ring_buffer_write(&ring_buffer,  packet+pos, size-pos);

    // decide on audio sync drift based on number of sbc frames in queue
    int sbc_frames_in_buffer = btstack_ring_buffer_bytes_available(&ring_buffer) / sbc_frame_size;
    if (sbc_frames_in_buffer < OPTIMAL_FRAMES_MIN){
        sbc_samples_fix = 1;    // duplicate last sample
    } else if (sbc_frames_in_buffer <= OPTIMAL_FRAMES_MAX){
        sbc_samples_fix = 0;    // nothing to do
    } else {
        sbc_samples_fix = -1;   // drop last sample
    }

    // dump
    printf("%6u %03u %d\n",  (int) btstack_run_loop_get_time_ms(), sbc_frames_in_buffer, sbc_samples_fix);
#endif

#ifdef STORE_SBC_TO_SBC_FILE
    fwrite(packet+pos, size-pos, 1, sbc_file);
#endif
}
Beispiel #7
0
void hal_audio_dma_done(void){
    if (audio_stream_paused){
        hal_audio_dma_play((const uint8_t *) silent_buffer, DMA_AUDIO_FRAMES*4);
        return;
    }
    // next buffer
    int next_playback_buffer = next_buffer(playback_buffer);
    uint8_t * playback_data;
    if (next_playback_buffer == write_buffer){

        // TODO: stop codec while playing silence when getting 'stream paused'

        // start playing silence
        audio_stream_paused = 1;
        hal_audio_dma_play((const uint8_t *) silent_buffer, DMA_AUDIO_FRAMES*4);
        printf("%6u - paused - bytes in buffer %u\n", (int) btstack_run_loop_get_time_ms(), btstack_ring_buffer_bytes_available(&ring_buffer));
        return;
    }
    playback_buffer = next_playback_buffer;
    playback_data = start_of_buffer(playback_buffer);
    hal_audio_dma_play(playback_data, audio_samples_len[playback_buffer]);
    // btstack_run_loop_embedded_trigger();
}
Beispiel #8
0
            fclose(wav_file);
        }
        dump_data = 0;
    }
#endif
#endif

    if (packet[1] & 0xf0){
        printf("SCO CRC Error: %x - data: ", packet[1] >> 4);
        printf_hexdump(&packet[3], size-3);
        return;
    }

#if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
#ifdef USE_PORTAUDIO
    uint32_t start = btstack_run_loop_get_time_ms();
    Pa_WriteStream( stream, &packet[3], size -3);
    uint32_t end   = btstack_run_loop_get_time_ms();
    if (end - start > 5){
        printf("Portaudio: write stream took %u ms\n", end - start);
    }
    dump_data = 0;
#endif
#endif

    if (dump_data){
        printf("data: ");
#if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
        int i;
        for (i=3;i<size;i++){
            printf("%c", packet[i]);
Beispiel #9
0
static void test_reset(void){
    test_data_start = btstack_run_loop_get_time_ms();
    test_data_sent = 0;
}
Beispiel #10
0
static void test_reset(le_streamer_connection_t * context){
    context->test_data_start = btstack_run_loop_get_time_ms();
    context->test_data_sent = 0;
}