#include "aem_adapter_media.h" #include "aem_adapter_audio.h" #include "aem_video_service.h" #include "aem_adapter_card_reader.h" #include "aem_app_comm.h" #include "aem_log.h" #include "aem_app_err_if.h" #include "tts_manager.h" #include #ifdef CONFIG_FILE_STREAM #include #endif #ifdef CONFIG_BT_MANAGER #include "bt_manager.h" #endif #if CONFIG_AUDIO #include #include #endif #include "bt_transmit.h" #define ENABLE_LCPLAYER_FADEIN_FADEOUT 1 #define toupper(a) (((a) >= 'a' && (a) <= 'z') ? (a) - ('a' - 'A') : (a)) static OS_MUTEX_DEFINE(aem_media_lock); typedef struct { uint8_t tts_lock; aem_media_type_e type; aem_media_state_e state; aem_media_info_t info; media_player_t *player; io_stream_t input_stream; io_stream_t output_stream; io_stream_t capture_input_stream; io_stream_t capture_output_stream; media_breakpoint_info_t bp; aem_media_event_cb event_cb[AEM_MEDIA_EVENT_CNT]; } aem_media_t; static aem_media_t s_media_info = {0}; static void media_event_cb(uint32_t event, void *data, uint32_t len, void *user_data) { media_init_param_t *init_param = (media_init_param_t *)data; AEM_LOG_I("media_event_cb event %d, len %d, param %p\n", event, len, init_param); if (s_media_info.player != NULL && s_media_info.player != user_data) { AEM_LOG_I("player : %p user_data : %p \n", s_media_info.player, user_data); if (s_media_info.type != AEM_MEDIA_TYPE_TTS) { return; } } switch (event) { case PLAYER_EVENT_OPEN: { if (init_param) { AEM_LOG_I("media_init_param_t type %d, stream_type %d, format %d, capture_format %d \n", init_param->type, init_param->stream_type, init_param->format, init_param->capture_format); switch (init_param->stream_type) { case AUDIO_STREAM_TTS: { s_media_info.type = AEM_MEDIA_TYPE_TTS; for (size_t i = 0; i < AEM_MEDIA_EVENT_CNT; i++) { if (s_media_info.event_cb[i] != NULL) { s_media_info.event_cb[i](s_media_info.type, AEM_MEDIA_STATE_OPEN); } } break; } case AUDIO_STREAM_LOCAL_MUSIC: s_media_info.type = AEM_MEDIA_TYPE_MUSIC; break; case AUDIO_STREAM_MUSIC: s_media_info.type = AEM_MEDIA_TYPE_BT_MUSIC; break; case AUDIO_STREAM_VOICE: s_media_info.type = AEM_MEDIA_TYPE_BT_CALL; break; default: break; } } break; } case PLAYER_EVENT_PLAY: { s_media_info.state = AEM_MEDIA_STATE_PLAY; for (size_t i = 0; i < AEM_MEDIA_EVENT_CNT; i++) { if (s_media_info.event_cb[i] != NULL) { s_media_info.event_cb[i](s_media_info.type, s_media_info.state); } } break; } case PLAYER_EVENT_CLOSE: { s_media_info.state = AEM_MEDIA_STATE_STOP; for (size_t i = 0; i < AEM_MEDIA_EVENT_CNT; i++) { if (s_media_info.event_cb[i] != NULL) { s_media_info.event_cb[i](s_media_info.type, s_media_info.state); } } break; } case PLAYBACK_EVENT_STOP_COMPLETE: { s_media_info.state = AEM_MEDIA_STATE_STOP_COMPLETE; for (size_t i = 0; i < AEM_MEDIA_EVENT_CNT; i++) { if (s_media_info.event_cb[i] != NULL) { s_media_info.event_cb[i](s_media_info.type, s_media_info.state); } } break; } default: break; } } static uint8_t get_param_type(aem_media_type_e type) { uint8_t param_type = MEDIA_SRV_TYPE_PLAYBACK; switch (type) { case AEM_MEDIA_TYPE_MUSIC: param_type = MEDIA_SRV_TYPE_PARSER_AND_PLAYBACK; break; case AEM_MEDIA_TYPE_BT_MUSIC: param_type = MEDIA_SRV_TYPE_PLAYBACK; break; case AEM_MEDIA_TYPE_BT_CALL: param_type = MEDIA_SRV_TYPE_PLAYBACK_AND_CAPTURE; break; default: break; } return param_type; } static uint8_t get_stream_type(aem_media_type_e type) { uint8_t stream_type = AUDIO_STREAM_DEFAULT; switch (type) { case AEM_MEDIA_TYPE_MUSIC: bt_manager_set_stream_type(AUDIO_STREAM_LOCAL_MUSIC); stream_type = AUDIO_STREAM_LOCAL_MUSIC; break; case AEM_MEDIA_TYPE_BT_MUSIC: bt_manager_set_stream_type(AUDIO_STREAM_MUSIC); stream_type = AUDIO_STREAM_MUSIC; break; case AEM_MEDIA_TYPE_BT_CALL: bt_manager_set_stream_type(AUDIO_STREAM_VOICE); stream_type = AUDIO_STREAM_VOICE; break; default: break; } return stream_type; } static int8_t get_param_format(aem_media_type_e type, char *path) { uint8_t codec_id = 0; uint8_t param_format = UNSUPPORT_TYPE; switch (type) { case AEM_MEDIA_TYPE_MUSIC: { if (path == NULL || strlen(path) == 0) { AEM_LOG_E("path is null\n"); return -EINVAL; } param_format = aem_adapter_get_file_type(path); break; } case AEM_MEDIA_TYPE_BT_MUSIC: { codec_id = bt_manager_a2dp_get_codecid(BTSRV_DEVICE_PHONE); if (codec_id == 0) { param_format = SBC_TYPE; } else if (codec_id == 2) { param_format = AAC_TYPE; } else { AEM_LOG_I("unknown code id %d", codec_id); return -EINVAL; } break; } case AEM_MEDIA_TYPE_BT_CALL: { param_format = bt_manager_sco_get_codecid(); break; } default: break; } return param_format; } static io_stream_t create_inputstream(aem_media_type_e type, char *path) { int ret = 0; io_stream_t input_stream = NULL; switch (type) { case AEM_MEDIA_TYPE_MUSIC: { if (path == NULL || strlen(path) == 0) { AEM_LOG_E("path is null\n"); return NULL; } input_stream = file_stream_create((void *)path); if (!input_stream) { AEM_LOG_E("stream create failed (%s)\n", path); return NULL; } if (stream_open(input_stream, MODE_IN)) { AEM_LOG_E("stream open failed (%s)\n", path); stream_destroy(input_stream); input_stream = NULL; return NULL; } break; } case AEM_MEDIA_TYPE_BT_MUSIC: { input_stream = ringbuff_stream_create_ext( media_mem_get_cache_pool(INPUT_PLAYBACK, AUDIO_STREAM_MUSIC), media_mem_get_cache_pool_size(INPUT_PLAYBACK, AUDIO_STREAM_MUSIC)); if (!input_stream) { AEM_LOG_E("stream open failed\n"); return NULL; } ret = stream_open(input_stream, MODE_IN_OUT | MODE_READ_BLOCK | MODE_BLOCK_TIMEOUT); if (ret) { AEM_LOG_E("stream open failed\n"); stream_destroy(input_stream); input_stream = NULL; return NULL; } break; } case AEM_MEDIA_TYPE_BT_CALL: { input_stream = ringbuff_stream_create_ext( media_mem_get_cache_pool(INPUT_PLAYBACK, AUDIO_STREAM_VOICE), media_mem_get_cache_pool_size(INPUT_PLAYBACK, AUDIO_STREAM_VOICE)); if (!input_stream) { AEM_LOG_E("stream open failed\n"); return NULL; } ret = stream_open(input_stream, MODE_IN_OUT | MODE_READ_BLOCK | MODE_BLOCK_TIMEOUT); if (ret) { AEM_LOG_E("stream open failed\n"); stream_destroy(input_stream); input_stream = NULL; return NULL; } break; } default: break; } return input_stream; } static io_stream_t catpure_create_inputstream(aem_media_type_e type) { int ret = 0; io_stream_t input_stream = NULL; return input_stream; } static io_stream_t catpure_create_outputstream(aem_media_type_e type) { int ret = 0; io_stream_t output_stream = NULL; switch (type) { case AEM_MEDIA_TYPE_BT_CALL: { uint8_t codec_id = 0; #ifdef CONFIG_BT_HFP_HF codec_id = bt_manager_sco_get_codecid(); #endif output_stream = sco_upload_stream_create(codec_id); if (!output_stream) { AEM_LOG_E("stream open failed\n"); return NULL; } if (stream_open(output_stream, MODE_OUT)) { AEM_LOG_E("stream open failed\n"); stream_destroy(output_stream); output_stream = NULL; return NULL; } break; } default: break; } return output_stream; } static void send_error_event(void) { for (size_t i = 0; i < AEM_MEDIA_EVENT_CNT; i++) { if (s_media_info.event_cb[i] != NULL) { s_media_info.event_cb[i](s_media_info.type, AEM_MEDIA_STATE_ERROR); } } } int aem_adapter_media_play(aem_media_type_e type, char *path, uint32_t time) { int ret = 0; AEM_LOG_I("type = %d, path = %s, time = %d\n", type, path, time); #if CONFIG_USB_MASS_STORAGE if (aem_card_read_flag() == true) { send_error_event(); return -1; } #endif #if defined(CONFIG_VIDEO_PLAYER) && defined(CONFIG_VIDEO_APP_AUDIO_ENABLE) if (aem_is_video_running() == true) { send_error_event(); return -1; } #endif if (type < AEM_MEDIA_TYPE_BT_CALL && s_media_info.type == AEM_MEDIA_TYPE_TTS && s_media_info.state == AEM_MEDIA_STATE_PLAY) { send_error_event(); return -1; } if (type < AEM_MEDIA_TYPE_BT_CALL && s_media_info.type > type) { send_error_event(); return -1; } for (size_t i = 0; i < AEM_MEDIA_EVENT_CNT; i++) { if (s_media_info.event_cb[i] != NULL) { s_media_info.event_cb[i](type, AEM_MEDIA_STATE_OPEN); } } aem_adapter_media_stop(); os_mutex_lock(&aem_media_lock, OS_FOREVER); media_init_param_t init_param; s_media_info.input_stream = create_inputstream(type, path); if (s_media_info.input_stream == NULL) { os_mutex_unlock(&aem_media_lock); send_error_event(); return -1; } s_media_info.capture_input_stream = catpure_create_inputstream(type); s_media_info.capture_output_stream = catpure_create_outputstream(type); int param_format = get_param_format(type, path); if (param_format < 0) { os_mutex_unlock(&aem_media_lock); send_error_event(); return -1; } #ifdef CONFIG_PLAYTTS if (s_media_info.tts_lock == 1) { tts_manager_unlock(); s_media_info.tts_lock = 0; } tts_manager_wait_finished(true); #endif memset(&init_param, 0, sizeof(media_init_param_t)); init_param.type = get_param_type(type); init_param.stream_type = get_stream_type(type); init_param.efx_stream_type = get_stream_type(type); init_param.event_notify_handle = media_event_cb; init_param.format = param_format; init_param.input_stream = s_media_info.input_stream; init_param.output_stream = s_media_info.output_stream; init_param.capture_input_stream = s_media_info.capture_input_stream; init_param.capture_output_stream = s_media_info.capture_output_stream; switch (type) { case AEM_MEDIA_TYPE_MUSIC: { if (aem_get_monkey_test_enable()) { extern int aem_set_system_media_volume(int volume); aem_set_system_media_volume(1); } init_param.support_tws = 1; init_param.dumpable = 1; init_param.dsp_output = 1; if (time != 0) { init_param.bp_file_offset = -1; init_param.bp_time_offset = time; } #ifdef CONFIG_BT_TRANSMIT bt_transmit_catpure_pre_start(); #endif s_media_info.player = media_player_open(&init_param); if (!s_media_info.player) { aem_adapter_media_stop(); os_mutex_unlock(&aem_media_lock); send_error_event(); return -1; } #ifdef CONFIG_BT_TRANSMIT /*makesure bt transmit STEREO mode*/ media_player_set_effect_output_mode(s_media_info.player, MEDIA_EFFECT_OUTPUT_DEFAULT); bt_transmit_catpure_start(init_param.output_stream, init_param.sample_rate, init_param.channels); #endif #if ENABLE_LCPLAYER_FADEIN_FADEOUT media_player_fade_in(s_media_info.player, 60); #endif media_player_play(s_media_info.player); break; } case AEM_MEDIA_TYPE_BT_MUSIC: { init_param.sample_rate = bt_manager_a2dp_get_sample_rate(BTSRV_DEVICE_PHONE); init_param.support_tws = 1; init_param.dumpable = 1; init_param.dsp_output = 1; if (audio_policy_get_out_audio_mode(init_param.stream_type) == AUDIO_MODE_STEREO) { init_param.channels = 2; } else { init_param.channels = 1; } s_media_info.player = media_player_open(&init_param); if (!s_media_info.player) { aem_adapter_media_stop(); os_mutex_unlock(&aem_media_lock); send_error_event(); return -1; } bt_manager_set_codec(bt_manager_a2dp_get_codecid(BTSRV_DEVICE_PHONE)); bt_manager_set_stream(STREAM_TYPE_A2DP, init_param.input_stream); #ifdef CONFIG_BT_AVRCP bt_manager_avrcp_sync_vol_to_remote(audio_system_get_stream_volume(AUDIO_STREAM_MUSIC)); #endif #if ENABLE_LCPLAYER_FADEIN_FADEOUT media_player_fade_in(s_media_info.player, 60); #endif media_player_play(s_media_info.player); break; } case AEM_MEDIA_TYPE_BT_CALL: { #ifdef CONFIG_PLAYTTS if (s_media_info.tts_lock == 0) { tts_manager_lock(); s_media_info.tts_lock = 1; } #endif init_param.format = param_format; init_param.sample_rate = bt_manager_sco_get_sample_rate(); init_param.capture_format = param_format; init_param.capture_bit_rate = (param_format == MSBC_TYPE) ? 26 : 0; init_param.capture_sample_rate_input = 16; init_param.capture_sample_rate_output = 16; init_param.dumpable = true; init_param.dsp_output = 1; if (audio_policy_get_out_audio_mode(init_param.stream_type) == AUDIO_MODE_STEREO) { init_param.channels = 2; } else { init_param.channels = 1; } if (audio_policy_get_record_audio_mode(init_param.stream_type) == AUDIO_MODE_STEREO) { init_param.capture_channels_input = 2; } else { init_param.capture_channels_input = 1; } s_media_info.player = media_player_open(&init_param); if (!s_media_info.player) { aem_adapter_media_stop(); os_mutex_unlock(&aem_media_lock); send_error_event(); return -1; } #if ENABLE_LCPLAYER_FADEIN_FADEOUT media_player_fade_in(s_media_info.player, 60); #endif bt_manager_set_stream(STREAM_TYPE_SCO, s_media_info.input_stream); media_player_play(s_media_info.player); #ifdef CONFIG_BT_HFP_HF bt_manager_hfp_sync_vol_to_remote(audio_system_get_stream_volume(AUDIO_STREAM_VOICE)); media_player_set_hfp_connected(s_media_info.player, true); #endif break; } default: break; } os_mutex_unlock(&aem_media_lock); return ret; } void aem_adapter_media_stop(void) { AEM_LOG_I("aem_adapter_media_stop \n"); if (AEM_MEDIA_STATE_CLOSE == s_media_info.state) { return; } os_mutex_lock(&aem_media_lock, OS_FOREVER); if (s_media_info.player == NULL) { os_mutex_unlock(&aem_media_lock); return; } #if ENABLE_LCPLAYER_FADEIN_FADEOUT media_player_fade_out(s_media_info.player, 60); os_sleep(60); #endif #ifdef CONFIG_BT_TRANSMIT bt_transmit_catpure_stop(); #endif /** reserve time to fade out*/ if (AEM_MEDIA_TYPE_BT_CALL == s_media_info.type) { bt_manager_set_stream(STREAM_TYPE_SCO, NULL); media_player_set_hfp_connected(s_media_info.player, false); } else if (AEM_MEDIA_TYPE_BT_MUSIC == s_media_info.type) { /** reserve time to fade out*/ bt_manager_set_stream(STREAM_TYPE_A2DP, NULL); } if (s_media_info.tts_lock == 1) { tts_manager_unlock(); s_media_info.tts_lock = 0; } if (s_media_info.player) { media_player_pause(s_media_info.player); media_player_stop(s_media_info.player); media_player_close(s_media_info.player); s_media_info.player = NULL; } if (s_media_info.input_stream) { stream_close(s_media_info.input_stream); stream_destroy(s_media_info.input_stream); s_media_info.input_stream = NULL; } if (s_media_info.output_stream) { stream_close(s_media_info.output_stream); stream_destroy(s_media_info.output_stream); s_media_info.output_stream = NULL; } if (s_media_info.capture_input_stream) { stream_close(s_media_info.capture_input_stream); stream_destroy(s_media_info.capture_input_stream); s_media_info.capture_input_stream = NULL; } if (s_media_info.capture_output_stream) { stream_close(s_media_info.capture_output_stream); stream_destroy(s_media_info.capture_output_stream); s_media_info.capture_output_stream = NULL; } s_media_info.state = AEM_MEDIA_STATE_CLOSE; s_media_info.type = AEM_MEDIA_TYPE_NONE; os_mutex_unlock(&aem_media_lock); } int aem_adapter_media_time_offset(void) { int time = 0; if (s_media_info.player && s_media_info.state == AEM_MEDIA_STATE_PLAY) { media_player_get_breakpoint(s_media_info.player, &s_media_info.bp); time = s_media_info.bp.time_offset; } AEM_LOG_I("aem_adapter_media_time_offset=%d \n", time); return time; } aem_media_state_e aem_adapter_media_get_state(void) { return s_media_info.state; } aem_media_type_e aem_adapter_media_get_type(void) { return s_media_info.type; } aem_media_info_t *aem_adapter_media_info(void) { memset(&s_media_info.info, 0, sizeof(aem_media_info_t)); if (media_player_get_mediainfo(s_media_info.player, (media_info_t *)&s_media_info.info)) { AEM_LOG_E("get media info failed\n"); return &s_media_info.info; } if (s_media_info.info.total_time < 0) { AEM_LOG_E("media info invalid\n"); s_media_info.info.total_time = 0; return &s_media_info.info; } AEM_LOG_I("total_time=%d, sample_rate=%d,\ channels=%d, avg_bitrate=%d\n", s_media_info.info.total_time, s_media_info.info.sample_rate, s_media_info.info.channels, s_media_info.info.avg_bitrate); return &s_media_info.info; } void aem_adapter_media_set_volume(aem_media_type_e type, int volume) { if (s_media_info.player && s_media_info.type == type) { media_player_set_volume(s_media_info.player, volume, volume); } } void aem_adapter_media_register_cb(aem_media_event_cb event_cb) { media_player_set_lifecycle_notifier(media_event_cb); for (size_t i = 0; i < AEM_MEDIA_EVENT_CNT; i++) { if (s_media_info.event_cb[i] == NULL) { s_media_info.event_cb[i] = event_cb; return; } } } /** * @Description : 匹配音乐文件,通过文件后缀匹配 * @Param : url:音乐文件完整路径 * @Param : match_str:需要匹配的文件后缀 * @Return : true:匹配成功,false:匹配失败 **/ static int match_file_suffix(const char *url, uint8_t *match_str) { int i; uint32_t str_len, cmp_len; uint8_t *src_str = (uint8_t *)url; if (*src_str == '\0') { return false; } str_len = strlen(url); cmp_len = strlen(match_str); if (str_len < cmp_len) { return false; } for (i = 0; i < cmp_len; i++) { if (toupper(match_str[i]) != toupper(src_str[str_len - cmp_len + i])) { break; } } if (i == cmp_len) { return true; } return false; } /** * @Description : 获取音乐文件类型 * @Param : path:音乐文件完整路径 * @Return : 音乐文件类型 **/ uint8_t aem_adapter_get_file_type(const char *path) { #ifdef CONFIG_DECODER_M4A if (match_file_suffix(path, ".aac") || match_file_suffix(path, ".m4a")) return M4A_TYPE; #endif #ifdef CONFIG_DECODER_WAV if (match_file_suffix(path, ".wav")) return WAV_TYPE; #endif #ifdef CONFIG_DECODER_MP3 if (match_file_suffix(path, ".mp3") || match_file_suffix(path, ".mp2") || match_file_suffix(path, ".mp1")) return MP3_TYPE; #endif #ifdef CONFIG_DECODER_APE if (match_file_suffix(path, ".ape")) return APE_TYPE; #endif #ifdef CONFIG_DECODER_WMA if (match_file_suffix(path, ".wma")) return WMA_TYPE; #endif #ifdef CONFIG_DECODER_FLAC if (match_file_suffix(path, ".flac") || match_file_suffix(path, ".fla")) return FLA_TYPE; #endif return UNSUPPORT_TYPE; }