Loading system/btif/co/bta_av_co.cc +13 −0 Original line number Original line Diff line number Diff line Loading @@ -1051,6 +1051,19 @@ const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) { return encoder_interface; return encoder_interface; } } const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void) { /* Protect access to bta_av_co_cb.codec_config */ mutex_global_lock(); const tA2DP_DECODER_INTERFACE* decoder_interface = A2DP_GetDecoderInterface(bta_av_co_cb.codec_config); /* Protect access to bta_av_co_cb.codec_config */ mutex_global_unlock(); return decoder_interface; } bool bta_av_co_set_codec_user_config( bool bta_av_co_set_codec_user_config( const btav_a2dp_codec_config_t& codec_user_config) { const btav_a2dp_codec_config_t& codec_user_config) { uint8_t result_codec_config[AVDT_CODEC_SIZE]; uint8_t result_codec_config[AVDT_CODEC_SIZE]; Loading system/btif/include/btif_av_co.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,12 @@ void bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params); // otherwise NULL. // otherwise NULL. const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void); const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void); // Gets the current A2DP decoder interface that can be used to decode received // A2DP packets - see |tA2DP_DECODER_INTERFACE|. // Returns the A2DP decoder interface if the current codec is setup, otherwise // NULL. const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void); // Sets the user preferred codec configuration. // Sets the user preferred codec configuration. // |codec_user_config| contains the preferred codec configuration. // |codec_user_config| contains the preferred codec configuration. // Returns true on success, otherwise false. // Returns true on success, otherwise false. Loading system/btif/src/btif_a2dp_sink.cc +38 −113 Original line number Original line Diff line number Diff line Loading @@ -35,9 +35,6 @@ #include "osi/include/osi.h" #include "osi/include/osi.h" #include "osi/include/thread.h" #include "osi/include/thread.h" #include "oi_codec_sbc.h" #include "oi_status.h" using LockGuard = std::lock_guard<std::mutex>; using LockGuard = std::lock_guard<std::mutex>; /** /** Loading Loading @@ -75,13 +72,6 @@ typedef struct { btif_a2dp_sink_focus_state_t focus_state; btif_a2dp_sink_focus_state_t focus_state; } tBTIF_MEDIA_SINK_FOCUS_UPDATE; } tBTIF_MEDIA_SINK_FOCUS_UPDATE; typedef struct { uint16_t num_frames_to_be_processed; uint16_t len; uint16_t offset; uint16_t layer_specific; } tBT_SBC_HDR; /* BTIF A2DP Sink control block */ /* BTIF A2DP Sink control block */ typedef struct { typedef struct { thread_t* worker_thread; thread_t* worker_thread; Loading @@ -89,11 +79,11 @@ typedef struct { fixed_queue_t* rx_audio_queue; fixed_queue_t* rx_audio_queue; bool rx_flush; /* discards any incoming data when true */ bool rx_flush; /* discards any incoming data when true */ alarm_t* decode_alarm; alarm_t* decode_alarm; uint8_t frames_to_process; tA2DP_SAMPLE_RATE sample_rate; tA2DP_SAMPLE_RATE sample_rate; tA2DP_CHANNEL_COUNT channel_count; tA2DP_CHANNEL_COUNT channel_count; btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */ btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */ void* audio_track; void* audio_track; const tA2DP_DECODER_INTERFACE* decoder_interface; } tBTIF_A2DP_SINK_CB; } tBTIF_A2DP_SINK_CB; // Mutex for below data structures. // Mutex for below data structures. Loading @@ -103,12 +93,6 @@ static tBTIF_A2DP_SINK_CB btif_a2dp_sink_cb; static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF}; static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF}; static OI_CODEC_SBC_DECODER_CONTEXT btif_a2dp_sink_context; static uint32_t btif_a2dp_sink_context_data[CODEC_DATA_WORDS( 2, SBC_CODEC_FAST_FILTER_BUFFERS)]; static int16_t btif_a2dp_sink_pcm_data[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS]; static void btif_a2dp_sink_startup_delayed(void* context); static void btif_a2dp_sink_startup_delayed(void* context); static void btif_a2dp_sink_shutdown_delayed(void* context); static void btif_a2dp_sink_shutdown_delayed(void* context); static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context); static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context); Loading @@ -118,7 +102,7 @@ static void btif_a2dp_sink_audio_handle_start_decoding(void); static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context); static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context); static void btif_a2dp_sink_audio_rx_flush_req(void); static void btif_a2dp_sink_audio_rx_flush_req(void); /* Handle incoming media packets A2DP SINK streaming */ /* Handle incoming media packets A2DP SINK streaming */ static void btif_a2dp_sink_handle_inc_media(tBT_SBC_HDR* p_msg); static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg); static void btif_a2dp_sink_decoder_update_event( static void btif_a2dp_sink_decoder_update_event( tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf); tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf); static void btif_a2dp_sink_clear_track_event(void); static void btif_a2dp_sink_clear_track_event(void); Loading Loading @@ -365,57 +349,31 @@ static void btif_a2dp_sink_audio_handle_start_decoding(void) { btif_decode_alarm_cb, NULL); btif_decode_alarm_cb, NULL); } } // Must be called while locked. static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) { static void btif_a2dp_sink_handle_inc_media(tBT_SBC_HDR* p_msg) { #ifndef OS_GENERIC uint8_t* sbc_start_frame = ((uint8_t*)(p_msg + 1) + p_msg->offset + 1); BtifAvrcpAudioTrackWriteData(btif_a2dp_sink_cb.audio_track, int count; reinterpret_cast<void*>(data), len); uint32_t pcmBytes, availPcmBytes; #endif int16_t* pcmDataPointer = } btif_a2dp_sink_pcm_data; /* Will be overwritten on next packet receipt */ OI_STATUS status; int num_sbc_frames = p_msg->num_frames_to_be_processed; uint32_t sbc_frame_len = p_msg->len - 1; availPcmBytes = sizeof(btif_a2dp_sink_pcm_data); // Must be called while locked. static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg) { if ((btif_av_get_peer_sep() == AVDT_TSEP_SNK) || if ((btif_av_get_peer_sep() == AVDT_TSEP_SNK) || (btif_a2dp_sink_cb.rx_flush)) { (btif_a2dp_sink_cb.rx_flush)) { APPL_TRACE_DEBUG("State Changed happened in this tick"); APPL_TRACE_DEBUG("State Changed happened in this tick"); return; return; } } APPL_TRACE_DEBUG("%s Number of SBC frames %d, frame_len %d", __func__, CHECK(btif_a2dp_sink_cb.decoder_interface); num_sbc_frames, sbc_frame_len); if (!btif_a2dp_sink_cb.decoder_interface->decode_packet(p_msg)) { APPL_TRACE_ERROR("%s Decoding failed!", __func__); for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count++) { pcmBytes = availPcmBytes; status = OI_CODEC_SBC_DecodeFrame( &btif_a2dp_sink_context, (const OI_BYTE**)&sbc_start_frame, (uint32_t*)&sbc_frame_len, (int16_t*)pcmDataPointer, (uint32_t*)&pcmBytes); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("%s: Decoding failure: %d", __func__, status); break; } } availPcmBytes -= pcmBytes; pcmDataPointer += pcmBytes / 2; p_msg->offset += (p_msg->len - 1) - sbc_frame_len; p_msg->len = sbc_frame_len + 1; } #ifndef OS_GENERIC BtifAvrcpAudioTrackWriteData( btif_a2dp_sink_cb.audio_track, (void*)btif_a2dp_sink_pcm_data, (sizeof(btif_a2dp_sink_pcm_data) - availPcmBytes)); #endif } } static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) { static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) { LockGuard lock(g_mutex); LockGuard lock(g_mutex); tBT_SBC_HDR* p_msg; BT_HDR* p_msg; int num_sbc_frames; int num_frames_to_process; if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) { if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) { APPL_TRACE_DEBUG("%s: empty queue", __func__); APPL_TRACE_DEBUG("%s: empty queue", __func__); return; return; Loading @@ -433,42 +391,20 @@ static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) { return; return; } } num_frames_to_process = btif_a2dp_sink_cb.frames_to_process; APPL_TRACE_DEBUG(" Process Frames + "); APPL_TRACE_DEBUG(" Process Frames + "); do { while (true) { p_msg = (tBT_SBC_HDR*)fixed_queue_try_peek_first( p_msg = (BT_HDR*)fixed_queue_try_dequeue(btif_a2dp_sink_cb.rx_audio_queue); btif_a2dp_sink_cb.rx_audio_queue); if (p_msg == NULL) { if (p_msg == NULL) return; break; /* Number of frames in queue packets */ } num_sbc_frames = p_msg->num_frames_to_be_processed; APPL_TRACE_DEBUG("Frames left in topmost packet %d", num_sbc_frames); APPL_TRACE_DEBUG("Remaining frames to process in tick %d", num_frames_to_process); APPL_TRACE_DEBUG("Number of packets in queue %d", APPL_TRACE_DEBUG("Number of packets in queue %d", fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue)); fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue)); if (num_sbc_frames > num_frames_to_process) { /* Queue packet has more frames */ p_msg->num_frames_to_be_processed = num_frames_to_process; btif_a2dp_sink_handle_inc_media(p_msg); p_msg->num_frames_to_be_processed = num_sbc_frames - num_frames_to_process; num_frames_to_process = 0; break; } /* Queue packet has less frames */ /* Queue packet has less frames */ btif_a2dp_sink_handle_inc_media(p_msg); btif_a2dp_sink_handle_inc_media(p_msg); p_msg = (tBT_SBC_HDR*)fixed_queue_try_dequeue(btif_a2dp_sink_cb.rx_audio_queue); if (p_msg == NULL) { APPL_TRACE_ERROR("Insufficient data in queue"); break; } num_frames_to_process = num_frames_to_process - p_msg->num_frames_to_be_processed; osi_free(p_msg); osi_free(p_msg); } while (num_frames_to_process > 0); } APPL_TRACE_DEBUG("Process Frames - "); APPL_TRACE_DEBUG("Process Frames - "); } } Loading @@ -483,7 +419,7 @@ void btif_a2dp_sink_set_rx_flush(bool enable) { static void btif_a2dp_sink_audio_rx_flush_event(void) { static void btif_a2dp_sink_audio_rx_flush_event(void) { LockGuard lock(g_mutex); LockGuard lock(g_mutex); /* Flush all received SBC buffers (encoded) */ /* Flush all received encoded audio buffers */ APPL_TRACE_DEBUG("%s", __func__); APPL_TRACE_DEBUG("%s", __func__); fixed_queue_flush(btif_a2dp_sink_cb.rx_audio_queue, osi_free); fixed_queue_flush(btif_a2dp_sink_cb.rx_audio_queue, osi_free); Loading @@ -492,8 +428,6 @@ static void btif_a2dp_sink_audio_rx_flush_event(void) { static void btif_a2dp_sink_decoder_update_event( static void btif_a2dp_sink_decoder_update_event( tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf) { tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf) { LockGuard lock(g_mutex); LockGuard lock(g_mutex); OI_STATUS status; APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__, APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__, p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[3], p_buf->codec_info[4], p_buf->codec_info[3], p_buf->codec_info[4], Loading @@ -519,15 +453,21 @@ static void btif_a2dp_sink_decoder_update_event( btif_a2dp_sink_cb.rx_flush = false; btif_a2dp_sink_cb.rx_flush = false; APPL_TRACE_DEBUG("%s: Reset to Sink role", __func__); APPL_TRACE_DEBUG("%s: Reset to Sink role", __func__); status = OI_CODEC_SBC_DecoderReset( &btif_a2dp_sink_context, btif_a2dp_sink_context_data, btif_a2dp_sink_cb.decoder_interface = bta_av_co_get_decoder_interface(); sizeof(btif_a2dp_sink_context_data), 2, 2, false); if (btif_a2dp_sink_cb.decoder_interface == NULL) { if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("%s: Cannot stream audio: no source decoder interface", APPL_TRACE_ERROR("%s: OI_CODEC_SBC_DecoderReset failed with error code %d", __func__); __func__, status); return; } } APPL_TRACE_DEBUG("%s: A2dpSink: SBC create track", __func__); if (!btif_a2dp_sink_cb.decoder_interface->decoder_init( btif_a2dp_sink_on_decode_complete)) { APPL_TRACE_ERROR("%s: A2dpSink: Failed to initialize decoder", __func__); return; } APPL_TRACE_DEBUG("%s: A2dpSink: create audio track", __func__); btif_a2dp_sink_cb.audio_track = btif_a2dp_sink_cb.audio_track = #ifndef OS_GENERIC #ifndef OS_GENERIC BtifAvrcpAudioTrackCreate(sample_rate, channel_type); BtifAvrcpAudioTrackCreate(sample_rate, channel_type); Loading @@ -538,15 +478,6 @@ static void btif_a2dp_sink_decoder_update_event( APPL_TRACE_ERROR("%s: A2dpSink: Track creation failed", __func__); APPL_TRACE_ERROR("%s: A2dpSink: Track creation failed", __func__); return; return; } } btif_a2dp_sink_cb.frames_to_process = A2DP_GetSinkFramesCountToProcess( BTIF_SINK_MEDIA_TIME_TICK_MS, p_buf->codec_info); APPL_TRACE_DEBUG("%s: Frames to be processed in 20 ms %d", __func__, btif_a2dp_sink_cb.frames_to_process); if (btif_a2dp_sink_cb.frames_to_process == 0) { APPL_TRACE_ERROR("%s: Cannot compute the number of frames to process", __func__); } } } uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { Loading @@ -563,17 +494,11 @@ uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { BTIF_TRACE_VERBOSE("%s +", __func__); BTIF_TRACE_VERBOSE("%s +", __func__); /* Allocate and queue this buffer */ /* Allocate and queue this buffer */ tBT_SBC_HDR* p_msg = reinterpret_cast<tBT_SBC_HDR*>( BT_HDR* p_msg = osi_malloc(sizeof(tBT_SBC_HDR) + p_pkt->offset + p_pkt->len)); reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(*p_msg) + p_pkt->len)); memcpy((uint8_t*)(p_msg + 1), (uint8_t*)(p_pkt + 1) + p_pkt->offset, memcpy(p_msg, p_pkt, sizeof(*p_msg)); p_pkt->len); p_msg->num_frames_to_be_processed = (*((uint8_t*)(p_pkt + 1) + p_pkt->offset)) & 0x0f; p_msg->len = p_pkt->len; p_msg->offset = 0; p_msg->offset = 0; p_msg->layer_specific = p_pkt->layer_specific; memcpy(p_msg->data, p_pkt->data + p_pkt->offset, p_pkt->len); BTIF_TRACE_VERBOSE("%s: frames to process %d, len %d", __func__, p_msg->num_frames_to_be_processed, p_msg->len); fixed_queue_enqueue(btif_a2dp_sink_cb.rx_audio_queue, p_msg); fixed_queue_enqueue(btif_a2dp_sink_cb.rx_audio_queue, p_msg); if (fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue) == if (fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue) == MAX_A2DP_DELAYED_START_FRAME_COUNT) { MAX_A2DP_DELAYED_START_FRAME_COUNT) { Loading system/include/hardware/bt_av.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,7 @@ typedef enum { // Add an entry for each sink codec here // Add an entry for each sink codec here BTAV_A2DP_CODEC_INDEX_SINK_SBC = BTAV_A2DP_CODEC_INDEX_SINK_MIN, BTAV_A2DP_CODEC_INDEX_SINK_SBC = BTAV_A2DP_CODEC_INDEX_SINK_MIN, BTAV_A2DP_CODEC_INDEX_SINK_AAC, BTAV_A2DP_CODEC_INDEX_SINK_MAX, BTAV_A2DP_CODEC_INDEX_SINK_MAX, Loading system/stack/Android.bp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ cc_library_static { ], ], include_dirs: [ include_dirs: [ "external/aac/libAACenc/include", "external/aac/libAACenc/include", "external/aac/libAACdec/include", "external/aac/libSYS/include", "external/aac/libSYS/include", "external/libldac/inc", "external/libldac/inc", "external/libldac/abr/inc", "external/libldac/abr/inc", Loading @@ -41,10 +42,12 @@ cc_library_static { ], ], srcs: [ srcs: [ "a2dp/a2dp_aac.cc", "a2dp/a2dp_aac.cc", "a2dp/a2dp_aac_decoder.cc", "a2dp/a2dp_aac_encoder.cc", "a2dp/a2dp_aac_encoder.cc", "a2dp/a2dp_api.cc", "a2dp/a2dp_api.cc", "a2dp/a2dp_codec_config.cc", "a2dp/a2dp_codec_config.cc", "a2dp/a2dp_sbc.cc", "a2dp/a2dp_sbc.cc", "a2dp/a2dp_sbc_decoder.cc", "a2dp/a2dp_sbc_encoder.cc", "a2dp/a2dp_sbc_encoder.cc", "a2dp/a2dp_sbc_up_sample.cc", "a2dp/a2dp_sbc_up_sample.cc", "a2dp/a2dp_vendor.cc", "a2dp/a2dp_vendor.cc", Loading Loading @@ -201,6 +204,7 @@ cc_test { ], ], static_libs: [ static_libs: [ "libbt-stack", "libbt-stack", "libbt-sbc-decoder", "libbt-sbc-encoder", "libbt-sbc-encoder", "libFraunhoferAAC", "libFraunhoferAAC", "libosi", "libosi", Loading Loading
system/btif/co/bta_av_co.cc +13 −0 Original line number Original line Diff line number Diff line Loading @@ -1051,6 +1051,19 @@ const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) { return encoder_interface; return encoder_interface; } } const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void) { /* Protect access to bta_av_co_cb.codec_config */ mutex_global_lock(); const tA2DP_DECODER_INTERFACE* decoder_interface = A2DP_GetDecoderInterface(bta_av_co_cb.codec_config); /* Protect access to bta_av_co_cb.codec_config */ mutex_global_unlock(); return decoder_interface; } bool bta_av_co_set_codec_user_config( bool bta_av_co_set_codec_user_config( const btav_a2dp_codec_config_t& codec_user_config) { const btav_a2dp_codec_config_t& codec_user_config) { uint8_t result_codec_config[AVDT_CODEC_SIZE]; uint8_t result_codec_config[AVDT_CODEC_SIZE]; Loading
system/btif/include/btif_av_co.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,12 @@ void bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params); // otherwise NULL. // otherwise NULL. const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void); const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void); // Gets the current A2DP decoder interface that can be used to decode received // A2DP packets - see |tA2DP_DECODER_INTERFACE|. // Returns the A2DP decoder interface if the current codec is setup, otherwise // NULL. const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void); // Sets the user preferred codec configuration. // Sets the user preferred codec configuration. // |codec_user_config| contains the preferred codec configuration. // |codec_user_config| contains the preferred codec configuration. // Returns true on success, otherwise false. // Returns true on success, otherwise false. Loading
system/btif/src/btif_a2dp_sink.cc +38 −113 Original line number Original line Diff line number Diff line Loading @@ -35,9 +35,6 @@ #include "osi/include/osi.h" #include "osi/include/osi.h" #include "osi/include/thread.h" #include "osi/include/thread.h" #include "oi_codec_sbc.h" #include "oi_status.h" using LockGuard = std::lock_guard<std::mutex>; using LockGuard = std::lock_guard<std::mutex>; /** /** Loading Loading @@ -75,13 +72,6 @@ typedef struct { btif_a2dp_sink_focus_state_t focus_state; btif_a2dp_sink_focus_state_t focus_state; } tBTIF_MEDIA_SINK_FOCUS_UPDATE; } tBTIF_MEDIA_SINK_FOCUS_UPDATE; typedef struct { uint16_t num_frames_to_be_processed; uint16_t len; uint16_t offset; uint16_t layer_specific; } tBT_SBC_HDR; /* BTIF A2DP Sink control block */ /* BTIF A2DP Sink control block */ typedef struct { typedef struct { thread_t* worker_thread; thread_t* worker_thread; Loading @@ -89,11 +79,11 @@ typedef struct { fixed_queue_t* rx_audio_queue; fixed_queue_t* rx_audio_queue; bool rx_flush; /* discards any incoming data when true */ bool rx_flush; /* discards any incoming data when true */ alarm_t* decode_alarm; alarm_t* decode_alarm; uint8_t frames_to_process; tA2DP_SAMPLE_RATE sample_rate; tA2DP_SAMPLE_RATE sample_rate; tA2DP_CHANNEL_COUNT channel_count; tA2DP_CHANNEL_COUNT channel_count; btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */ btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */ void* audio_track; void* audio_track; const tA2DP_DECODER_INTERFACE* decoder_interface; } tBTIF_A2DP_SINK_CB; } tBTIF_A2DP_SINK_CB; // Mutex for below data structures. // Mutex for below data structures. Loading @@ -103,12 +93,6 @@ static tBTIF_A2DP_SINK_CB btif_a2dp_sink_cb; static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF}; static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF}; static OI_CODEC_SBC_DECODER_CONTEXT btif_a2dp_sink_context; static uint32_t btif_a2dp_sink_context_data[CODEC_DATA_WORDS( 2, SBC_CODEC_FAST_FILTER_BUFFERS)]; static int16_t btif_a2dp_sink_pcm_data[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS]; static void btif_a2dp_sink_startup_delayed(void* context); static void btif_a2dp_sink_startup_delayed(void* context); static void btif_a2dp_sink_shutdown_delayed(void* context); static void btif_a2dp_sink_shutdown_delayed(void* context); static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context); static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context); Loading @@ -118,7 +102,7 @@ static void btif_a2dp_sink_audio_handle_start_decoding(void); static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context); static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context); static void btif_a2dp_sink_audio_rx_flush_req(void); static void btif_a2dp_sink_audio_rx_flush_req(void); /* Handle incoming media packets A2DP SINK streaming */ /* Handle incoming media packets A2DP SINK streaming */ static void btif_a2dp_sink_handle_inc_media(tBT_SBC_HDR* p_msg); static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg); static void btif_a2dp_sink_decoder_update_event( static void btif_a2dp_sink_decoder_update_event( tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf); tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf); static void btif_a2dp_sink_clear_track_event(void); static void btif_a2dp_sink_clear_track_event(void); Loading Loading @@ -365,57 +349,31 @@ static void btif_a2dp_sink_audio_handle_start_decoding(void) { btif_decode_alarm_cb, NULL); btif_decode_alarm_cb, NULL); } } // Must be called while locked. static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) { static void btif_a2dp_sink_handle_inc_media(tBT_SBC_HDR* p_msg) { #ifndef OS_GENERIC uint8_t* sbc_start_frame = ((uint8_t*)(p_msg + 1) + p_msg->offset + 1); BtifAvrcpAudioTrackWriteData(btif_a2dp_sink_cb.audio_track, int count; reinterpret_cast<void*>(data), len); uint32_t pcmBytes, availPcmBytes; #endif int16_t* pcmDataPointer = } btif_a2dp_sink_pcm_data; /* Will be overwritten on next packet receipt */ OI_STATUS status; int num_sbc_frames = p_msg->num_frames_to_be_processed; uint32_t sbc_frame_len = p_msg->len - 1; availPcmBytes = sizeof(btif_a2dp_sink_pcm_data); // Must be called while locked. static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg) { if ((btif_av_get_peer_sep() == AVDT_TSEP_SNK) || if ((btif_av_get_peer_sep() == AVDT_TSEP_SNK) || (btif_a2dp_sink_cb.rx_flush)) { (btif_a2dp_sink_cb.rx_flush)) { APPL_TRACE_DEBUG("State Changed happened in this tick"); APPL_TRACE_DEBUG("State Changed happened in this tick"); return; return; } } APPL_TRACE_DEBUG("%s Number of SBC frames %d, frame_len %d", __func__, CHECK(btif_a2dp_sink_cb.decoder_interface); num_sbc_frames, sbc_frame_len); if (!btif_a2dp_sink_cb.decoder_interface->decode_packet(p_msg)) { APPL_TRACE_ERROR("%s Decoding failed!", __func__); for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count++) { pcmBytes = availPcmBytes; status = OI_CODEC_SBC_DecodeFrame( &btif_a2dp_sink_context, (const OI_BYTE**)&sbc_start_frame, (uint32_t*)&sbc_frame_len, (int16_t*)pcmDataPointer, (uint32_t*)&pcmBytes); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("%s: Decoding failure: %d", __func__, status); break; } } availPcmBytes -= pcmBytes; pcmDataPointer += pcmBytes / 2; p_msg->offset += (p_msg->len - 1) - sbc_frame_len; p_msg->len = sbc_frame_len + 1; } #ifndef OS_GENERIC BtifAvrcpAudioTrackWriteData( btif_a2dp_sink_cb.audio_track, (void*)btif_a2dp_sink_pcm_data, (sizeof(btif_a2dp_sink_pcm_data) - availPcmBytes)); #endif } } static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) { static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) { LockGuard lock(g_mutex); LockGuard lock(g_mutex); tBT_SBC_HDR* p_msg; BT_HDR* p_msg; int num_sbc_frames; int num_frames_to_process; if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) { if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) { APPL_TRACE_DEBUG("%s: empty queue", __func__); APPL_TRACE_DEBUG("%s: empty queue", __func__); return; return; Loading @@ -433,42 +391,20 @@ static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) { return; return; } } num_frames_to_process = btif_a2dp_sink_cb.frames_to_process; APPL_TRACE_DEBUG(" Process Frames + "); APPL_TRACE_DEBUG(" Process Frames + "); do { while (true) { p_msg = (tBT_SBC_HDR*)fixed_queue_try_peek_first( p_msg = (BT_HDR*)fixed_queue_try_dequeue(btif_a2dp_sink_cb.rx_audio_queue); btif_a2dp_sink_cb.rx_audio_queue); if (p_msg == NULL) { if (p_msg == NULL) return; break; /* Number of frames in queue packets */ } num_sbc_frames = p_msg->num_frames_to_be_processed; APPL_TRACE_DEBUG("Frames left in topmost packet %d", num_sbc_frames); APPL_TRACE_DEBUG("Remaining frames to process in tick %d", num_frames_to_process); APPL_TRACE_DEBUG("Number of packets in queue %d", APPL_TRACE_DEBUG("Number of packets in queue %d", fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue)); fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue)); if (num_sbc_frames > num_frames_to_process) { /* Queue packet has more frames */ p_msg->num_frames_to_be_processed = num_frames_to_process; btif_a2dp_sink_handle_inc_media(p_msg); p_msg->num_frames_to_be_processed = num_sbc_frames - num_frames_to_process; num_frames_to_process = 0; break; } /* Queue packet has less frames */ /* Queue packet has less frames */ btif_a2dp_sink_handle_inc_media(p_msg); btif_a2dp_sink_handle_inc_media(p_msg); p_msg = (tBT_SBC_HDR*)fixed_queue_try_dequeue(btif_a2dp_sink_cb.rx_audio_queue); if (p_msg == NULL) { APPL_TRACE_ERROR("Insufficient data in queue"); break; } num_frames_to_process = num_frames_to_process - p_msg->num_frames_to_be_processed; osi_free(p_msg); osi_free(p_msg); } while (num_frames_to_process > 0); } APPL_TRACE_DEBUG("Process Frames - "); APPL_TRACE_DEBUG("Process Frames - "); } } Loading @@ -483,7 +419,7 @@ void btif_a2dp_sink_set_rx_flush(bool enable) { static void btif_a2dp_sink_audio_rx_flush_event(void) { static void btif_a2dp_sink_audio_rx_flush_event(void) { LockGuard lock(g_mutex); LockGuard lock(g_mutex); /* Flush all received SBC buffers (encoded) */ /* Flush all received encoded audio buffers */ APPL_TRACE_DEBUG("%s", __func__); APPL_TRACE_DEBUG("%s", __func__); fixed_queue_flush(btif_a2dp_sink_cb.rx_audio_queue, osi_free); fixed_queue_flush(btif_a2dp_sink_cb.rx_audio_queue, osi_free); Loading @@ -492,8 +428,6 @@ static void btif_a2dp_sink_audio_rx_flush_event(void) { static void btif_a2dp_sink_decoder_update_event( static void btif_a2dp_sink_decoder_update_event( tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf) { tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf) { LockGuard lock(g_mutex); LockGuard lock(g_mutex); OI_STATUS status; APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__, APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__, p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[3], p_buf->codec_info[4], p_buf->codec_info[3], p_buf->codec_info[4], Loading @@ -519,15 +453,21 @@ static void btif_a2dp_sink_decoder_update_event( btif_a2dp_sink_cb.rx_flush = false; btif_a2dp_sink_cb.rx_flush = false; APPL_TRACE_DEBUG("%s: Reset to Sink role", __func__); APPL_TRACE_DEBUG("%s: Reset to Sink role", __func__); status = OI_CODEC_SBC_DecoderReset( &btif_a2dp_sink_context, btif_a2dp_sink_context_data, btif_a2dp_sink_cb.decoder_interface = bta_av_co_get_decoder_interface(); sizeof(btif_a2dp_sink_context_data), 2, 2, false); if (btif_a2dp_sink_cb.decoder_interface == NULL) { if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("%s: Cannot stream audio: no source decoder interface", APPL_TRACE_ERROR("%s: OI_CODEC_SBC_DecoderReset failed with error code %d", __func__); __func__, status); return; } } APPL_TRACE_DEBUG("%s: A2dpSink: SBC create track", __func__); if (!btif_a2dp_sink_cb.decoder_interface->decoder_init( btif_a2dp_sink_on_decode_complete)) { APPL_TRACE_ERROR("%s: A2dpSink: Failed to initialize decoder", __func__); return; } APPL_TRACE_DEBUG("%s: A2dpSink: create audio track", __func__); btif_a2dp_sink_cb.audio_track = btif_a2dp_sink_cb.audio_track = #ifndef OS_GENERIC #ifndef OS_GENERIC BtifAvrcpAudioTrackCreate(sample_rate, channel_type); BtifAvrcpAudioTrackCreate(sample_rate, channel_type); Loading @@ -538,15 +478,6 @@ static void btif_a2dp_sink_decoder_update_event( APPL_TRACE_ERROR("%s: A2dpSink: Track creation failed", __func__); APPL_TRACE_ERROR("%s: A2dpSink: Track creation failed", __func__); return; return; } } btif_a2dp_sink_cb.frames_to_process = A2DP_GetSinkFramesCountToProcess( BTIF_SINK_MEDIA_TIME_TICK_MS, p_buf->codec_info); APPL_TRACE_DEBUG("%s: Frames to be processed in 20 ms %d", __func__, btif_a2dp_sink_cb.frames_to_process); if (btif_a2dp_sink_cb.frames_to_process == 0) { APPL_TRACE_ERROR("%s: Cannot compute the number of frames to process", __func__); } } } uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { Loading @@ -563,17 +494,11 @@ uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { BTIF_TRACE_VERBOSE("%s +", __func__); BTIF_TRACE_VERBOSE("%s +", __func__); /* Allocate and queue this buffer */ /* Allocate and queue this buffer */ tBT_SBC_HDR* p_msg = reinterpret_cast<tBT_SBC_HDR*>( BT_HDR* p_msg = osi_malloc(sizeof(tBT_SBC_HDR) + p_pkt->offset + p_pkt->len)); reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(*p_msg) + p_pkt->len)); memcpy((uint8_t*)(p_msg + 1), (uint8_t*)(p_pkt + 1) + p_pkt->offset, memcpy(p_msg, p_pkt, sizeof(*p_msg)); p_pkt->len); p_msg->num_frames_to_be_processed = (*((uint8_t*)(p_pkt + 1) + p_pkt->offset)) & 0x0f; p_msg->len = p_pkt->len; p_msg->offset = 0; p_msg->offset = 0; p_msg->layer_specific = p_pkt->layer_specific; memcpy(p_msg->data, p_pkt->data + p_pkt->offset, p_pkt->len); BTIF_TRACE_VERBOSE("%s: frames to process %d, len %d", __func__, p_msg->num_frames_to_be_processed, p_msg->len); fixed_queue_enqueue(btif_a2dp_sink_cb.rx_audio_queue, p_msg); fixed_queue_enqueue(btif_a2dp_sink_cb.rx_audio_queue, p_msg); if (fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue) == if (fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue) == MAX_A2DP_DELAYED_START_FRAME_COUNT) { MAX_A2DP_DELAYED_START_FRAME_COUNT) { Loading
system/include/hardware/bt_av.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,7 @@ typedef enum { // Add an entry for each sink codec here // Add an entry for each sink codec here BTAV_A2DP_CODEC_INDEX_SINK_SBC = BTAV_A2DP_CODEC_INDEX_SINK_MIN, BTAV_A2DP_CODEC_INDEX_SINK_SBC = BTAV_A2DP_CODEC_INDEX_SINK_MIN, BTAV_A2DP_CODEC_INDEX_SINK_AAC, BTAV_A2DP_CODEC_INDEX_SINK_MAX, BTAV_A2DP_CODEC_INDEX_SINK_MAX, Loading
system/stack/Android.bp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ cc_library_static { ], ], include_dirs: [ include_dirs: [ "external/aac/libAACenc/include", "external/aac/libAACenc/include", "external/aac/libAACdec/include", "external/aac/libSYS/include", "external/aac/libSYS/include", "external/libldac/inc", "external/libldac/inc", "external/libldac/abr/inc", "external/libldac/abr/inc", Loading @@ -41,10 +42,12 @@ cc_library_static { ], ], srcs: [ srcs: [ "a2dp/a2dp_aac.cc", "a2dp/a2dp_aac.cc", "a2dp/a2dp_aac_decoder.cc", "a2dp/a2dp_aac_encoder.cc", "a2dp/a2dp_aac_encoder.cc", "a2dp/a2dp_api.cc", "a2dp/a2dp_api.cc", "a2dp/a2dp_codec_config.cc", "a2dp/a2dp_codec_config.cc", "a2dp/a2dp_sbc.cc", "a2dp/a2dp_sbc.cc", "a2dp/a2dp_sbc_decoder.cc", "a2dp/a2dp_sbc_encoder.cc", "a2dp/a2dp_sbc_encoder.cc", "a2dp/a2dp_sbc_up_sample.cc", "a2dp/a2dp_sbc_up_sample.cc", "a2dp/a2dp_vendor.cc", "a2dp/a2dp_vendor.cc", Loading Loading @@ -201,6 +204,7 @@ cc_test { ], ], static_libs: [ static_libs: [ "libbt-stack", "libbt-stack", "libbt-sbc-decoder", "libbt-sbc-encoder", "libbt-sbc-encoder", "libFraunhoferAAC", "libFraunhoferAAC", "libosi", "libosi", Loading