/* * Bluetooth low-complexity, subband codec (SBC) * * Copyright (C) 2017 Aurelien Jacobs <aurel@gnuage.org> * Copyright (C) 2012-2013 Intel Corporation * Copyright (C) 2008-2010 Nokia Corporation * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch> * Copyright (C) 2005-2008 Brad Midgley <bmidgley@xmission.com> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file * SBC encoder implementation */ #include <stdbool.h> #include "libavutil/opt.h" #include "avcodec.h" #include "internal.h" #include "profiles.h" #include "put_bits.h" #include "sbc.h" #include "sbcdsp.h" typedef struct SBCEncContext { AVClass *class; int64_t max_delay; int msbc; DECLARE_ALIGNED(SBC_ALIGN, struct sbc_frame, frame); DECLARE_ALIGNED(SBC_ALIGN, SBCDSPContext, dsp); } SBCEncContext; static int sbc_analyze_audio(SBCDSPContext *s, struct sbc_frame *frame) { int ch, blk; int16_t *x; switch (frame->subbands) { case 4: for (ch = 0; ch < frame->channels; ch++) { x = &s->X[ch][s->position - 4 * s->increment + frame->blocks * 4]; for (blk = 0; blk < frame->blocks; blk += s->increment) { s->sbc_analyze_4s( s, x, frame->sb_sample_f[blk][ch], frame->sb_sample_f[blk + 1][ch] - frame->sb_sample_f[blk][ch]); x -= 4 * s->increment; } } return frame->blocks * 4; case 8: for (ch = 0; ch < frame->channels; ch++) { x = &s->X[ch][s->position - 8 * s->increment + frame->blocks * 8]; for (blk = 0; blk < frame->blocks; blk += s->increment) { s->sbc_analyze_8s( s, x, frame->sb_sample_f[blk][ch], frame->sb_sample_f[blk + 1][ch] - frame->sb_sample_f[blk][ch]); x -= 8 * s->increment; } } return frame->blocks * 8; default: return AVERROR(EIO); } } /* * Packs the SBC frame from frame into the memory in avpkt. * Returns the length of the packed frame. */ static size_t sbc_pack_frame(AVPacket *avpkt, struct sbc_frame *frame, int joint, bool msbc) { PutBitContext pb; /* Will copy the header parts for CRC-8 calculation here */ uint8_t crc_header[11] = { 0 }; int crc_pos; uint32_t audio_sample; int ch, sb, blk; /* channel, subband, block and bit counters */ int bits[2][8]; /* bits distribution */ uint32_t levels[2][8]; /* levels are derived from that */ uint32_t sb_sample_delta[2][8]; if (msbc) { avpkt->data[0] = MSBC_SYNCWORD; avpkt->data[1] = 0; avpkt->data[2] = 0; } else { avpkt->data[0] = SBC_SYNCWORD; avpkt->data[1] = (frame->frequency & 0x03) << 6; avpkt->data[1] |= (((frame->blocks >> 2) - 1) & 0x03) << 4; avpkt->data[1] |= (frame->mode & 0x03) << 2; avpkt->data[1] |= (frame->allocation & 0x01) << 1; avpkt->data[1] |= ((frame->subbands == 8) & 0x01) << 0; avpkt->data[2] = frame->bitpool; if (frame->bitpool > frame->subbands << (4 + (frame->mode == STEREO || frame->mode == JOINT_STEREO))) return -5; } /* Can't fill in crc yet */ crc_header[0] = avpkt->data[1]; crc_header[1] = avpkt->data[2]; crc_pos = 16; init_put_bits(&pb, avpkt->data + 4, avpkt->size); if (frame->mode == JOINT_STEREO) { put_bits(&pb, frame->subbands, joint); crc_header[crc_pos >> 3] = joint; crc_pos += frame->subbands; } for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { put_bits(&pb, 4, frame->scale_factor[ch][sb] & 0x0F); crc_header[crc_pos >> 3] <<= 4; crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F; crc_pos += 4; } } /* align the last crc byte */ if (crc_pos % 8) crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8); avpkt->data[3] = ff_sbc_crc8(frame->crc_ctx, crc_header, crc_pos); ff_sbc_calculate_bits(frame, bits); for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { levels[ch][sb] = ((1 << bits[ch][sb]) - 1) << (32 - (frame->scale_factor[ch][sb] + SCALE_OUT_BITS + 2)); sb_sample_delta[ch][sb] = (uint32_t) 1 << (frame->scale_factor[ch][sb] + SCALE_OUT_BITS + 1); } } for (blk = 0; blk < frame->blocks; blk++) { for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { if (bits[ch][sb] == 0) continue; audio_sample = ((uint64_t) levels[ch][sb] * (sb_sample_delta[ch][sb] + frame->sb_sample_f[blk][ch][sb])) >> 32; put_bits(&pb, bits[ch][sb], audio_sample); } } } flush_put_bits(&pb); return (put_bits_count(&pb) + 7) / 8; } static int sbc_encode_init(AVCodecContext *avctx) { SBCEncContext *sbc = avctx->priv_data; struct sbc_frame *frame = &sbc->frame; if (avctx->profile == FF_PROFILE_SBC_MSBC) sbc->msbc = 1; if (sbc->msbc) { if (avctx->channels != 1) { av_log(avctx, AV_LOG_ERROR, "mSBC require mono channel.\n"); return AVERROR(EINVAL); } if (avctx->sample_rate != 16000) { av_log(avctx, AV_LOG_ERROR, "mSBC require 16 kHz samplerate.\n"); return AVERROR(EINVAL); } frame->mode = SBC_MODE_MONO; frame->subbands = 8; frame->blocks = MSBC_BLOCKS; frame->allocation = SBC_AM_LOUDNESS; frame->bitpool = 26; avctx->frame_size = 8 * MSBC_BLOCKS; } else { int d; if (avctx->global_quality > 255*FF_QP2LAMBDA) { av_log(avctx, AV_LOG_ERROR, "bitpool > 255 is not allowed.\n"); return AVERROR(EINVAL); } if (avctx->channels == 1) { frame->mode = SBC_MODE_MONO; if (sbc->max_delay <= 3000 || avctx->bit_rate > 270000) frame->subbands = 4; else frame->subbands = 8; } else { if (avctx->bit_rate < 180000 || avctx->bit_rate > 420000) frame->mode = SBC_MODE_JOINT_STEREO; else frame->mode = SBC_MODE_STEREO; if (sbc->max_delay <= 4000 || avctx->bit_rate > 420000) frame->subbands = 4; else frame->subbands = 8; } /* sbc algorithmic delay is ((blocks + 10) * subbands - 2) / sample_rate */ frame->blocks = av_clip(((sbc->max_delay * avctx->sample_rate + 2) / (1000000 * frame->subbands)) - 10, 4, 16) & ~3; frame->allocation = SBC_AM_LOUDNESS; d = frame->blocks * ((frame->mode == SBC_MODE_DUAL_CHANNEL) + 1); frame->bitpool = (((avctx->bit_rate * frame->subbands * frame->blocks) / avctx->sample_rate) - 4 * frame->subbands * avctx->channels - (frame->mode == SBC_MODE_JOINT_STEREO)*frame->subbands - 32 + d/2) / d; if (avctx->global_quality > 0) frame->bitpool = avctx->global_quality / FF_QP2LAMBDA; avctx->frame_size = 4*((frame->subbands >> 3) + 1) * 4*(frame->blocks >> 2); } for (int i = 0; avctx->codec->supported_samplerates[i]; i++) if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) frame->frequency = i; frame->channels = avctx->channels; frame->codesize = frame->subbands * frame->blocks * avctx->channels * 2; frame->crc_ctx = av_crc_get_table(AV_CRC_8_EBU); memset(&sbc->dsp.X, 0, sizeof(sbc->dsp.X)); sbc->dsp.position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7; sbc->dsp.increment = sbc->msbc ? 1 : 4; ff_sbcdsp_init(&sbc->dsp); return 0; } static int sbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *av_frame, int *got_packet_ptr) { SBCEncContext *sbc = avctx->priv_data; struct sbc_frame *frame = &sbc->frame; uint8_t joint = frame->mode == SBC_MODE_JOINT_STEREO; uint8_t dual = frame->mode == SBC_MODE_DUAL_CHANNEL; int ret, j = 0; int frame_length = 4 + (4 * frame->subbands * frame->channels) / 8 + ((frame->blocks * frame->bitpool * (1 + dual) + joint * frame->subbands) + 7) / 8; /* input must be large enough to encode a complete frame */ if (av_frame->nb_samples * frame->channels * 2 < frame->codesize) return 0; if ((ret = ff_alloc_packet2(avctx, avpkt, frame_length, 0)) < 0) return ret; /* Select the needed input data processing function and call it */ if (frame->subbands == 8) sbc->dsp.position = sbc->dsp.sbc_enc_process_input_8s( sbc->dsp.position, av_frame->data[0], sbc->dsp.X, frame->subbands * frame->blocks, frame->channels); else sbc->dsp.position = sbc->dsp.sbc_enc_process_input_4s( sbc->dsp.position, av_frame->data[0], sbc->dsp.X, frame->subbands * frame->blocks, frame->channels); sbc_analyze_audio(&sbc->dsp, &sbc->frame); if (frame->mode == JOINT_STEREO) j = sbc->dsp.sbc_calc_scalefactors_j(frame->sb_sample_f, frame->scale_factor, frame->blocks, frame->subbands); else sbc->dsp.sbc_calc_scalefactors(frame->sb_sample_f, frame->scale_factor, frame->blocks, frame->channels, frame->subbands); emms_c(); sbc_pack_frame(avpkt, frame, j, sbc->msbc); *got_packet_ptr = 1; return 0; } #define OFFSET(x) offsetof(SBCEncContext, x) #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "sbc_delay", "set maximum algorithmic latency", OFFSET(max_delay), AV_OPT_TYPE_DURATION, {.i64 = 13000}, 1000,13000, AE }, { "msbc", "use mSBC mode (wideband speech mono SBC)", OFFSET(msbc), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AE }, { NULL }, }; static const AVClass sbc_class = { .class_name = "sbc encoder", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, }; AVCodec ff_sbc_encoder = { .name = "sbc", .long_name = NULL_IF_CONFIG_SMALL("SBC (low-complexity subband codec)"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_SBC, .priv_data_size = sizeof(SBCEncContext), .init = sbc_encode_init, .encode2 = sbc_encode_frame, .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0}, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .supported_samplerates = (const int[]) { 16000, 32000, 44100, 48000, 0 }, .priv_class = &sbc_class, .profiles = NULL_IF_CONFIG_SMALL(ff_sbc_profiles), };