2011-09-15 16:42:52 +03:00
|
|
|
#ifndef _avidump__hpp__included__
|
|
|
|
#define _avidump__hpp__included__
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <vector>
|
|
|
|
#include <list>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef NO_THREADS
|
|
|
|
#include <thread>
|
|
|
|
#include <condition_variable>
|
|
|
|
#include <mutex>
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Class of thread.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
typedef std::thread thread_class;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Class of condition variables.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
typedef std::condition_variable cv_class;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Class of mutexes.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
typedef std::mutex mutex_class;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Class of unique mutexes (for condition variable waiting).
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
typedef std::unique_lock<std::mutex> umutex_class;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Class of thread.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
struct thread_class
|
|
|
|
{
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Does nothing.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
template<typename T, typename... args>
|
|
|
|
thread_class(T obj, args... a) {}
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Does nothing.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void join() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Class of mutexes.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
typedef struct mutex_class
|
|
|
|
{
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Does nothing.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void lock() {}
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Does nothing.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void unlock() {}
|
|
|
|
} umutex_class;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Class of condition variables.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
struct cv_class
|
|
|
|
{
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Does nothing.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void wait(umutex_class& m) {}
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Does nothing.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void notify_all() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Size of audio buffer (enough to buffer 3 frames).
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
#define AVIDUMPER_AUDIO_BUFFER 4096
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Information about frame in AVI.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
struct avi_frame
|
|
|
|
{
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Constructor.
|
2011-09-13 17:50:18 +03:00
|
|
|
*
|
2011-09-15 15:12:26 +03:00
|
|
|
* parameter _flags: Flags for frame.
|
|
|
|
* parameter _type: AVI type for frame (big-endian!).
|
|
|
|
* parameter _offset: Offset of frame from start of MOVI.
|
|
|
|
* parameter _size: Size of frame data.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
avi_frame(uint32_t _flags, uint32_t _type, uint32_t _offset, uint32_t _size);
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Write the index entry for frame.
|
2011-09-13 17:50:18 +03:00
|
|
|
*
|
2011-09-15 15:12:26 +03:00
|
|
|
* parameter buf: Buffer to write to.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void write(uint8_t* buf);
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Flags.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint32_t flags;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Chunk type.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint32_t type;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Chunk offset.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint32_t offset;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Chunk size.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint32_t size;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Parameters for AVI dumping.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
struct avi_info
|
|
|
|
{
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Zlib compression level (0-9).
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
unsigned compression_level;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Audio drop counter increments by this much every frame.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint64_t audio_drop_counter_inc;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Audio drop counter modulus (when audio drop counter warps around, sample is dropped).
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint64_t audio_drop_counter_max;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Audio sampling rate to write to AVI.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint32_t audio_sampling_rate;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Native audio sampling rate to write to auxillary SOX file.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
double audio_native_sampling_rate;
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Interval of keyframes (WARNING: >1 gives non-keyframes which AVISource() doesn't like).
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint32_t keyframe_interval;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* The actual AVI dumper.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
class avidumper
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
avidumper(const std::string& _prefix, struct avi_info parameters);
|
|
|
|
~avidumper() throw();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Waits for the encode thread. Not needed: Operations that need to synchronize synchronize themselves.
|
|
|
|
*/
|
|
|
|
void wait_idle() throw();
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Dump a frame (new segment starts if needed). Pixel byte order is BGRx.
|
2011-09-13 17:50:18 +03:00
|
|
|
*
|
2011-09-15 15:12:26 +03:00
|
|
|
* parameter data: The frame data.
|
|
|
|
* parameter width: Width of frame.
|
|
|
|
* parameter height: Height of frame.
|
|
|
|
* parameter fps_n: Numerator of fps value.
|
|
|
|
* parameter fps_d: Denomerator of fps value.
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
|
|
|
* throws std::runtime_error: Error dumping frame.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void on_frame(const uint32_t* data, uint16_t width, uint16_t height, uint32_t fps_n, uint32_t fps_d)
|
|
|
|
throw(std::bad_alloc, std::runtime_error);
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Dump an audio sample
|
2011-09-13 17:50:18 +03:00
|
|
|
*
|
2011-09-15 15:12:26 +03:00
|
|
|
* parameter left: Signed sample for left channel (-32768 - 327678).
|
|
|
|
* parameter right: Signed sample for right channel (-32768 - 327678).
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
|
|
|
* throws std::runtime_error: Error dumping sample.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void on_sample(short left, short right) throw(std::bad_alloc, std::runtime_error);
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Notify end of dump.
|
2011-09-13 17:50:18 +03:00
|
|
|
*
|
2011-09-15 15:12:26 +03:00
|
|
|
* throws std::bad_alloc: Not enough memory.
|
|
|
|
* throws std::runtime_error: Error closing dump.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void on_end() throw(std::bad_alloc, std::runtime_error);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Causes current thread to become encode thread. Do not call this, the code internally uses it.
|
|
|
|
*
|
2011-09-15 15:12:26 +03:00
|
|
|
* returns: Return status for the thread.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
int encode_thread();
|
|
|
|
|
|
|
|
/**
|
2011-09-15 15:12:26 +03:00
|
|
|
* Set capture errored flag.
|
|
|
|
*
|
|
|
|
* parameter err: The error message.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void set_capture_error(const char* err) throw();
|
|
|
|
private:
|
|
|
|
void print_summary(std::ostream& str);
|
|
|
|
void on_frame_threaded(const uint32_t* data, uint16_t width, uint16_t height, uint32_t fps_n, uint32_t fps_d)
|
|
|
|
throw(std::bad_alloc, std::runtime_error);
|
|
|
|
void flush_audio_to(unsigned commit_ptr);
|
|
|
|
void open_and_write_avi_header(uint16_t width, uint16_t height, uint32_t fps_n, uint32_t fps_d);
|
|
|
|
void fixup_avi_header_and_close();
|
|
|
|
std::ofstream sox_stream;
|
|
|
|
std::ofstream avi_stream;
|
|
|
|
bool capture_error;
|
|
|
|
std::string capture_error_str;
|
|
|
|
bool sox_open;
|
|
|
|
bool avi_open;
|
|
|
|
//Global settings.
|
|
|
|
unsigned compression_level;
|
|
|
|
uint64_t audio_drop_counter_inc;
|
|
|
|
uint64_t audio_drop_counter_max;
|
|
|
|
uint32_t audio_sampling_rate;
|
|
|
|
double audio_native_sampling_rate;
|
|
|
|
uint32_t keyframe_interval;
|
|
|
|
//Previous frame.
|
|
|
|
uint16_t pwidth;
|
|
|
|
uint16_t pheight;
|
|
|
|
uint32_t pfps_n;
|
|
|
|
uint32_t pfps_d;
|
|
|
|
//Current segment.
|
|
|
|
uint32_t segment_movi_ptr;
|
|
|
|
uint32_t segment_frames;
|
|
|
|
uint32_t segment_samples;
|
|
|
|
uint32_t segment_last_keyframe;
|
|
|
|
uint32_t current_segment;
|
|
|
|
uint32_t fixup_avi_size;
|
|
|
|
uint32_t fixup_avi_frames;
|
|
|
|
uint32_t fixup_avi_length;
|
|
|
|
uint32_t fixup_avi_a_length;
|
|
|
|
uint32_t fixup_movi_size;
|
|
|
|
std::list<avi_frame> segment_chunks;
|
|
|
|
//Global info.
|
|
|
|
std::string prefix;
|
|
|
|
uint64_t total_data;
|
|
|
|
uint64_t total_frames;
|
|
|
|
uint64_t total_samples;
|
|
|
|
uint64_t raw_samples;
|
|
|
|
uint64_t audio_drop_counter;
|
|
|
|
//Temporary buffers.
|
|
|
|
std::vector<uint8_t> pframe;
|
|
|
|
std::vector<uint8_t> tframe;
|
|
|
|
std::vector<uint8_t> cframe;
|
|
|
|
short audio_buffer[AVIDUMPER_AUDIO_BUFFER];
|
|
|
|
unsigned audio_put_ptr;
|
|
|
|
unsigned audio_get_ptr;
|
|
|
|
volatile unsigned audio_commit_ptr; //Protected by frame_mutex.
|
|
|
|
//Multithreading stuff.
|
|
|
|
thread_class* frame_thread;
|
|
|
|
cv_class frame_cond;
|
|
|
|
mutex_class frame_mutex;
|
|
|
|
const uint32_t* mt_data;
|
|
|
|
volatile uint16_t mt_width;
|
|
|
|
volatile uint16_t mt_height;
|
|
|
|
volatile uint32_t mt_fps_n;
|
|
|
|
volatile uint32_t mt_fps_d;
|
|
|
|
volatile bool sigquit;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|