Skip to content

Commit

Permalink
Create aac_utils to hold encoder/decoder common utils
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 635443367
  • Loading branch information
trevorknight authored and jwcullen committed May 20, 2024
1 parent 5686c76 commit b06b2d2
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 124 deletions.
24 changes: 16 additions & 8 deletions iamf/cli/codec/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@ cc_library(
srcs = ["aac_decoder.cc"],
hdrs = ["aac_decoder.h"],
deps = [
":aac_utils",
":decoder_base",
"//iamf/cli/proto:codec_config_cc_proto",
"//iamf/common:macros",
"//iamf/common:write_bit_buffer",
"//iamf/obu:codec_config",
"//iamf/obu/decoder_config:aac_decoder_config",
"@com_google_absl//absl/log",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@fdk_aac//:aac_decoder_lib",
"@fdk_aac//:aac_encoder_lib",
"@fdk_aac//:fdk_sys_lib",
],
)
Expand All @@ -27,20 +25,32 @@ cc_library(
srcs = ["aac_encoder.cc"],
hdrs = ["aac_encoder.h"],
deps = [
":decoder_base",
":aac_utils",
":encoder_base",
"//iamf/cli:audio_frame_with_data",
"//iamf/cli/proto:codec_config_cc_proto",
"//iamf/common:macros",
"//iamf/common:obu_util",
"//iamf/common:write_bit_buffer",
"//iamf/obu:codec_config",
"//iamf/obu/decoder_config:aac_decoder_config",
"@com_google_absl//absl/log",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@fdk_aac//:aac_decoder_lib",
"@fdk_aac//:aac_encoder_lib",
"@fdk_aac//:fdk_sys_lib",
],
)

