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
|
#pragma once
#include <functional>
#include "libs/ffmpeg/FFmpegHeaders.h"
#include "cutscene/Decoder.h"
namespace cutscene {
namespace ffmpeg {
struct CodecContextParameters {
int width = -1;
int height = -1;
AVPixelFormat pixel_format = AV_PIX_FMT_NONE;
uint64_t channel_layout = 0;
int sample_rate = -1;
AVSampleFormat audio_format = AV_SAMPLE_FMT_NONE;
AVCodecID codec_id = AV_CODEC_ID_NONE;
};
struct DecoderStatus {
int videoStreamIndex = -1;
AVStream* videoStream = nullptr;
CodecContextParameters videoCodecPars;
const AVCodec* videoCodec = nullptr;
AVCodecContext* videoCodecCtx = nullptr;
int audioStreamIndex = -1;
AVStream* audioStream = nullptr;
CodecContextParameters audioCodecPars;
const AVCodec* audioCodec = nullptr;
AVCodecContext* audioCodecCtx = nullptr;
// Subtitles are a bit different since they max come from a different file
bool externalSubtitles = false;
int subtitleStreamIndex = -1;
AVStream* subtitleStream = nullptr;
CodecContextParameters subtitleCodecPars;
const AVCodec* subtitleCodec = nullptr;
AVCodecContext* subtitleCodecCtx = nullptr;
DecoderStatus();
~DecoderStatus();
DecoderStatus(const DecoderStatus&) = delete;
DecoderStatus& operator=(const DecoderStatus&) = delete;
};
template<typename Frame>
class FFMPEGStreamDecoder {
protected:
typedef Frame frame_type;
DecoderStatus* m_status = nullptr;
AVFrame* m_decodeFrame = nullptr;
SCP_queue<FramePtr<frame_type>> m_decodedFrames;
void pushFrame(FramePtr<frame_type>&& frame);
public:
explicit FFMPEGStreamDecoder(DecoderStatus* status);
virtual ~FFMPEGStreamDecoder();
FFMPEGStreamDecoder(const FFMPEGStreamDecoder&) = delete;
FFMPEGStreamDecoder& operator=(const FFMPEGStreamDecoder&) = delete;
virtual void decodePacket(AVPacket* packet) = 0;
virtual void finishDecoding() = 0;
virtual void flushBuffers() = 0;
virtual FramePtr<frame_type> getFrame();
};
template <typename Frame>
void FFMPEGStreamDecoder<Frame>::pushFrame(FramePtr<frame_type>&& frame)
{
m_decodedFrames.push(std::move(frame));
}
template <typename Frame>
FFMPEGStreamDecoder<Frame>::FFMPEGStreamDecoder(DecoderStatus* status):m_status(status)
{
m_decodeFrame = av_frame_alloc();
}
template <typename Frame>
FFMPEGStreamDecoder<Frame>::~FFMPEGStreamDecoder()
{
av_frame_free(&m_decodeFrame);
}
template <typename Frame>
FramePtr<typename FFMPEGStreamDecoder<Frame>::frame_type> FFMPEGStreamDecoder<Frame>::getFrame()
{
if (m_decodedFrames.empty()) {
return nullptr;
}
auto frame = std::move(m_decodedFrames.front());
m_decodedFrames.pop();
return frame;
}
}
}
|