/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FLAC_PARSER_H_ #define FLAC_PARSER_H_ #include #include #include #include #include // libFLAC parser #include "FLAC/stream_decoder.h" #include "data_source.h" typedef int status_t; struct FlacPicture { int type; std::string mimeType; std::string description; FLAC__uint32 width; FLAC__uint32 height; FLAC__uint32 depth; FLAC__uint32 colors; std::vector data; }; class FLACParser { public: FLACParser(DataSource *source); ~FLACParser(); bool init(); // stream properties unsigned getMaxBlockSize() const { return mStreamInfo.max_blocksize; } unsigned getSampleRate() const { return mStreamInfo.sample_rate; } unsigned getChannels() const { return mStreamInfo.channels; } unsigned getBitsPerSample() const { return mStreamInfo.bits_per_sample; } FLAC__uint64 getTotalSamples() const { return mStreamInfo.total_samples; } const FLAC__StreamMetadata_StreamInfo& getStreamInfo() const { return mStreamInfo; } bool areVorbisCommentsValid() const { return mVorbisCommentsValid; } std::vector getVorbisComments() { return mVorbisComments; } bool arePicturesValid() const { return mPicturesValid; } const std::vector &getPictures() const { return mPictures; } int64_t getLastFrameTimestamp() const { return (1000000LL * mWriteHeader.number.sample_number) / getSampleRate(); } int64_t getLastFrameFirstSampleIndex() const { return mWriteHeader.number.sample_number; } int64_t getNextFrameFirstSampleIndex() const { return mWriteHeader.number.sample_number + mWriteHeader.blocksize; } bool decodeMetadata(); size_t readBuffer(void *output, size_t output_size); bool getSeekPositions(int64_t timeUs, std::array &result); void flush() { reset(mCurrentPos); } void reset(int64_t newPosition) { if (mDecoder != NULL) { mCurrentPos = newPosition; mEOF = false; if (newPosition == 0) { mStreamInfoValid = false; mVorbisCommentsValid = false; mPicturesValid = false; mVorbisComments.clear(); mPictures.clear(); FLAC__stream_decoder_reset(mDecoder); } else { FLAC__stream_decoder_flush(mDecoder); } } } int64_t getDecodePosition() { uint64_t position; if (mDecoder != NULL && FLAC__stream_decoder_get_decode_position(mDecoder, &position)) { return position; } return -1; } const char *getDecoderStateString() { return FLAC__stream_decoder_get_resolved_state_string(mDecoder); } bool isDecoderAtEndOfStream() const { return FLAC__stream_decoder_get_state(mDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM; } private: DataSource *mDataSource; void (*mCopy)(int8_t *dst, const int *const *src, unsigned bytesPerSample, unsigned nSamples, unsigned nChannels); // handle to underlying libFLAC parser FLAC__StreamDecoder *mDecoder; // current position within the data source off64_t mCurrentPos; bool mEOF; // cached when the STREAMINFO metadata is parsed by libFLAC FLAC__StreamMetadata_StreamInfo mStreamInfo; bool mStreamInfoValid; const FLAC__StreamMetadata_SeekTable *mSeekTable; uint64_t firstFrameOffset; // cached when the VORBIS_COMMENT metadata is parsed by libFLAC std::vector mVorbisComments; bool mVorbisCommentsValid; // cached when the PICTURE metadata is parsed by libFLAC std::vector mPictures; bool mPicturesValid; // cached when a decoded PCM block is "written" by libFLAC parser bool mWriteRequested; bool mWriteCompleted; FLAC__FrameHeader mWriteHeader; const FLAC__int32 *const *mWriteBuffer; // most recent error reported by libFLAC parser FLAC__StreamDecoderErrorStatus mErrorStatus; // no copy constructor or assignment FLACParser(const FLACParser &); FLACParser &operator=(const FLACParser &); // FLAC parser callbacks as C++ instance methods FLAC__StreamDecoderReadStatus readCallback(FLAC__byte buffer[], size_t *bytes); FLAC__StreamDecoderSeekStatus seekCallback(FLAC__uint64 absolute_byte_offset); FLAC__StreamDecoderTellStatus tellCallback( FLAC__uint64 *absolute_byte_offset); FLAC__StreamDecoderLengthStatus lengthCallback(FLAC__uint64 *stream_length); FLAC__bool eofCallback(); FLAC__StreamDecoderWriteStatus writeCallback( const FLAC__Frame *frame, const FLAC__int32 *const buffer[]); void metadataCallback(const FLAC__StreamMetadata *metadata); void errorCallback(FLAC__StreamDecoderErrorStatus status); // FLAC parser callbacks as C-callable functions static FLAC__StreamDecoderReadStatus read_callback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); static FLAC__StreamDecoderSeekStatus seek_callback( const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); static FLAC__StreamDecoderTellStatus tell_callback( const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); static FLAC__StreamDecoderLengthStatus length_callback( const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); static FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data); static FLAC__StreamDecoderWriteStatus write_callback( const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data); static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); }; #endif // FLAC_PARSER_H_