Files
2026-08-24 10:03:24 +08:00

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);
}
}