File: Decoder.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (173 lines) | stat: -rw-r--r-- 3,747 bytes parent folder | download | duplicates (2)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#pragma once

#include <memory>

#include "globalincs/pstypes.h"
#include "utils/boost/syncboundedqueue.h"

namespace cutscene {
struct FrameSize {
	size_t width = 0;
	size_t height = 0;
	size_t stride = 0;

	FrameSize();
	FrameSize(size_t width, size_t in_height, size_t in_stride);
};

class VideoFrame {
 protected:
	VideoFrame() = default;

  public:
	virtual ~VideoFrame() = default;

	double frameTime = -1.0;
	int id = -1;

	virtual size_t getPlaneNumber() = 0;

	virtual FrameSize getPlaneSize(size_t plane) = 0;

	virtual void* getPlaneData(size_t plane) = 0;
};

/**
 * @brief Pointer type for passing frame data between threads
 *
 */
template<typename T>
using FramePtr = std::unique_ptr<T>;

typedef std::unique_ptr<VideoFrame> VideoFramePtr;

enum class FramePixelFormat {
	Invalid,
	YUV420,
	BGR,
	BGRA
};

struct MovieProperties {
	FrameSize size;

	float fps = -1.0f;
	float duration = 0.0f;

	FramePixelFormat pixelFormat = FramePixelFormat::Invalid;
};

struct AudioFrame {
	SCP_vector<short> audioData;

	int channels = -1;

	int rate = -1;
};
typedef std::unique_ptr<AudioFrame> AudioFramePtr;

struct SubtitleFrame {
    double displayStartTime = -1.0;
    double displayEndTime = -1.0;

	SCP_string text;
};
typedef std::unique_ptr<SubtitleFrame> SubtitleFramePtr;

struct PlaybackProperties {
	bool with_audio = true;
	bool looping = false;
};

/**
 * @brief Abstract class for decoding a video or audio stream
 *
 * A decoder maintaines two queues of decoded audio and video frames which are filled from a background thread and
 * retrieved by the main thread.
 */
class Decoder {
 private:
	std::unique_ptr<sync_bounded_queue<VideoFramePtr>> m_videoQueue;
	std::unique_ptr<sync_bounded_queue<AudioFramePtr>> m_audioQueue;
	std::unique_ptr<sync_bounded_queue<SubtitleFramePtr>> m_subtitleQueue;

	bool m_decoding;
	size_t m_queueSize = 0;

 protected:
	Decoder();

 public:
	Decoder(const Decoder&) = delete;
	Decoder& operator=(const Decoder&) = delete;

	virtual ~Decoder();

	/**
	 * @brief Initializes the decoder
	 *
	 * @note A implementation should initialize the datastructures required for decoding here.
	 *
	 * @param fileName The name of the file that should be opened
	 * @return @c true if the initialization was successful, @c false otherwise
	 */
	virtual bool initialize(const SCP_string& fileName, const PlaybackProperties& properties) = 0;

	/**
	 * @brief Returns the properties of the video
	 * @return The properties
	 */
	virtual MovieProperties getProperties() const = 0;

	/**
	 * @brief Starts decoding the video
	 */
	virtual void startDecoding() = 0;

	/**
	 * @brief Determines if the video has audio
	 * @return @c true if audio is included in the video
	 */
	virtual bool hasAudio() const = 0;

	virtual bool hasSubtitles() const = 0;

	/**
	 * @brief Ends decoding of the video file
	 */
	virtual void close() = 0;

	bool isAudioQueueFull() { return m_audioQueue->size() == m_queueSize; }

	bool isAudioFrameAvailable() { return !m_audioQueue->empty(); }

	size_t getAudioQueueSize() { return m_audioQueue->size(); }

	bool tryPopAudioData(AudioFramePtr&);

	bool isSubtitleQueueFull() { return m_subtitleQueue->size() == m_queueSize; }

	bool tryPopSubtitleData(SubtitleFramePtr&);

	bool isVideoQueueFull() { return m_videoQueue->size() == m_queueSize; }

	bool isVideoFrameAvailable() { return !m_videoQueue->empty(); }

	size_t getVideoQueueSize() { return m_videoQueue->size(); }

	bool tryPopVideoFrame(VideoFramePtr&);

	void stopDecoder();

	bool isDecoding() { return m_decoding; }

 protected:
	void initializeQueues(size_t queueSize);

	void pushAudioData(AudioFramePtr&& data);

	void pushSubtitleData(SubtitleFramePtr&& data);

	void pushFrameData(VideoFramePtr&& frame);
};
}