static void bluetooth_exit(struct bluetooth_data *data) { struct bluetooth_a2dp *a2dp = &data->a2dp; if (data->server.fd >= 0) bt_audio_service_close(data->server.fd); if (data->stream.fd >= 0) close(data->stream.fd); if (data->hw_thread) { pthread_cancel(data->hw_thread); pthread_join(data->hw_thread, 0); } if (a2dp->sbc_initialized) sbc_finish(&a2dp->sbc); if (data->pipefd[0] > 0) close(data->pipefd[0]); if (data->pipefd[1] > 0) close(data->pipefd[1]); free(data); }
void codec_sbc_release(void *ctx) { sbc_t *sbc = (sbc_t *) ctx; sbc_finish(sbc); g_free(sbc); }
static inline void a2dp_free(snd_pcm_a2dp_t *a2dp) { if (a2dp->sk > fileno(stderr)) close(a2dp->sk); sbc_finish(&a2dp->sbc); free(a2dp); }
static gboolean gst_sbc_dec_stop (GstAudioDecoder * dec) { GstSbcDec *sbcdec = GST_SBC_DEC (dec); GST_INFO_OBJECT (sbcdec, "Finish subband codec"); sbc_finish (&sbcdec->sbc); sbcdec->samples_per_frame = 0; sbcdec->frame_len = 0; return TRUE; }
static gboolean gst_sbc_enc_stop (GstAudioEncoder * audio_enc) { GstSbcEnc *enc = GST_SBC_ENC (audio_enc); GST_INFO_OBJECT (enc, "Finish subband codec"); sbc_finish (&enc->sbc); enc->subbands = 0; enc->blocks = 0; enc->rate = 0; enc->channels = 0; enc->bitpool = 0; return TRUE; }
static GstStateChangeReturn sbc_enc_change_state(GstElement *element, GstStateChange transition) { GstSbcEnc *enc = GST_SBC_ENC(element); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: GST_DEBUG("Setup subband codec"); sbc_init(&enc->sbc, 0); break; case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG("Finish subband codec"); sbc_finish(&enc->sbc); break; default: break; } return parent_class->change_state(element, transition); }
int a2dp_init(int rate, int channels, a2dpData* dataPtr) { struct bluetooth_data* data; pthread_attr_t attr; int err; DBG("a2dp_init rate: %d channels: %d", rate, channels); *dataPtr = NULL; data = malloc(sizeof(struct bluetooth_data)); if (!data) return -1; memset(data, 0, sizeof(struct bluetooth_data)); data->server.fd = -1; data->stream.fd = -1; data->state = A2DP_STATE_NONE; data->command = A2DP_CMD_NONE; strncpy(data->address, "00:00:00:00:00:00", 18); data->rate = rate; data->channels = channels; sbc_init(&data->sbc, 0); pthread_mutex_init(&data->mutex, NULL); pthread_cond_init(&data->thread_start, NULL); pthread_cond_init(&data->thread_wait, NULL); pthread_cond_init(&data->client_wait, NULL); pthread_mutex_lock(&data->mutex); data->started = 0; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); err = pthread_create(&data->thread, &attr, a2dp_thread, data); if (err) { /* If the thread create fails we must not wait */ pthread_mutex_unlock(&data->mutex); err = -err; goto error; } /* Make sure the state machine is ready and waiting */ while (!data->started) { pthread_cond_wait(&data->thread_start, &data->mutex); } /* Poke the state machine to get it going */ pthread_cond_signal(&data->thread_wait); pthread_mutex_unlock(&data->mutex); pthread_attr_destroy(&attr); *dataPtr = data; return 0; error: bluetooth_close(data); sbc_finish(&data->sbc); pthread_attr_destroy(&attr); a2dp_free(data); return err; }
static void* a2dp_thread(void *d) { struct bluetooth_data* data = (struct bluetooth_data*)d; a2dp_command_t command = A2DP_CMD_NONE; int err = 0; DBG("a2dp_thread started"); prctl(PR_SET_NAME, (int)"a2dp_thread", 0, 0, 0); pthread_mutex_lock(&data->mutex); data->started = 1; pthread_cond_signal(&data->thread_start); while (1) { while (1) { pthread_cond_wait(&data->thread_wait, &data->mutex); /* Initialization needed */ if (data->state == A2DP_STATE_NONE && data->command != A2DP_CMD_QUIT) { err = bluetooth_init(data); } /* New state command signaled */ if (command != data->command) { command = data->command; break; } } switch (command) { case A2DP_CMD_CONFIGURE: if (data->state != A2DP_STATE_INITIALIZED) break; err = bluetooth_configure(data); break; case A2DP_CMD_START: if (data->state != A2DP_STATE_CONFIGURED) break; err = bluetooth_start(data); break; case A2DP_CMD_STOP: if (data->state != A2DP_STATE_STARTED) break; err = bluetooth_stop(data); break; case A2DP_CMD_QUIT: bluetooth_close(data); sbc_finish(&data->sbc); a2dp_free(data); goto done; case A2DP_CMD_INIT: /* already called bluetooth_init() */ default: break; } // reset last command in case of error to allow // re-execution of the same command if (err < 0) { command = A2DP_CMD_NONE; } } done: pthread_mutex_unlock(&data->mutex); DBG("a2dp_thread finished"); return NULL; }
static void decode(char *filename, char *output, int tofile, bool msbc) { unsigned char buf[BUF_SIZE], *stream; struct stat st; sbc_t sbc; int fd, ad, pos, streamlen, framelen, count; size_t len; int format = AFMT_S16_BE, frequency, channels; ssize_t written; if (stat(filename, &st) < 0) { fprintf(stderr, "Can't get size of file %s: %s\n", filename, strerror(errno)); return; } stream = malloc(st.st_size); if (!stream) { fprintf(stderr, "Can't allocate memory for %s: %s\n", filename, strerror(errno)); return; } fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open file %s: %s\n", filename, strerror(errno)); goto free; } if (read(fd, stream, st.st_size) != st.st_size) { fprintf(stderr, "Can't read content of %s: %s\n", filename, strerror(errno)); close(fd); goto free; } close(fd); pos = 0; streamlen = st.st_size; if (tofile) ad = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0644); else ad = open(output, O_WRONLY, 0); if (ad < 0) { fprintf(stderr, "Can't open output %s: %s\n", output, strerror(errno)); goto free; } if (msbc) sbc_init_msbc(&sbc, 0L); else sbc_init(&sbc, 0L); sbc.endian = SBC_BE; framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len); channels = sbc.mode == SBC_MODE_MONO ? 1 : 2; switch (sbc.frequency) { case SBC_FREQ_16000: frequency = 16000; break; case SBC_FREQ_32000: frequency = 32000; break; case SBC_FREQ_44100: frequency = 44100; break; case SBC_FREQ_48000: frequency = 48000; break; default: frequency = 0; } if (verbose) { fprintf(stderr,"decoding %s with rate %d, %d subbands, " "%d bits, allocation method %s and mode %s\n", filename, frequency, sbc.subbands * 4 + 4, sbc.bitpool, sbc.allocation == SBC_AM_SNR ? "SNR" : "LOUDNESS", sbc.mode == SBC_MODE_MONO ? "MONO" : sbc.mode == SBC_MODE_STEREO ? "STEREO" : "JOINTSTEREO"); } if (tofile) { struct au_header au_hdr; au_hdr.magic = AU_MAGIC; au_hdr.hdr_size = BE_INT(24); au_hdr.data_size = BE_INT(0); au_hdr.encoding = BE_INT(AU_FMT_LIN16); au_hdr.sample_rate = BE_INT(frequency); au_hdr.channels = BE_INT(channels); written = write(ad, &au_hdr, sizeof(au_hdr)); if (written < (ssize_t) sizeof(au_hdr)) { fprintf(stderr, "Failed to write header\n"); goto close; } } else { if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { fprintf(stderr, "Can't set audio format on %s: %s\n", output, strerror(errno)); goto close; } if (ioctl(ad, SNDCTL_DSP_CHANNELS, &channels) < 0) { fprintf(stderr, "Can't set number of channels on %s: %s\n", output, strerror(errno)); goto close; } if (ioctl(ad, SNDCTL_DSP_SPEED, &frequency) < 0) { fprintf(stderr, "Can't set audio rate on %s: %s\n", output, strerror(errno)); goto close; } } count = len; while (framelen > 0) { /* we have completed an sbc_decode at this point sbc.len is the * length of the frame we just decoded count is the number of * decoded bytes yet to be written */ if (count + len >= BUF_SIZE) { /* buffer is too full to stuff decoded audio in so it * must be written to the device */ written = write(ad, buf, count); if (written > 0) count -= written; } /* sanity check */ if (count + len >= BUF_SIZE) { fprintf(stderr, "buffer size of %d is too small for decoded" " data (%lu)\n", BUF_SIZE, (unsigned long) (len + count)); exit(1); } /* push the pointer in the file forward to the next bit to be * decoded tell the decoder to decode up to the remaining * length of the file (!) */ pos += framelen; framelen = sbc_decode(&sbc, stream + pos, streamlen - pos, buf + count, sizeof(buf) - count, &len); /* increase the count */ count += len; } if (count > 0) { written = write(ad, buf, count); if (written > 0) count -= written; } close: sbc_finish(&sbc); close(ad); free: free(stream); }
static void decode(char *filename, char *audiodevice, int tofile) { unsigned char buf[BUF_SIZE], *stream; struct stat st; off_t filesize; sbc_t sbc; int fd, ad, pos, streamlen, framelen, count, format = AFMT_S16_BE; if (stat(filename, &st) < 0) { fprintf(stderr, "Can't get size of file %s: %s\n", filename, strerror(errno)); return; } filesize = st.st_size; stream = malloc(st.st_size); if (!stream) { fprintf(stderr, "Can't allocate memory for %s: %s\n", filename, strerror(errno)); return; } fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open file %s: %s\n", filename, strerror(errno)); goto free; } if (read(fd, stream, st.st_size) != st.st_size) { fprintf(stderr, "Can't read content of %s: %s\n", filename, strerror(errno)); close(fd); goto free; } close(fd); pos = 0; streamlen = st.st_size; ad = open(audiodevice, O_WRONLY | (tofile ? (O_CREAT | O_TRUNC) : 0), tofile ? 0644 : 0); if (ad < 0) { fprintf(stderr, "Can't open audio device %s: %s\n", audiodevice, strerror(errno)); goto free; } sbc_init(&sbc, SBC_NULL); framelen = sbc_decode(&sbc, stream, streamlen); printf("%d Hz, %d channels\n", sbc.rate, sbc.channels); if (!tofile) { if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { fprintf(stderr, "Can't set audio format on %s: %s\n", audiodevice, strerror(errno)); goto close; } if (ioctl(ad, SNDCTL_DSP_CHANNELS, &sbc.channels) < 0) { fprintf(stderr, "Can't set number of channels on %s: %s\n", audiodevice, strerror(errno)); goto close; } if (ioctl(ad, SNDCTL_DSP_SPEED, &sbc.rate) < 0) { fprintf(stderr, "Can't set audio rate on %s: %s\n", audiodevice, strerror(errno)); goto close; } } count = 0; while (framelen > 0) { // we have completed an sbc_decode at this point // sbc.len is the length of the frame we just decoded // count is the number of decoded bytes yet to be written if (count + sbc.len > BUF_SIZE) { // buffer is too full to stuff decoded audio in // so it must be written to the device write(ad, buf, count); count = 0; } // sanity check if(count + sbc.len > BUF_SIZE) { fprintf(stderr, "buffer size of %d is too small for decoded data (%d)\n", BUF_SIZE, sbc.len + count); exit(1); } // move the latest decoded data into buf and increase the count memcpy(buf + count, sbc.data, sbc.len); count += sbc.len; // push the pointer in the file forward to the next bit to be decoded // tell the decoder to decode up to the remaining length of the file (!) pos += framelen; framelen = sbc_decode(&sbc, stream + pos, streamlen - pos); } if (count > 0) write(ad, buf, count); close: sbc_finish(&sbc); close(ad); free: free(stream); }
static void encode(char *filename, int subbands, int bitpool, int joint, int dualchannel, int snr, int blocks) { struct au_header au_hdr; sbc_t sbc; int fd, size, srate, codesize, nframes; size_t encoded; ssize_t len; if (sizeof(au_hdr) != 24) { /* Sanity check just in case */ fprintf(stderr, "FIXME: sizeof(au_hdr) != 24\n"); return; } if (strcmp(filename, "-")) { fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open file %s: %s\n", filename, strerror(errno)); return; } } else fd = fileno(stdin); len = read(fd, &au_hdr, sizeof(au_hdr)); if (len < (ssize_t) sizeof(au_hdr)) { if (fd > fileno(stderr)) fprintf(stderr, "Can't read header from file %s: %s\n", filename, strerror(errno)); else perror("Can't read audio header"); goto done; } if (au_hdr.magic != AU_MAGIC || BE_INT(au_hdr.hdr_size) > 128 || BE_INT(au_hdr.hdr_size) < sizeof(au_hdr) || BE_INT(au_hdr.encoding) != AU_FMT_LIN16) { fprintf(stderr, "Not in Sun/NeXT audio S16_BE format\n"); goto done; } sbc_init(&sbc, 0L); switch (BE_INT(au_hdr.sample_rate)) { case 16000: sbc.frequency = SBC_FREQ_16000; break; case 32000: sbc.frequency = SBC_FREQ_32000; break; case 44100: sbc.frequency = SBC_FREQ_44100; break; case 48000: sbc.frequency = SBC_FREQ_48000; break; } srate = BE_INT(au_hdr.sample_rate); sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8; if (BE_INT(au_hdr.channels) == 1) { sbc.mode = SBC_MODE_MONO; if (joint || dualchannel) { fprintf(stderr, "Audio is mono but joint or " "dualchannel mode has been specified\n"); goto done; } } else if (joint && !dualchannel) sbc.mode = SBC_MODE_JOINT_STEREO; else if (!joint && dualchannel) sbc.mode = SBC_MODE_DUAL_CHANNEL; else if (!joint && !dualchannel) sbc.mode = SBC_MODE_STEREO; else { fprintf(stderr, "Both joint and dualchannel mode have been " "specified\n"); goto done; } sbc.endian = SBC_BE; /* Skip extra bytes of the header if any */ if (read(fd, input, BE_INT(au_hdr.hdr_size) - len) < 0) goto done; sbc.bitpool = bitpool; sbc.allocation = snr ? SBC_AM_SNR : SBC_AM_LOUDNESS; sbc.blocks = blocks == 4 ? SBC_BLK_4 : blocks == 8 ? SBC_BLK_8 : blocks == 12 ? SBC_BLK_12 : SBC_BLK_16; if (verbose) { fprintf(stderr, "encoding %s with rate %d, %d blocks, " "%d subbands, %d bits, allocation method %s, " "and mode %s\n", filename, srate, blocks, subbands, bitpool, sbc.allocation == SBC_AM_SNR ? "SNR" : "LOUDNESS", sbc.mode == SBC_MODE_MONO ? "MONO" : sbc.mode == SBC_MODE_STEREO ? "STEREO" : "JOINTSTEREO"); } codesize = sbc_get_codesize(&sbc); nframes = sizeof(input) / codesize; while (1) { unsigned char *inp, *outp; /* read data for up to 'nframes' frames of input data */ size = read(fd, input, codesize * nframes); if (size < 0) { /* Something really bad happened */ perror("Can't read audio data"); break; } if (size < codesize) { /* Not enough data for encoding even a single frame */ break; } /* encode all the data from the input buffer in a loop */ inp = input; outp = output; while (size >= codesize) { len = sbc_encode(&sbc, inp, codesize, outp, sizeof(output) - (outp - output), &encoded); if (len != codesize || encoded <= 0) { fprintf(stderr, "sbc_encode fail, len=%zd, encoded=%lu\n", len, (unsigned long) encoded); break; } size -= len; inp += len; outp += encoded; } len = write(fileno(stdout), output, outp - output); if (len != outp - output) { perror("Can't write SBC output"); break; } if (size != 0) { /* * sbc_encode failure has been detected earlier or end * of file reached (have trailing partial data which is * insufficient to encode SBC frame) */ break; } } sbc_finish(&sbc); done: if (fd > fileno(stderr)) close(fd); }