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