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 407cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov/* 417cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov * 2DH5 payload size of: 427cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov * 679 bytes - (4 bytes L2CAP Header + 12 bytes AVDTP Header) 437cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov */ 447cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov#define MAX_2MBPS_AVDTP_MTU 663 457cff5f55bf30f305291c0827482f03f0b52fb990Pavlin 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; 19007ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov int aac_param_value, aac_sampling_freq, aac_peak_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 2317cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: original AVDTP MTU size: %d", __func__, 2327cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov a2dp_aac_encoder_cb.TxAaMtuSize); 2337cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov if (a2dp_aac_encoder_cb.is_peer_edr && 2347cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov !a2dp_aac_encoder_cb.peer_supports_3mbps) { 2357cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov // This condition would be satisfied only if the remote device is 2367cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov // EDR and supports only 2 Mbps, but the effective AVDTP MTU size 2377cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov // exceeds the 2DH5 packet size. 2387cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, 2397cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov "%s: The remote device is EDR but does not support 3 Mbps", 2407cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov __func__); 2417cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov if (peer_mtu > MAX_2MBPS_AVDTP_MTU) { 2427cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov LOG_WARN(LOG_TAG, "%s: Restricting AVDTP MTU size from %d to %d", 2437cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov __func__, peer_mtu, MAX_2MBPS_AVDTP_MTU); 2447cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov peer_mtu = MAX_2MBPS_AVDTP_MTU; 2457cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov } 2467cff5f55bf30f305291c0827482f03f0b52fb990Pavlin Radoslavov } 247d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint16_t mtu_size = BT_DEFAULT_BUFFER_SIZE - A2DP_AAC_OFFSET - sizeof(BT_HDR); 248d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (mtu_size < peer_mtu) { 249d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.TxAaMtuSize = mtu_size; 250d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } else { 251d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.TxAaMtuSize = peer_mtu; 252d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 253d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 254d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: MTU=%d, peer_mtu=%d", __func__, 255d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.TxAaMtuSize, peer_mtu); 256d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: sample_rate: %d channel_mode: %d ", __func__, 257d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->sample_rate, p_encoder_params->channel_mode); 258d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 259d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Audio Object Type - MANDATORY 260d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // A2DP_AAC_OBJECT_TYPE_MPEG2_LC -> AOT_AAC_LC 261d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // A2DP_AAC_OBJECT_TYPE_MPEG4_LC -> AOT_AAC_LC 262d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // A2DP_AAC_OBJECT_TYPE_MPEG4_LTP -> AOT_AAC_LTP 263d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE -> AOT_AAC_SCAL 264d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_LC; 265d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int object_type = A2DP_GetObjectTypeCodeAac(p_codec_info); 266d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov switch (object_type) { 267d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov case A2DP_AAC_OBJECT_TYPE_MPEG2_LC: 268d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_LC; 269d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov break; 270d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov case A2DP_AAC_OBJECT_TYPE_MPEG4_LC: 271d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_LC; 272d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov break; 273d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP: 274d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_LTP; 275d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov break; 276d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE: 277d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = AOT_AAC_SCAL; 278d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov break; 279d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov default: 280d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 281d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_AOT: " 282d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "invalid object type %d", 283d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, object_type); 284d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 285d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 286d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_AOT, 287d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value); 288d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 289d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 290d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_AOT to %d: " 291d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 292d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 293d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 294d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 295d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 2963b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Set the encoder's parameters: audioMuxVersion 2971ba312d994f30b27f6dccd75c437e7b63dbebf23Pavlin Radoslavov aac_param_value = 2; // audioMuxVersion = "2" 2983b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 2993b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato AACENC_AUDIOMUXVER, aac_param_value); 3003b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato if (aac_error != AACENC_OK) { 301d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 3023b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_AUDIOMUXVER to %d: " 3033b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "AAC error 0x%x", 3043b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato __func__, aac_param_value, aac_error); 305d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 306d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 3073b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato 3083b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Set the encoder's parameters: Signaling mode of the extension AOT 3093b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_param_value = 1; // Signaling mode of the extension AOT = 1 310d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 3113b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato AACENC_SIGNALING_MODE, aac_param_value); 312d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 313d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 3143b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_SIGNALING_MODE to %d: " 315d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 316d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 317d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 318d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 319d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 320d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Sample Rate - MANDATORY 321d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = A2DP_GetTrackSampleRateAac(p_codec_info); 322d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 323d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_SAMPLERATE, aac_param_value); 324d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 325d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 326d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_SAMPLERATE to %d: " 327d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 328d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 329d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 330d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 3313b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_sampling_freq = aac_param_value; // Save for extra usage below 3323b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato 3333b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Set the encoder's parameters: Bit Rate - MANDATORY 3343b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_param_value = A2DP_GetBitRateAac(p_codec_info); 3353b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Calculate the bit rate from MTU and sampling frequency 33607ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov aac_peak_bit_rate = 3373b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato A2DP_ComputeMaxBitRateAac(p_codec_info, a2dp_aac_encoder_cb.TxAaMtuSize); 33807ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov aac_param_value = std::min(aac_param_value, aac_peak_bit_rate); 3393b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato LOG_DEBUG(LOG_TAG, "%s: MTU = %d Sampling Frequency = %d Bit Rate = %d", 3403b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato __func__, a2dp_aac_encoder_cb.TxAaMtuSize, aac_sampling_freq, 34107ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov aac_param_value); 34207ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov if (aac_param_value == -1) { 3433b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato LOG_ERROR(LOG_TAG, 3443b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_BITRATE: " 3453b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "invalid codec bit rate", 3463b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato __func__); 3473b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato return; // TODO: Return an error? 3483b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato } 3493b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 35007ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov AACENC_BITRATE, aac_param_value); 3513b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato if (aac_error != AACENC_OK) { 3523b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato LOG_ERROR(LOG_TAG, 3533b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_BITRATE to %d: " 3543b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "AAC error 0x%x", 35507ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov __func__, aac_param_value, aac_error); 3563b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato return; // TODO: Return an error? 3573b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato } 3583b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato 3593b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato // Set the encoder's parameters: PEAK Bit Rate 3603b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 36107ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov AACENC_PEAK_BITRATE, aac_peak_bit_rate); 3623b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato if (aac_error != AACENC_OK) { 3633b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato LOG_ERROR(LOG_TAG, 3643b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "%s: Cannot set AAC parameter AACENC_PEAK_BITRATE to %d: " 3653b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato "AAC error 0x%x", 36607ceaa497006b51e463f82565e602210a6731275Pavlin Radoslavov __func__, aac_peak_bit_rate, aac_error); 3673b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato return; // TODO: Return an error? 3683b8f12614fd2a97332104230cb98a4c13bda93c7Kenmochi, Chisato } 369d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 370d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Channel Mode - MANDATORY 371d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (A2DP_GetTrackChannelCountAac(p_codec_info) == 1) { 372d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = MODE_1; // Mono 373d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } else { 374d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = MODE_2; // Stereo 375d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 376d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 377d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_CHANNELMODE, aac_param_value); 378d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 379d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 380d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_CHANNELMODE to %d: " 381d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 382d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 383d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 384d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 385d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 386d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Transport Type 387d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = TT_MP4_LATM_MCP1; // muxConfigPresent = 1 388d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 389d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_TRANSMUX, aac_param_value); 390d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 391d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 392d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_TRANSMUX to %d: " 393d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 394d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 395d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 396d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 397d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 398d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Header Period 399d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = 1; 400d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 401d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_HEADER_PERIOD, aac_param_value); 402d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 403d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 404d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_HEADER_PERIOD to %d: " 405d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 406d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 407d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 408d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 409d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 410d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Set the encoder's parameters: Variable Bit Rate Support 411d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_param_value = A2DP_GetVariableBitRateSupportAac(p_codec_info); 412d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_param_value == -1) { 413d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 414d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_BITRATEMODE: " 415d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "invalid codec bit rate mode", 416d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__); 417d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 418d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 419d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, 420d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_BITRATEMODE, aac_param_value); 421d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 422d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 423d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot set AAC parameter AACENC_BITRATEMODE to %d: " 424d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "AAC error 0x%x", 425d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_param_value, aac_error); 426d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 427d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 428d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 429d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Mark the end of setting the encoder's parameters 430d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = 431d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aacEncEncode(a2dp_aac_encoder_cb.aac_handle, NULL, NULL, NULL, NULL); 432d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 433d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 434d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot complete setting the AAC parameters: AAC error 0x%x", 435d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_error); 436d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 437d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 438d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 439d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Retrieve the encoder info so we can save the frame length 440d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_InfoStruct aac_info; 441d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error = aacEncInfo(a2dp_aac_encoder_cb.aac_handle, &aac_info); 442d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 443d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, 444d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: Cannot retrieve the AAC encoder info: AAC error 0x%x", 445d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, aac_error); 446d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; // TODO: Return an error? 447d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 448d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->frame_length = aac_info.frameLength; 449d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->input_channels_n = aac_info.inputChannels; 450d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->max_encoded_buffer_bytes = aac_info.maxOutBufBytes; 451d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, 452d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%s: AAC frame_length = %u input_channels_n = %u " 453d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "max_encoded_buffer_bytes = %d", 454d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, p_encoder_params->frame_length, 455d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->input_channels_n, 456d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->max_encoded_buffer_bytes); 457d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 458d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 459d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_encoder_cleanup(void) { 460d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_encoder_cb.has_aac_handle) 461d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aacEncClose(&a2dp_aac_encoder_cb.aac_handle); 462d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov memset(&a2dp_aac_encoder_cb, 0, sizeof(a2dp_aac_encoder_cb)); 463d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 464d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 465d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_feeding_reset(void) { 466d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* By default, just clear the entire state */ 467d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov memset(&a2dp_aac_encoder_cb.aac_feeding_state, 0, 468d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov sizeof(a2dp_aac_encoder_cb.aac_feeding_state)); 469d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 470d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick = 471d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov (a2dp_aac_encoder_cb.feeding_params.sample_rate * 472d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8 * 473d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.channel_count * 474d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov A2DP_AAC_ENCODER_INTERVAL_MS) / 475d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 1000; 476d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 477d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: PCM bytes per tick %u", __func__, 478d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick); 479d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 480d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 481d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_feeding_flush(void) { 482d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.counter = 0; 483d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 484d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 485d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovperiod_ms_t a2dp_aac_get_encoder_interval_ms(void) { 486d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return A2DP_AAC_ENCODER_INTERVAL_MS; 487d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 488d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 489d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovvoid a2dp_aac_send_frames(uint64_t timestamp_us) { 490d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t nb_frame = 0; 491d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t nb_iterations = 0; 492d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 493d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_get_num_frame_iteration(&nb_iterations, &nb_frame, timestamp_us); 494d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: Sending %d frames per iteration, %d iterations", 495d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, nb_frame, nb_iterations); 496d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (nb_frame == 0) return; 497d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 498d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov for (uint8_t counter = 0; counter < nb_iterations; counter++) { 499d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Transcode frame and enqueue 500d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encode_frames(nb_frame); 501d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 502d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 503d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 504d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// Obtains the number of frames to send and number of iterations 505d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// to be used. |num_of_iterations| and |num_of_frames| parameters 506d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov// are used as output param for returning the respective values. 507d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations, 508d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t* num_of_frames, 509d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint64_t timestamp_us) { 510d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t result = 0; 511d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t nof = 0; 512d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t noi = 1; 513d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 514d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t pcm_bytes_per_frame = 515d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_encoder_params.frame_length * 516d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.channel_count * 517d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8; 518d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: pcm_bytes_per_frame %u", __func__, 519d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov pcm_bytes_per_frame); 520d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 521d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t us_this_tick = A2DP_AAC_ENCODER_INTERVAL_MS * 1000; 522d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint64_t now_us = timestamp_us; 523d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us != 0) 524d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov us_this_tick = 525d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov (now_us - a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us); 526d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us = now_us; 527d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 528d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.counter += 529d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick * us_this_tick / 530d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov (A2DP_AAC_ENCODER_INTERVAL_MS * 1000); 531d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 532d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov result = a2dp_aac_encoder_cb.aac_feeding_state.counter / pcm_bytes_per_frame; 533d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.counter -= result * pcm_bytes_per_frame; 534d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nof = result; 535d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 536d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: effective num of frames %u, iterations %u", 537d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov __func__, nof, noi); 538d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 539d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *num_of_frames = nof; 540d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *num_of_iterations = noi; 541d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 542d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 543d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic void a2dp_aac_encode_frames(uint8_t nb_frame) { 544d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_AAC_ENCODER_PARAMS* p_encoder_params = 545d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov &a2dp_aac_encoder_cb.aac_encoder_params; 546d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov tA2DP_FEEDING_PARAMS* p_feeding_params = &a2dp_aac_encoder_cb.feeding_params; 547d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t remain_nb_frame = nb_frame; 548d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t read_buffer[BT_DEFAULT_BUFFER_SIZE]; 549d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int pcm_bytes_per_frame = p_encoder_params->frame_length * 550d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->channel_count * 551d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->bits_per_sample / 8; 552d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov CHECK(pcm_bytes_per_frame <= static_cast<int>(sizeof(read_buffer))); 553d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 554d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Setup the input buffer 555d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_BufDesc in_buf_desc; 556d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov void* in_buf_vector[1] = {nullptr}; 557d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int in_buf_identifiers[1] = {IN_AUDIO_DATA}; 558d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int in_buf_sizes[1] = {pcm_bytes_per_frame}; 559d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int in_buf_element_sizes[1] = {p_feeding_params->bits_per_sample / 8}; 560d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.numBufs = 1; 561d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.bufs = in_buf_vector; 562d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.bufferIdentifiers = in_buf_identifiers; 563d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.bufSizes = in_buf_sizes; 564d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_desc.bufElSizes = in_buf_element_sizes; 565d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 566d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // Setup the output buffer (partially) 567d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_BufDesc out_buf_desc; 568d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov void* out_buf_vector[1] = {nullptr}; 569d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int out_buf_identifiers[1] = {OUT_BITSTREAM_DATA}; 570d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int out_buf_sizes[1] = {p_encoder_params->max_encoded_buffer_bytes}; 571d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // NOTE: out_buf_element_sizes below is probably unused by the encoder 572d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int out_buf_element_sizes[1] = {p_feeding_params->bits_per_sample / 8}; 573d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.numBufs = 1; 574d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.bufs = out_buf_vector; 575d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.bufferIdentifiers = out_buf_identifiers; 576d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.bufSizes = out_buf_sizes; 577d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_desc.bufElSizes = out_buf_element_sizes; 578d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov CHECK(p_encoder_params->max_encoded_buffer_bytes <= 579d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov static_cast<int>(BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR))); 580d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 581d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_InArgs aac_in_args; 582d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_in_args.numInSamples = 583d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_encoder_params->frame_length * p_feeding_params->channel_count; 584d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_in_args.numAncBytes = 0; 585d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 586d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_OutArgs aac_out_args = { 587d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov .numOutBytes = 0, .numInSamples = 0, .numAncBytes = 0}; 588d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 589d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t count; 590d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov int written = 0; 591d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 592d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov while (nb_frame) { 593d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov BT_HDR* p_buf = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE); 594d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->offset = A2DP_AAC_OFFSET; 595d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->len = 0; 596d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->layer_specific = 0; 59767ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov a2dp_aac_encoder_cb.stats.media_read_total_expected_packets++; 598d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 599d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov count = 0; 600d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov do { 60167ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov // 60267ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov // Read the PCM data and encode it 60367ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov // 604d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (a2dp_aac_read_feeding(read_buffer)) { 605d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t* packet = (uint8_t*)(p_buf + 1) + p_buf->offset + p_buf->len; 606d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (!a2dp_aac_encoder_cb.has_aac_handle) { 607d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: invalid AAC handle", __func__); 6089434886ffbb5ce552d1172d98743323fa34e81f9Pavlin Radoslavov a2dp_aac_encoder_cb.stats.media_read_total_dropped_packets++; 609d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov osi_free(p_buf); 610d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; 611d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 612d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov in_buf_vector[0] = read_buffer; 613d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov out_buf_vector[0] = packet + count; 614d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov AACENC_ERROR aac_error = 615d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aacEncEncode(a2dp_aac_encoder_cb.aac_handle, &in_buf_desc, 616d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov &out_buf_desc, &aac_in_args, &aac_out_args); 617d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (aac_error != AACENC_OK) { 618d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: AAC encoding error: 0x%x", __func__, 619d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov aac_error); 6209434886ffbb5ce552d1172d98743323fa34e81f9Pavlin Radoslavov a2dp_aac_encoder_cb.stats.media_read_total_dropped_packets++; 621d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov osi_free(p_buf); 622d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return; 623d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 624d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov written = aac_out_args.numOutBytes; 625d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov count += written; 626d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->len += written; 627d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nb_frame--; 628d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->layer_specific++; // added a frame to the buffer 629d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } else { 630d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov LOG_WARN(LOG_TAG, "%s: underflow %d", __func__, nb_frame); 631d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.aac_feeding_state.counter += 632d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nb_frame * p_encoder_params->frame_length * 633d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->channel_count * 634d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_feeding_params->bits_per_sample / 8; 635d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 636d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // no more pcm to read 637d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nb_frame = 0; 638d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 639d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } while ((written == 0) && nb_frame); 640d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 641d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // NOTE: We don't check whether the packet will fit in the MTU, 642d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // because AAC doesn't give us control over the encoded frame size. 643d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // If the packet is larger than the MTU, it will be fragmented before 644d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov // transmission. 645d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (p_buf->len) { 646d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* 647d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * Timestamp of the media packet header represent the TS of the 648d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov * first frame, i.e the timestamp before including this frame. 649d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov */ 650d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov *((uint32_t*)(p_buf + 1)) = a2dp_aac_encoder_cb.timestamp; 651d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 652d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.timestamp += 653d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov p_buf->layer_specific * p_encoder_params->frame_length; 654d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 655d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint8_t done_nb_frame = remain_nb_frame - nb_frame; 656d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov remain_nb_frame = nb_frame; 657d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (!a2dp_aac_encoder_cb.enqueue_callback(p_buf, done_nb_frame)) return; 658d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } else { 65967ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov a2dp_aac_encoder_cb.stats.media_read_total_dropped_packets++; 660d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov osi_free(p_buf); 661d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 662d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 663d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 664d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 665d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavovstatic bool a2dp_aac_read_feeding(uint8_t* read_buffer) { 666d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t read_size = a2dp_aac_encoder_cb.aac_encoder_params.frame_length * 667d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.channel_count * 668d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8; 669d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 67067ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov a2dp_aac_encoder_cb.stats.media_read_total_expected_reads_count++; 67167ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov a2dp_aac_encoder_cb.stats.media_read_total_expected_read_bytes += read_size; 67267ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov 673d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* Read Data from UIPC channel */ 674d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov uint32_t nb_byte_read = 675d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_cb.read_callback(read_buffer, read_size); 67667ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov a2dp_aac_encoder_cb.stats.media_read_total_actual_read_bytes += nb_byte_read; 677d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 678d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (nb_byte_read < read_size) { 679d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov if (nb_byte_read == 0) return false; 680d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 681d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov /* Fill the unfilled part of the read buffer with silence (0) */ 682d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov memset(((uint8_t*)read_buffer) + nb_byte_read, 0, read_size - nb_byte_read); 683d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov nb_byte_read = read_size; 684d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov } 68567ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov a2dp_aac_encoder_cb.stats.media_read_total_actual_reads_count++; 68667ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov 687d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov return true; 688d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 689d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 69067ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavovperiod_ms_t A2dpCodecConfigAac::encoderIntervalMs() const { 69167ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov return a2dp_aac_get_encoder_interval_ms(); 69267ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov} 69367ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov 69467ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavovvoid A2dpCodecConfigAac::debug_codec_dump(int fd) { 695d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov a2dp_aac_encoder_stats_t* stats = &a2dp_aac_encoder_cb.stats; 696d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 69767ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov A2dpCodecConfig::debug_codec_dump(fd); 698d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 699d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov dprintf(fd, 70067ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov " Packet counts (expected/dropped) : %zu / " 701d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%zu\n", 702d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_expected_packets, 703d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_dropped_packets); 704d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 705d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov dprintf(fd, 70667ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov " PCM read counts (expected/actual) : %zu / " 707d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%zu\n", 708d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_expected_reads_count, 709d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_actual_reads_count); 710d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov 711d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov dprintf(fd, 71267ae84fb7f01d8458bfc1dcb506f32e7d9350d17Pavlin Radoslavov " PCM read bytes (expected/actual) : %zu / " 713d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov "%zu\n", 714d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_expected_read_bytes, 715d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov stats->media_read_total_actual_read_bytes); 716d5f4960b425ac84cc7a9fd699f39c06869ce2666Pavlin Radoslavov} 717