Separate async frame and async tile APIs

This commit is contained in:
Martin Piatka
2019-03-13 15:00:05 +01:00
parent e62f6773ab
commit 835239498d
10 changed files with 72 additions and 6 deletions

View File

@@ -74,6 +74,7 @@ private:
compress_state_real(struct module *parent, const char *config_string);
void start(struct compress_state *proxy);
void async_consumer(struct compress_state *s);
void async_tile_consumer(struct compress_state *s);
thread asynch_consumer_thread;
public:
static compress_state_real *create(struct module *parent, const char *config_string,
@@ -121,8 +122,10 @@ void show_compress_help()
static void async_poison(struct compress_state_real *s){
if (s->funcs->compress_frame_async_push_func) {
s->funcs->compress_frame_async_push_func(s->state[0], {}); // poison
} else if (s->funcs->compress_tile_async_push_func){
for(size_t i = 0; i < s->state.size(); i++){
s->funcs->compress_frame_async_push_func(s->state[i], {}); // poison
s->funcs->compress_tile_async_push_func(s->state[i], {}); // poison
}
}
}
@@ -272,6 +275,8 @@ void compress_state_real::start(struct compress_state *proxy)
{
if (funcs->compress_frame_async_push_func) {
asynch_consumer_thread = thread(&compress_state_real::async_consumer, this, proxy);
} else if (funcs->compress_tile_async_push_func){
asynch_consumer_thread = thread(&compress_state_real::async_tile_consumer, this, proxy);
}
}
@@ -338,6 +343,12 @@ void compress_frame(struct compress_state *proxy, shared_ptr<video_frame> frame)
if (s->funcs->compress_frame_async_push_func) {
assert(s->funcs->compress_frame_async_pop_func);
if (frame) {
frame->compress_start = t0;
}
s->funcs->compress_frame_async_push_func(s->state[0], frame);
} else if (s->funcs->compress_tile_async_push_func) {
assert(s->funcs->compress_tile_async_pop_func);
if (!frame) {
async_poison(s);
return;
@@ -354,7 +365,7 @@ void compress_frame(struct compress_state *proxy, shared_ptr<video_frame> frame)
frame = NULL;
for(unsigned i = 0; i < separate_tiles.size(); i++){
s->funcs->compress_frame_async_push_func(s->state[i], separate_tiles[i]);
s->funcs->compress_tile_async_push_func(s->state[i], separate_tiles[i]);
}
} else {
@@ -488,7 +499,7 @@ static void compress_done(struct module *mod)
compress_state_real::~compress_state_real()
{
if (funcs->compress_frame_async_push_func) {
if (asynch_consumer_thread.joinable()) {
asynch_consumer_thread.join();
}
@@ -498,7 +509,7 @@ compress_state_real::~compress_state_real()
}
namespace {
void compress_state_real::async_consumer(struct compress_state *s)
void compress_state_real::async_tile_consumer(struct compress_state *s)
{
vector<shared_ptr<video_frame>> compressed_tiles;
unsigned expected_seq = 0;
@@ -508,7 +519,7 @@ void compress_state_real::async_consumer(struct compress_state *s)
std::shared_ptr<video_frame> ret = nullptr;
//discard frames with seq lower than expected
do {
ret = funcs->compress_frame_async_pop_func(state[i]);
ret = funcs->compress_tile_async_pop_func(state[i]);
} while(ret && ret->seq < expected_seq);
if (!ret) {
@@ -547,6 +558,23 @@ void compress_state_real::async_consumer(struct compress_state *s)
if(expected_seq > 0) expected_seq++;
}
}
void compress_state_real::async_consumer(struct compress_state *s)
{
while (true) {
auto frame = funcs->compress_frame_async_pop_func(state[0]);
if (!discard_frames) {
s->queue.push(frame);
}
if (!frame) {
return;
}
}
}
} // end of anonymous namespace
shared_ptr<video_frame> compress_pop(struct compress_state *proxy)

View File

@@ -121,6 +121,25 @@ typedef void (*compress_frame_async_push_t)(struct module *state, std::shared_pt
*/
typedef std::shared_ptr<video_frame> (*compress_frame_async_pop_t)(struct module *state);
/**
* @brief Passes tile to compress module for async processing.
*
* compress_frame_async_pop_t() should be called thereafter to fetch compressed frame.
*
* @param[in] state driver internal state
* @param[in] in_frame uncompressed frame or empty shared_ptr to pass a poisoned pile
*/
typedef void (*compress_tile_async_push_t)(struct module *state, std::shared_ptr<video_frame> in_frame);
/**
* @brief Fetches compressed tile passed with compress_tile_async_push()
*
* @param[in] state driver internal state
* @return compressed frame, empty shared_ptr corresponding with poisoned
* pill can be also returned
*/
typedef std::shared_ptr<video_frame> (*compress_tile_async_pop_t)(struct module *state);
void compress_frame(struct compress_state *, std::shared_ptr<video_frame>);
struct compress_preset {
@@ -138,13 +157,14 @@ struct compress_preset {
};
/**
* There are 3 possible APIs for video compress modules. Each module may choose
* There are 4 possible APIs for video compress modules. Each module may choose
* which one to implement, however, only one should be implemented (there is no
* "smart" heuristics to pick one if more APIs are implemented). Available options
* are:
* 1. Frame API - compress entire frame (all tiles)
* 2. Tile API - compress one tile
* 3. Async API - compress a frame asynchronously
* 4. Async tile API - compress a tile asynchronously
*/
struct video_compress_info {
const char * name; ///< compress (unique) name
@@ -153,6 +173,8 @@ struct video_compress_info {
compress_tile_t compress_tile_func; ///< compress function for Tile API
compress_frame_async_push_t compress_frame_async_push_func; ///< Async API
compress_frame_async_pop_t compress_frame_async_pop_func; ///< Async API
compress_tile_async_push_t compress_tile_async_push_func; ///< Async tile API
compress_tile_async_pop_t compress_tile_async_pop_func; ///< Async tile API
std::list<compress_preset> (*get_presets)(); ///< list of available presets
};

View File

@@ -513,6 +513,8 @@ const struct video_compress_info cineform_info = {
cineform_compress_init,
NULL,
NULL,
NULL,
NULL,
cineform_compress_push,
cineform_compress_pop,
get_cineform_presets,

View File

@@ -384,6 +384,8 @@ static struct video_compress_info j2k_compress_info = {
j2k_compress_init,
NULL,
NULL,
NULL,
NULL,
j2k_compress_push,
j2k_compress_pop,
[] { return list<compress_preset>{}; }

View File

@@ -289,6 +289,8 @@ const struct video_compress_info cuda_dxt_info = {
cuda_dxt_compress_tile,
NULL,
NULL,
NULL,
NULL,
[] { return list<compress_preset>{}; }
};

View File

@@ -330,6 +330,8 @@ const struct video_compress_info rtdxt_info = {
NULL,
NULL,
NULL,
NULL,
NULL,
[] {
return dxt_is_supported() ? list<compress_preset>{
{ "DXT1", 35, [](const struct video_desc *d){return (long)(d->width * d->height * d->fps * 4.0);},

View File

@@ -588,6 +588,8 @@ const struct video_compress_info jpeg_info = {
[](struct module *mod) {
return static_cast<struct state_video_compress_jpeg *>(mod->priv_data)->pop();
},
NULL,
NULL,
[] {
return gpujpeg_init_device(cuda_devices[0], TRUE) == 0 ? list<compress_preset>{
{ "60", 60, [](const struct video_desc *d){return (long)(d->width * d->height * d->fps * 0.68);},

View File

@@ -1782,6 +1782,8 @@ const struct video_compress_info libavcodec_info = {
libavcodec_compress_tile,
NULL,
NULL,
NULL,
NULL,
get_libavcodec_presets,
};

View File

@@ -113,6 +113,8 @@ const struct video_compress_info none_info = {
NULL,
NULL,
NULL,
NULL,
NULL,
[] {
return std::list<compress_preset>{
{ "", 100, [](const struct video_desc *d){return (long)(d->width * d->height * d->fps * get_bpp(d->color_spec) * 8.0);},

View File

@@ -306,6 +306,8 @@ const struct video_compress_info uyvy_info = {
NULL,
NULL,
NULL,
NULL,
NULL,
[] {return list<compress_preset>{}; }
};