Merge branch 'rr1-maint'

This commit is contained in:
Ilari Liusvaara 2013-02-12 00:28:48 +02:00
commit e83cc21e8a

View file

@ -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();