summaryrefslogtreecommitdiff
authorqidi.huang <qidi.huang@amlogic.com>2018-02-02 10:39:51 (GMT)
committer qidi.huang <qidi.huang@amlogic.com>2018-02-04 14:29:28 (GMT)
commit94837340db8d2bdff8263a067370ed4b8d553c0a (patch)
tree0602570fa86aded49031e984d9d535a53ae95790
parentd9a5234049224989dab628c94a335e5f7cfc63d7 (diff)
downloadaudio-94837340db8d2bdff8263a067370ed4b8d553c0a.zip
audio-94837340db8d2bdff8263a067370ed4b8d553c0a.tar.gz
audio-94837340db8d2bdff8263a067370ed4b8d553c0a.tar.bz2
Audio: fix H.265 hw_sync problem. [1/1]
PD# 158987 1) Length of data returned from HAL to AudioFlinger is wrong. 2) Open audio stream with wrong format. 3) Format of Netflix stream data is changed. Change-Id: I424c519589b35ee95c323b62905565c988b6d09c Signed-off-by: Jian Xu <jian.xu@amlogic.com>
Diffstat
-rw-r--r--audio_hw.c70
-rw-r--r--audio_hwsync.c34
-rw-r--r--audio_hwsync.h13
3 files changed, 69 insertions, 48 deletions
diff --git a/audio_hw.c b/audio_hw.c
index ac30e41..fbdf367 100644
--- a/audio_hw.c
+++ b/audio_hw.c
@@ -134,7 +134,7 @@ static int out_pause(struct audio_stream_out *stream);
static inline short CLIP(int r)
{
return (r > 0x7fff) ? 0x7fff :
- (r < -0x8000) ? 0x8000 :
+ (r < -0x8000) ? -0x8000 :
r;
}
//code here for audio hal mixer when hwsync with af mixer output stream output
@@ -338,7 +338,7 @@ static int start_output_stream(struct aml_stream_out *out)
}
#endif
}
- card = get_aml_card();
+ card = 0;//get_aml_card();
if (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
port = PORT_PCM;
out->config = pcm_config_bt;
@@ -450,7 +450,7 @@ static int start_output_stream_direct(struct aml_stream_out *out)
codec_type = TYPE_MULTI_PCM;
}
- card = get_aml_card();
+ card = 0;//get_aml_card();
ALOGI("%s: hdmi sound card id %d,device id %d \n", __func__, card, port);
if (out->multich== 6) {
ALOGI("round 6ch to 8 ch output \n");
@@ -754,12 +754,8 @@ static audio_channel_mask_t out_get_channels_direct(const struct audio_stream *s
static audio_format_t out_get_format(const struct audio_stream *stream __unused)
{
- ALOGV("Amlogic_HAL - out_get_format() return constant format pcm_16_bit");
- // return AUDIO_FORMAT_PCM_16_BIT;
-
- // return hal_format for passing VTS
const struct aml_stream_out *out = (const struct aml_stream_out *)stream;
- //ALOGV("Amlogic_HAL - out_get_format() = %d", out->hal_format);
+ ALOGV("Amlogic_HAL - out_get_format() = %d", out->hal_format);
// if hal_format doesn't have a valid value,
// return default value AUDIO_FORMAT_PCM_16_BIT
if (out->hal_format == 0)
@@ -767,17 +763,6 @@ static audio_format_t out_get_format(const struct audio_stream *stream __unused)
return out->hal_format;
}
-static audio_format_t out_get_format_direct(const struct audio_stream *stream)
-{
- const struct aml_stream_out *out = (const struct aml_stream_out *)stream;
- ALOGV("Amlogic_HAL - out_get_format_direct() = %d", out->config.format);
- // if hal_format doesn't have a valid value,
- // return default value AUDIO_FORMAT_PCM_16_BIT
- if (out->config.format == 0)
- return AUDIO_FORMAT_PCM_16_BIT;
- return out->config.format;
-}
-
static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
{
return 0;
@@ -960,7 +945,7 @@ out_flush(struct audio_stream_out *stream)
out->last_frames_postion = 0;
out->spdif_enc_init_frame_write_sum = 0;
out->frame_skip_sum = 0;
- out->skip_frame = 3;
+ out->skip_frame = 0;
exit:
pthread_mutex_unlock(&adev->lock);
@@ -1551,7 +1536,7 @@ static ssize_t out_write_legacy(struct audio_stream_out *stream, const void* buf
/* if hwsync output stream are enabled,write other output to a mixe buffer and sleep for the pcm duration time */
if (adev->hwsync_output != NULL && adev->hwsync_output != out) {
//ALOGI("dev hwsync enable,hwsync %p) cur (%p),size %d\n",adev->hwsync_output,out,bytes);
- // out->frame_write_sum += in_frames;
+ out->frame_write_sum += in_frames;
#if 0
if (!out->standby) {
do_output_standby(out);
@@ -2290,6 +2275,7 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf
int samesource_flag = 0;
uint32_t latency_frames = 0;
uint64_t total_frame = 0;
+ int return_bytes = bytes;
audio_hwsync_t *hw_sync = &out->hwsync;
/* acquiring hw device mutex systematically is useful if a low priority thread is waiting
* on the output stream mutex - e.g. executing select_mode() while holding the hw device
@@ -2325,8 +2311,10 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf
out->spdif_enc_init_frame_write_sum = out->frame_write_sum;
}
// todo: check timestamp header PTS discontinue for new sync point after seek
- aml_audio_hwsync_init(&out->hwsync);
- out->spdif_enc_init_frame_write_sum = out->frame_write_sum;
+ if ((codec_type == TYPE_AC3 || codec_type == TYPE_EAC3)) {
+ aml_audio_hwsync_init(&out->hwsync);
+ out->spdif_enc_init_frame_write_sum = out->frame_write_sum;
+ }
}
if (out->standby) {
ret = start_output_stream_direct(out);
@@ -2431,10 +2419,11 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf
}
}
if (outsize > 0) {
+ return_bytes = hwsync_cost_bytes;
in_frames = outsize / frame_size;
write_buf = hw_sync->hw_sync_body_buf;
} else {
- bytes = hwsync_cost_bytes;
+ return_bytes = hwsync_cost_bytes;
pthread_mutex_unlock(&adev->lock);
goto exit;
}
@@ -2445,13 +2434,13 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf
out_frames = in_frames;
buf = (void *) write_buf;
if (getprop_bool("media.hdmihal.outdump")) {
- FILE *fp1 = fopen("/data/tmp/hdmi_audio_out.pcm", "a+");
+ FILE *fp1 = fopen("/data/hal_audio_out.pcm", "a+");
if (fp1) {
- int flen = fwrite((char *)buffer, 1, out_frames * frame_size, fp1);
+ int flen = fwrite((char *)buffer, 1, bytes, fp1);
//LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size);
fclose(fp1);
} else {
- LOGFUNC("could not open file:/data/hdmi_audio_out.pcm");
+ LOGFUNC("could not open file:/data/hal_audio_out.pcm");
}
}
if (codec_type_is_raw_data(out->codec_type) && !(out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)) {
@@ -2535,6 +2524,16 @@ static ssize_t out_write_direct(struct audio_stream_out *stream, const void* buf
sample[kk * 2 + 1] = CLIP(r);
}
}
+#if 0
+ FILE *fp1 = fopen("/data/pcm_write.pcm", "a+");
+ if (fp1) {
+ int flen = fwrite((char *)buf, 1, out_frames * frame_size, fp1);
+ //LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size);
+ fclose(fp1);
+ } else {
+ LOGFUNC("could not open file:/data/pcm_write.pcm");
+ }
+#endif
ret = pcm_write(out->pcm, (void *) buf, out_frames * frame_size);
if (ret == 0) {
out->frame_write_sum += out_frames;
@@ -2560,7 +2559,7 @@ exit:
out_get_sample_rate(&stream->common));
}
- return bytes;
+ return return_bytes;
}
static ssize_t out_write_tv(struct audio_stream_out *stream, const void* buffer,
@@ -2653,7 +2652,7 @@ static int start_input_stream(struct aml_stream_in *in)
adev->in_device |= in->device;
select_devices(adev);
}
- card = get_aml_card();
+ card = 0;//get_aml_card();
ALOGV("%s(in->requested_rate=%d, in->config.rate=%d)",
__FUNCTION__, in->requested_rate, in->config.rate);
@@ -3388,7 +3387,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
hwsync_lpcm = (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC && config->sample_rate <= 48000 &&
audio_is_linear_pcm(config->format) && channel_count <= 2);
ALOGI("hwsync_lpcm %d\n", hwsync_lpcm);
- if (flags & AUDIO_OUTPUT_FLAG_PRIMARY || hwsync_lpcm) {
+ if (flags & AUDIO_OUTPUT_FLAG_PRIMARY/* hwsync_lpcm*/) {
out->stream.common.get_channels = out_get_channels;
out->stream.common.get_format = out_get_format;
out->stream.write = out_write_legacy;
@@ -3402,7 +3401,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
config->sample_rate = out_get_sample_rate(&out->stream.common);
} else if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
out->stream.common.get_channels = out_get_channels_direct;
- out->stream.common.get_format = out_get_format_direct;
+ out->stream.common.get_format = out_get_format;
out->stream.write = out_write_direct;
out->stream.common.standby = out_standby_direct;
if (config->format == AUDIO_FORMAT_DEFAULT) {
@@ -3419,7 +3418,12 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
config->sample_rate = 48000;
}
out->config.rate = out->hal_rate = config->sample_rate;
- out->hal_format = out->config.format= config->format;
+ if (config->format == AUDIO_FORMAT_PCM_16_BIT)
+ out->config.format = PCM_FORMAT_S16_LE;
+ else if (config->format == AUDIO_FORMAT_PCM_32_BIT)
+ out->config.format = PCM_FORMAT_S32_LE;
+
+ out->hal_format = config->format;
if (config->format == AUDIO_FORMAT_IEC61937) {
if (audio_channel_count_from_out_mask(config->channel_mask) == 2 &&
(config->sample_rate == 192000 ||config->sample_rate == 176400)) {
@@ -4006,7 +4010,7 @@ static int adev_open(const hw_module_t* module, const char* name,
adev->hw_device.open_input_stream = adev_open_input_stream;
adev->hw_device.close_input_stream = adev_close_input_stream;
adev->hw_device.dump = adev_dump;
- card = get_aml_card();
+ card = 0;//get_aml_card();
if ((card < 0) || (card > 7)) {
ALOGE("error to get audio card");
return -EINVAL;
diff --git a/audio_hwsync.c b/audio_hwsync.c
index a04fc70..98b9efa 100644
--- a/audio_hwsync.c
+++ b/audio_hwsync.c
@@ -43,7 +43,7 @@ int aml_audio_hwsync_find_frame(audio_hwsync_t *p_hwsync,
size_t remain = in_bytes;
uint8_t *p = (uint8_t *)in_buffer;
uint64_t time_diff = 0;
-
+ int pts_found = 0;
if (p_hwsync == NULL || in_buffer == NULL)
return 0;
@@ -52,27 +52,25 @@ int aml_audio_hwsync_find_frame(audio_hwsync_t *p_hwsync,
//if (p_hwsync->hw_sync_state == HW_SYNC_STATE_RESYNC) {
//}
if (p_hwsync->hw_sync_state == HW_SYNC_STATE_HEADER) {
- //ALOGI("Add to header buffer [%d], 0x%x", out->hw_sync_header_cnt, *p);
+ //ALOGI("Add to header buffer [%d], 0x%x", p_hwsync->hw_sync_header_cnt, *p);
p_hwsync->hw_sync_header[p_hwsync->hw_sync_header_cnt++] = *p++;
remain--;
- if (p_hwsync->hw_sync_header_cnt == 16) {
+ if (p_hwsync->hw_sync_header_cnt == HW_SYNC_HEADER_CNT) {
uint64_t pts;
if (!hwsync_header_valid(&p_hwsync->hw_sync_header[0])) {
//ALOGE("!!!!!!hwsync header out of sync! Resync.should not happen????");
p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER;
- memcpy(p_hwsync->hw_sync_header, p_hwsync->hw_sync_header + 1, 15);
+ memcpy(p_hwsync->hw_sync_header, p_hwsync->hw_sync_header + 1, HW_SYNC_HEADER_CNT - 1);
p_hwsync->hw_sync_header_cnt--;
continue;
}
- if ((in_bytes-remain) > 16)
+ if ((in_bytes-remain) > HW_SYNC_HEADER_CNT)
ALOGI("got the frame sync header cost %zu",in_bytes-remain);
p_hwsync->hw_sync_state = HW_SYNC_STATE_BODY;
p_hwsync->hw_sync_body_cnt = hwsync_header_get_size(&p_hwsync->hw_sync_header[0]);
p_hwsync->hw_sync_frame_size = p_hwsync->hw_sync_body_cnt;
- p_hwsync->body_align_cnt = 0;
+ p_hwsync->hw_sync_header_cnt = 0;
pts = hwsync_header_get_pts(&p_hwsync->hw_sync_header[0]);
- //memcpy(write_buf+write_pos,&p_hwsync->hw_sync_header[0],16);
- //write_pos += 16;
pts = pts * 90 / 1000000;
time_diff = get_pts_gap(pts, p_hwsync->last_apts_from_header) / 90;
ALOGV("pts %"PRIx64",frame len %zu\n", pts, p_hwsync->hw_sync_body_cnt);
@@ -84,24 +82,40 @@ int aml_audio_hwsync_find_frame(audio_hwsync_t *p_hwsync,
}
p_hwsync->last_apts_from_header = pts;
*cur_pts = pts;
+ pts_found = 1;
//ALOGI("get header body_cnt = %d, pts = %lld", out->hw_sync_body_cnt, pts);
}
continue;
} else if (p_hwsync->hw_sync_state == HW_SYNC_STATE_BODY) {
int m = (p_hwsync->hw_sync_body_cnt < remain) ? p_hwsync->hw_sync_body_cnt : remain;
- //ALOGI("m = %d", m);
// process m bytes body with an empty fragment for alignment
if (m > 0) {
//ret = pcm_write(out->pcm, p, m - align);
+#if 0
+ FILE *fp1 = fopen("/data/find_body.pcm", "a+");
+ if (fp1) {
+ int flen = fwrite((char *)p, 1, m, fp1);
+ //LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size);
+ fclose(fp1);
+ } else {
+ ALOGE("could not open file:/data/find_body.pcm");
+ }
+#endif
memcpy(p_hwsync->hw_sync_body_buf + p_hwsync->hw_sync_frame_size - p_hwsync->hw_sync_body_cnt, p, m);
p += m;
remain -= m;
- //ALOGI("pcm_write %d, remain %d", m - align, remain);
p_hwsync->hw_sync_body_cnt -= m;
if (p_hwsync->hw_sync_body_cnt == 0) {
p_hwsync->hw_sync_state = HW_SYNC_STATE_HEADER;
p_hwsync->hw_sync_header_cnt = 0;
*outsize = p_hwsync->hw_sync_frame_size;
+ /*
+ sometimes the audioflinger burst size is smaller than hwsync payload
+ we need use the last found pts when got a complete hwsync payload
+ */
+ if (!pts_found) {
+ *cur_pts = p_hwsync->last_apts_from_header;
+ }
ALOGV("we found the frame total body,yeah\n");
break;//continue;
}
diff --git a/audio_hwsync.h b/audio_hwsync.h
index c78cab0..b65e2ad 100644
--- a/audio_hwsync.h
+++ b/audio_hwsync.h
@@ -30,17 +30,19 @@
#define HW_SYNC_STATE_HEADER 0
#define HW_SYNC_STATE_BODY 1
#define HW_SYNC_STATE_RESYNC 2
+#define HW_SYNC_HEADER_CNT 20
+
#define APTS_DISCONTINUE_THRESHOLD (90000)
#define APTS_DISCONTINUE_THRESHOLD_MIN (90000/1000*100)
#define APTS_DISCONTINUE_THRESHOLD_MAX (5*90000)
typedef struct audio_hwsync {
- uint8_t hw_sync_header[16];
+ uint8_t hw_sync_header[HW_SYNC_HEADER_CNT];
size_t hw_sync_header_cnt;
int hw_sync_state;
- size_t hw_sync_body_cnt;
- int hw_sync_frame_size;
- uint8_t hw_sync_body_buf[4096];
+ uint32_t hw_sync_body_cnt;
+ uint32_t hw_sync_frame_size;
+ uint8_t hw_sync_body_buf[8192];
uint8_t body_align[64];
uint8_t body_align_cnt;
bool first_apts_flag;//flag to indicate set first apts
@@ -52,7 +54,8 @@ static inline bool hwsync_header_valid(uint8_t *header)
return (header[0] == 0x55) &&
(header[1] == 0x55) &&
(header[2] == 0x00) &&
- (header[3] == 0x01);
+ //(header[3] == 0x01 || header[3] == 0x02);
+ (header[3] == 0x02);
}
static inline uint64_t hwsync_header_get_pts(uint8_t *header)