cc_library(
name = "aac_utils",
srcs = ["aac_utils.cc"],
hdrs = ["aac_utils.h"],
deps = [
"//iamf/cli/proto:codec_config_cc_proto",
"@com_google_absl//absl/log",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@fdk_aac//:aac_encoder_lib",
"@fdk_aac//:fdk_sys_lib",
],
Expand Down Expand Up @@ -128,7 +138,6 @@ cc_library(
hdrs = ["opus_decoder.h"],
deps = [
":decoder_base",
":encoder_base",
"//iamf/cli:audio_frame_with_data",
"//iamf/cli/proto:codec_config_cc_proto",
"//iamf/common:macros",
Expand All @@ -148,7 +157,6 @@ cc_library(
srcs = ["opus_encoder.cc"],
hdrs = ["opus_encoder.h"],
deps = [
":decoder_base",
":encoder_base",
"//iamf/cli:audio_frame_with_data",
"//iamf/cli/proto:codec_config_cc_proto",
Expand Down
57 changes: 3 additions & 54 deletions iamf/cli/codec/aac_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <vector>

// This symbol conflicts with `aacenc_lib.h` and `aacdecoder_lib.h`.
Expand All @@ -25,69 +24,19 @@

#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "iamf/cli/codec/aac_utils.h"
#include "iamf/cli/codec/decoder_base.h"
#include "iamf/cli/proto/codec_config.pb.h"
#include "iamf/common/macros.h"
#include "iamf/common/write_bit_buffer.h"
#include "iamf/obu/codec_config.h"
#include "iamf/obu/decoder_config/aac_decoder_config.h"
#include "libAACdec/include/aacdecoder_lib.h"
#include "libAACenc/include/aacenc_lib.h"
#include "libSYS/include/FDK_audio.h"
#include "libSYS/include/machine_type.h"

namespace iamf_tools {

// IAMF requires raw AAC frames with no ADTS header.
const auto kAacTranportType = TT_MP4_RAW;

// `libfdk_aac` has the bytes per sample fixed at compile time.
const size_t kFdkAacBytesPerSample = sizeof(INT_PCM);
const size_t kFdkAacBitDepth = kFdkAacBytesPerSample * 8;

namespace {

absl::Status AacEncErrorToAbslStatus(AACENC_ERROR aac_error_code,
const std::string& error_message) {
absl::StatusCode status_code;
switch (aac_error_code) {
case AACENC_OK:
return absl::OkStatus();
case AACENC_INVALID_HANDLE:
status_code = absl::StatusCode::kInvalidArgument;
break;
case AACENC_MEMORY_ERROR:
status_code = absl::StatusCode::kResourceExhausted;
break;
case AACENC_UNSUPPORTED_PARAMETER:
status_code = absl::StatusCode::kInvalidArgument;
break;
case AACENC_INVALID_CONFIG:
status_code = absl::StatusCode::kFailedPrecondition;
break;
case AACENC_INIT_ERROR:
case AACENC_INIT_AAC_ERROR:
case AACENC_INIT_SBR_ERROR:
case AACENC_INIT_TP_ERROR:
case AACENC_INIT_META_ERROR:
case AACENC_INIT_MPS_ERROR:
status_code = absl::StatusCode::kInternal;
break;
case AACENC_ENCODE_EOF:
status_code = absl::StatusCode::kOutOfRange;
break;
case AACENC_ENCODE_ERROR:
default:
status_code = absl::StatusCode::kUnknown;
break;
}

return absl::Status(
status_code,
absl::StrCat(error_message, " AACENC_ERROR= ", aac_error_code));
}

absl::Status ConfigureAacDecoder(const AacDecoderConfig& raw_aac_decoder_config,
int num_channels,
AAC_DECODER_INSTANCE* decoder_) {
Expand Down Expand Up @@ -140,7 +89,7 @@ AacDecoder::~AacDecoder() {

absl::Status AacDecoder::Initialize() {
// Initialize the decoder.
decoder_ = aacDecoder_Open(kAacTranportType, /*nrOfLayers=*/1);
decoder_ = aacDecoder_Open(GetAacTransportationType(), /*nrOfLayers=*/1);

if (decoder_ == nullptr) {
LOG(ERROR) << "Failed to initialize AAC decoder.";
Expand Down Expand Up @@ -197,7 +146,7 @@ absl::Status AacDecoder::DecodeAudioFrame(
std::vector<int32_t> time_sample(num_channels_, 0);
for (int j = 0; j < num_channels_; ++j) {
time_sample[j] = static_cast<int32_t>(output_pcm[i + j])
<< (32 - kFdkAacBitDepth);
<< (32 - GetFdkAacBitDepth());
}
decoded_samples.push_back(time_sample);
}
Expand Down
68 changes: 6 additions & 62 deletions iamf/cli/codec/aac_encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,17 @@
*/
#include "iamf/cli/codec/aac_encoder.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <string>
#include <utility>
#include <vector>

// This symbol conflicts with `aacenc_lib.h` and `aacdecoder_lib.h`.
#ifdef IS_LITTLE_ENDIAN
#undef IS_LITTLE_ENDIAN
#endif

#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "iamf/cli/audio_frame_with_data.h"
#include "iamf/cli/codec/aac_utils.h"
#include "iamf/cli/proto/codec_config.pb.h"
#include "iamf/common/macros.h"
#include "iamf/common/obu_util.h"
Expand All @@ -39,55 +31,7 @@

namespace iamf_tools {

// IAMF requires raw AAC frames with no ADTS header.
const auto kAacTranportType = TT_MP4_RAW;

// `libfdk_aac` has the bytes per sample fixed at compile time.
const size_t kFdkAacBytesPerSample = sizeof(INT_PCM);
const size_t kFdkAacBitDepth = kFdkAacBytesPerSample * 8;

namespace {

absl::Status AacEncErrorToAbslStatus(AACENC_ERROR aac_error_code,
const std::string& error_message) {
absl::StatusCode status_code;
switch (aac_error_code) {
case AACENC_OK:
return absl::OkStatus();
case AACENC_INVALID_HANDLE:
status_code = absl::StatusCode::kInvalidArgument;
break;
case AACENC_MEMORY_ERROR:
status_code = absl::StatusCode::kResourceExhausted;
break;
case AACENC_UNSUPPORTED_PARAMETER:
status_code = absl::StatusCode::kInvalidArgument;
break;
case AACENC_INVALID_CONFIG:
status_code = absl::StatusCode::kFailedPrecondition;
break;
case AACENC_INIT_ERROR:
case AACENC_INIT_AAC_ERROR:
case AACENC_INIT_SBR_ERROR:
case AACENC_INIT_TP_ERROR:
case AACENC_INIT_META_ERROR:
case AACENC_INIT_MPS_ERROR:
status_code = absl::StatusCode::kInternal;
break;
case AACENC_ENCODE_EOF:
status_code = absl::StatusCode::kOutOfRange;
break;
case AACENC_ENCODE_ERROR:
default:
status_code = absl::StatusCode::kUnknown;
break;
}

return absl::Status(
status_code,
absl::StrCat(error_message, " AACENC_ERROR= ", aac_error_code));
}

absl::Status ConfigureAacEncoder(
const iamf_tools_cli_proto::AacEncoderMetadata& encoder_metadata,
int num_channels, uint32_t num_samples_per_frame,
Expand All @@ -98,7 +42,7 @@ absl::Status ConfigureAacEncoder(
"Failed to configure encoder metadata mode."));

RETURN_IF_NOT_OK(AacEncErrorToAbslStatus(
aacEncoder_SetParam(encoder, AACENC_TRANSMUX, kAacTranportType),
aacEncoder_SetParam(encoder, AACENC_TRANSMUX, GetAacTransportationType()),
"Failed to configure encoder transport type."));

// IAMF only supports AAC-LC.
Expand Down Expand Up @@ -233,8 +177,8 @@ absl::Status AacEncoder::EncodeAudioFrame(
"Failed to get encoder info."));

// Convert input to the array that will be passed to `aacEncEncode`.
if (input_bit_depth != kFdkAacBitDepth) {
LOG(ERROR) << "Expected AAC to be " << kFdkAacBitDepth
if (input_bit_depth != GetFdkAacBitDepth()) {
LOG(ERROR) << "Expected AAC to be " << GetFdkAacBitDepth()
<< " bits, got "
"bit-depth: "
<< input_bit_depth;
Expand Down Expand Up @@ -262,8 +206,8 @@ absl::Status AacEncoder::EncodeAudioFrame(
void* in_buffers[1] = {encoder_input_pcm.data()};
INT in_buffer_identifiers[1] = {IN_AUDIO_DATA};
INT in_buffer_sizes[1] = {
static_cast<INT>(encoder_input_pcm.size() * kFdkAacBytesPerSample)};
INT in_buffer_element_sizes[1] = {kFdkAacBytesPerSample};
static_cast<INT>(encoder_input_pcm.size() * GetFdkAacBytesPerSample())};
INT in_buffer_element_sizes[1] = {GetFdkAacBytesPerSample()};
AACENC_BufDesc inBufDesc = {.numBufs = 1,
.bufs = in_buffers,
.bufferIdentifiers = in_buffer_identifiers,
Expand Down
59 changes: 59 additions & 0 deletions iamf/cli/codec/aac_utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "iamf/cli/codec/aac_utils.h"

#include <string>

#include "absl/log/log.h"

// This symbol conflicts with `aacenc_lib.h` and `aacdecoder_lib.h`.
#ifdef IS_LITTLE_ENDIAN
#undef IS_LITTLE_ENDIAN
#endif

#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "iamf/cli/proto/codec_config.pb.h"
#include "libAACenc/include/aacenc_lib.h"

namespace iamf_tools {

absl::Status AacEncErrorToAbslStatus(AACENC_ERROR aac_error_code,
const std::string& error_message) {
absl::StatusCode status_code;
switch (aac_error_code) {
case AACENC_OK:
return absl::OkStatus();
case AACENC_INVALID_HANDLE:
status_code = absl::StatusCode::kInvalidArgument;
break;
case AACENC_MEMORY_ERROR:
status_code = absl::StatusCode::kResourceExhausted;
break;
case AACENC_UNSUPPORTED_PARAMETER:
status_code = absl::StatusCode::kInvalidArgument;
break;
case AACENC_INVALID_CONFIG:
status_code = absl::StatusCode::kFailedPrecondition;
break;
case AACENC_INIT_ERROR:
case AACENC_INIT_AAC_ERROR:
case AACENC_INIT_SBR_ERROR:
case AACENC_INIT_TP_ERROR:
case AACENC_INIT_META_ERROR:
case AACENC_INIT_MPS_ERROR:
status_code = absl::StatusCode::kInternal;
break;
case AACENC_ENCODE_EOF:
status_code = absl::StatusCode::kOutOfRange;
break;
case AACENC_ENCODE_ERROR:
default:
status_code = absl::StatusCode::kUnknown;
break;
}

return absl::Status(
status_code,
absl::StrCat(error_message, " AACENC_ERROR= ", aac_error_code));
}

} // namespace iamf_tools
30 changes: 30 additions & 0 deletions iamf/cli/codec/aac_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef CLI_CODEC_AAC_UTILS_H_
#define CLI_CODEC_AAC_UTILS_H_

#include <cstddef>
#include <string>

#include "absl/status/status.h"
#include "iamf/cli/proto/codec_config.pb.h"
#include "libAACenc/include/aacenc_lib.h"
#include "libSYS/include/FDK_audio.h"
#include "libSYS/include/machine_type.h"

namespace iamf_tools {

/*!\brief IAMF requires raw AAC frames with no ADTS header. */
constexpr TRANSPORT_TYPE GetAacTransportationType() { return TT_MP4_RAW; }

/*!\brief The FDK AAC encoder uses 16-bit PCM. */
constexpr size_t GetFdkAacBytesPerSample() { return sizeof(INT_PCM); }

/*!\brief Convenience method for getting bit depth. */
constexpr size_t GetFdkAacBitDepth() { return GetFdkAacBytesPerSample() * 8; }

/*!\brief Converts an AACENC_ERROR to an absl::Status. */
absl::Status AacEncErrorToAbslStatus(AACENC_ERROR aac_error_code,
const std::string& error_message);

} // namespace iamf_tools

#endif // CLI_CODEC_AAC_UTILS_H_

0 comments on commit b06b2d2

Please sign in to comment.