A2DP - Advanced Audio Distribution Profile
A2DP提供通過藍牙連接傳輸音頻流的能力十艾,比如手機播放音樂,藍牙耳機通過藍牙連接聽歌梯浪。在上面的例子中,手機扮演A2DP源(Source)的角色,藍牙耳機扮演A2DP接收器(Sink)的角色灼捂。因此A2DP服務是單項傳輸,無論是單聲道(mono)還是雙聲道(stereo)换团。A2DP主要實現(xiàn)SDC(sub band codec纵东,默認的a2dp編解碼方式),AAC啥寇,F(xiàn)DK偎球, LDAC,APTX等簡單codec辑甜。
A2DP的服務能力
A2DP服務是需要和AVRCP服務一起使用的衰絮。AVRCP控制器用來獲取A2DP源的數(shù)據(jù)信息,如title(曲名)磷醋,artist(演唱者)猫牡,album(專輯)及控制命令(play,stop邓线,repeat等)淌友。
1,A2DP接收器(Sink)
需要注冊的回調:
1骇陈,hci_packet_handler (注冊回調處理接收到的包震庭,比如發(fā)現(xiàn)包,配對包你雌,數(shù)據(jù)包等等)
2器联,a2dp_sink_packet_handler(注冊回調處理連接事件,如established/released婿崭,并執(zhí)行對應的配置工作拨拓,如codec配置;處理播放狀態(tài)如opened氓栈,paused渣磷,stopped,并執(zhí)行對應的動作授瘦;
3醋界,handle_l2cap_media_data_packet(注冊回調處理音頻流數(shù)據(jù)祟身,支持存儲和播放,默認是SBC編碼格式物独,可以解碼成PCM進行播放)
4袜硫,avrcp_packet_handler(注冊回調處理avrcp的命令回調,如connect挡篓,disconnect等)
5婉陷,avrcp_controller_packet_handler(注冊回調處理avrcp命令和消息通知,如poschanged官研,statuschanged等)
6秽澳,stdin_process,用戶控制的回調
A2DP和AVRCP服務配置
應用層需要創(chuàng)建A2DP和AVRCP的SDP記錄戏羽,然后注冊在SDP服務里
// Initialize SDP ? ?
sdp_init();? ?
// Create A2DP Sink service record and register it with SDP? ?
memset(sdp_avdtp_sink_service_buffer, 0, sizeof(sdp_avdtp_sink_service_buffer));? ?
a2dp_sink_create_sdp_record(sdp_avdtp_sink_service_buffer, 0x10001, AVDTP_SINK_FEATURE_MASK_HEADPHONE, NULL, NULL);? ?
sdp_register_service(sdp_avdtp_sink_service_buffer);
所以整個服務啟動流程如下:
1担神,l2cap_init();? //初始化藍牙鏈路
2,sm_init(); //初始化security manager始花,BLE也就是藍牙4.0后需要妄讯;
3,a2dp_sink_init();? //初始化a2dp和回調
a2dp_sink_register_packet_handler(&a2dp_sink_packet_handler);? ? a2dp_sink_register_media_handler(&handle_l2cap_media_data_packet);
4酷宵,local_stream_endpoint = a2dp_sink_create_stream_endpoint(...); //初始化音頻流終端亥贸,并進行對應的配置如codec,大小等浇垦,可視作處理音頻流的具體對象)
5炕置,avrcp_init();? ? //初始化avrcp并注冊回調
avrcp_register_packet_handler(&avrcp_packet_handler);
// Initialize AVRCP Controller? ?
avrcp_controller_init();? ?
avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler);? ? ? ??
// Initialize AVRCP Target? ?
avrcp_target_init();? ?
avrcp_target_register_packet_handler(&avrcp_target_packet_handler);
6,sdp_init(); //初始化sdp男韧,其他設備可以發(fā)現(xiàn)a2dp和avrcp服務
?// Create A2DP Sink service record and register it with SDP? ?
memset(sdp_avdtp_sink_service_buffer, 0, sizeof(sdp_avdtp_sink_service_buffer));? ? // 150字節(jié)內(nèi)存
a2dp_sink_create_sdp_record(sdp_avdtp_sink_service_buffer, 0x10001, AVDTP_SINK_FEATURE_MASK_HEADPHONE, NULL, NULL);? ?
sdp_register_service(sdp_avdtp_sink_service_buffer);
avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10002, controller_supported_features, NULL, NULL);? ?
sdp_register_service(sdp_avrcp_controller_service_buffer);? ? ? ?
// Create AVRCP Target service record and register it with SDP. We receive Category 2 commands from the media player, e.g. volume up/down? ?
memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer));? ?
uint16_t target_supported_features = AVRCP_FEATURE_MASK_CATEGORY_MONITOR_OR_AMPLIFIER;? ?
avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10003, target_supported_features, NULL, NULL);? ?
sdp_register_service(sdp_avrcp_target_service_buffer);
// Create Device ID (PnP) service record and register it with SDP? ?
memset(device_id_sdp_service_buffer, 0, sizeof(device_id_sdp_service_buffer));? ?
device_id_create_sdp_record(device_id_sdp_service_buffer, 0x10004, DEVICE_ID_VENDOR_ID_SOURCE_BLUETOOTH, BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, 1, 1);? ?
sdp_register_service(device_id_sdp_service_buffer);
7朴摊,gap_set_local_name("A2DP Sink Demo 00:00:00:00:00:00");? ? //設置設備名稱和address(mac地址)
gap_discoverable_control(1);? ? //可被發(fā)現(xiàn)
gap_set_class_of_device(0x200408); //設置device class
8,hci_event_callback_registration.callback = &hci_packet_handler;? ? // Register for HCI events?
hci_add_event_handler(&hci_event_callback_registration);
總結:從底到頂?shù)呐渲眠^程就是:初始化l2cap, sm(如果要支持ble)-> 注冊hci回調->配置gap(名稱此虑,地址甚纲,設備類型,并確認可被發(fā)現(xiàn))-> 配置SDP(設備id寡壮,產(chǎn)品id贩疙,avrcp和a2dp的服務配置)-> 初始化avrcp, avrcp target, avrcp controller及a2dp sink(source)讹弯,stream endpoint并注冊對應的回調
2况既,A2DP源(Source)
成為A2DP源需要應用的藍牙協(xié)議棧和Sink大致一樣。區(qū)別主要在以下內(nèi)容:
1组民,A2DP源在經(jīng)典藍牙協(xié)議框架里是作為master設備存在棒仍,不是外設,所以需要配置hci:hci_set_master_slave_policy(0)臭胜,0是master莫其,1是讓連接設備確認癞尚;
2,不同于A2DP Sink乱陡,A2DP初始化源的過程相對簡單浇揩,只需要a2dp_source_init()和a2dp_source_register_packet_handler就可,此handle為處理音頻流的handle憨颠;
3胳徽,stream_endpoint和avrcp初始化和Sink一樣,同理SDP爽彤,GAP都一樣
4养盗,配置音頻流,如采樣率等
總結:大致和A2DP接收器一樣适篙,只是具體角色和handle不一樣