普通文本  |  212行  |  5.21 KB

// 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;
}