nvencoder: Fix b-frame encoding on Linux

On Windows, Win32 event handle is used to wait for encoded output,
but it's not available on Linux. We should delay bitstream locking
if encoder returns "need-more-input"

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4004>
This commit is contained in:
Seungha Yang 2023-02-20 02:10:07 +09:00 committed by GStreamer Marge Bot
parent 0b52663815
commit b1c14b0357
2 changed files with 36 additions and 2 deletions

View file

@ -367,6 +367,7 @@ GstNvEncObject::InitSession (NV_ENC_INITIALIZE_PARAMS * params,
}
task_size_ = task_size;
lookahead_ = params->encodeConfig->rcParams.lookaheadDepth;
initialized_ = true;
out:
@ -490,8 +491,34 @@ GstNvEncObject::Encode (GstVideoCodecFrame * codec_frame,
active_resource_queue_.insert (task->resource);
}
/* On Windows and if async encoding is enabled, output thread will wait
* for completion event. But on Linux, async encoding is not supported.
* So, we should wait for NV_ENC_SUCCESS in case of sync mode
* (it would introduce latency though).
* Otherwise nvEncLockBitstream() will return error */
if (params.completionEvent) {
/* Windows only path */
task_queue_.push (task);
cond_.notify_all ();
} else {
pending_task_queue_.push (task);
if (status == NV_ENC_SUCCESS) {
bool notify = false;
/* XXX: nvEncLockBitstream() will return NV_ENC_ERR_INVALID_PARAM
* if lookahead is enabled. See also
* https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/494
*/
while (pending_task_queue_.size() > lookahead_) {
notify = true;
task_queue_.push (pending_task_queue_.front ());
pending_task_queue_.pop ();
}
if (notify)
cond_.notify_all ();
}
}
return NV_ENC_SUCCESS;
}
@ -531,6 +558,11 @@ GstNvEncObject::Drain (GstNvEncTask * task)
break;
} while (true);
while (!pending_task_queue_.empty ()) {
task_queue_.push (pending_task_queue_.front ());
pending_task_queue_.pop ();
}
task_queue_.push (task);
cond_.notify_all ();

View file

@ -233,6 +233,7 @@ private:
/* list of GstNvEncResource in task_queue */
std::set <GstNvEncResource *> active_resource_queue_;
std::queue <GstNvEncTask *> task_queue_;
std::queue <GstNvEncTask *> pending_task_queue_;
std::queue <GstNvEncTask *> empty_task_queue_;
gint64 user_token_;
GstCudaContext *context_ = nullptr;
@ -245,6 +246,7 @@ private:
bool initialized_ = false;
bool flushing_ = false;
guint task_size_ = 0;
guint lookahead_ = 0;
NV_ENC_DEVICE_TYPE device_type_ = NV_ENC_DEVICE_TYPE_CUDA;
NV_ENC_BUFFER_FORMAT buffer_format_ = NV_ENC_BUFFER_FORMAT_UNDEFINED;