// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "xing_header.h" #include /* XING VBR-Header size description 4 'Xing' or 'Info' 4 flags (indicates which fields are used) 4 frames (optional) 4 bytes (optional) 100 toc (optional) 4 a VBR quality indicator: 0=best 100=worst (optional) */ typedef struct { char desc[4]; uint32_t flags; } xing_header_t; // for XING VBR Header flags #define FRAMES_FLAG 0x0001 #define BYTES_FLAG 0x0002 #define TOC_FLAG 0x0004 #define VBR_SCALE_FLAG 0x0008 //! Byte swap unsigned int static inline uint32_t swap32(uint32_t ui) { return (ui >> 24) | ((ui << 8) & 0x00FF0000) | ((ui >> 8) & 0x0000FF00) | (ui << 24); } uint8_t parseXingHeader(uint8_t *data, size_t datasize, xing_info_t *info) { char *p1 = memmem(data, datasize, "Xing", 4); char *p2 = memmem(data, datasize, "Info", 4); if (p1 != NULL || p2 != NULL) { xing_header_t *head = (xing_header_t *)(p1 != NULL ? p1 : p2); uint8_t *raw_data = (uint8_t *)head + sizeof(xing_header_t); head->flags = swap32(head->flags); uint8_t offset = 0; // get flags (mandatory in XING header) // extract total number of frames in file if (head->flags & FRAMES_FLAG) { uint32_t *tmp = (uint32_t *)&raw_data[offset]; info->TotalFrames = swap32(*tmp); offset += 4; } else { return 0; } // extract total number of bytes in file if (head->flags & BYTES_FLAG) { uint32_t *tmp = (uint32_t *)&raw_data[offset]; info->TotalBytes = swap32(*tmp); offset += 4; } // extract TOC if (head->flags & TOC_FLAG) { memcpy(info->TOC, &raw_data[offset], sizeof(info->TOC)); offset += sizeof(info->TOC); } // extract quality status if (head->flags & VBR_SCALE_FLAG) { info->Quality = raw_data[offset + 3]; } return 1; } else { return 0; } }