audio: qahw: Fix for incorrect frame issue for DTS passthrough
-For DTS stream, only send data till STREAM DATA chunk as DSP
can't parse other chunks.
-For .cpt stream send all the bytes.
Change-Id: I561e3c76b1611dd351eb2aaa5741f022af767b17
diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c
index d8634a4..db189eb 100644
--- a/qahw_api/test/qahw_playback_test.c
+++ b/qahw_api/test/qahw_playback_test.c
@@ -64,7 +64,12 @@
#define DEFAULT_PRESET_STRENGTH -1
+#define DTSHD_CHUNK_HEADER_KEYWORD "DTSHDHDR"
+#define DTSHD_CHUNK_STREAM_KEYWORD "STRMDATA"
+#define DTSHD_META_KEYWORD_SIZE 8 /*in bytes */
+
static int get_wav_header_length (FILE* file_stream);
+static ssize_t get_bytes_to_read(FILE* file, int filetype);
static void init_streams(void);
int pthread_cancel(pthread_t thread);
@@ -652,6 +657,21 @@
pthread_t drift_query_thread;
struct drift_data drift_params;
+ int offset = 0;
+ bool is_offload = params->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+ size_t bytes_wanted = 0;
+ size_t write_length = 0;
+ size_t bytes_remaining = 0;
+ size_t bytes_written = 0;
+
+ size_t bytes_read = 0;
+ char *data_ptr = NULL;
+ bool exit = false;
+ bool read_complete_file = true;
+ ssize_t bytes_to_read = 0;
+ int32_t latency;
+
+
memset(&drift_params, 0, sizeof(struct drift_data));
fprintf(log_file, "stream %d: play_later %d \n", params->stream_index, params->play_later);
@@ -710,22 +730,13 @@
}
fprintf(log_file, "stream %d: kvpairs are set\n", params->stream_index);
break;
- default:
+ case FILE_DTS:
+ read_complete_file = false;
+ break;
+ default:
break;
}
- int offset = 0;
- bool is_offload = params->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
- size_t bytes_wanted = 0;
- size_t write_length = 0;
- size_t bytes_remaining = 0;
- size_t bytes_written = 0;
- size_t bytes_read = 0;
- char *data_ptr = NULL;
- bool exit = false;
- int32_t latency;
-
-
if (is_offload) {
fprintf(log_file, "stream %d: set callback for offload stream for playback usecase\n", params->stream_index);
qahw_out_set_callback(params->out_handle, async_callback, params);
@@ -835,28 +846,37 @@
if (event_trigger == true)
tigger_event(params->out_handle);
+ bytes_to_read = get_bytes_to_read(params->file_stream, params->filetype);
+ if (bytes_to_read <= 0)
+ read_complete_file = true;
+
while (!exit && !stop_playback) {
if (!bytes_remaining) {
fprintf(log_file, "\nstream %d: reading bytes %zd\n", params->stream_index, bytes_wanted);
bytes_read = read_bytes(params, data_ptr, bytes_wanted);
fprintf(log_file, "stream %d: read bytes %zd\n", params->stream_index, bytes_read);
- if (bytes_read <= 0) {
- if (is_eof(params)) {
- fprintf(log_file, "stream %d: end of file\n", params->stream_index);
- if (is_offload) {
- pthread_mutex_lock(¶ms->drain_lock);
- qahw_out_drain(params->out_handle, QAHW_DRAIN_ALL);
- pthread_cond_wait(¶ms->drain_cond, ¶ms->drain_lock);
- fprintf(log_file, "stream %d: out of compress drain\n", params->stream_index);
- pthread_mutex_unlock(¶ms->drain_lock);
- }
- /* Caution: Below ADL log shouldnt be altered without notifying automation APT since
- * it used for automation testing
- */
- fprintf(log_file, "ADL: stream %d: playback completed successfully\n", params->stream_index);
+ if ((!read_complete_file && (bytes_to_read <= 0)) || (bytes_read <= 0)) {
+ fprintf(log_file, "stream %d: end of file\n", params->stream_index);
+ if (is_offload) {
+ pthread_mutex_lock(¶ms->drain_lock);
+ qahw_out_drain(params->out_handle, QAHW_DRAIN_ALL);
+ pthread_cond_wait(¶ms->drain_cond, ¶ms->drain_lock);
+ fprintf(log_file, "stream %d: out of compress drain\n", params->stream_index);
+ pthread_mutex_unlock(¶ms->drain_lock);
}
+ /*
+ * Caution: Below ADL log shouldnt be altered without notifying
+ * automation APT since it used for automation testing
+ */
+ fprintf(log_file, "ADL: stream %d: playback completed successfully\n", params->stream_index);
exit = true;
continue;
+ } else {
+ if (!read_complete_file) {
+ bytes_to_read -= bytes_read;
+ if ((bytes_to_read > 0) && (bytes_to_read < bytes_wanted))
+ bytes_wanted = bytes_to_read;
+ }
}
bytes_remaining = write_length = bytes_read;
}
@@ -864,6 +884,9 @@
offset = write_length - bytes_remaining;
fprintf(log_file, "stream %d: writing to hal %zd bytes, offset %d, write length %zd\n",
params->stream_index, bytes_remaining, offset, write_length);
+
+
+ bytes_written = bytes_remaining;
bytes_written = write_to_hal(params->out_handle, data_ptr+offset, bytes_remaining, params);
if (bytes_written < 0) {
fprintf(stderr, "write failed %d", bytes_written);
@@ -877,6 +900,7 @@
params->stream_index, bytes_written, bytes_remaining, latency);
}
+
if (params->ethread_data != nullptr) {
fprintf(log_file, "stream %d: un-loading effects\n", params->stream_index);
// disable effect
@@ -1657,6 +1681,104 @@
return wav_header_len;
}
+/* convert big-endian to little-endian */
+uint64_t convert_BE_to_LE( uint64_t in)
+{
+ uint64_t out;
+ char *p_in = (char *) ∈
+ char *p_out = (char *) &out;
+ p_out[0] = p_in[7];
+ p_out[1] = p_in[6];
+ p_out[2] = p_in[5];
+ p_out[3] = p_in[4];
+ p_out[4] = p_in[3];
+ p_out[5] = p_in[2];
+ p_out[6] = p_in[1];
+ p_out[7] = p_in[0];
+ return out;
+}
+
+static ssize_t get_bytes_to_read(FILE* file, int file_type)
+{
+ char keyword[DTSHD_META_KEYWORD_SIZE + 1];
+ bool is_dtshd_stream =false;
+ uint64_t read_chunk_size = 0;
+ uint64_t chunk_size = 0;
+ ssize_t file_read_size = -1;
+ ssize_t header_read_size = -1;
+ long int pos;
+ int ret = 0;
+
+ if (file_type == FILE_DTS) {
+
+ //first locate the ASCII header "DTSHDHDR"identifier
+ while (!feof(file) && (header_read_size < 1024) &
+ (fread(&keyword, sizeof(char), DTSHD_META_KEYWORD_SIZE, file)
+ == DTSHD_META_KEYWORD_SIZE)) {
+ //update the number of bytes was read for identifying the header
+ header_read_size = ftell(file);
+
+ if (strncmp(keyword, DTSHD_CHUNK_HEADER_KEYWORD,
+ DTSHD_META_KEYWORD_SIZE) == 0) {
+ // read the 8-byte size field
+ if (fread(&read_chunk_size, sizeof(char),
+ DTSHD_META_KEYWORD_SIZE, file) == DTSHD_META_KEYWORD_SIZE) {
+ is_dtshd_stream = true;
+ chunk_size = convert_BE_to_LE(read_chunk_size);
+ pos = ftell(file);
+ fseek(file, chunk_size, SEEK_CUR);
+ fprintf(stderr,"DTS header chunk offset:%lu and chunk_size:%llu \n",
+ pos, chunk_size);
+ break;
+ }
+ else {
+ printf(" file read error \n");
+ break;
+ } //end reading chunk size
+ }
+ }
+
+ if (!is_dtshd_stream) {
+ fprintf(stderr, "raw dts hd stream");
+ fseek(file, 0, SEEK_SET);
+ return file_read_size;
+ }
+ /* parsing each chunk data */
+ while (!feof(file) &&
+ fread(&keyword, sizeof(uint8_t), DTSHD_META_KEYWORD_SIZE, file)
+ == DTSHD_META_KEYWORD_SIZE) {
+ /* check for the stream audio data */
+ ret = strncmp(keyword,
+ DTSHD_CHUNK_STREAM_KEYWORD,
+ DTSHD_META_KEYWORD_SIZE);
+ if (!ret) {
+ ret = fread(&read_chunk_size, 1, DTSHD_META_KEYWORD_SIZE, file);
+ chunk_size = convert_BE_to_LE(read_chunk_size);
+ if (ret != DTSHD_META_KEYWORD_SIZE) {
+ fprintf(stderr,"%s %d file read error ret %\n",
+ __func__, __LINE__, ret);
+ file_read_size = -EINVAL;
+ break;
+ }
+ file_read_size = chunk_size;
+ fprintf(stderr, "DTS read_chunk_size %llu and file_read_size: %zd\n",
+ chunk_size,
+ file_read_size);
+ break;
+ } else {
+ fprintf(log_file, "Identified chunk of %c %c %c %c %c %c %c %c \n",
+ keyword[0], keyword[1], keyword[2], keyword[3],
+ keyword[4], keyword[5], keyword[6], keyword[7] );
+ ret = fread(&read_chunk_size, 1, DTSHD_META_KEYWORD_SIZE, file);
+ pos = ftell(file);
+ chunk_size = convert_BE_to_LE(read_chunk_size);
+ fseek(file, chunk_size, SEEK_CUR);
+ }
+ }
+ }
+ return file_read_size;
+}
+
static qahw_module_handle_t * load_hal(audio_devices_t dev) {
qahw_module_handle_t *hal = NULL;