From 94837340db8d2bdff8263a067370ed4b8d553c0a Mon Sep 17 00:00:00 2001 From: qidi.huang Date: Fri, 02 Feb 2018 10:39:51 +0000 Subject: 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 --- 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) -- cgit