/* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA"). * All rights reserved. * * This software is supplied "AS IS" without any warranties. * RDA assumes no responsibility or liability for the use of the software, * conveys no license or title under any patent, copyright, or mask work * right to the product. RDA reserves the right to make changes in the * software without notification. RDA also make no representation or * warranty that such application will be suitable for the specified use * without further testing or modification. */ #ifndef _AUDIO_READER_H_ #define _AUDIO_READER_H_ #include "osi_compiler.h" OSI_EXTERN_C_BEGIN /** * \brief forward declaration */ struct auReader; struct osiPipe; /** * \brief audio reader operations */ typedef struct { /** delete the audio reader */ void (*destroy)(struct auReader *d); /** refer to \p auReaderRead */ int (*read)(struct auReader *d, void *buf, unsigned size); /** refer to \p auReaderSeek */ int (*seek)(struct auReader *d, int offset, int whence); /** refer to \p auReaderIsEof */ bool (*is_eof)(struct auReader *d); } auReaderOps_t; /** * \brief audio reader base * * Audio reader is an abstraction of file. The basic operation is to read * from the reader. And the reader doen't care about the content. * * When implement an audio reader, the first field should be * auReaderOps_t. */ typedef struct auReader { auReaderOps_t ops; ///< audio reader operations } auReader_t; /** * \brief delete the audio reader * * When \p d is NULL, nothing will be done. * * \param d audio reader */ void auReaderDelete(auReader_t *d); /** * \brief read data from audio reader * * When the reader reaches end of file, it will return 0. * * \param d audio reader * \param buf buf to be fetched, can't be NULL if \p size is not 0. * \param size buf size * \return * - the size fetched from audio reader, which may be less than \p size. * - -1 for invalid parameters, or file read error. */ int auReaderRead(auReader_t *d, void *buf, unsigned size); /** * \brief read data from audio reader, at specified offset * * This is the same as \p auReaderSeek followed by \p auReaderRead. * * \param d audio reader * \param offset specified offset * \param buf buf to be fetched, can't be NULL if \p size is not 0. * \param size buf size * \return * - the size fetched from audio reader, which may be less than \p size. * - -1 for invalid parameters, or file read error. */ int auReaderReadAt(auReader_t *d, int offset, void *buf, unsigned size); /** * \brief whether the audio reader support seek * * When \p seek function pointer is NULL, it is not seekable. * * \param d audio reader * \return * - true if the audio reader supports seek * - false if the audio reader doesn't support seek */ bool auReaderIsSeekable(auReader_t *d); /** * \brief audio reader seek * * Macros for \p whence are defined in stdio.h. * * \param d audio reader * \param offset offset according to the directive whence * \param whence SEEK_SET, SEEK_CUR, SEEK_END * \return * - offset location from the beginning of reader on success. * - -1 on error. */ int auReaderSeek(auReader_t *d, int offset, int whence); /** * \brief audio reader drop data * * When audio reader supports seek, it is the same to seek forward. * Otherwise, it will try to read-and-drop specified size. * * \param d audio reader * \param size byte count to be dropped * \return * - 0 on success. * - -1 on error. */ int auReaderDrop(auReader_t *d, unsigned size); /** * \brief whether the reader reaches end of file * * \param d audio reader * \return * - true when the reader reaches end of file * - false if not */ bool auReaderIsEof(auReader_t *d); /** * \brief opaque data strcture of file based audio reader */ typedef struct auFileReader auFileReader_t; /** * \brief create a file based audio reader * * \param fname file name * \return * - the created audio reader * - NULL if invalid parameter, or out of memory */ auFileReader_t *auFileReaderCreate(const char *fname); /** * \brief opaque data structure of meory based audio reader */ typedef struct auMemReader auMemReader_t; /** * \brief create a memory based audio reader * * When \p buf is NULL or \p size is 0, it will create an empty audio reader. * * \param buf buffer * \param size buffer size * \return * - the created audio reader * - NULL if out of memory */ auMemReader_t *auMemReaderCreate(const void *buf, unsigned size); /** * \brief opaque data structure for pip based audio reader */ typedef struct auPipeReader auPipeReader_t; /** * \brief create a pipe based audio reader * * Pipe base audio reader will decouple audio data producing and consuming. * Seek is unsupported in pipe based audio reader. Audio reader will just * access the reader side of pipe. * * \param pipe the pipe to be read * \return * - the created audio reader * - NULL if out of memory, or invalid parameter */ auPipeReader_t *auPipeReaderCreate(struct osiPipe *pipe); /** * \brief set wait timeout for audio pipe reader * * By default, audio pipe read will wait a while when the pipe is empty, or * not enough for the requested byte count. This can set the wait timeout, * 0 for not waiting and \p OSI_WAIT_FOREVER for infinite wait until the * requested data are read. * * When \p timeout is set to 0, the pipe will be read repeatedly. In most * cases, it is not wanted. * * \param d the audio pipe reader * \param timeout wait timeout */ void auPipeReaderSetWait(auPipeReader_t *d, unsigned timeout); /** * \brief helper to manage input buffer for audio reader * * The struct definition is just to make it easier to embed data struct. * DON'T acess members directly. */ typedef struct { uint8_t *buf; ///< the real input buffer unsigned size; ///< byte count in the buffer unsigned pos; ///< read position in the buffer unsigned file_pos; ///< file position for the read position unsigned data_start; ///< valid data start in file unsigned data_end; ///< valid data end in file } auReadBuf_t; /** * \brief initialize read buffer * * \param d read buffer * \param buf real input buffer pointer */ void auReadBufInit(auReadBuf_t *d, void *buf); /** * \brief clear read buffer, and set file position * * \param d read buffer * \param file_pos file position */ void auReadBufReset(auReadBuf_t *d, unsigned file_pos); /** * \brief fetch from reader * * When needed, it will read from audio reader, and try to ensure * valid data size is greater than \p size. * * \param d read buffer * \param reader audio reader * \param size requested valid data size * \return * - valid data size in read buffer */ unsigned auReadBufFetch(auReadBuf_t *d, auReader_t *reader, unsigned size); /** * \brief skip bytes in reader buffer * * \p size may be larger than valid data size in read buffer. In this * case, it will call \p auReaderDrop. * * \param d read buffer * \param reader audio reader * \param size requested byte count to be skipped * \return * - true on success. * - false on error. */ bool auReadBufSkip(auReadBuf_t *d, auReader_t *reader, unsigned size); /** * \brief set pipe reader timeout * * * \param d pipe reader * \param timeout timeout * \return * - NULL. */ void auPipeReaderSetWait(auPipeReader_t *d, unsigned timeout); /** * \brief valid data pointer * * \param d read buffer * \return * - valid data pointer */ static inline uint8_t *auReadBufData(auReadBuf_t *d) { return &d->buf[d->pos]; } /** * \brief valid data size * * \param d read buffer * \return * - valid data size */ static inline unsigned auReadBufSize(auReadBuf_t *d) { return d->size - d->pos; } /** * \brief file position * * \param d read buffer * \return * - file position */ static inline unsigned auReadBufFilePos(auReadBuf_t *d) { return d->file_pos; } /** * \brief data start position in file * * \param d read buffer * \return * - data start position in file */ static inline unsigned auReadBufDataStart(auReadBuf_t *d) { return d->data_start; } /** * \brief data end position in file * * \param d read buffer * \return * - data end position in file */ static inline unsigned auReadBufDataEnd(auReadBuf_t *d) { return d->data_end; } /** * \brief set data start position in file * * \param d read buffer * \param data_start data start position in file */ static inline void auReadBufSetDataStart(auReadBuf_t *d, unsigned data_start) { d->data_start = data_start; } /** * \brief set data end position in file * * \param d read buffer * \param data_end data end position in file */ static inline void auReadBufSetDataEnd(auReadBuf_t *d, unsigned data_end) { d->data_end = data_end; } /** * \brief data read is finish * * \param d read buffer * \return * - true finish * - false not finish */ static inline bool auReadBufFetchAllData(auReadBuf_t *d) { return (d->file_pos >= d->data_end); } OSI_EXTERN_C_END #endif