summaryrefslogtreecommitdiff
authorJian Xu <jian.xu@amlogic.com>2016-10-31 12:09:09 (GMT)
committer Jian Xu <jian.xu@amlogic.com>2016-10-31 12:10:04 (GMT)
commit8130d6718f86217daf2f4bdc35180c0b6a9aabf3 (patch)
tree78022efacc33b73f2b7abb0c5b2e28709611e708
parent56f838805e84501d5c07b1f92ef41d0db64bbde2 (diff)
downloadaudio-8130d6718f86217daf2f4bdc35180c0b6a9aabf3.zip
audio-8130d6718f86217daf2f4bdc35180c0b6a9aabf3.tar.gz
audio-8130d6718f86217daf2f4bdc35180c0b6a9aabf3.tar.bz2
PD#133610: audio: fix audioserver deadlock issue when standy
Change-Id: Ifc00a0c5959649c47f92d94e42e589d36cf3db6c
Diffstat
-rw-r--r--audio_hw.c143
-rw-r--r--audio_hw.h3
-rw-r--r--spdifenc_wrap.cpp11
-rw-r--r--spdifenc_wrap.h4
4 files changed, 100 insertions, 61 deletions
diff --git a/audio_hw.c b/audio_hw.c
index de44ad0..462a101 100644
--- a/audio_hw.c
+++ b/audio_hw.c
@@ -54,7 +54,7 @@
//extern uint64_t spdifenc_get_total();
extern void aml_audio_hwsync_clear_status(struct aml_stream_out *out);
extern int aml_audio_hwsync_find_frame(struct aml_stream_out *out,
- const void *in_buffer, size_t in_bytes, uint64_t *cur_pts, int *outsize);
+ const void *in_buffer, size_t in_bytes, uint64_t *cur_pts, int *outsize);
/* ALSA cards for AML */
#define CARD_AMLOGIC_BOARD 0
@@ -486,7 +486,7 @@ static int start_output_stream(struct aml_stream_out *out)
if (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
port = PORT_PCM;
out->config = pcm_config_bt;
- } else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT){
+ } else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
port = PORT_SPDIF;
}
@@ -638,8 +638,8 @@ static int start_output_stream_direct(struct aml_stream_out *out)
out->config.channels = 8;
}
ALOGI("ALSA open configs: channels=%d, format=%d, period_count=%d, period_size=%d,,rate=%d",
- out->config.channels, out->config.format, out->config.period_count,
- out->config.period_size, out->config.rate);
+ out->config.channels, out->config.format, out->config.period_count,
+ out->config.period_size, out->config.rate);
if (out->pcm == NULL) {
out->pcm = pcm_open(card, port, PCM_OUT, &out->config);
@@ -653,7 +653,7 @@ static int start_output_stream_direct(struct aml_stream_out *out)
}
if (codec_type_is_raw_data(codec_type) && !(out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)) {
- spdifenc_init(out->pcm);
+ spdifenc_init(out->pcm, out->hal_format);
out->spdif_enc_init_frame_write_sum = out->frame_write_sum;
}
out->codec_type = codec_type;
@@ -831,32 +831,32 @@ static size_t out_get_buffer_size(const struct audio_stream *stream)
*/
size_t size = out->config.period_size;
switch (out->hal_format) {
- case AUDIO_FORMAT_AC3:
- case AUDIO_FORMAT_DTS:
- if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) {
- size = 4 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT;
- } else {
- size = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE / 2;
- }
- break;
- case AUDIO_FORMAT_E_AC3:
- if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) {
- size = 16 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT;
- } else {
- size = PERIOD_SIZE; //2*PLAYBACK_PERIOD_COUNT*PERIOD_SIZE;
- }
- break;
- case AUDIO_FORMAT_DTS_HD:
- case AUDIO_FORMAT_TRUEHD:
- if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) {
- size = 16 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT;
- } else {
- size = 4 * PLAYBACK_PERIOD_COUNT * PERIOD_SIZE;
- }
- break;
- case AUDIO_FORMAT_PCM:
- default:
- size = PERIOD_SIZE;
+ case AUDIO_FORMAT_AC3:
+ case AUDIO_FORMAT_DTS:
+ if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) {
+ size = 4 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT;
+ } else {
+ size = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE / 2;
+ }
+ break;
+ case AUDIO_FORMAT_E_AC3:
+ if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) {
+ size = 16 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT;
+ } else {
+ size = PERIOD_SIZE; //2*PLAYBACK_PERIOD_COUNT*PERIOD_SIZE;
+ }
+ break;
+ case AUDIO_FORMAT_DTS_HD:
+ case AUDIO_FORMAT_TRUEHD:
+ if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) {
+ size = 16 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT;
+ } else {
+ size = 4 * PLAYBACK_PERIOD_COUNT * PERIOD_SIZE;
+ }
+ break;
+ case AUDIO_FORMAT_PCM:
+ default:
+ size = PERIOD_SIZE;
}
size = ((size + 15) / 16) * 16;
return size * audio_stream_out_frame_size((struct audio_stream_out *)stream);
@@ -963,7 +963,30 @@ static int do_output_standby(struct aml_stream_out *out)
}
return 0;
}
+/* must be called with hw device and output stream mutexes locked */
+static int do_output_standby_direct(struct aml_stream_out *out)
+{
+ int status = 0;
+
+ ALOGI("%s,out %p", __FUNCTION__, out);
+ if (!out->standby) {
+ if (out->buffer) {
+ free(out->buffer);
+ out->buffer = NULL;
+ }
+
+ out->standby = 1;
+ pcm_close(out->pcm);
+ out->pcm = NULL;
+ }
+ set_codec_type(TYPE_PCM);
+ /* clear the hdmitx channel config to default */
+ if (out->multich == 6) {
+ sysfs_set_sysfs_str("/sys/class/amhdmitx/amhdmitx0/aud_output_chs", "0:0");
+ }
+ return status;
+}
static int out_standby(struct audio_stream *stream)
{
LOGFUNC("%s(%p)", __FUNCTION__, stream);
@@ -1001,9 +1024,6 @@ static int out_standby_direct(struct audio_stream *stream)
if (out->multich == 6) {
sysfs_set_sysfs_str("/sys/class/amhdmitx/amhdmitx0/aud_output_chs", "0:0");
}
- if (out->hal_format != AUDIO_FORMAT_DTS_HD) {
- set_codec_type(TYPE_PCM);
- }
pthread_mutex_unlock(&out->lock);
pthread_mutex_unlock(&out->dev->lock);
return status;
@@ -1020,9 +1040,15 @@ out_flush(struct audio_stream_out *stream)
LOGFUNC("%s(%p)", __FUNCTION__, stream);
struct aml_stream_out *out = (struct aml_stream_out *) stream;
struct aml_audio_device *adev = out->dev;
+ do_standby_func standy_func = NULL;
+ if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
+ standy_func = do_output_standby_direct;
+ } else {
+ standy_func = do_output_standby;
+ }
pthread_mutex_lock(&adev->lock);
pthread_mutex_lock(&out->lock);
- do_output_standby(out);
+ standy_func(out);
out->frame_write_sum = 0;
out->last_frames_postion = 0;
pthread_mutex_unlock(&adev->lock);
@@ -1040,7 +1066,15 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
int ret;
uint val = 0;
bool force_input_standby = false;
-
+ do_standby_func standy_func = NULL;
+ do_startup_func startup_func = NULL;
+ if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
+ standy_func = do_output_standby_direct;
+ startup_func = start_output_stream_direct;
+ } else {
+ standy_func = do_output_standby;
+ startup_func = start_output_stream;
+ }
LOGFUNC("%s(kvpairs(%s), out_device=%#x)", __FUNCTION__, kvpairs, adev->out_device);
parms = str_parms_create_str(kvpairs);
@@ -1052,7 +1086,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
if (((adev->out_device & AUDIO_DEVICE_OUT_ALL) != val) && (val != 0)) {
if (1/* out == adev->active_output[0]*/) {
ALOGI("audio hw select device!\n");
- do_output_standby(out);
+ standy_func(out);
/* a change in output device may change the microphone selection */
if (adev->active_input &&
adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
@@ -1063,7 +1097,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
(adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) ||
((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
(adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET))) {
- do_output_standby(out);
+ standy_func(out);
}
}
adev->out_device &= ~AUDIO_DEVICE_OUT_ALL;
@@ -1090,8 +1124,8 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
pthread_mutex_lock(&adev->lock);
pthread_mutex_lock(&out->lock);
if (!out->standby) {
- do_output_standby(out);
- start_output_stream(out);
+ standy_func(out);
+ startup_func(out);
out->standby = 0;
}
pthread_mutex_unlock(&adev->lock);
@@ -1109,8 +1143,8 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
pthread_mutex_lock(&adev->lock);
pthread_mutex_lock(&out->lock);
if (!out->standby) {
- do_output_standby(out);
- start_output_stream(out);
+ standy_func(out);
+ startup_func(out);
out->standby = 0;
}
pthread_mutex_unlock(&adev->lock);
@@ -1197,7 +1231,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
out->last_frames_postion = 0;
/* clear up previous playback output status */
if (!out->standby) {
- do_output_standby(out);
+ standy_func(out);
}
//adev->hwsync_output = sync_enable?out:NULL;
if (sync_enable) {
@@ -1342,7 +1376,7 @@ static int audio_effect_process(struct audio_stream_out *stream,
}
static ssize_t out_write_legacy(struct audio_stream_out *stream, const void* buffer,
- size_t bytes)
+ size_t bytes)
{
int ret = 0;
size_t oldBytes = bytes;
@@ -2013,7 +2047,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
samesource_flag = get_sysfs_int("/sys/class/audiodsp/audio_samesource");
if (samesource_flag == 0 && codec_type == 0) {
ALOGI("to enable same source,need reset alsa,type %d,same source flag %d \n",
- codec_type, samesource_flag);
+ codec_type, samesource_flag);
pcm_stop(out->pcm);
}
}
@@ -2063,7 +2097,7 @@ exit:
}
static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buffer,
- size_t bytes)
+ size_t bytes)
{
int ret = 0;
struct aml_stream_out *out = (struct aml_stream_out *) stream;
@@ -2102,7 +2136,7 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf
we use the AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO to distiguwish the two cases.
*/
if ((codec_type == TYPE_AC3 || codec_type == TYPE_EAC3) && (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)) {
- spdifenc_init(out->pcm);
+ spdifenc_init(out->pcm, out->hal_format);
out->spdif_enc_init_frame_write_sum = out->frame_write_sum;
}
// todo: check timestamp header PTS discontinue for new sync point after seek
@@ -2382,7 +2416,7 @@ exit:
}
static ssize_t out_write_tv(struct audio_stream_out *stream, const void* buffer,
- size_t bytes)
+ size_t bytes)
{
// TV temporarily use legacy out write.
/* TODO: add TV platform specific write here */
@@ -3145,7 +3179,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
int ret;
ALOGI("**enter %s(devices=0x%04x,format=%#x, ch=0x%04x, SR=%d, flags=0x%x)", __FUNCTION__, devices,
- config->format, config->channel_mask, config->sample_rate, flags);
+ config->format, config->channel_mask, config->sample_rate, flags);
out = (struct aml_stream_out *)calloc(1, sizeof(struct aml_stream_out));
if (!out) {
@@ -3162,10 +3196,11 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->stream.common.get_channels = out_get_channels;
out->stream.common.get_format = out_get_format;
- if (out->is_tv_platform)
+ if (out->is_tv_platform) {
out->stream.write = out_write_tv;
- else
+ } else {
out->stream.write = out_write;
+ }
out->stream.common.standby = out_standby;
out->hal_rate = out->config.rate;
@@ -3180,7 +3215,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
//out->config = pcm_config_out_direct;
out->hal_channel_mask = config->channel_mask;
if (config->sample_rate == 0) {
- config->sample_rate = 48000;
+ config->sample_rate = 48000;
}
out->config.rate = out->hal_rate = config->sample_rate;
out->hal_format = config->format;
@@ -3193,7 +3228,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
if (channel_count > 2) {
ALOGI("[adev_open_output_stream]: out/%p channel/%d\n", out,
- channel_count);
+ channel_count);
out->multich = channel_count;
out->config.channels = channel_count;
}
@@ -3202,7 +3237,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->config.channels = 2;
out->multich = 2;
}
- } else if(flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC){
+ } else if (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) {
// TODO: add hwsync write here
//out->stream.write = out_write_hwsync;
}
diff --git a/audio_hw.h b/audio_hw.h
index cd82df3..890f8b1 100644
--- a/audio_hw.h
+++ b/audio_hw.h
@@ -159,5 +159,6 @@ struct aml_stream_in {
int read_status;
struct aml_audio_device *dev;
};
-
+typedef int (*do_standby_func)(struct aml_stream_out *out);
+typedef int (*do_startup_func)(struct aml_stream_out *out);
#endif
diff --git a/spdifenc_wrap.cpp b/spdifenc_wrap.cpp
index 469169c..9eb9a8a 100644
--- a/spdifenc_wrap.cpp
+++ b/spdifenc_wrap.cpp
@@ -2,6 +2,7 @@
#define LOG_TAG "AudioSPDIF-wrap"
#include <stdint.h>
#include <utils/Log.h>
+#include <system/audio.h>
#include <audio_utils/spdif/SPDIFEncoder.h>
#include <tinyalsa/asoundlib.h>
#include <cutils/properties.h>
@@ -31,8 +32,9 @@ namespace android
class MySPDIFEncoder : public SPDIFEncoder
{
public:
- MySPDIFEncoder(struct pcm *mypcm)
- : pcm_handle(mypcm), mTotalBytes(0), eac3_frame(0)
+ MySPDIFEncoder(struct pcm *mypcm, audio_format_t format)
+ : SPDIFEncoder(format),
+ pcm_handle(mypcm), mTotalBytes(0), eac3_frame(0), mformat(format)
{};
virtual ssize_t writeOutput(const void* buffer, size_t bytes)
{
@@ -61,15 +63,16 @@ protected:
private:
uint64_t mTotalBytes;
uint64_t eac3_frame;
+ audio_format_t mformat;
};
static MySPDIFEncoder *myencoder = NULL;
-extern "C" int spdifenc_init(struct pcm *mypcm)
+extern "C" int spdifenc_init(struct pcm *mypcm, audio_format_t format)
{
if (myencoder) {
delete myencoder;
myencoder = NULL;
}
- myencoder = new MySPDIFEncoder(mypcm);
+ myencoder = new MySPDIFEncoder(mypcm, format);
if (myencoder == NULL) {
ALOGE("init SPDIFEncoder failed \n");
return -1;
diff --git a/spdifenc_wrap.h b/spdifenc_wrap.h
index 5d18df3..2d388f3 100644
--- a/spdifenc_wrap.h
+++ b/spdifenc_wrap.h
@@ -5,7 +5,7 @@
extern "C" {
#endif
-int spdifenc_init(struct pcm *mypcm);
+int spdifenc_init(struct pcm *mypcm, audio_format_t format);
int spdifenc_write(const void *buffer, size_t numBytes);
uint64_t spdifenc_get_total(void);
@@ -13,4 +13,4 @@ uint64_t spdifenc_get_total(void);
}
#endif
-#endif //__SPDIFENC_WRAP_H__ \ No newline at end of file
+#endif //__SPDIFENC_WRAP_H__