344 lines
13 KiB
C
344 lines
13 KiB
C
/*
|
|
* hardware/amlogic/audio/utils/aml_dump_debug.c
|
|
*
|
|
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* This source code is subject to the terms and conditions defined in the
|
|
* file 'LICENSE' which is part of this source code package.
|
|
*
|
|
*/
|
|
#define LOG_TAG "aml_dump_debug"
|
|
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
|
|
#include "aml_audio_log.h"
|
|
|
|
#include "aml_dump_debug.h"
|
|
#include "aml_malloc_debug.h"
|
|
#include "aml_audio_property.h"
|
|
|
|
#define FRAME_MAGIC 0x46524D45 // "FRME"
|
|
|
|
typedef struct {
|
|
uint32_t frame_magic;
|
|
uint32_t buffer_size; // audio data size
|
|
uint32_t iec_data_size; // IEC data size
|
|
} frame_header;
|
|
typedef struct aml_dump_debug {
|
|
pthread_t threadid;
|
|
bool bexit;
|
|
dump_debug_item_t *items;
|
|
|
|
} aml_dump_debug_t;
|
|
|
|
aml_dump_debug_t * g_debug_handle = NULL;
|
|
static char defaultDumpPath[] = "/data/vendor/audiohal/";
|
|
|
|
/*-----------------------------------------------------------
|
|
*this table sequence must match with enum AML_DUMP_DEBUG_INFO
|
|
*-----------------------------------------------------------
|
|
*/
|
|
|
|
dump_debug_item_t aml_debug_items[AML_DEBUG_DUMP_MAX] = {
|
|
/*define debug items*/
|
|
{AML_DEBUG_AUDIOHAL_DEBUG, AML_DEBUG_AUDIOHAL_DEBUG_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_DEBUG
|
|
{AML_DEBUG_AUDIOHAL_LEVEL_DETECT, AML_DEBUG_AUDIOHAL_LEVEL_DETECT_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_LEVEL_DETECT
|
|
{AML_DEBUG_AUDIOHAL_HW_SYNC, AML_DEBUG_AUDIOHAL_HW_SYNC_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_HW_SYNC
|
|
{AML_DEBUG_AUDIOHAL_ALSA, AML_DEBUG_AUDIOHAL_ALSA_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_ALSA
|
|
{AML_DEBUG_AUDIOHAL_SYNCPTS, AML_DEBUG_AUDIOHAL_SYNCPTS_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_SYNCPTS
|
|
{AML_DEBUG_AUDIOHAL_MATENC, AML_DEBUG_AUDIOHAL_MATENC_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_MATENC
|
|
{AML_DEBUG_AUDIOHAL_TRACE, AML_DEBUG_AUDIOHAL_TRACE_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_TRACE
|
|
{AML_DEBUG_AUDIOHAL_DECODED_INFO, AML_DEBUG_AUDIOINFO_REPORT_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_DECODED_INFO
|
|
{AML_DEBUG_AUDIOHAL_AUT, AML_DEBUG_AUDIOHAL_AUT_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_AUT
|
|
{AML_DEBUG_AUDIOHAL_EDID, AML_DEBUG_AUDIOHAL_EDID_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_EDID
|
|
{AML_DEBUG_AUDIOHAL_MS12, AML_DEBUG_AUDIOHAL_MS12_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_MS12
|
|
{AML_DEBUG_AUDIOHAL_MEDIA_SYNC, AML_DEBUG_AUDIOHAL_MEDIA_SYNC_PROPERTY, 0}, //AML_DEBUG_MEDIA_SYNC
|
|
{AML_DEBUG_AUDIOHAL_DTS, AML_DEBUG_AUDIOHAL_DTS_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_DTS
|
|
{AML_DEBUG_AUDIOHAL_CONTINUOUS_STANDBY, AML_DEBUG_AUDIOHAL_CONTINUOUS_STANDBY_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_CONTINUOUS_STANDBY
|
|
{AML_DEBUG_AUDIOHAL_PARSER, AML_DEBUG_AUDIOHAL_PARSER_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_PARSER
|
|
{AML_DEBUG_AUDIOHAL_GAME_MODE, AML_DEBUG_AUDIOHAL_GAME_MODE_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_GAME_MODE
|
|
{AML_DEBUG_AUDIOHAL_HWMIXER, AML_DEBUG_AUDIOHAL_HWMIXER_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_HWMIXER
|
|
{AML_DEBUG_AUDIOHAL_LIMITER, AML_DEBUG_AUDIOHAL_LIMITER_PROPERTY, 0}, //AML_DEBUG_AUDIOHAL_LIMITER
|
|
|
|
/*define dump items*/
|
|
{AML_DUMP_AUDIOHAL_IN, AML_DUMP_AUDIOHAL_IN_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_IN
|
|
{AML_DUMP_AUDIOHAL_OUT, AML_DUMP_AUDIOHAL_OUT_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_OUT
|
|
{AML_DUMP_AUDIOHAL_MS12, AML_DUMP_AUDIOHAL_MS12_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_MS12
|
|
{AML_DUMP_AUDIOHAL_DTS, AML_DUMP_AUDIOHAL_DTS_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_DTS
|
|
{AML_DUMP_AUDIOHAL_SPDIF, AML_DUMP_AUDIOHAL_SPDIF_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_SPDIF
|
|
{AML_DUMP_AUDIOHAL_SUBMIXING, AML_DUMP_AUDIOHAL_SUBMIXING_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_SUBMIXING
|
|
{AML_DUMP_AUDIOHAL_TV, AML_DUMP_AUDIOHAL_TV_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_TV_PATH
|
|
{AML_DUMP_AUDIOHAL_DTV, AML_DUMP_AUDIOHAL_DTV_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_DTV
|
|
{AML_DUMP_AUDIOHAL_MMAP, AML_DUMP_AUDIOHAL_MMAP_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_MMAP
|
|
{AML_DUMP_AUDIOHAL_HFP, AML_DUMP_AUDIOHAL_HFP_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_HFP
|
|
{AML_DUMP_AUDIOHAL_SCO, AML_DUMP_AUDIOHAL_SCO_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_SCO
|
|
{AML_DUMP_AUDIOHAL_A2DP, AML_DUMP_AUDIOHAL_A2DP_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_A2DP
|
|
{AML_DUMP_AUDIOHAL_USB, AML_DUMP_AUDIOHAL_USB_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_USB
|
|
{AML_DUMP_AUDIOHAL_DECODER, AML_DUMP_AUDIOHAL_DECODER_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_DECODER
|
|
{AML_DUMP_AUDIOHAL_RESAMPLE, AML_DUMP_AUDIOHAL_RESAMPLE_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_RESAMPLE
|
|
{AML_DUMP_AUDIOHAL_SPEED, AML_DUMP_AUDIOHAL_SPEED_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_SPEED
|
|
{AML_DUMP_AUDIOHAL_CAPTURE, AML_DUMP_AUDIOHAL_CAPTURE_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_CAPTURE
|
|
{AML_DUMP_AUDIOHAL_EFFECT, AML_DUMP_AUDIOHAL_EFFECT_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_EFFECT
|
|
{AML_DUMP_AUDIOHAL_VOLUME, AML_DUMP_AUDIOHAL_VOLUME_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_VOLUME
|
|
{AML_DUMP_AUDIOHAL_ASYNC, AML_DUMP_AUDIOHAL_ASYNC_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_ASYNC
|
|
{AML_DUMP_AUDIOHAL_ABUFFER, AML_DUMP_AUDIOHAL_ABUFFER_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_ABUFFER
|
|
{AML_DUMP_AUDIOHAL_AI, AML_DUMP_AUDIOHAL_AI_PROPERTY, 0}, //AML_DUMP_AUDIOHAL_AI
|
|
};
|
|
|
|
static void aml_debug_update(void)
|
|
{
|
|
int i = 0;
|
|
int ret = -1;
|
|
for (i = 0; i < AML_DEBUG_DUMP_MAX; i++) {
|
|
ret = aml_audio_property_get_int(aml_debug_items[i].name, 0);
|
|
aml_debug_items[i].value = ret;
|
|
if (get_debug_value(AML_DEBUG_AUDIOHAL_TRACE))
|
|
ALOGI("%s %s = 0x%x", __func__, aml_debug_items[i].name, aml_debug_items[i].value);
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void *aml_debug_Thread(void *pArg)
|
|
{
|
|
aml_dump_debug_t * p_handle = (aml_dump_debug_t *)pArg;
|
|
|
|
while (!p_handle->bexit) {
|
|
aml_debug_update();
|
|
usleep(1000 * 1000);
|
|
}
|
|
ALOGI("exit %s", __FUNCTION__);
|
|
return ((void *)0);
|
|
}
|
|
|
|
|
|
void aml_audio_debug_open(char *path)
|
|
{
|
|
if (g_debug_handle == NULL) {
|
|
g_debug_handle = aml_audio_calloc(1, sizeof(aml_dump_debug_t));
|
|
if (g_debug_handle) {
|
|
if (pthread_create(&g_debug_handle->threadid, NULL, &aml_debug_Thread, (void *)g_debug_handle)) {
|
|
ALOGE("%s create thread failed", __FUNCTION__);
|
|
return;
|
|
}
|
|
g_debug_handle->bexit = false;
|
|
g_debug_handle->items = aml_debug_items;
|
|
} else {
|
|
ALOGE("%s calloc failed", __FUNCTION__);
|
|
return;
|
|
}
|
|
}
|
|
if (path !=NULL) {
|
|
snprintf(defaultDumpPath, sizeof(defaultDumpPath), "%s", path);
|
|
}
|
|
|
|
ALOGI("%s exit. dump path is %s", __FUNCTION__, defaultDumpPath);
|
|
return;
|
|
}
|
|
|
|
void aml_audio_debug_close(void)
|
|
{
|
|
aml_dump_debug_t * p_handle = g_debug_handle;
|
|
if (p_handle) {
|
|
p_handle->bexit = true;
|
|
if (p_handle->threadid != 0) {
|
|
pthread_join(p_handle->threadid, NULL);
|
|
}
|
|
aml_audio_free(p_handle);
|
|
g_debug_handle = NULL;
|
|
}
|
|
ALOGI("%s exit", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
int aml_dump_audio_bitstreams(const char *filename, const void *buf, size_t bytes)
|
|
{
|
|
if (!filename) {
|
|
ALOGE("%s %d, path is null, please check it.", __func__, __LINE__);
|
|
return -1;
|
|
}
|
|
|
|
char mPath[100];
|
|
sprintf(mPath, "%s%s", defaultDumpPath, filename);
|
|
|
|
FILE *fp = fopen(mPath, "ab+");
|
|
if (fp) {
|
|
fwrite((char *)buf, 1, bytes, fp);
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
ALOGE("fail to open path=%s, errno=%d/%s", mPath, errno, strerror(errno));
|
|
return -1;
|
|
|
|
}
|
|
|
|
int aml_dump_audio_bitstreams_with_id(const char *filename, const void *buf, size_t bytes, int stream_id)
|
|
{
|
|
int ret = 0;
|
|
char file_name[256] = { 0 };
|
|
snprintf(file_name, 256, "ID_%d_%s", stream_id, filename);
|
|
ret = aml_dump_audio_bitstreams(file_name, buf, bytes);
|
|
return ret;
|
|
}
|
|
|
|
int aml_dump_audio_buffer(const char *filename, struct audio_buffer *abuffer) {
|
|
if (!filename || !abuffer) {
|
|
AM_LOGE("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
if (!check_audio_buffer_valid(abuffer)) {
|
|
AM_LOGE("Invalid audio_buffer");
|
|
return -1;
|
|
}
|
|
char mPath[256];
|
|
sprintf(mPath, "%s%s", defaultDumpPath, filename);
|
|
|
|
FILE *fp = fopen(mPath, "ab+");
|
|
if (!fp) {
|
|
AM_LOGE("Failed to open file: %s", mPath);
|
|
return -1;
|
|
}
|
|
|
|
// Write frame header
|
|
frame_header fheader = {
|
|
.frame_magic = FRAME_MAGIC,
|
|
.buffer_size = abuffer->size,
|
|
.iec_data_size = abuffer->iec_data_size
|
|
};
|
|
|
|
if (fwrite(&fheader, sizeof(fheader), 1, fp) != 1) {
|
|
AM_LOGE("Failed to write frame header");
|
|
fclose(fp);
|
|
return -1;
|
|
}
|
|
|
|
// Write metadata
|
|
if (fwrite(abuffer, sizeof(struct audio_buffer), 1, fp) != 1) {
|
|
AM_LOGE("Failed to write metadata");
|
|
fclose(fp);
|
|
return -1;
|
|
}
|
|
|
|
// Write audio data
|
|
if (abuffer->size > 0 && abuffer->buffer) {
|
|
if (fwrite(abuffer->buffer, abuffer->size, 1, fp) != 1) {
|
|
AM_LOGE("Failed to write audio buffer");
|
|
fclose(fp);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Write IEC data
|
|
if (abuffer->iec_data_size > 0 && abuffer->iec_data_buf) {
|
|
if (fwrite(abuffer->iec_data_buf, abuffer->iec_data_size, 1, fp) != 1) {
|
|
AM_LOGE("Failed to write IEC data buffer");
|
|
fclose(fp);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
|
|
int aml_dump_audio_buffer_with_id(const char *filename, struct audio_buffer *abuffer, int id)
|
|
{
|
|
int ret = 0;
|
|
char file_name[256] = { 0 };
|
|
snprintf(file_name, 256, "abuffer_id_%d_%s", id, filename);
|
|
ret = aml_dump_audio_buffer(file_name, abuffer);
|
|
return ret;
|
|
}
|
|
|
|
void* aml_audio_buffer_file_open(const char *filename) {
|
|
if (!filename) {
|
|
AM_LOGE("Invalid filename");
|
|
return NULL;
|
|
}
|
|
|
|
FILE *fp = fopen(filename, "rb");
|
|
if (!fp) {
|
|
AM_LOGE("Failed to open file: %s", filename);
|
|
return NULL;
|
|
}
|
|
AM_LOGI("Opened audio buffer file: %s, fp: %p", filename, fp);
|
|
return (void *)fp;
|
|
}
|
|
|
|
int aml_audio_buffer_file_read(void *handle, struct audio_buffer *abuffer) {
|
|
frame_header fheader;
|
|
FILE * fp = (FILE *)handle;
|
|
struct audio_buffer abuffer_tmp;
|
|
|
|
if (!handle || !abuffer) {
|
|
AM_LOGE("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
// Read frame header
|
|
if (fread(&fheader, sizeof(fheader), 1, fp) != 1) {
|
|
return -1; // EOF
|
|
}
|
|
|
|
if (fheader.frame_magic != FRAME_MAGIC) {
|
|
AM_LOGE("Invalid frame magic: 0x%x", fheader.frame_magic);
|
|
return -1;
|
|
}
|
|
|
|
// Read metadata
|
|
if (fread(&abuffer_tmp, sizeof(struct audio_buffer), 1, fp) != 1) {
|
|
AM_LOGE("Failed to read metadata");
|
|
return -1;
|
|
}
|
|
|
|
abuffer_tmp.buffer = abuffer->buffer;
|
|
abuffer_tmp.iec_data_buf = abuffer->iec_data_buf;
|
|
memcpy(abuffer, &abuffer_tmp, sizeof(struct audio_buffer));
|
|
|
|
// Read audio data
|
|
if (fheader.buffer_size > 0) {
|
|
if (fheader.buffer_size > ABUFFER_READ_DATA_MAX_SIZE) {
|
|
AM_LOGE("Buffer size %u exceeds max limit %u", fheader.buffer_size, ABUFFER_READ_DATA_MAX_SIZE);
|
|
return -1;
|
|
}
|
|
|
|
if (fread((void*)abuffer->buffer, fheader.buffer_size, 1, fp) != 1) {
|
|
AM_LOGE("Failed to read audio buffer");
|
|
return -1;
|
|
}
|
|
|
|
abuffer->size = fheader.buffer_size;
|
|
} else {
|
|
abuffer->size = 0;
|
|
}
|
|
|
|
// Read IEC data
|
|
if (fheader.iec_data_size > 0) {
|
|
if (fheader.iec_data_size > ABUFFER_READ_IEC_DATA_MAX_SIZE) {
|
|
AM_LOGE("IEC data size %u exceeds max limit %u", fheader.iec_data_size, ABUFFER_READ_IEC_DATA_MAX_SIZE);
|
|
return -1;
|
|
}
|
|
|
|
if (fread((void*)abuffer->iec_data_buf, fheader.iec_data_size, 1, fp) != 1) {
|
|
AM_LOGE("Failed to read IEC buffer");
|
|
return -1;
|
|
}
|
|
|
|
abuffer->iec_data_size = fheader.iec_data_size;
|
|
} else {
|
|
abuffer->iec_data_size = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void aml_audio_buffer_file_close(void *handle) {
|
|
if (handle) {
|
|
fclose((FILE *)handle);
|
|
}
|
|
}
|