audio: hal: Add support to send codec specific data in gapless
Codec specific metadata is sent only for first stream in gapless
playback.
This causes incorrect configuration to be set for second
stream and distortions are observed due to framedrops in adsp.
Add support to send codec specific format data of second stream
during gapless playback.
Use vorbis bitstream format info from metadata instead of hardcoding.
This avoids sending gapless metadata each time set parameters
is called during vorbis playback.
Set flag to send new metadata at start of session for first track
and for the next stream in gapless after return from partial drain.
Change-Id: I3d8be22a4e28c50335820cab1e2b924f3b3b2d1c
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 96b0a8b..9d80112 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -72,6 +72,8 @@
#define AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE "music_offload_ape_sample_rate"
#define AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT "music_offload_seek_table_present"
+#define AUDIO_OFFLOAD_CODEC_VORBIS_BITSTREAM_FMT "music_offload_vorbis_bitstream_fmt"
+
/* Query handle fm parameter*/
#define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm"
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 67d30ca..3d62613 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -682,25 +682,23 @@
if (out->format == AUDIO_FORMAT_FLAC) {
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
if (ret >= 0) {
- out->gapless_mdata.min_blk_size =
out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
if (ret >= 0) {
- out->gapless_mdata.max_blk_size =
out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ALOGV("FLAC metadata: min_blk_size %d, max_blk_size %d min_frame_size %d max_frame_size %d",
out->compr_config.codec->options.flac_dec.min_blk_size,
@@ -713,63 +711,63 @@
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.frame_length = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.compatible_version = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.bit_depth = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_PB, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.pb = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MB, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.mb = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_KB, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.kb = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.num_channels = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.max_run = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.max_frame_bytes = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.avg_bit_rate = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.sample_rate = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.channel_layout_tag = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ALOGV("ALAC CSD values: frameLength %d bitDepth %d numChannels %d"
" maxFrameBytes %d, avgBitRate %d, sampleRate %d",
@@ -785,52 +783,52 @@
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.compatible_version = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.compression_level = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.format_flags = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.blocks_per_frame = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.final_frame_blocks = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.total_frames = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.bits_per_sample = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.num_channels = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.sample_rate = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.seek_table_present = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ALOGV("APE CSD values: compatibleVersion %d compressionLevel %d"
" formatFlags %d blocksPerFrame %d finalFrameBlocks %d"
@@ -849,49 +847,59 @@
}
else if (out->format == AUDIO_FORMAT_VORBIS) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_VORBIS_BITSTREAM_FMT, value, sizeof(value));
+ if (ret >= 0) {
// transcoded bitstream mode
- out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = 1;
- out->send_new_metadata = 1;
+ out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = (atoi(value) > 0) ? 1 : 0;
+ out->is_compr_metadata_avail = true;
+ }
}
else if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->format = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.avg_bit_rate = atoi(value);
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.super_block_align = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.channelmask = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.encodeopt = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
- ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
+ ALOGV("WMA params: fmt %x, bit rate %x, balgn %x, sr %d, chmsk %x"
+ " encop %x, op1 %x, op2 %x",
out->compr_config.codec->format,
+ out->compr_config.codec->options.wma.avg_bit_rate,
out->compr_config.codec->options.wma.super_block_align,
out->compr_config.codec->options.wma.bits_per_sample,
out->compr_config.codec->options.wma.channelmask,
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 9f27219..a47fe77 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1270,6 +1270,10 @@
ALOGE("%s: Next track returned error %d",__func__, ret);
if (ret != -ENETRESET) {
send_callback = true;
+ pthread_mutex_lock(&out->lock);
+ out->send_new_metadata = 1;
+ out->send_next_track_params = true;
+ pthread_mutex_unlock(&out->lock);
event = STREAM_CBK_EVENT_DRAIN_READY;
ALOGV("copl(%p):send drain callback, ret %d", out, ret);
} else
@@ -1593,6 +1597,9 @@
ret = -EIO;
goto error_open;
}
+ /* compress_open sends params of the track, so reset the flag here */
+ out->is_compr_metadata_avail = false;
+
if (out->offload_callback)
compress_nonblock(out->compr, out->non_blocking);
@@ -1767,6 +1774,8 @@
} else {
ALOGD("copl(%p):standby", out);
stop_compressed_output_l(out);
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
out->gapless_mdata.encoder_delay = 0;
out->gapless_mdata.encoder_padding = 0;
if (out->compr != NULL) {
@@ -1792,7 +1801,6 @@
{
int ret = 0;
char value[32];
- bool is_meta_data_params = false;
if (!out || !parms) {
ALOGE("%s: return invalid ",__func__);
@@ -1805,36 +1813,19 @@
out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ALOGV("ADTS format is set in offload mode");
}
- out->send_new_metadata = 1;
}
ret = audio_extn_parse_compress_metadata(out, parms);
- ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
- if(ret >= 0)
- is_meta_data_params = true;
- ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
- if(ret >= 0)
- is_meta_data_params = true;
- ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
- if(ret >= 0)
- is_meta_data_params = true;
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
if (ret >= 0) {
- is_meta_data_params = true;
out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
if (ret >= 0) {
- is_meta_data_params = true;
out->gapless_mdata.encoder_padding = atoi(value);
}
- if(!is_meta_data_params) {
- ALOGV("%s: Not gapless meta data params", __func__);
- return 0;
- }
- out->send_new_metadata = 1;
ALOGV("%s new encoder delay %u and padding %u", __func__,
out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
@@ -2126,6 +2117,12 @@
ALOGD("copl(%p):send new gapless metadata", out);
compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
out->send_new_metadata = 0;
+ if (out->send_next_track_params && out->is_compr_metadata_avail) {
+ ALOGD("copl(%p):send next track params in gapless", out);
+ compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
+ }
}
ret = compress_write(out->compr, buffer, bytes);
@@ -2921,6 +2918,8 @@
}
out->send_new_metadata = 1;
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
out->offload_state = OFFLOAD_STATE_IDLE;
out->playback_started = 0;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 67f5279..88f5f15 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -213,6 +213,8 @@
void *offload_cookie;
struct compr_gapless_mdata gapless_mdata;
int send_new_metadata;
+ bool send_next_track_params;
+ bool is_compr_metadata_avail;
unsigned int bit_width;
struct audio_device *dev;