Compress sync tile API: fetch additional frames

Modified the API in order to fetch additional frames from compression
with iterative passing NULL pointer (similarly as for audio).

This is particularly usefull when inter-frame compression outputs 2
frames at once, which can occur when B-frames would be enabled. It,
however sometimes happen even when B-frames are disbled, eg. with
h264/hevc_mf HW encoder on AMD (AMDh265Encoder; see commit d70e2fb3c).

Please note that semantic of passing NUL frame is different in this API
to that in async API, where it works as a poison pill.
This commit is contained in:
Martin Pulec
2023-08-18 10:14:07 +02:00
parent f035e43ac5
commit 690244686a
4 changed files with 35 additions and 19 deletions

View File

@@ -371,20 +371,23 @@ void compress_frame(struct compress_state *proxy, shared_ptr<video_frame> frame)
for(unsigned i = 0; i < separate_tiles.size(); i++){
s->funcs->compress_tile_async_push_func(s->state[i], separate_tiles[i]);
}
return;
}
} else {
if (!frame) { // pass poisoned pill
proxy->queue.push(shared_ptr<video_frame>());
return;
}
// sync APIs - pass poisoned pill to the queue but not to compressions,
if (!frame) { // which doesn't need that but use NULL frame differently
proxy->queue.push(shared_ptr<video_frame>());
return;
}
shared_ptr<video_frame> sync_api_frame;
shared_ptr<video_frame> sync_api_frame;
do {
if (s->funcs->compress_frame_func) {
sync_api_frame = s->funcs->compress_frame_func(s->state[0], frame);
} else if(s->funcs->compress_tile_func) {
sync_api_frame = compress_frame_tiles(proxy, frame);
} else {
assert(!"No egliable compress API found");
assert(!"No eligible compress API found");
}
// empty return value here represents error, but we don't want to pass it to queue, since it would
@@ -392,11 +395,10 @@ void compress_frame(struct compress_state *proxy, shared_ptr<video_frame> frame)
if (!sync_api_frame) {
return;
}
sync_api_frame->compress_end = get_time_in_ns();
proxy->queue.push(sync_api_frame);
}
frame = nullptr;
} while (s->funcs->compress_tile_func != nullptr);
}
/**
@@ -439,19 +441,24 @@ static shared_ptr<video_frame> compress_frame_tiles(struct compress_state *proxy
shared_ptr<video_frame> frame)
{
struct compress_state_real *s = proxy->ptr;
if(!check_state_count(frame->tile_count, proxy)){
return NULL;
const int tile_cnt = (int) proxy->ptr->state.size();
vector<shared_ptr<video_frame>> separate_tiles;
if (frame) {
if (!check_state_count(frame->tile_count, proxy)) {
return nullptr;
}
separate_tiles = vf_separate_tiles(frame);
} else {
separate_tiles.resize(tile_cnt);
}
vector<shared_ptr<video_frame>> separate_tiles = vf_separate_tiles(frame);
// frame pointer may no longer be valid
frame = NULL;
vector<task_result_handle_t> task_handle(separate_tiles.size());
vector<task_result_handle_t> task_handle(tile_cnt);
vector <compress_worker_data> data_tile(separate_tiles.size());
for(unsigned int i = 0; i < separate_tiles.size(); ++i) {
vector <compress_worker_data> data_tile(tile_cnt);
for (int i = 0; i < tile_cnt; ++i) {
struct compress_worker_data *data = &data_tile[i];
data->state = s->state[i];
data->frame = separate_tiles[i];

View File

@@ -68,7 +68,7 @@
#include "types.h"
#define VIDEO_COMPRESS_ABI_VERSION 10
#define VIDEO_COMPRESS_ABI_VERSION 11
#ifdef __cplusplus
extern "C" {
@@ -125,7 +125,8 @@ typedef std::shared_ptr<video_frame> (*compress_frame_t)(struct module *state,
* @brief Compresses tile of a video frame
*
* @param[in] state driver internal state
* @param[in] in_frame uncompressed frame containing exactly one tile
* @param[in] in_frame uncompressed frame containing exactly one tile;
* empty shared_ptr to flush remaining tiles
* @return compressed frame with one tile, may be NULL if compression failed
*/
typedef std::shared_ptr<video_frame> (*compress_tile_t)(struct module *state, std::shared_ptr<video_frame> in_frame);

View File

@@ -189,6 +189,10 @@ static bool configure_with(struct state_video_compress_cuda_dxt *s, struct video
shared_ptr<video_frame> cuda_dxt_compress_tile(struct module *mod, shared_ptr<video_frame> tx)
{
if (!tx) {
return {};
}
struct state_video_compress_cuda_dxt *s =
(struct state_video_compress_cuda_dxt *) mod->priv_data;

View File

@@ -1210,6 +1210,10 @@ restore_metadata(state_video_compress_libav *s, struct video_frame *out,
static shared_ptr<video_frame> libavcodec_compress_tile(struct module *mod, shared_ptr<video_frame> tx)
{
if (!tx) {
return {};
}
struct state_video_compress_libav *s = (struct state_video_compress_libav *) mod->priv_data;
shared_ptr<video_frame> out{};
list<shared_ptr<void>> cleanup_callbacks; // at function exit handlers