1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
#pragma once
#include "globalincs/pstypes.h"
#include "libs/ffmpeg/FFmpegContext.h"
#include "osapi/osapi.h"
#include "sound/IAudioFile.h"
#include "sound/audiostr.h"
#include "sound/openal.h"
namespace sound {
namespace ffmpeg {
struct AudioProperties
{
int sample_rate = -1;
int64_t channel_layout = -1;
AVSampleFormat format = AV_SAMPLE_FMT_NONE;
};
// Forward declaration
class FFmpegAudioReader;
/**
* @brief A class responsible for reading auto data from media files
*
* Contrary to its name it doesn't only support Wave files but can also play Ogg files.
*
* @details This uses FFmpeg to decode the audio files.
*/
class FFmpegWaveFile : public IAudioFile {
std::unique_ptr<libs::ffmpeg::FFmpegContext> m_ctx;
AudioProperties m_baseAudioProps;
AudioProperties m_audioProps;
SwrContext* m_resampleCtx = nullptr;
int m_audioStreamIndex = -1;
AVStream* m_audioStream = nullptr;
AVFrame* m_decodeFrame = nullptr;
AVCodecContext* m_audioCodecCtx = nullptr;
std::unique_ptr<FFmpegAudioReader> m_frameReader;
size_t getBufferedData(uint8_t* buffer, size_t buffer_size);
public:
FFmpegWaveFile();
~FFmpegWaveFile() override;
// Disallow copying
FFmpegWaveFile(const FFmpegWaveFile&) = delete;
FFmpegWaveFile& operator=(const FFmpegWaveFile&) = delete;
/**
* @brief Opens the specified file for playback
*
* After this call you can start reading from this file
*
* @param pszFilename The filename
* @param keep_ext @c true if the extension of the specified file name should be kept
* @return @c true if the file was succesfully loaded, @c false otherwise
*/
bool Open(const char* pszFilename, bool keep_ext = true) override;
/**
* @brief Sets up the given in-memory "soundfile"
*
* @param snddata The sound
* @param snd_len The sound's length
* @return @c true if the sound was succesfully loaded, @c false otherwise
*/
bool OpenMem(const uint8_t* snddata, size_t snd_len) override;
/**
* @brief Prepare file for audio reading
*
* This reset the file poiner to the start of the stream and reset internal data. Future calls to Read start reading
* from the beginning of the file again
*
* @return @c true if succesfull, @c false otherwise
*/
bool Cue() override;
/**
* @brief Read audio data into a buffer
*
* Reads up to cbSize bytes of audio data into the buffer. cbSize must be a multiple of the size of one sample
*
* @param pbDest The buffer to write data to
* @param cbSize The size of the buffer
* @return The number of bytes written into the buffer. Can be 0 if no data is available, try a bigger buffer.
* Returns -1 when the end of the stream or an error has been encountered
*/
int Read(uint8_t* pbDest, size_t cbSize) override;
AudioFileProperties getFileProperties() override;
void setResamplingProperties(const ResampleProperties& resampleProps) override;
private:
const AVCodec* prepareOpened();
size_t handleDecodedFrame(AVFrame* av_frame, uint8_t* out_buffer, size_t buffer_size);
int getTotalSamples() const;
int getNumChannels() const;
/**
* @brief Changes the audio format the read functions return
*
* This will enable resampling of the audio read from the file. This can be used to reduce the number of channels the audio has if it's not supported.
*
* @param props The desired properties of the output
*/
void setAdjustedAudioProperties(const AudioProperties& props);
};
} // namespace ffmpeg
} // namespace sound
|