blob: 9791e1c4f18c2074024d488db9b54da56262f957 [file] [log] [blame]
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#define LOG_TAG "PAL: MetadataParser"
#include <string>
#include <log/log.h>
#include <unistd.h>
#include "PalDefs.h"
#include "MetadataParser.h"
int MetadataParser::parseMetadata(uint8_t* metadata, size_t metadataSize,
pal_clbk_buffer_info *bufferInfo) {
size_t mdBytesRead = 0;
if (!metadata || metadataSize < std::min(START_METADATA_SIZE(), END_METADATA_SIZE())) {
//TODO: may not work for multiple frames/buffer
ALOGE("%s: Metadata payload smaller than expected, bytes 0x%x, expected 0x%x",
__func__, mdBytesRead, std::min(START_METADATA_SIZE(), END_METADATA_SIZE()));
return -EINVAL;
}
while (mdBytesRead < metadataSize) {
metadata_header_t* metadataItem =
reinterpret_cast<metadata_header_t*>(metadata + mdBytesRead);
if (!metadataItem) {
return 0;
}
mdBytesRead += sizeof(metadata_header_t);
switch (metadataItem->metadata_id) {
//TODO: check if 2 start metadata/2 end metadata is present
case MODULE_CMN_MD_ID_BUFFER_START: {
size_t startMetadataPayloadSize = metadataItem->payload_size;
if (mdBytesRead + startMetadataPayloadSize > metadataSize) {
ALOGE("%s: Metadata item payload size larger than advertized metadata size"
" metadata id 0x%x, mdBytesRead = 0x%x, item payload size 0x%x,"
" metadata size = 0x%x ", __func__, metadataItem->metadata_id,
mdBytesRead, startMetadataPayloadSize, metadataSize);
return -EINVAL;
}
module_cmn_md_buffer_start_t* startMetadata =
reinterpret_cast<module_cmn_md_buffer_start_t*>(metadata + mdBytesRead);
if (!startMetadata) {
ALOGE("%s: Metadata start payload not found at offset 0x%x",
__func__, mdBytesRead);
return -EINVAL;
}
bufferInfo->frame_index = static_cast<uint64_t>((static_cast<uint64_t>(
startMetadata->buffer_index_msw) << 32) | startMetadata->buffer_index_lsw);
ALOGV("%s: startMetadata frame_index %llu", __func__, bufferInfo->frame_index);
mdBytesRead += sizeof(module_cmn_md_buffer_start_t);
break;
}
case MODULE_CMN_MD_ID_BUFFER_END: {
size_t endMetadataPayloadSize = metadataItem->payload_size;
if (mdBytesRead + endMetadataPayloadSize > metadataSize) {
ALOGE("%s: Metadata item payload size larger than advertized metadata size,"
" metadata id 0x%x, mdBytesRead = 0x%x, item payload size 0x%x,"
" metadata size = 0x%x ", __func__, metadataItem->metadata_id,
mdBytesRead, endMetadataPayloadSize, static_cast<uint32_t>(metadataSize));
return -EINVAL;
}
module_cmn_md_buffer_end_t* endMetadata =
reinterpret_cast<module_cmn_md_buffer_end_t*>(metadata + mdBytesRead);
if (!endMetadata) {
ALOGE("%s: Metadata end payload not found at offset 0x%x",
__func__, mdBytesRead);
return -EINVAL;
}
// TODO: compare previous input buffer index from start metadata,
// treat different values as error
bufferInfo->frame_index = static_cast<uint64_t>((static_cast<uint64_t>(
endMetadata->buffer_index_msw) << 32) | endMetadata->buffer_index_lsw);
if (endMetadata->flags) {
ALOGV("%s: End Metdata Flags=0x%x", __func__, endMetadata->flags);
if (((endMetadata->flags & MD_END_PAYLOAD_FLAGS_BIT_MASK_ERROR_RECOVERY_DONE)
>> MD_END_PAYLOAD_FLAGS_SHIFT_ERROR_RECOVERY_DONE)
== MD_END_RESULT_ERROR_RECOVERY_DONE ) {
ALOGI("%s: Error detected in input buffer and recovery attempted", __func__);
} else if ( ((endMetadata->flags & MD_END_PAYLOAD_FLAGS_BIT_MASK_ERROR_RESULT)
>> MD_END_PAYLOAD_FLAGS_SHIFT_ERROR_RESULT) == MD_END_RESULT_FAILED ) {
ALOGI("%s: Non-recoverable error detected in input buffer", __func__);
}
}
mdBytesRead += sizeof(module_cmn_md_buffer_end_t);
break;
}
case MODULE_CMN_MD_ID_MEDIA_FORMAT: {
size_t mfMetadataPayloadSize = metadataItem->payload_size;
if (mdBytesRead + mfMetadataPayloadSize > metadataSize){
ALOGE("%s: Metadata item payload size larger than advertized metadata size,"
" metadata id 0x%x, mdBytesRead = 0x%x, item payload size 0x%x,"
" metadata size = 0x%x ", __func__, metadataItem->metadata_id,
mdBytesRead, mfMetadataPayloadSize, metadataSize);
return -EINVAL;
}
media_format_t* mfPayload =
reinterpret_cast<media_format_t*>(metadata + mdBytesRead);
mdBytesRead += sizeof(media_format_t);
if (!mfPayload) {
ALOGE("%s: Media metadata payload not found at offset 0x%x",
__func__, mdBytesRead);
return -EINVAL;
}
if (mfPayload->fmt_id != MEDIA_FMT_ID_PCM) {
ALOGE("%s: Format ID within Media metadata payload not PCM,"
" fmt_id=x%x, offset=0x%x", __func__, mfPayload->fmt_id,
(uint32_t)offsetof(media_format_t, fmt_id));
return -EINVAL;
}
payload_media_fmt_pcm_t* pcmPayload =
reinterpret_cast<payload_media_fmt_pcm_t*>(metadata + mdBytesRead);
bufferInfo->sample_rate = pcmPayload->sample_rate;
bufferInfo->channel_count = pcmPayload->num_channels;
ALOGI("%s: sample_rate=%u, channel_count=%u", __func__,
bufferInfo->sample_rate, bufferInfo->channel_count);
mdBytesRead +=
ALIGN(sizeof(payload_media_fmt_pcm_t) +
pcmPayload->num_channels * sizeof(int8_t), 4);
break;
}
default: {
ALOGE("%s: Unknown Metadata marker found at offset 0x%x, Metadata ID=0x%x",
__func__, mdBytesRead, metadataItem->metadata_id);
// increment bytes read
mdBytesRead += metadataItem->payload_size;
break;
}
}
ALOGV("%s: mdBytesRead=%zu, metadataSize=%zu", __func__, mdBytesRead, metadataSize);
} // end while
return 0;
}
void MetadataParser::fillMetaData(uint8_t *metadata,
uint64_t frameIndex, size_t filledLength,
pal_media_config *streamMediaConfig) {
bool isEncode = false;
if (streamMediaConfig->aud_fmt_id == PAL_AUDIO_FMT_PCM_S8 ||
streamMediaConfig->aud_fmt_id == PAL_AUDIO_FMT_PCM_S16_LE ||
streamMediaConfig->aud_fmt_id == PAL_AUDIO_FMT_PCM_S24_LE ||
streamMediaConfig->aud_fmt_id == PAL_AUDIO_FMT_PCM_S24_3LE ||
streamMediaConfig->aud_fmt_id == PAL_AUDIO_FMT_PCM_S32_LE) {
isEncode = true;
}
auto getOffsetForEndMetadata = [&](uint32_t bufSize)
{
uint32_t sampleSizePerCh =
BYTES_PER_SAMPLE(streamMediaConfig->bit_width) *
streamMediaConfig->ch_info.channels;
return (isEncode) ? (bufSize / sampleSizePerCh) : bufSize;
};
// Fill start metadata
metadata_header_t* startMetadata = reinterpret_cast<metadata_header_t*>(metadata);
startMetadata->metadata_id = MODULE_CMN_MD_ID_BUFFER_START;
startMetadata->flags = static_cast<uint32_t>(MD_HEADER_FLAGS_BUFFER_ASSOCIATED << 4);
startMetadata->offset = 0;
startMetadata->payload_size = sizeof(module_cmn_md_buffer_start_t);
metadata += sizeof(metadata_header_t);
module_cmn_md_buffer_start_t startMetadataPayload = {GET_LSW(frameIndex),
GET_MSW(frameIndex)};
memcpy(reinterpret_cast<void*>(metadata),
reinterpret_cast<const void*>(&startMetadataPayload),
sizeof(module_cmn_md_buffer_start_t));
metadata += startMetadata->payload_size;
// Fill end metadata
metadata_header_t* endMetadata = reinterpret_cast<metadata_header_t*>(metadata);
endMetadata->metadata_id = MODULE_CMN_MD_ID_BUFFER_END;
endMetadata->flags = static_cast<uint32_t>(MD_HEADER_FLAGS_BUFFER_ASSOCIATED << 4);
endMetadata->offset = getOffsetForEndMetadata(filledLength);
endMetadata->payload_size = sizeof(module_cmn_md_buffer_end_t);
metadata += sizeof(metadata_header_t);
module_cmn_md_buffer_end_t endMetadataPayload = {GET_LSW(frameIndex),
GET_MSW(frameIndex),
0};
memcpy(reinterpret_cast<void*>(metadata),
reinterpret_cast<const void*>(&endMetadataPayload),
sizeof(module_cmn_md_buffer_end_t));
}