Switch internally to 16-bit graphics instead of 32-bit
[lsnes.git] / avidump / avidump.hpp
blobadfc83dc33d2b68f80446e95ef1421c83ee6a080
1 #ifndef _avidump__hpp__included__
2 #define _avidump__hpp__included__
4 #include <cstdint>
5 #include <iostream>
6 #include <fstream>
7 #include <vector>
8 #include <list>
9 #include <stdexcept>
11 #ifdef USE_THREADS
12 #define REALLY_USE_THREADS 1
13 #endif
14 #ifndef NO_THREADS
15 #ifdef __linux__
16 #define REALLY_USE_THREADS 1
17 #endif
18 #endif
20 #ifdef REALLY_USE_THREADS
21 #include <thread>
22 #include <condition_variable>
23 #include <mutex>
25 /**
26 * Class of thread.
28 typedef std::thread thread_class;
30 /**
31 * Class of condition variables.
33 typedef std::condition_variable cv_class;
35 /**
36 * Class of mutexes.
38 typedef std::mutex mutex_class;
40 /**
41 * Class of unique mutexes (for condition variable waiting).
43 typedef std::unique_lock<std::mutex> umutex_class;
45 #else
47 /**
48 * Class of thread.
50 struct thread_class
52 /**
53 * Does nothing.
55 template<typename T, typename... args>
56 thread_class(T obj, args... a) {}
57 /**
58 * Does nothing.
60 void join() {}
63 /**
64 * Class of mutexes.
66 typedef struct mutex_class
68 /**
69 * Does nothing.
71 void lock() {}
72 /**
73 * Does nothing.
75 void unlock() {}
76 } umutex_class;
78 /**
79 * Class of condition variables.
81 struct cv_class
83 /**
84 * Does nothing.
86 void wait(umutex_class& m) {}
87 /**
88 * Does nothing.
90 void notify_all() {}
93 #endif
95 /**
96 * Size of audio buffer (enough to buffer 3 frames).
98 #define AVIDUMPER_AUDIO_BUFFER 4096
101 * Information about frame in AVI.
103 struct avi_frame
106 * Constructor.
108 * parameter _flags: Flags for frame.
109 * parameter _type: AVI type for frame (big-endian!).
110 * parameter _offset: Offset of frame from start of MOVI.
111 * parameter _size: Size of frame data.
113 avi_frame(uint32_t _flags, uint32_t _type, uint32_t _offset, uint32_t _size);
116 * Write the index entry for frame.
118 * parameter buf: Buffer to write to.
120 void write(uint8_t* buf);
123 * Flags.
125 uint32_t flags;
128 * Chunk type.
130 uint32_t type;
133 * Chunk offset.
135 uint32_t offset;
138 * Chunk size.
140 uint32_t size;
144 * Parameters for AVI dumping.
146 struct avi_info
149 * Zlib compression level (0-9).
151 unsigned compression_level;
154 * Audio sampling rate to write to AVI.
156 uint32_t audio_sampling_rate;
159 * Interval of keyframes (WARNING: >1 gives non-keyframes which AVISource() doesn't like).
161 uint32_t keyframe_interval;
163 * Maximum number of frames per segement (0 => infinite)
165 uint32_t max_frames_per_segment;
169 * The actual AVI dumper.
171 class avidumper
173 public:
174 avidumper(const std::string& _prefix, struct avi_info parameters);
175 ~avidumper() throw();
178 * Waits for the encode thread. Not needed: Operations that need to synchronize synchronize themselves.
180 void wait_idle() throw();
183 * Dump a frame (new segment starts if needed). Pixel byte order is BGRx.
185 * parameter data: The frame data.
186 * parameter width: Width of frame.
187 * parameter height: Height of frame.
188 * parameter fps_n: Numerator of fps value.
189 * parameter fps_d: Denomerator of fps value.
190 * throws std::bad_alloc: Not enough memory.
191 * throws std::runtime_error: Error dumping frame.
193 void on_frame(const uint16_t* data, uint16_t width, uint16_t height, uint32_t fps_n, uint32_t fps_d)
194 throw(std::bad_alloc, std::runtime_error);
197 * Dump an audio sample
199 * parameter left: Signed sample for left channel (-32768 - 327678).
200 * parameter right: Signed sample for right channel (-32768 - 327678).
201 * throws std::bad_alloc: Not enough memory.
202 * throws std::runtime_error: Error dumping sample.
204 void on_sample(short left, short right) throw(std::bad_alloc, std::runtime_error);
207 * Notify end of dump.
209 * throws std::bad_alloc: Not enough memory.
210 * throws std::runtime_error: Error closing dump.
212 void on_end() throw(std::bad_alloc, std::runtime_error);
215 * Causes current thread to become encode thread. Do not call this, the code internally uses it.
217 * returns: Return status for the thread.
219 int encode_thread();
222 * Set capture errored flag.
224 * parameter err: The error message.
226 void set_capture_error(const char* err) throw();
227 private:
228 void print_summary(std::ostream& str);
229 void on_frame_threaded(const uint16_t* data, uint16_t width, uint16_t height, uint32_t fps_n, uint32_t fps_d)
230 throw(std::bad_alloc, std::runtime_error);
231 void flush_audio_to(unsigned commit_ptr);
232 void open_and_write_avi_header(uint16_t width, uint16_t height, uint32_t fps_n, uint32_t fps_d);
233 void fixup_avi_header_and_close();
234 std::ofstream avi_stream;
235 bool capture_error;
236 std::string capture_error_str;
237 bool avi_open;
238 //Global settings.
239 unsigned compression_level;
240 uint32_t audio_sampling_rate;
241 uint32_t keyframe_interval;
242 uint32_t maxframes;
243 //Previous frame.
244 uint16_t pwidth;
245 uint16_t pheight;
246 uint32_t pfps_n;
247 uint32_t pfps_d;
248 //Current segment.
249 uint32_t segment_movi_ptr;
250 uint32_t segment_frames;
251 uint32_t segment_samples;
252 uint32_t segment_last_keyframe;
253 uint32_t current_segment;
254 uint32_t fixup_avi_size;
255 uint32_t fixup_avi_frames;
256 uint32_t fixup_avi_length;
257 uint32_t fixup_avi_a_length;
258 uint32_t fixup_movi_size;
259 std::list<avi_frame> segment_chunks;
260 //Global info.
261 std::string prefix;
262 uint64_t total_data;
263 uint64_t total_frames;
264 uint64_t total_samples;
265 //Temporary buffers.
266 std::vector<uint8_t> pframe;
267 std::vector<uint8_t> tframe;
268 std::vector<uint8_t> cframe;
269 short audio_buffer[AVIDUMPER_AUDIO_BUFFER];
270 unsigned audio_put_ptr;
271 unsigned audio_get_ptr;
272 volatile unsigned audio_commit_ptr; //Protected by frame_mutex.
273 //Multithreading stuff.
274 thread_class* frame_thread;
275 cv_class frame_cond;
276 mutex_class frame_mutex;
277 const uint16_t* mt_data;
278 volatile uint16_t mt_width;
279 volatile uint16_t mt_height;
280 volatile uint32_t mt_fps_n;
281 volatile uint32_t mt_fps_d;
282 volatile bool sigquit;
285 #endif