a2dp_aac_encoder.cc revision 3b8f12614fd2a97332104230cb98a4c13bda93c7
1d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov/* 2d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * Copyright (C) 2016 The Android Open Source Project 3d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * 4d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * Licensed under the Apache License, Version 2.0 (the "License"); 5d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * you may not use this file except in compliance with the License. 6d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * You may obtain a copy of the License at 7d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * 8d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * http://www.apache.org/licenses/LICENSE-2.0 9d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * 10d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * Unless required by applicable law or agreed to in writing, software 11d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * distributed under the License is distributed on an "AS IS" BASIS, 12d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * See the License for the specific language governing permissions and 14d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * limitations under the License. 15d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov */ 16d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 17d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#define LOG_TAG "a2dp_aac_encoder" 18d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 19d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include "a2dp_aac_encoder.h" 20d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 21d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include <inttypes.h> 22d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include <stdio.h> 23d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include <string.h> 24d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 25d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include <aacenc_lib.h> 26d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include <base/logging.h> 27d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 28d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include "a2dp_aac.h" 29d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include "bt_common.h" 30d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include "osi/include/log.h" 31d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#include "osi/include/osi.h" 32d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 33d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// 34d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// Encoder for AAC Source Codec 35d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// 36d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 37d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#define STATS_UPDATE_MAX(current_value_storage, new_value) \ 38d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov do { \ 39d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if ((new_value) > (current_value_storage)) \ 40d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov (current_value_storage) = (new_value); \ 41d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } while (0) 42d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 43d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// A2DP AAC encoder interval in milliseconds 44d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#define A2DP_AAC_ENCODER_INTERVAL_MS 20 45d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 46d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// offset 47d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE) 48d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#define A2DP_AAC_OFFSET (AVDT_MEDIA_OFFSET + 1) 49d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#else 50d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#define A2DP_AAC_OFFSET AVDT_MEDIA_OFFSET 51d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#endif 52d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 53d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovtypedef struct { 54d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t sample_rate; 55d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t channel_mode; 56d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t bits_per_sample; 57d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t frame_length; // Samples per channel in a frame 58d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t input_channels_n; // Number of channels 59d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int max_encoded_buffer_bytes; // Max encoded bytes per frame 60d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} tA2DP_AAC_ENCODER_PARAMS; 61d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 62d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovtypedef struct { 63d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t counter; 64d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t bytes_per_tick; /* pcm bytes read each media task tick */ 65d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint64_t last_frame_us; 66d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} tA2DP_AAC_FEEDING_STATE; 67d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 68d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovtypedef struct { 69d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint64_t session_start_us; 70d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 71d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov size_t media_read_total_expected_packets; 72d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov size_t media_read_total_expected_reads_count; 73d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov size_t media_read_total_expected_read_bytes; 74d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 75d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov size_t media_read_total_dropped_packets; 76d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov size_t media_read_total_actual_reads_count; 77d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov size_t media_read_total_actual_read_bytes; 78d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} a2dp_aac_encoder_stats_t; 79d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 80d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovtypedef struct { 81d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_source_read_callback_t read_callback; 82d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_source_enqueue_callback_t enqueue_callback; 83d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint16_t TxAaMtuSize; 84d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 85d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool use_SCMS_T; 86d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool is_peer_edr; // True if the peer device supports EDR 87d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool peer_supports_3mbps; // True if the peer device supports 3Mbps EDR 88d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint16_t peer_mtu; // MTU of the A2DP peer 89d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t timestamp; // Timestamp for the A2DP frames 90d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 91d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov HANDLE_AACENCODER aac_handle; 92d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool has_aac_handle; // True if aac_handle is valid 93d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 94d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_FEEDING_PARAMS feeding_params; 95d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_AAC_ENCODER_PARAMS aac_encoder_params; 96d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_AAC_FEEDING_STATE aac_feeding_state; 97d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 98d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_stats_t stats; 99d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} tA2DP_AAC_ENCODER_CB; 100d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 101d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic tA2DP_AAC_ENCODER_CB a2dp_aac_encoder_cb; 102d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 103d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic void a2dp_aac_encoder_update(uint16_t peer_mtu, 104d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov A2dpCodecConfig* a2dp_codec_config, 105d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool* p_restart_input, 106d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool* p_restart_output, 107d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool* p_config_updated); 108d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations, 109d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t* num_of_frames, 110d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint64_t timestamp_us); 111d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic void a2dp_aac_encode_frames(uint8_t nb_frame); 112d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic bool a2dp_aac_read_feeding(uint8_t* read_buffer); 113d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 114d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovbool A2DP_LoadEncoderAac(void) { 115d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Nothing to do - the library is statically linked 116d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return true; 117d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 118d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 119d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid A2DP_UnloadEncoderAac(void) { 120d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Nothing to do - the library is statically linked 121d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_encoder_cb.has_aac_handle) 122d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aacEncClose(&a2dp_aac_encoder_cb.aac_handle); 123d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov memset(&a2dp_aac_encoder_cb, 0, sizeof(a2dp_aac_encoder_cb)); 124d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 125d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 126d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_encoder_init(const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, 127d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov A2dpCodecConfig* a2dp_codec_config, 128d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_source_read_callback_t read_callback, 129d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_source_enqueue_callback_t enqueue_callback) { 130d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_encoder_cb.has_aac_handle) 131d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aacEncClose(&a2dp_aac_encoder_cb.aac_handle); 132d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov memset(&a2dp_aac_encoder_cb, 0, sizeof(a2dp_aac_encoder_cb)); 133d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 134d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.stats.session_start_us = time_get_os_boottime_us(); 135d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 136d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.read_callback = read_callback; 137d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.enqueue_callback = enqueue_callback; 138d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.is_peer_edr = p_peer_params->is_peer_edr; 139d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.peer_supports_3mbps = p_peer_params->peer_supports_3mbps; 140d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.peer_mtu = p_peer_params->peer_mtu; 141d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.timestamp = 0; 142d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 143d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.use_SCMS_T = false; // TODO: should be a parameter 144d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE) 145d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.use_SCMS_T = true; 146d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov#endif 147d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 148d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // NOTE: Ignore the restart_input / restart_output flags - this initization 149d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // happens when the connection is (re)started. 150d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool restart_input = false; 151d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool restart_output = false; 152d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool config_updated = false; 153d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_update(a2dp_aac_encoder_cb.peer_mtu, a2dp_codec_config, 154d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov &restart_input, &restart_output, &config_updated); 155d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 156d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 157d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovbool A2dpCodecConfigAac::updateEncoderUserConfig( 158d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, bool* p_restart_input, 159d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool* p_restart_output, bool* p_config_updated) { 160d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.is_peer_edr = p_peer_params->is_peer_edr; 161d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.peer_supports_3mbps = p_peer_params->peer_supports_3mbps; 162d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.peer_mtu = p_peer_params->peer_mtu; 163d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.timestamp = 0; 164d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 165d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_encoder_cb.peer_mtu == 0) { 166d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 167d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot update the codec encoder for %s: " 168d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "invalid peer MTU", 169d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, name().c_str()); 170d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return false; 171d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 172d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 173d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_update(a2dp_aac_encoder_cb.peer_mtu, this, p_restart_input, 174d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_restart_output, p_config_updated); 175d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return true; 176d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 177d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 178d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// Update the A2DP AAC encoder. 179d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// |peer_mtu| is the peer MTU. 180d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// |a2dp_codec_config| is the A2DP codec to use for the update. 181d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic void a2dp_aac_encoder_update(uint16_t peer_mtu, 182d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov A2dpCodecConfig* a2dp_codec_config, 183d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool* p_restart_input, 184d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool* p_restart_output, 185d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov bool* p_config_updated) { 186d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_AAC_ENCODER_PARAMS* p_encoder_params = 187d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov &a2dp_aac_encoder_cb.aac_encoder_params; 188d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t codec_info[AVDT_CODEC_SIZE]; 189d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_ERROR aac_error; 1903b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato int aac_param_value, aac_sampling_freq, aac_bit_rate; 191d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 192d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *p_restart_input = false; 193d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *p_restart_output = false; 194d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *p_config_updated = false; 195d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 196d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (!a2dp_aac_encoder_cb.has_aac_handle) { 197d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_ERROR aac_error = aacEncOpen(&a2dp_aac_encoder_cb.aac_handle, 0, 198d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 2 /* max 2 channels: stereo */); 199d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 200d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: Cannot open AAC encoder handle: AAC error 0x%x", 201d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_error); 202d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 203d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 204d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.has_aac_handle = true; 205d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 206d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 207d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (!a2dp_codec_config->copyOutOtaCodecConfig(codec_info)) { 208d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 209d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot update the codec encoder for %s: " 210d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "invalid codec config", 211d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, a2dp_codec_config->name().c_str()); 212d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; 213d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 214d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov const uint8_t* p_codec_info = codec_info; 215d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 216d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // The feeding parameters 217d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_FEEDING_PARAMS* p_feeding_params = &a2dp_aac_encoder_cb.feeding_params; 218d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->sample_rate = A2DP_GetTrackSampleRateAac(p_codec_info); 219d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->bits_per_sample = 220d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_codec_config->getAudioBitsPerSample(); 221d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->channel_count = A2DP_GetTrackChannelCountAac(p_codec_info); 222d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: sample_rate=%u bits_per_sample=%u channel_count=%u", 223d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, p_feeding_params->sample_rate, 224d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->bits_per_sample, p_feeding_params->channel_count); 225d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 226d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // The codec parameters 227d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->sample_rate = 228d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.sample_rate; 229d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->channel_mode = A2DP_GetChannelModeCodeAac(p_codec_info); 230d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 231d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint16_t mtu_size = BT_DEFAULT_BUFFER_SIZE - A2DP_AAC_OFFSET - sizeof(BT_HDR); 232d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (mtu_size < peer_mtu) { 233d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.TxAaMtuSize = mtu_size; 234d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } else { 235d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.TxAaMtuSize = peer_mtu; 236d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 237d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 238d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: MTU=%d, peer_mtu=%d", __func__, 239d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.TxAaMtuSize, peer_mtu); 240d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: sample_rate: %d channel_mode: %d ", __func__, 241d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->sample_rate, p_encoder_params->channel_mode); 242d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 243d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Audio Object Type - MANDATORY 244d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // A2DP_AAC_OBJECT_TYPE_MPEG2_LC -> AOT_AAC_LC 245d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // A2DP_AAC_OBJECT_TYPE_MPEG4_LC -> AOT_AAC_LC 246d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // A2DP_AAC_OBJECT_TYPE_MPEG4_LTP -> AOT_AAC_LTP 247d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE -> AOT_AAC_SCAL 248d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_LC; 249d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int object_type = A2DP_GetObjectTypeCodeAac(p_codec_info); 250d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov switch (object_type) { 251d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov case A2DP_AAC_OBJECT_TYPE_MPEG2_LC: 252d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_LC; 253d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov break; 254d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov case A2DP_AAC_OBJECT_TYPE_MPEG4_LC: 255d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_LC; 256d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov break; 257d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP: 258d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_LTP; 259d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov break; 260d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE: 261d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_SCAL; 262d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov break; 263d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov default: 264d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 265d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_AOT: " 266d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "invalid object type %d", 267d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, object_type); 268d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 269d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 270d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_AOT, 271d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value); 272d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 273d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 274d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_AOT to %d: " 275d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 276d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 277d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 278d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 279d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 2803b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Set the encoder's parameters: audioMuxVersion 2813b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_param_value = 1; // audioMuxVersion = 1 2823b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 2833b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato AACENC_AUDIOMUXVER, aac_param_value); 2843b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato if (aac_error != AACENC_OK) { 285d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 2863b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_AUDIOMUXVER to %d: " 2873b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "AAC error 0x%x", 2883b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato __func__, aac_param_value, aac_error); 289d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 290d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 2913b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato 2923b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Set the encoder's parameters: Signaling mode of the extension AOT 2933b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_param_value = 1; // Signaling mode of the extension AOT = 1 294d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 2953b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato AACENC_SIGNALING_MODE, aac_param_value); 296d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 297d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 2983b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_SIGNALING_MODE to %d: " 299d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 300d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 301d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 302d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 303d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 304d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Sample Rate - MANDATORY 305d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = A2DP_GetTrackSampleRateAac(p_codec_info); 306d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 307d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_SAMPLERATE, aac_param_value); 308d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 309d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 310d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_SAMPLERATE to %d: " 311d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 312d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 313d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 314d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 3153b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_sampling_freq = aac_param_value; // Save for extra usage below 3163b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato 3173b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Set the encoder's parameters: Bit Rate - MANDATORY 3183b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_param_value = A2DP_GetBitRateAac(p_codec_info); 3193b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Calculate the bit rate from MTU and sampling frequency 3203b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_bit_rate = 3213b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato A2DP_ComputeMaxBitRateAac(p_codec_info, a2dp_aac_encoder_cb.TxAaMtuSize); 3223b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_bit_rate = std::min(aac_param_value, aac_bit_rate); 3233b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato LOG_DEBUG(LOG_TAG, "%s: MTU = %d Sampling Frequency = %d Bit Rate = %d", 3243b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato __func__, a2dp_aac_encoder_cb.TxAaMtuSize, aac_sampling_freq, 3253b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_bit_rate); 3263b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato if (aac_bit_rate == -1) { 3273b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato LOG_ERROR(LOG_TAG, 3283b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_BITRATE: " 3293b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "invalid codec bit rate", 3303b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato __func__); 3313b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato return; // TODO: Return an error? 3323b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato } 3333b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 3343b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato AACENC_BITRATE, aac_bit_rate); 3353b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato if (aac_error != AACENC_OK) { 3363b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato LOG_ERROR(LOG_TAG, 3373b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_BITRATE to %d: " 3383b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "AAC error 0x%x", 3393b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato __func__, aac_bit_rate, aac_error); 3403b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato return; // TODO: Return an error? 3413b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato } 3423b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato 3433b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Set the encoder's parameters: PEAK Bit Rate 3443b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 3453b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato AACENC_PEAK_BITRATE, aac_bit_rate); 3463b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato if (aac_error != AACENC_OK) { 3473b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato LOG_ERROR(LOG_TAG, 3483b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_PEAK_BITRATE to %d: " 3493b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "AAC error 0x%x", 3503b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato __func__, aac_bit_rate, aac_error); 3513b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato return; // TODO: Return an error? 3523b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato } 353d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 354d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Channel Mode - MANDATORY 355d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (A2DP_GetTrackChannelCountAac(p_codec_info) == 1) { 356d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = MODE_1; // Mono 357d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } else { 358d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = MODE_2; // Stereo 359d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 360d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 361d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_CHANNELMODE, aac_param_value); 362d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 363d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 364d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_CHANNELMODE to %d: " 365d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 366d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 367d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 368d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 369d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 370d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Transport Type 371d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = TT_MP4_LATM_MCP1; // muxConfigPresent = 1 372d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 373d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_TRANSMUX, aac_param_value); 374d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 375d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 376d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_TRANSMUX to %d: " 377d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 378d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 379d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 380d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 381d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 382d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Header Period 383d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = 1; 384d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 385d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_HEADER_PERIOD, aac_param_value); 386d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 387d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 388d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_HEADER_PERIOD to %d: " 389d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 390d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 391d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 392d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 393d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 394d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Variable Bit Rate Support 395d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = A2DP_GetVariableBitRateSupportAac(p_codec_info); 396d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_param_value == -1) { 397d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 398d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_BITRATEMODE: " 399d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "invalid codec bit rate mode", 400d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__); 401d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 402d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 403d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 404d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_BITRATEMODE, aac_param_value); 405d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 406d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 407d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_BITRATEMODE to %d: " 408d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 409d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 410d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 411d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 412d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 413d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Mark the end of setting the encoder's parameters 414d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = 415d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aacEncEncode(a2dp_aac_encoder_cb.aac_handle, NULL, NULL, NULL, NULL); 416d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 417d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 418d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot complete setting the AAC parameters: AAC error 0x%x", 419d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_error); 420d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 421d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 422d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 423d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Retrieve the encoder info so we can save the frame length 424d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_InfoStruct aac_info; 425d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncInfo(a2dp_aac_encoder_cb.aac_handle, &aac_info); 426d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 427d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 428d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot retrieve the AAC encoder info: AAC error 0x%x", 429d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_error); 430d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 431d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 432d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->frame_length = aac_info.frameLength; 433d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->input_channels_n = aac_info.inputChannels; 434d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->max_encoded_buffer_bytes = aac_info.maxOutBufBytes; 435d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, 436d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: AAC frame_length = %u input_channels_n = %u " 437d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "max_encoded_buffer_bytes = %d", 438d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, p_encoder_params->frame_length, 439d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->input_channels_n, 440d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->max_encoded_buffer_bytes); 441d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 442d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 443d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_encoder_cleanup(void) { 444d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_encoder_cb.has_aac_handle) 445d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aacEncClose(&a2dp_aac_encoder_cb.aac_handle); 446d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov memset(&a2dp_aac_encoder_cb, 0, sizeof(a2dp_aac_encoder_cb)); 447d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 448d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 449d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_feeding_reset(void) { 450d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* By default, just clear the entire state */ 451d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov memset(&a2dp_aac_encoder_cb.aac_feeding_state, 0, 452d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov sizeof(a2dp_aac_encoder_cb.aac_feeding_state)); 453d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 454d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick = 455d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov (a2dp_aac_encoder_cb.feeding_params.sample_rate * 456d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8 * 457d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.channel_count * 458d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov A2DP_AAC_ENCODER_INTERVAL_MS) / 459d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 1000; 460d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 461d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: PCM bytes per tick %u", __func__, 462d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick); 463d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 464d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 465d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_feeding_flush(void) { 466d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.counter = 0; 467d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 468d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 469d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovperiod_ms_t a2dp_aac_get_encoder_interval_ms(void) { 470d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return A2DP_AAC_ENCODER_INTERVAL_MS; 471d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 472d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 473d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_send_frames(uint64_t timestamp_us) { 474d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t nb_frame = 0; 475d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t nb_iterations = 0; 476d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 477d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_get_num_frame_iteration(&nb_iterations, &nb_frame, timestamp_us); 478d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: Sending %d frames per iteration, %d iterations", 479d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, nb_frame, nb_iterations); 480d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (nb_frame == 0) return; 481d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 482d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov for (uint8_t counter = 0; counter < nb_iterations; counter++) { 483d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Transcode frame and enqueue 484d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encode_frames(nb_frame); 485d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 486d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 487d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 488d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// Obtains the number of frames to send and number of iterations 489d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// to be used. |num_of_iterations| and |num_of_frames| parameters 490d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// are used as output param for returning the respective values. 491d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations, 492d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t* num_of_frames, 493d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint64_t timestamp_us) { 494d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t result = 0; 495d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t nof = 0; 496d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t noi = 1; 497d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 498d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t pcm_bytes_per_frame = 499d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_encoder_params.frame_length * 500d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.channel_count * 501d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8; 502d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: pcm_bytes_per_frame %u", __func__, 503d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov pcm_bytes_per_frame); 504d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 505d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t us_this_tick = A2DP_AAC_ENCODER_INTERVAL_MS * 1000; 506d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint64_t now_us = timestamp_us; 507d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us != 0) 508d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov us_this_tick = 509d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov (now_us - a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us); 510d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us = now_us; 511d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 512d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.counter += 513d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick * us_this_tick / 514d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov (A2DP_AAC_ENCODER_INTERVAL_MS * 1000); 515d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 516d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov result = a2dp_aac_encoder_cb.aac_feeding_state.counter / pcm_bytes_per_frame; 517d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.counter -= result * pcm_bytes_per_frame; 518d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nof = result; 519d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 520d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: effective num of frames %u, iterations %u", 521d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, nof, noi); 522d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 523d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *num_of_frames = nof; 524d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *num_of_iterations = noi; 525d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 526d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 527d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic void a2dp_aac_encode_frames(uint8_t nb_frame) { 528d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_AAC_ENCODER_PARAMS* p_encoder_params = 529d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov &a2dp_aac_encoder_cb.aac_encoder_params; 530d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_FEEDING_PARAMS* p_feeding_params = &a2dp_aac_encoder_cb.feeding_params; 531d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t remain_nb_frame = nb_frame; 532d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t read_buffer[BT_DEFAULT_BUFFER_SIZE]; 533d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int pcm_bytes_per_frame = p_encoder_params->frame_length * 534d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->channel_count * 535d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->bits_per_sample / 8; 536d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov CHECK(pcm_bytes_per_frame <= static_cast<int>(sizeof(read_buffer))); 537d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 538d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Setup the input buffer 539d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_BufDesc in_buf_desc; 540d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov void* in_buf_vector[1] = {nullptr}; 541d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int in_buf_identifiers[1] = {IN_AUDIO_DATA}; 542d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int in_buf_sizes[1] = {pcm_bytes_per_frame}; 543d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int in_buf_element_sizes[1] = {p_feeding_params->bits_per_sample / 8}; 544d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.numBufs = 1; 545d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.bufs = in_buf_vector; 546d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.bufferIdentifiers = in_buf_identifiers; 547d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.bufSizes = in_buf_sizes; 548d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.bufElSizes = in_buf_element_sizes; 549d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 550d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Setup the output buffer (partially) 551d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_BufDesc out_buf_desc; 552d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov void* out_buf_vector[1] = {nullptr}; 553d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int out_buf_identifiers[1] = {OUT_BITSTREAM_DATA}; 554d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int out_buf_sizes[1] = {p_encoder_params->max_encoded_buffer_bytes}; 555d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // NOTE: out_buf_element_sizes below is probably unused by the encoder 556d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int out_buf_element_sizes[1] = {p_feeding_params->bits_per_sample / 8}; 557d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.numBufs = 1; 558d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.bufs = out_buf_vector; 559d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.bufferIdentifiers = out_buf_identifiers; 560d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.bufSizes = out_buf_sizes; 561d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.bufElSizes = out_buf_element_sizes; 562d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov CHECK(p_encoder_params->max_encoded_buffer_bytes <= 563d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov static_cast<int>(BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR))); 564d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 565d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_InArgs aac_in_args; 566d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_in_args.numInSamples = 567d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->frame_length * p_feeding_params->channel_count; 568d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_in_args.numAncBytes = 0; 569d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 570d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_OutArgs aac_out_args = { 571d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov .numOutBytes = 0, .numInSamples = 0, .numAncBytes = 0}; 572d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 573d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t count; 574d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int written = 0; 575d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 576d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov while (nb_frame) { 577d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov BT_HDR* p_buf = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE); 578d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 579d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* Init buffer */ 580d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->offset = A2DP_AAC_OFFSET; 581d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->len = 0; 582d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->layer_specific = 0; 583d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 584d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov count = 0; 585d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov do { 586d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* Read PCM data */ 587d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_read_feeding(read_buffer)) { 588d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t* packet = (uint8_t*)(p_buf + 1) + p_buf->offset + p_buf->len; 589d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (!a2dp_aac_encoder_cb.has_aac_handle) { 590d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: invalid AAC handle", __func__); 591d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov osi_free(p_buf); 592d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; 593d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 594d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_vector[0] = read_buffer; 595d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_vector[0] = packet + count; 596d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_ERROR aac_error = 597d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aacEncEncode(a2dp_aac_encoder_cb.aac_handle, &in_buf_desc, 598d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov &out_buf_desc, &aac_in_args, &aac_out_args); 599d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 600d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: AAC encoding error: 0x%x", __func__, 601d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error); 602d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov osi_free(p_buf); 603d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; 604d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 605d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov written = aac_out_args.numOutBytes; 606d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov count += written; 607d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->len += written; 608d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nb_frame--; 609d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->layer_specific++; // added a frame to the buffer 610d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } else { 611d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_WARN(LOG_TAG, "%s: underflow %d", __func__, nb_frame); 612d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.counter += 613d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nb_frame * p_encoder_params->frame_length * 614d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->channel_count * 615d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->bits_per_sample / 8; 616d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 617d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // no more pcm to read 618d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nb_frame = 0; 619d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 620d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } while ((written == 0) && nb_frame); 621d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 622d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // NOTE: We don't check whether the packet will fit in the MTU, 623d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // because AAC doesn't give us control over the encoded frame size. 624d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // If the packet is larger than the MTU, it will be fragmented before 625d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // transmission. 626d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (p_buf->len) { 627d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* 628d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * Timestamp of the media packet header represent the TS of the 629d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * first frame, i.e the timestamp before including this frame. 630d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov */ 631d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *((uint32_t*)(p_buf + 1)) = a2dp_aac_encoder_cb.timestamp; 632d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 633d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.timestamp += 634d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->layer_specific * p_encoder_params->frame_length; 635d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 636d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t done_nb_frame = remain_nb_frame - nb_frame; 637d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov remain_nb_frame = nb_frame; 638d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (!a2dp_aac_encoder_cb.enqueue_callback(p_buf, done_nb_frame)) return; 639d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } else { 640d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov osi_free(p_buf); 641d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 642d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 643d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 644d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 645d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic bool a2dp_aac_read_feeding(uint8_t* read_buffer) { 646d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t read_size = a2dp_aac_encoder_cb.aac_encoder_params.frame_length * 647d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.channel_count * 648d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8; 649d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 650d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* Read Data from UIPC channel */ 651d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t nb_byte_read = 652d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.read_callback(read_buffer, read_size); 653d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 654d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (nb_byte_read < read_size) { 655d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (nb_byte_read == 0) return false; 656d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 657d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* Fill the unfilled part of the read buffer with silence (0) */ 658d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov memset(((uint8_t*)read_buffer) + nb_byte_read, 0, read_size - nb_byte_read); 659d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nb_byte_read = read_size; 660d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 661d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return true; 662d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 663d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 664d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_debug_codec_dump(int fd) { 665d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_stats_t* stats = &a2dp_aac_encoder_cb.stats; 666d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 667d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov dprintf(fd, "\nA2DP AAC State:\n"); 668d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 669d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov dprintf(fd, 670d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov " Packets expected/dropped : %zu / " 671d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%zu\n", 672d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_expected_packets, 673d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_dropped_packets); 674d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 675d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov dprintf(fd, 676d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov " PCM reads count expected/actual : %zu / " 677d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%zu\n", 678d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_expected_reads_count, 679d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_actual_reads_count); 680d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 681d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov dprintf(fd, 682d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov " PCM read bytes expected/actual : %zu / " 683d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%zu\n", 684d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_expected_read_bytes, 685d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_actual_read_bytes); 686d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 687