/* * 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 #include #include #include #include #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); } }