base->profile = VAProfileNone;
base->rt_format = 0;
base->codedbuf_size = 0;
+ g_atomic_int_set (&base->reconf, FALSE);
}
static void
}
static GstFlowReturn
+gst_va_base_enc_drain (GstVideoEncoder * venc)
+{
+ GstVaBaseEnc *base = GST_VA_BASE_ENC (venc);
+ GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base);
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstVideoCodecFrame *frame_enc = NULL;
+ gboolean is_last = FALSE;
+
+ GST_DEBUG_OBJECT (base, "Encoder is draining");
+
+ /* Kickout all cached frames */
+ if (!base_class->reorder_frame (base, NULL, TRUE, &frame_enc)) {
+ ret = GST_FLOW_ERROR;
+ goto error_and_purge_all;
+ }
+
+ while (frame_enc) {
+ is_last = FALSE;
+
+ if (g_queue_is_empty (&base->reorder_list))
+ is_last = TRUE;
+
+ ret = base_class->encode_frame (base, frame_enc, is_last);
+ if (ret != GST_FLOW_OK)
+ goto error_and_purge_all;
+
+ frame_enc = NULL;
+
+ ret = _push_out_one_buffer (base);
+ if (ret != GST_FLOW_OK)
+ goto error_and_purge_all;
+
+ if (!base_class->reorder_frame (base, NULL, TRUE, &frame_enc)) {
+ ret = GST_FLOW_ERROR;
+ goto error_and_purge_all;
+ }
+ }
+
+ g_assert (g_queue_is_empty (&base->reorder_list));
+
+ /* Output all frames. */
+ while (!g_queue_is_empty (&base->output_list)) {
+ ret = _push_out_one_buffer (base);
+ if (ret != GST_FLOW_OK)
+ goto error_and_purge_all;
+ }
+
+ /* Also clear the reference list. */
+ g_queue_clear_full (&base->ref_list,
+ (GDestroyNotify) gst_video_codec_frame_unref);
+
+ return GST_FLOW_OK;
+
+error_and_purge_all:
+ if (frame_enc) {
+ gst_clear_buffer (&frame_enc->output_buffer);
+ gst_video_encoder_finish_frame (venc, frame_enc);
+ }
+
+ if (!g_queue_is_empty (&base->output_list)) {
+ GST_WARNING_OBJECT (base, "Still %d frame in the output list"
+ " after drain", g_queue_get_length (&base->output_list));
+ while (!g_queue_is_empty (&base->output_list)) {
+ frame_enc = g_queue_pop_head (&base->output_list);
+ gst_video_codec_frame_unref (frame_enc);
+ gst_clear_buffer (&frame_enc->output_buffer);
+ gst_video_encoder_finish_frame (venc, frame_enc);
+ }
+ }
+
+ if (!g_queue_is_empty (&base->reorder_list)) {
+ GST_WARNING_OBJECT (base, "Still %d frame in the reorder list"
+ " after drain", g_queue_get_length (&base->reorder_list));
+ while (!g_queue_is_empty (&base->reorder_list)) {
+ frame_enc = g_queue_pop_head (&base->reorder_list);
+ gst_video_codec_frame_unref (frame_enc);
+ gst_clear_buffer (&frame_enc->output_buffer);
+ gst_video_encoder_finish_frame (venc, frame_enc);
+ }
+ }
+
+ /* Also clear the reference list. */
+ g_queue_clear_full (&base->ref_list,
+ (GDestroyNotify) gst_video_codec_frame_unref);
+
+ return ret;
+}
+
+static gboolean
+gst_va_base_enc_reset (GstVaBaseEnc * base)
+{
+ GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base);
+
+ GST_DEBUG_OBJECT (base, "Reconfiguration");
+ if (gst_va_base_enc_drain (GST_VIDEO_ENCODER (base)) != GST_FLOW_OK)
+ return FALSE;
+
+ if (!base_class->reconfig (base)) {
+ GST_ERROR_OBJECT (base, "Error at reconfiguration error");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GstFlowReturn
gst_va_base_enc_handle_frame (GstVideoEncoder * venc,
GstVideoCodecFrame * frame)
{
GST_TIME_ARGS (GST_BUFFER_DTS (frame->input_buffer)),
GST_TIME_ARGS (GST_BUFFER_PTS (frame->input_buffer)));
+ if (g_atomic_int_compare_and_exchange (&base->reconf, TRUE, FALSE)) {
+ if (!gst_va_base_enc_reset (base))
+ return GST_FLOW_ERROR;
+ }
+
ret = gst_va_base_enc_import_input_buffer (base,
frame->input_buffer, &in_buf);
if (ret != GST_FLOW_OK)
}
static GstFlowReturn
-gst_va_base_enc_drain (GstVideoEncoder * venc)
-{
- GstVaBaseEnc *base = GST_VA_BASE_ENC (venc);
- GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base);
- GstFlowReturn ret = GST_FLOW_OK;
- GstVideoCodecFrame *frame_enc = NULL;
- gboolean is_last = FALSE;
-
- GST_DEBUG_OBJECT (base, "Encoder is draining");
-
- /* Kickout all cached frames */
- if (!base_class->reorder_frame (base, NULL, TRUE, &frame_enc)) {
- ret = GST_FLOW_ERROR;
- goto error_and_purge_all;
- }
-
- while (frame_enc) {
- is_last = FALSE;
-
- if (g_queue_is_empty (&base->reorder_list))
- is_last = TRUE;
-
- ret = base_class->encode_frame (base, frame_enc, is_last);
- if (ret != GST_FLOW_OK)
- goto error_and_purge_all;
-
- frame_enc = NULL;
-
- ret = _push_out_one_buffer (base);
- if (ret != GST_FLOW_OK)
- goto error_and_purge_all;
-
- if (!base_class->reorder_frame (base, NULL, TRUE, &frame_enc)) {
- ret = GST_FLOW_ERROR;
- goto error_and_purge_all;
- }
- }
-
- g_assert (g_queue_is_empty (&base->reorder_list));
-
- /* Output all frames. */
- while (!g_queue_is_empty (&base->output_list)) {
- ret = _push_out_one_buffer (base);
- if (ret != GST_FLOW_OK)
- goto error_and_purge_all;
- }
-
- /* Also clear the reference list. */
- g_queue_clear_full (&base->ref_list,
- (GDestroyNotify) gst_video_codec_frame_unref);
-
- return GST_FLOW_OK;
-
-error_and_purge_all:
- if (frame_enc) {
- gst_clear_buffer (&frame_enc->output_buffer);
- gst_video_encoder_finish_frame (venc, frame_enc);
- }
-
- if (!g_queue_is_empty (&base->output_list)) {
- GST_WARNING_OBJECT (base, "Still %d frame in the output list"
- " after drain", g_queue_get_length (&base->output_list));
- while (!g_queue_is_empty (&base->output_list)) {
- frame_enc = g_queue_pop_head (&base->output_list);
- gst_video_codec_frame_unref (frame_enc);
- gst_clear_buffer (&frame_enc->output_buffer);
- gst_video_encoder_finish_frame (venc, frame_enc);
- }
- }
-
- if (!g_queue_is_empty (&base->reorder_list)) {
- GST_WARNING_OBJECT (base, "Still %d frame in the reorder list"
- " after drain", g_queue_get_length (&base->reorder_list));
- while (!g_queue_is_empty (&base->reorder_list)) {
- frame_enc = g_queue_pop_head (&base->reorder_list);
- gst_video_codec_frame_unref (frame_enc);
- gst_clear_buffer (&frame_enc->output_buffer);
- gst_video_encoder_finish_frame (venc, frame_enc);
- }
- }
-
- /* Also clear the reference list. */
- g_queue_clear_full (&base->ref_list,
- (GDestroyNotify) gst_video_codec_frame_unref);
-
- return ret;
-}
-
-static GstFlowReturn
gst_va_base_enc_finish (GstVideoEncoder * venc)
{
return gst_va_base_enc_drain (venc);
gst_va_base_enc_set_format (GstVideoEncoder * venc, GstVideoCodecState * state)
{
GstVaBaseEnc *base = GST_VA_BASE_ENC (venc);
- GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base);
g_return_val_if_fail (state->caps != NULL, FALSE);
gst_video_codec_state_unref (base->input_state);
base->input_state = gst_video_codec_state_ref (state);
- if (gst_va_base_enc_drain (venc) != GST_FLOW_OK)
- return FALSE;
-
- if (!gst_va_encoder_close (base->encoder)) {
- GST_ERROR_OBJECT (base, "Failed to close the VA encoder");
- return FALSE;
- }
-
- if (!base_class->reconfig (base)) {
- GST_ERROR_OBJECT (base, "Reconfig the encoder error");
+ if (!gst_va_base_enc_reset (base))
return FALSE;
- }
/* Sub class should open the encoder if reconfig succeeds. */
return gst_va_encoder_is_open (base->encoder);