static int _out_a2dp_suspend(struct astream_out *out, bool suspend) { pthread_mutex_lock(&out->lock); out->suspended = suspend; out_standby_stream_locked(out); pthread_mutex_unlock(&out->lock); return 0; }
static int out_standby(struct audio_stream *stream) { struct astream_out *out = (struct astream_out *)stream; pthread_mutex_lock(&out->lock); out_standby_stream_locked(out); pthread_mutex_unlock(&out->lock); return 0; }
static int out_close_stream_locked(struct astream_out *out) { out_standby_stream_locked(out); if (out->data) { LOGV("%s: calling a2dp_cleanup()", __func__); a2dp_cleanup(out->data); out->data = NULL; } return 0; }
static int out_standby(struct audio_stream *stream) { struct astream_out *out = (struct astream_out *)stream; pthread_mutex_lock(&out->lock); #ifdef GLOBALCONFIG_BLUETOOTH_A2DP_NOT_STANDBY // for T map with a2dp char checkTmap[PROPERTY_VALUE_MAX]; property_get("sys.sktgps", checkTmap, "0"); if (atoi(checkTmap) == 1) { LOGV("======================================================"); LOGV("T-Map is operating, a2dp doesn't enter standby state"); LOGV("======================================================"); pthread_mutex_unlock(&out->lock); return 0; } #endif out_standby_stream_locked(out); pthread_mutex_unlock(&out->lock); return 0; }
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { struct astream_out *out = (struct astream_out *)stream; int ret; size_t frames_total = bytes / sizeof(uint32_t); // always stereo 16 bit uint32_t *buf = (uint32_t *)buffer; size_t frames_written = 0; pthread_mutex_lock(&out->buf_lock); pthread_mutex_lock(&out->lock); if (!out->bt_enabled || out->suspended) { LOGV("a2dp write: bluetooth disabled bt_en %d, suspended %d", out->bt_enabled, out->suspended); ret = -1; goto err_bt_disabled; } if (out->standby) { acquire_wake_lock(PARTIAL_WAKE_LOCK, A2DP_WAKE_LOCK_NAME); out->standby = false; out->last_write_time = system_time(); out->buf_rd_idx = 0; out->buf_wr_idx = 0; out->buf_frames_ready = 0; } ret = _out_init_locked(out, NULL); if (ret < 0) { goto err_init; } pthread_mutex_unlock(&out->lock); if(isToMono){ int16_t mono; int16_t *stereoData = (int16_t *)buffer; uint16_t i; for(i = 0; i<bytes/4; i++) { // to Mono mono = (int16_t)(((int32_t)*(stereoData+2*i) + (int32_t)*(stereoData+2*i+1)) >> 1); // to Stereo again *(stereoData+2*i) = *(stereoData+2*i+1) = mono; } } while (frames_written < frames_total) { size_t frames = _out_frames_available_locked(out); if (frames == 0) { int ret = pthread_cond_timeout_np(&out->buf_cond, &out->buf_lock, BUF_WRITE_AVAILABILITY_TIMEOUT_MS); if (ret != 0) { pthread_mutex_lock(&out->lock); goto err_write; } frames = _out_frames_available_locked(out); } if (frames > frames_total - frames_written) { frames = frames_total - frames_written; } memcpy(out->buf + out->buf_wr_idx, buf + frames_written, frames * sizeof(uint32_t)); frames_written += frames; _out_inc_wr_idx_locked(out, frames); pthread_mutex_lock(&out->lock); if (out->standby) { goto err_write; } pthread_mutex_unlock(&out->lock); } pthread_mutex_unlock(&out->buf_lock); return bytes; /* out->lock must be locked and out->buf_lock unlocked when jumping here */ err_write: err_init: err_bt_disabled: pthread_mutex_unlock(&out->buf_lock); LOGV("!!!! write error"); out_standby_stream_locked(out); pthread_mutex_unlock(&out->lock); /* XXX: simulate audio output timing in case of error?!?! */ usleep(out->buffer_duration_us); return ret; }