199 lines
7.7 KiB
C++
199 lines
7.7 KiB
C++
/*
|
|
* Copyright (C) 2022 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <sstream>
|
|
#include <utility>
|
|
|
|
#include <system/audio.h>
|
|
#define LOG_TAG "AidlConversionNdk"
|
|
//#define LOG_NDEBUG 0
|
|
#include <utils/Log.h>
|
|
#include <utils/Errors.h>
|
|
|
|
#include <media/AidlConversionCppNdk.h>
|
|
#include <media/AidlConversionNdk.h>
|
|
#include <Utils.h>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// AIDL NDK backend to legacy audio data structure conversion utilities.
|
|
|
|
namespace aidl {
|
|
namespace android {
|
|
|
|
using hardware::audio::common::PlaybackTrackMetadata;
|
|
using hardware::audio::common::RecordTrackMetadata;
|
|
using ::android::BAD_VALUE;
|
|
using ::android::OK;
|
|
|
|
namespace {
|
|
|
|
::android::status_t combineString(
|
|
const std::vector<std::string>& v, char separator, std::string* result) {
|
|
std::ostringstream oss;
|
|
for (const auto& s : v) {
|
|
if (oss.tellp() > 0) {
|
|
oss << separator;
|
|
}
|
|
if (s.find(separator) == std::string::npos) {
|
|
oss << s;
|
|
} else {
|
|
ALOGE("%s: string \"%s\" contains separator character \"%c\"",
|
|
__func__, s.c_str(), separator);
|
|
return BAD_VALUE;
|
|
}
|
|
}
|
|
*result = oss.str();
|
|
return OK;
|
|
}
|
|
|
|
std::vector<std::string> splitString(const std::string& s, char separator) {
|
|
std::istringstream iss(s);
|
|
std::string t;
|
|
std::vector<std::string> result;
|
|
while (std::getline(iss, t, separator)) {
|
|
result.push_back(std::move(t));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags) {
|
|
std::vector<std::string> result;
|
|
std::copy_if(tags.begin(), tags.end(), std::back_inserter(result),
|
|
::aidl::android::hardware::audio::common::maybeVendorExtension);
|
|
return result;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
// buffer_provider_t is not supported thus skipped
|
|
ConversionResult<buffer_config_t> aidl2legacy_AudioConfig_buffer_config_t(
|
|
const media::audio::common::AudioConfig& aidl, bool isInput) {
|
|
buffer_config_t legacy;
|
|
|
|
legacy.samplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.base.sampleRate));
|
|
legacy.mask |= EFFECT_CONFIG_SMP_RATE;
|
|
|
|
legacy.channels = VALUE_OR_RETURN(
|
|
aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.base.channelMask, isInput));
|
|
legacy.mask |= EFFECT_CONFIG_CHANNELS;
|
|
|
|
legacy.format =
|
|
VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.base.format));
|
|
legacy.mask |= EFFECT_CONFIG_FORMAT;
|
|
legacy.buffer.frameCount = aidl.frameCount;
|
|
|
|
// TODO: add accessMode and mask
|
|
return legacy;
|
|
}
|
|
|
|
ConversionResult<media::audio::common::AudioConfig>
|
|
legacy2aidl_buffer_config_t_AudioConfig(const buffer_config_t& legacy, bool isInput) {
|
|
media::audio::common::AudioConfig aidl;
|
|
|
|
if (legacy.mask & EFFECT_CONFIG_SMP_RATE) {
|
|
aidl.base.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.samplingRate));
|
|
}
|
|
if (legacy.mask & EFFECT_CONFIG_CHANNELS) {
|
|
aidl.base.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
|
|
static_cast<audio_channel_mask_t>(legacy.channels), isInput));
|
|
}
|
|
if (legacy.mask & EFFECT_CONFIG_FORMAT) {
|
|
aidl.base.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(
|
|
static_cast<audio_format_t>(legacy.format)));
|
|
}
|
|
aidl.frameCount = legacy.buffer.frameCount;
|
|
|
|
// TODO: add accessMode and mask
|
|
return aidl;
|
|
}
|
|
|
|
::android::status_t aidl2legacy_AudioAttributesTags(
|
|
const std::vector<std::string>& aidl, char* legacy) {
|
|
std::string aidlTags;
|
|
RETURN_STATUS_IF_ERROR(combineString(
|
|
filterOutNonVendorTags(aidl), AUDIO_ATTRIBUTES_TAGS_SEPARATOR, &aidlTags));
|
|
RETURN_STATUS_IF_ERROR(aidl2legacy_string(aidlTags, legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
|
|
return OK;
|
|
}
|
|
|
|
ConversionResult<std::vector<std::string>> legacy2aidl_AudioAttributesTags(const char* legacy) {
|
|
std::string legacyTags = VALUE_OR_RETURN(legacy2aidl_string(
|
|
legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
|
|
return filterOutNonVendorTags(splitString(legacyTags, AUDIO_ATTRIBUTES_TAGS_SEPARATOR));
|
|
}
|
|
|
|
ConversionResult<playback_track_metadata_v7>
|
|
aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(const PlaybackTrackMetadata& aidl) {
|
|
playback_track_metadata_v7 legacy;
|
|
legacy.base.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
|
|
legacy.base.content_type = VALUE_OR_RETURN(aidl2legacy_AudioContentType_audio_content_type_t(
|
|
aidl.contentType));
|
|
legacy.base.gain = aidl.gain;
|
|
legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
|
|
aidl.channelMask, false /*isInput*/));
|
|
RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
|
|
return legacy;
|
|
}
|
|
|
|
ConversionResult<PlaybackTrackMetadata>
|
|
legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(
|
|
const playback_track_metadata_v7& legacy) {
|
|
PlaybackTrackMetadata aidl;
|
|
aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.base.usage));
|
|
aidl.contentType = VALUE_OR_RETURN(legacy2aidl_audio_content_type_t_AudioContentType(
|
|
legacy.base.content_type));
|
|
aidl.gain = legacy.base.gain;
|
|
aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
|
|
legacy.channel_mask, false /*isInput*/));
|
|
aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
|
|
return aidl;
|
|
}
|
|
|
|
ConversionResult<record_track_metadata_v7>
|
|
aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(const RecordTrackMetadata& aidl) {
|
|
record_track_metadata_v7 legacy;
|
|
legacy.base.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
|
|
legacy.base.gain = aidl.gain;
|
|
if (aidl.destinationDevice.has_value()) {
|
|
RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl.destinationDevice.value(),
|
|
&legacy.base.dest_device, legacy.base.dest_device_address));
|
|
} else {
|
|
legacy.base.dest_device = AUDIO_DEVICE_NONE;
|
|
}
|
|
legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
|
|
aidl.channelMask, true /*isInput*/));
|
|
RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
|
|
return legacy;
|
|
}
|
|
|
|
ConversionResult<RecordTrackMetadata>
|
|
legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy) {
|
|
RecordTrackMetadata aidl;
|
|
aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.base.source));
|
|
aidl.gain = legacy.base.gain;
|
|
if (legacy.base.dest_device != AUDIO_DEVICE_NONE) {
|
|
aidl.destinationDevice = VALUE_OR_RETURN(legacy2aidl_audio_device_AudioDevice(
|
|
legacy.base.dest_device, legacy.base.dest_device_address));
|
|
}
|
|
aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
|
|
legacy.channel_mask, true /*isInput*/));
|
|
aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
|
|
return aidl;
|
|
}
|
|
|
|
} // namespace android
|
|
} // aidl
|