Files
fs2open.github.com/code/sound/ffmpeg/FFmpegWaveFile.h
asarium 2dc2295a59 Make FFmpeg an optional requirement
This does some refactoring to make it possible to cimpile and run FSO
without needing to link to FFmpeg. Since that eliminates support for
cutscenes or sound this is mostly useful for running a standalone server
which has no need for this anyway.

This reduces the image size of the standalone Docker image to only 20MB
and also resolves any licensing issues that might have existed.
2020-02-29 17:24:56 +01:00

113 lines
3.1 KiB
C++

#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 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:
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