// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <gtest/gtest.h>
extern "C" {
#include <sbc/sbc.h>
#include "cras_sbc_codec.h"
#include "cras_a2dp_info.h"
}
static size_t cras_sbc_codec_create_called;
static size_t cras_sbc_codec_destroy_called;
static uint8_t codec_create_freq_val;
static uint8_t codec_create_mode_val;
static uint8_t codec_create_subbands_val;
static uint8_t codec_create_alloc_val;
static uint8_t codec_create_blocks_val;
static uint8_t codec_create_bitpool_val;
static int cras_sbc_get_frame_length_val;
static int cras_sbc_get_codesize_val;
static size_t a2dp_write_link_mtu_val;
static size_t encode_out_encoded_return_val;
static struct cras_audio_codec *sbc_codec;
static int cras_sbc_codec_create_fail;
static struct a2dp_info a2dp;
static a2dp_sbc_t sbc;
void ResetStubData() {
cras_sbc_codec_create_called = 0;
cras_sbc_codec_destroy_called = 0;
codec_create_freq_val = 0;
codec_create_mode_val = 0;
codec_create_subbands_val = 0;
codec_create_alloc_val = 0;
codec_create_blocks_val = 0;
codec_create_bitpool_val = 0;
cras_sbc_get_frame_length_val = 5;
cras_sbc_get_codesize_val = 5;
sbc_codec = NULL;
cras_sbc_codec_create_fail = 0;
a2dp_write_link_mtu_val = 40;
encode_out_encoded_return_val = 0;
sbc.frequency = SBC_SAMPLING_FREQ_48000;
sbc.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO;
sbc.allocation_method = SBC_ALLOCATION_LOUDNESS;
sbc.subbands = SBC_SUBBANDS_8;
sbc.block_length = SBC_BLOCK_LENGTH_16;
sbc.max_bitpool = 50;
a2dp.a2dp_buf_used = 0;
a2dp.frame_count = 0;
a2dp.samples = 0;
a2dp.nsamples = 0;
}
namespace {
TEST(A2dpInfoInit, InitA2dp) {
ResetStubData();
init_a2dp(&a2dp, &sbc);
ASSERT_EQ(1, cras_sbc_codec_create_called);
ASSERT_EQ(SBC_FREQ_48000, codec_create_freq_val);
ASSERT_EQ(SBC_MODE_JOINT_STEREO, codec_create_mode_val);
ASSERT_EQ(SBC_AM_LOUDNESS, codec_create_alloc_val);
ASSERT_EQ(SBC_SB_8, codec_create_subbands_val);
ASSERT_EQ(SBC_BLK_16, codec_create_blocks_val);
ASSERT_EQ(50, codec_create_bitpool_val);
ASSERT_NE(a2dp.codec, (void *)NULL);
ASSERT_EQ(a2dp.a2dp_buf_used, 13);
ASSERT_EQ(a2dp.frame_count, 0);
ASSERT_EQ(a2dp.seq_num, 0);
ASSERT_EQ(a2dp.samples, 0);
destroy_a2dp(&a2dp);
}
TEST(A2dpInfoInit, InitA2dpFail) {
ResetStubData();
int err;
cras_sbc_codec_create_fail = 1;
err = init_a2dp(&a2dp, &sbc);
ASSERT_EQ(1, cras_sbc_codec_create_called);
ASSERT_NE(0, err);
ASSERT_EQ(a2dp.codec, (void *)NULL);
}
TEST(A2dpInfoInit, DestroyA2dp) {
ResetStubData();
init_a2dp(&a2dp, &sbc);
destroy_a2dp(&a2dp);
ASSERT_EQ(1, cras_sbc_codec_destroy_called);
}
TEST(A2dpInfoInit, DrainA2dp) {
ResetStubData();
init_a2dp(&a2dp, &sbc);
a2dp.a2dp_buf_used = 99;
a2dp.samples = 10;
a2dp.seq_num = 11;
a2dp.frame_count = 12;
a2dp_drain(&a2dp);
ASSERT_EQ(a2dp.a2dp_buf_used, 13);
ASSERT_EQ(a2dp.frame_count, 0);
ASSERT_EQ(a2dp.seq_num, 0);
ASSERT_EQ(a2dp.samples, 0);
destroy_a2dp(&a2dp);
}
TEST(A2dpEncode, WriteA2dp) {
unsigned int processed;
ResetStubData();
init_a2dp(&a2dp, &sbc);
encode_out_encoded_return_val = 4;
processed = a2dp_encode(&a2dp, NULL, 20, 4, (size_t)40);
ASSERT_EQ(20, processed);
ASSERT_EQ(4, a2dp.frame_count);
// 13 + 4 used a2dp buffer still below half mtu unwritten
ASSERT_EQ(17, a2dp.a2dp_buf_used);
ASSERT_EQ(5, a2dp.samples);
ASSERT_EQ(5, a2dp.nsamples);
ASSERT_EQ(0, a2dp.seq_num);
encode_out_encoded_return_val = 15;
processed = a2dp_encode(&a2dp, NULL, 20, 4, (size_t)40);
ASSERT_EQ(32, a2dp.a2dp_buf_used);
ASSERT_EQ(10, a2dp.samples);
ASSERT_EQ(10, a2dp.nsamples);
ASSERT_EQ(0, a2dp.seq_num);
}
} // namespace
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
int decode(struct cras_audio_codec *codec, const void *input,
size_t input_len, void *output, size_t output_len,
size_t *count)
{
return input_len;
}
int encode(struct cras_audio_codec *codec, const void *input,
size_t input_len, void *output, size_t output_len,
size_t *count)
{
// Written half the output buffer.
*count = encode_out_encoded_return_val;
return input_len;
}
struct cras_audio_codec *cras_sbc_codec_create(uint8_t freq,
uint8_t mode, uint8_t subbands, uint8_t alloc,
uint8_t blocks, uint8_t bitpool)
{
if (!cras_sbc_codec_create_fail) {
sbc_codec = (struct cras_audio_codec *)calloc(1, sizeof(*sbc_codec));
sbc_codec->decode = decode;
sbc_codec->encode = encode;
}
cras_sbc_codec_create_called++;
codec_create_freq_val = freq;
codec_create_mode_val = mode;
codec_create_subbands_val = subbands;
codec_create_alloc_val = alloc;
codec_create_blocks_val = blocks;
codec_create_bitpool_val = bitpool;
return sbc_codec;
}
void cras_sbc_codec_destroy(struct cras_audio_codec *codec)
{
cras_sbc_codec_destroy_called++;
free(codec);
}
int cras_sbc_get_codesize(struct cras_audio_codec *codec)
{
return cras_sbc_get_codesize_val;
}
int cras_sbc_get_frame_length(struct cras_audio_codec *codec)
{
return cras_sbc_get_frame_length_val;
}