mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-04 05:22:30 +00:00
va: encoder: extend prepare_output() virtual function
The output of VP9 and AV1 encoder is a little different from the H264 and H265 encoder, it may contain repeat frames and so the output frame number may be more than the input. We need to call finish_subframe() when some frame will be repeated later. So we need to extend the current prepare_output() virtual function. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3015>
This commit is contained in:
parent
a278137f7e
commit
39144f612e
4 changed files with 60 additions and 28 deletions
|
@ -269,7 +269,7 @@ gst_va_base_enc_import_input_buffer (GstVaBaseEnc * base,
|
|||
return gst_va_buffer_importer_import (&importer, inbuf, buf);
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
GstBuffer *
|
||||
gst_va_base_enc_create_output_buffer (GstVaBaseEnc * base,
|
||||
GstVaEncodePicture * picture)
|
||||
{
|
||||
|
@ -404,37 +404,38 @@ config_failed:
|
|||
static GstFlowReturn
|
||||
_push_buffer_to_downstream (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
|
||||
{
|
||||
GstVaEncodePicture *enc_picture;
|
||||
GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base);
|
||||
GstBuffer *buf;
|
||||
GstFlowReturn ret;
|
||||
gboolean complete = TRUE;
|
||||
|
||||
if (base_class->prepare_output)
|
||||
base_class->prepare_output (base, frame);
|
||||
|
||||
enc_picture =
|
||||
*((GstVaEncodePicture **) gst_video_codec_frame_get_user_data (frame));
|
||||
|
||||
buf = gst_va_base_enc_create_output_buffer (base, enc_picture);
|
||||
if (!buf) {
|
||||
GST_ERROR_OBJECT (base, "Failed to create output buffer");
|
||||
if (!base_class->prepare_output (base, frame, &complete)) {
|
||||
GST_ERROR_OBJECT (base, "Failed to prepare output");
|
||||
goto error;
|
||||
}
|
||||
|
||||
gst_buffer_replace (&frame->output_buffer, buf);
|
||||
gst_clear_buffer (&buf);
|
||||
if (frame->output_buffer)
|
||||
GST_LOG_OBJECT (base, "Push to downstream: frame system_frame_number: %d,"
|
||||
" pts: %" GST_TIME_FORMAT ", dts: %" GST_TIME_FORMAT
|
||||
" duration: %" GST_TIME_FORMAT ", buffer size: %" G_GSIZE_FORMAT,
|
||||
frame->system_frame_number, GST_TIME_ARGS (frame->pts),
|
||||
GST_TIME_ARGS (frame->dts), GST_TIME_ARGS (frame->duration),
|
||||
gst_buffer_get_size (frame->output_buffer));
|
||||
|
||||
GST_LOG_OBJECT (base, "Push to downstream: frame system_frame_number: %d,"
|
||||
" pts: %" GST_TIME_FORMAT ", dts: %" GST_TIME_FORMAT
|
||||
" duration: %" GST_TIME_FORMAT ", buffer size: %" G_GSIZE_FORMAT,
|
||||
frame->system_frame_number, GST_TIME_ARGS (frame->pts),
|
||||
GST_TIME_ARGS (frame->dts), GST_TIME_ARGS (frame->duration),
|
||||
gst_buffer_get_size (frame->output_buffer));
|
||||
if (complete) {
|
||||
ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (base), frame);
|
||||
} else {
|
||||
if (frame->output_buffer) {
|
||||
ret = gst_video_encoder_finish_subframe (GST_VIDEO_ENCODER (base), frame);
|
||||
} else {
|
||||
/* Allow to output later and no data here. */
|
||||
ret = GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (base), frame);
|
||||
return ret;
|
||||
|
||||
error:
|
||||
gst_clear_buffer (&frame->output_buffer);
|
||||
gst_clear_buffer (&buf);
|
||||
gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (base), frame);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
|
|
|
@ -91,8 +91,9 @@ struct _GstVaBaseEncClass
|
|||
GstFlowReturn (*encode_frame) (GstVaBaseEnc * encoder,
|
||||
GstVideoCodecFrame * frame,
|
||||
gboolean is_last);
|
||||
void (*prepare_output) (GstVaBaseEnc * encoder,
|
||||
GstVideoCodecFrame * frame);
|
||||
gboolean (*prepare_output) (GstVaBaseEnc * encoder,
|
||||
GstVideoCodecFrame * frame,
|
||||
gboolean * complete);
|
||||
|
||||
GstVaCodecs codec;
|
||||
VAEntrypoint entrypoint;
|
||||
|
@ -136,6 +137,8 @@ gboolean gst_va_base_enc_add_trellis_parameter (GstVaBaseEnc * base
|
|||
void gst_va_base_enc_add_codec_tag (GstVaBaseEnc * base,
|
||||
const gchar * codec_name);
|
||||
void gst_va_base_enc_reset_state (GstVaBaseEnc * base);
|
||||
GstBuffer * gst_va_base_enc_create_output_buffer (GstVaBaseEnc * base,
|
||||
GstVaEncodePicture * picture);
|
||||
|
||||
void gst_va_base_enc_update_property_uint (GstVaBaseEnc * base,
|
||||
guint32 * old_val,
|
||||
|
|
|
@ -3038,11 +3038,13 @@ gst_va_h264_enc_flush (GstVideoEncoder * venc)
|
|||
return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_va_h264_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
|
||||
static gboolean
|
||||
gst_va_h264_enc_prepare_output (GstVaBaseEnc * base,
|
||||
GstVideoCodecFrame * frame, gboolean * complete)
|
||||
{
|
||||
GstVaH264Enc *self = GST_VA_H264_ENC (base);
|
||||
GstVaH264EncFrame *frame_enc;
|
||||
GstBuffer *buf;
|
||||
|
||||
frame_enc = _enc_frame (frame);
|
||||
|
||||
|
@ -3054,6 +3056,18 @@ gst_va_h264_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
|
|||
(gint64) self->gop.num_reorder_frames);
|
||||
base->output_frame_count++;
|
||||
frame->duration = base->frame_duration;
|
||||
|
||||
buf = gst_va_base_enc_create_output_buffer (base, frame_enc->picture);
|
||||
if (!buf) {
|
||||
GST_ERROR_OBJECT (base, "Failed to create output buffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_buffer_replace (&frame->output_buffer, buf);
|
||||
gst_clear_buffer (&buf);
|
||||
|
||||
*complete = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
|
|
|
@ -4611,11 +4611,13 @@ gst_va_h265_enc_new_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_va_h265_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
|
||||
static gboolean
|
||||
gst_va_h265_enc_prepare_output (GstVaBaseEnc * base,
|
||||
GstVideoCodecFrame * frame, gboolean * complete)
|
||||
{
|
||||
GstVaH265Enc *self = GST_VA_H265_ENC (base);
|
||||
GstVaH265EncFrame *frame_enc;
|
||||
GstBuffer *buf;
|
||||
|
||||
frame_enc = _enc_frame (frame);
|
||||
|
||||
|
@ -4627,6 +4629,18 @@ gst_va_h265_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
|
|||
(gint64) self->gop.num_reorder_frames);
|
||||
base->output_frame_count++;
|
||||
frame->duration = base->frame_duration;
|
||||
|
||||
buf = gst_va_base_enc_create_output_buffer (base, frame_enc->picture);
|
||||
if (!buf) {
|
||||
GST_ERROR_OBJECT (base, "Failed to create output buffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_buffer_replace (&frame->output_buffer, buf);
|
||||
gst_clear_buffer (&buf);
|
||||
|
||||
*complete = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
|
Loading…
Reference in a new issue