Merge branch 'rr1-maint'
This commit is contained in:
commit
e83cc21e8a
1 changed files with 123 additions and 25 deletions
|
@ -46,6 +46,8 @@
|
||||||
#define ITERATION_TIME 15000
|
#define ITERATION_TIME 15000
|
||||||
//Opus bitrate to use.
|
//Opus bitrate to use.
|
||||||
#define OPUS_BITRATE 48000
|
#define OPUS_BITRATE 48000
|
||||||
|
//Opus max bitrate to use.
|
||||||
|
#define OPUS_MAX_BITRATE 255000
|
||||||
//Ogg Opus granule rate.
|
//Ogg Opus granule rate.
|
||||||
#define OGGOPUS_GRANULERATE 48000
|
#define OGGOPUS_GRANULERATE 48000
|
||||||
//Record buffer size threshold divider.
|
//Record buffer size threshold divider.
|
||||||
|
@ -62,6 +64,7 @@ namespace
|
||||||
class stream_collection;
|
class stream_collection;
|
||||||
|
|
||||||
volatile unsigned opus_bitrate = OPUS_BITRATE;
|
volatile unsigned opus_bitrate = OPUS_BITRATE;
|
||||||
|
volatile unsigned opus_max_bitrate = OPUS_MAX_BITRATE;
|
||||||
struct _bitrate_setting : public setting
|
struct _bitrate_setting : public setting
|
||||||
{
|
{
|
||||||
_bitrate_setting() : setting(lsnes_set, "opus-bitrate") {}
|
_bitrate_setting() : setting(lsnes_set, "opus-bitrate") {}
|
||||||
|
@ -80,6 +83,24 @@ namespace
|
||||||
}
|
}
|
||||||
std::string get() throw(std::bad_alloc) { return (stringfmt() << opus_bitrate).str(); }
|
std::string get() throw(std::bad_alloc) { return (stringfmt() << opus_bitrate).str(); }
|
||||||
} bitrate_setting;
|
} bitrate_setting;
|
||||||
|
struct _max_bitrate_setting : public setting
|
||||||
|
{
|
||||||
|
_max_bitrate_setting() : setting(lsnes_set, "opus-max-bitrate") {}
|
||||||
|
~_max_bitrate_setting() {}
|
||||||
|
bool blank(bool x) throw (std::bad_alloc, std::runtime_error)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("This setting can't be blanked");
|
||||||
|
}
|
||||||
|
bool is_set() throw() { return true; }
|
||||||
|
void set(const std::string& value) throw(std::bad_alloc, std::runtime_error)
|
||||||
|
{
|
||||||
|
unsigned tmp = parse_value<unsigned>(value);
|
||||||
|
if(tmp < 8000 || tmp > 255000)
|
||||||
|
throw std::runtime_error("Bitrate out of range");
|
||||||
|
opus_max_bitrate = tmp;
|
||||||
|
}
|
||||||
|
std::string get() throw(std::bad_alloc) { return (stringfmt() << opus_max_bitrate).str(); }
|
||||||
|
} max_bitrate_setting;
|
||||||
|
|
||||||
//Recording active flag.
|
//Recording active flag.
|
||||||
volatile bool active_flag = false;
|
volatile bool active_flag = false;
|
||||||
|
@ -105,6 +126,89 @@ namespace
|
||||||
//Lock protecting current collection.
|
//Lock protecting current collection.
|
||||||
mutex_class current_collection_lock;
|
mutex_class current_collection_lock;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//Bitrate tracker.
|
||||||
|
struct bitrate_tracker
|
||||||
|
{
|
||||||
|
bitrate_tracker() throw();
|
||||||
|
void reset() throw();
|
||||||
|
double get_min() throw();
|
||||||
|
double get_avg() throw();
|
||||||
|
double get_max() throw();
|
||||||
|
double get_length() throw();
|
||||||
|
uint64_t get_bytes() throw();
|
||||||
|
uint64_t get_blocks() throw();
|
||||||
|
void submit(uint32_t bytes, uint32_t samples) throw();
|
||||||
|
private:
|
||||||
|
uint64_t blocks;
|
||||||
|
uint64_t samples;
|
||||||
|
uint64_t bytes;
|
||||||
|
uint32_t minrate;
|
||||||
|
uint32_t maxrate;
|
||||||
|
};
|
||||||
|
|
||||||
|
bitrate_tracker::bitrate_tracker() throw()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitrate_tracker::reset() throw()
|
||||||
|
{
|
||||||
|
blocks = 0;
|
||||||
|
samples = 0;
|
||||||
|
bytes = 0;
|
||||||
|
minrate = std::numeric_limits<uint32_t>::max();
|
||||||
|
maxrate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double bitrate_tracker::get_min() throw()
|
||||||
|
{
|
||||||
|
return blocks ? minrate / 1000.0 : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double bitrate_tracker::get_avg() throw()
|
||||||
|
{
|
||||||
|
return samples ? bytes / (125.0 * samples / OPUS_SAMPLERATE) : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double bitrate_tracker::get_max() throw()
|
||||||
|
{
|
||||||
|
return blocks ? maxrate / 1000.0 : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double bitrate_tracker::get_length() throw()
|
||||||
|
{
|
||||||
|
return 1.0 * samples / OPUS_SAMPLERATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t bitrate_tracker::get_bytes() throw()
|
||||||
|
{
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t bitrate_tracker::get_blocks() throw()
|
||||||
|
{
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitrate_tracker::submit(uint32_t _bytes, uint32_t _samples) throw()
|
||||||
|
{
|
||||||
|
blocks++;
|
||||||
|
samples += _samples;
|
||||||
|
bytes += _bytes;
|
||||||
|
uint32_t irate = _bytes * 8 * OPUS_SAMPLERATE / OPUS_BLOCK_SIZE;
|
||||||
|
minrate = min(minrate, irate);
|
||||||
|
maxrate = max(maxrate, irate);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& s, bitrate_tracker& t)
|
||||||
|
{
|
||||||
|
s << t.get_bytes() << " bytes for " << t.get_length() << "s (" << t.get_blocks() << " blocks)"
|
||||||
|
<< std::endl << "Bitrate (kbps): min: " << t.get_min() << " avg: " << t.get_avg() << " max:"
|
||||||
|
<< t.get_max() << std::endl;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//Information about individual opus packet in stream.
|
//Information about individual opus packet in stream.
|
||||||
struct opus_packetinfo
|
struct opus_packetinfo
|
||||||
|
@ -659,6 +763,7 @@ out:
|
||||||
|
|
||||||
void opus_stream::import_stream_sox(std::ifstream& data)
|
void opus_stream::import_stream_sox(std::ifstream& data)
|
||||||
{
|
{
|
||||||
|
bitrate_tracker brtrack;
|
||||||
int err;
|
int err;
|
||||||
unsigned char tmpi[65536];
|
unsigned char tmpi[65536];
|
||||||
float tmp[OPUS_MAX_OUT];
|
float tmp[OPUS_MAX_OUT];
|
||||||
|
@ -706,7 +811,8 @@ out:
|
||||||
postgap_length = OPUS_BLOCK_SIZE - bs;
|
postgap_length = OPUS_BLOCK_SIZE - bs;
|
||||||
for(size_t j = bs; j < OPUS_BLOCK_SIZE; j++)
|
for(size_t j = bs; j < OPUS_BLOCK_SIZE; j++)
|
||||||
tmp[j] = 0;
|
tmp[j] = 0;
|
||||||
int r = opus_encode_float(enc, tmp, OPUS_BLOCK_SIZE, tmpi, sizeof(tmpi));
|
const size_t opus_out_max2 = opus_max_bitrate * OPUS_BLOCK_SIZE / 384000;
|
||||||
|
int r = opus_encode_float(enc, tmp, OPUS_BLOCK_SIZE, tmpi, opus_out_max2);
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
if(ctrl_cluster) fs.free_cluster_chain(ctrl_cluster);
|
if(ctrl_cluster) fs.free_cluster_chain(ctrl_cluster);
|
||||||
if(data_cluster) fs.free_cluster_chain(data_cluster);
|
if(data_cluster) fs.free_cluster_chain(data_cluster);
|
||||||
|
@ -721,8 +827,10 @@ out:
|
||||||
opus_encoder_destroy(enc);
|
opus_encoder_destroy(enc);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
brtrack.submit(r, bs);
|
||||||
}
|
}
|
||||||
opus_encoder_destroy(enc);
|
opus_encoder_destroy(enc);
|
||||||
|
messages << "Imported stream: " << brtrack;
|
||||||
try {
|
try {
|
||||||
write_trailier();
|
write_trailier();
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
@ -1572,7 +1680,7 @@ out:
|
||||||
|
|
||||||
//Compress Opus block.
|
//Compress Opus block.
|
||||||
void compress_opus_block(OpusEncoder* e, float* buf, size_t& use, opus_stream& active_stream,
|
void compress_opus_block(OpusEncoder* e, float* buf, size_t& use, opus_stream& active_stream,
|
||||||
double& total_compressed, double& total_blocks)
|
bitrate_tracker& brtrack)
|
||||||
{
|
{
|
||||||
const size_t opus_out_max = 1276;
|
const size_t opus_out_max = 1276;
|
||||||
unsigned char opus_output[opus_out_max];
|
unsigned char opus_output[opus_out_max];
|
||||||
|
@ -1587,13 +1695,12 @@ out:
|
||||||
cblock = 120;
|
cblock = 120;
|
||||||
else
|
else
|
||||||
return; //No valid data to compress.
|
return; //No valid data to compress.
|
||||||
|
const size_t opus_out_max2 = opus_max_bitrate * cblock / 384000;
|
||||||
int c = opus_encode_float(e, buf, cblock, opus_output, opus_out_max);
|
int c = opus_encode_float(e, buf, cblock, opus_output, opus_out_max2);
|
||||||
if(c > 0) {
|
if(c > 0) {
|
||||||
//Successfully compressed a block.
|
//Successfully compressed a block.
|
||||||
size_t opus_output_len = c;
|
size_t opus_output_len = c;
|
||||||
total_compressed += c;
|
brtrack.submit(c, cblock);
|
||||||
total_blocks++;
|
|
||||||
try {
|
try {
|
||||||
active_stream.write(cblock / 120, opus_output, opus_output_len);
|
active_stream.write(cblock / 120, opus_output, opus_output_len);
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
|
@ -1662,16 +1769,14 @@ out:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_tangent_positive_edge(OpusEncoder* e, opus_stream*& active_stream,
|
void handle_tangent_positive_edge(OpusEncoder* e, opus_stream*& active_stream, bitrate_tracker& brtrack)
|
||||||
double& total_compressed, double& total_blocks)
|
|
||||||
{
|
{
|
||||||
umutex_class m2(current_collection_lock);
|
umutex_class m2(current_collection_lock);
|
||||||
if(!current_collection)
|
if(!current_collection)
|
||||||
return;
|
return;
|
||||||
opus_encoder_ctl(e, OPUS_RESET_STATE);
|
opus_encoder_ctl(e, OPUS_RESET_STATE);
|
||||||
opus_encoder_ctl(e, OPUS_SET_BITRATE(opus_bitrate));
|
opus_encoder_ctl(e, OPUS_SET_BITRATE(opus_bitrate));
|
||||||
total_compressed = 0;
|
brtrack.reset();
|
||||||
total_blocks = 0;
|
|
||||||
uint64_t ctime;
|
uint64_t ctime;
|
||||||
{
|
{
|
||||||
umutex_class m(time_mutex);
|
umutex_class m(time_mutex);
|
||||||
|
@ -1687,16 +1792,13 @@ out:
|
||||||
messages << "Can't start stream: " << e.what() << std::endl;
|
messages << "Can't start stream: " << e.what() << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
messages << "Tangent positive edge." << std::endl;
|
messages << "Tangent enaged." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_tangent_negative_edge(opus_stream*& active_stream, double total_compressed,
|
void handle_tangent_negative_edge(opus_stream*& active_stream, bitrate_tracker& brtrack)
|
||||||
double total_blocks)
|
|
||||||
{
|
{
|
||||||
umutex_class m2(current_collection_lock);
|
umutex_class m2(current_collection_lock);
|
||||||
messages << "Tangent negative edge. "
|
messages << "Tangent disenaged: " << brtrack;
|
||||||
<< total_compressed << " bytes in " << total_blocks << " blocks, "
|
|
||||||
<< (0.4 * total_compressed / total_blocks) << " kbps" << std::endl;
|
|
||||||
active_stream->write_trailier();
|
active_stream->write_trailier();
|
||||||
if(current_collection) {
|
if(current_collection) {
|
||||||
try {
|
try {
|
||||||
|
@ -1756,16 +1858,14 @@ out:
|
||||||
float buf_inr[OPUS_BLOCK_SIZE];
|
float buf_inr[OPUS_BLOCK_SIZE];
|
||||||
float buf_outr[OUTPUT_SIZE];
|
float buf_outr[OUTPUT_SIZE];
|
||||||
float buf_out[buf_max];
|
float buf_out[buf_max];
|
||||||
double total_compressed = 0;
|
bitrate_tracker brtrack;
|
||||||
double total_blocks = 0;
|
|
||||||
opus_stream* active_stream = NULL;
|
opus_stream* active_stream = NULL;
|
||||||
|
|
||||||
drain_input();
|
drain_input();
|
||||||
while(1) {
|
while(1) {
|
||||||
if(clear_workflag(WORKFLAG_QUIT_REQUEST) & WORKFLAG_QUIT_REQUEST) {
|
if(clear_workflag(WORKFLAG_QUIT_REQUEST) & WORKFLAG_QUIT_REQUEST) {
|
||||||
if(!active_flag && active_stream)
|
if(!active_flag && active_stream)
|
||||||
handle_tangent_negative_edge(active_stream, total_compressed,
|
handle_tangent_negative_edge(active_stream, brtrack);
|
||||||
total_blocks);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint64_t ticks = get_utime();
|
uint64_t ticks = get_utime();
|
||||||
|
@ -1774,11 +1874,10 @@ out:
|
||||||
drain_input();
|
drain_input();
|
||||||
buf_in_use = 0;
|
buf_in_use = 0;
|
||||||
buf_inr_use = 0;
|
buf_inr_use = 0;
|
||||||
handle_tangent_positive_edge(oenc, active_stream, total_compressed,
|
handle_tangent_positive_edge(oenc, active_stream, brtrack);
|
||||||
total_blocks);
|
|
||||||
}
|
}
|
||||||
else if((!active_flag || quit) && active_stream)
|
else if((!active_flag || quit) && active_stream)
|
||||||
handle_tangent_negative_edge(active_stream, total_compressed, total_blocks);
|
handle_tangent_negative_edge(active_stream, brtrack);
|
||||||
if(quit)
|
if(quit)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1794,8 +1893,7 @@ out:
|
||||||
|
|
||||||
//If we have full opus block and recording is enabled, compress it.
|
//If we have full opus block and recording is enabled, compress it.
|
||||||
if(buf_inr_use >= OPUS_BLOCK_SIZE && active_stream)
|
if(buf_inr_use >= OPUS_BLOCK_SIZE && active_stream)
|
||||||
compress_opus_block(oenc, buf_inr, buf_inr_use, *active_stream,
|
compress_opus_block(oenc, buf_inr, buf_inr_use, *active_stream, brtrack);
|
||||||
total_compressed, total_blocks);
|
|
||||||
|
|
||||||
//Update time, starting/ending streams.
|
//Update time, starting/ending streams.
|
||||||
update_time();
|
update_time();
|
||||||
|
|
Loading…
Add table
Reference in a new issue