mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-05-11 13:02:52 +00:00
Compare commits
6 commits
44cf596c3b
...
bcc3cc465b
Author | SHA1 | Date | |
---|---|---|---|
bcc3cc465b | |||
d7eeb62f38 | |||
753aeccde7 | |||
24c669d374 | |||
b19d7db583 | |||
47f92a830c |
|
@ -229,6 +229,8 @@ struct _GstVaH264Enc
|
|||
guint32 ref_num_list1;
|
||||
|
||||
guint num_reorder_frames;
|
||||
|
||||
GstVideoCodecFrame *last_keyframe;
|
||||
} gop;
|
||||
|
||||
struct
|
||||
|
@ -1546,6 +1548,7 @@ gst_va_h264_enc_reset_state (GstVaBaseEnc * base)
|
|||
self->gop.ref_num_list0 = 0;
|
||||
self->gop.ref_num_list1 = 0;
|
||||
self->gop.num_reorder_frames = 0;
|
||||
self->gop.last_keyframe = NULL;
|
||||
|
||||
self->rc.max_bitrate = 0;
|
||||
self->rc.target_bitrate = 0;
|
||||
|
@ -1715,58 +1718,101 @@ _push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
|
|||
{
|
||||
GstVaH264Enc *self = GST_VA_H264_ENC (base);
|
||||
GstVaH264EncFrame *frame;
|
||||
gboolean add_cached_key_frame = FALSE;
|
||||
|
||||
g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
|
||||
FALSE);
|
||||
|
||||
if (gst_frame) {
|
||||
/* Begin a new GOP, should have a empty reorder_list. */
|
||||
if (self->gop.cur_frame_index == self->gop.idr_period) {
|
||||
g_assert (g_queue_is_empty (&base->reorder_list));
|
||||
self->gop.cur_frame_index = 0;
|
||||
self->gop.cur_frame_num = 0;
|
||||
}
|
||||
|
||||
frame = _enc_frame (gst_frame);
|
||||
frame->poc =
|
||||
((self->gop.cur_frame_index * 2) % self->gop.max_pic_order_cnt);
|
||||
|
||||
/* TODO: move most this logic onto vabaseenc class */
|
||||
if (self->gop.cur_frame_index == 0) {
|
||||
g_assert (frame->poc == 0);
|
||||
GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
|
||||
" a new GOP", gst_frame->system_frame_number);
|
||||
/* Force to insert the key frame inside a GOP, just end the current
|
||||
GOP and start a new one. */
|
||||
if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame) &&
|
||||
!(self->gop.cur_frame_index == 0 ||
|
||||
self->gop.cur_frame_index == self->gop.idr_period)) {
|
||||
GST_DEBUG_OBJECT (base, "system_frame_number: %d is a force key "
|
||||
"frame(IDR), begin a new GOP.", gst_frame->system_frame_number);
|
||||
|
||||
g_queue_clear_full (&base->ref_list,
|
||||
(GDestroyNotify) gst_video_codec_frame_unref);
|
||||
frame->poc = 0;
|
||||
frame->type = self->gop.frame_types[0].slice_type;
|
||||
frame->is_ref = self->gop.frame_types[0].is_ref;
|
||||
frame->pyramid_level = self->gop.frame_types[0].pyramid_level;
|
||||
frame->left_ref_poc_diff = self->gop.frame_types[0].left_ref_poc_diff;
|
||||
frame->right_ref_poc_diff = self->gop.frame_types[0].right_ref_poc_diff;
|
||||
|
||||
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (gst_frame);
|
||||
|
||||
/* The previous key frame should be already be poped out. */
|
||||
g_assert (self->gop.last_keyframe == NULL);
|
||||
|
||||
/* An empty reorder list, start the new GOP immediately. */
|
||||
if (g_queue_is_empty (&base->reorder_list)) {
|
||||
self->gop.cur_frame_index = 1;
|
||||
self->gop.cur_frame_num = 0;
|
||||
g_queue_clear_full (&base->ref_list,
|
||||
(GDestroyNotify) gst_video_codec_frame_unref);
|
||||
last = FALSE;
|
||||
} else {
|
||||
/* Cache the key frame and end the current GOP.
|
||||
Next time calling this push() without frame, start the new GOP. */
|
||||
self->gop.last_keyframe = gst_frame;
|
||||
last = TRUE;
|
||||
}
|
||||
|
||||
add_cached_key_frame = TRUE;
|
||||
} else {
|
||||
/* Begin a new GOP, should have a empty reorder_list. */
|
||||
if (self->gop.cur_frame_index == self->gop.idr_period) {
|
||||
g_assert (g_queue_is_empty (&base->reorder_list));
|
||||
self->gop.cur_frame_index = 0;
|
||||
self->gop.cur_frame_num = 0;
|
||||
}
|
||||
|
||||
frame->poc =
|
||||
((self->gop.cur_frame_index * 2) % self->gop.max_pic_order_cnt);
|
||||
|
||||
/* TODO: move most this logic onto vabaseenc class */
|
||||
if (self->gop.cur_frame_index == 0) {
|
||||
g_assert (frame->poc == 0);
|
||||
GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
|
||||
" a new GOP", gst_frame->system_frame_number);
|
||||
|
||||
g_queue_clear_full (&base->ref_list,
|
||||
(GDestroyNotify) gst_video_codec_frame_unref);
|
||||
|
||||
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (gst_frame);
|
||||
}
|
||||
|
||||
frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
|
||||
frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
|
||||
frame->pyramid_level =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
|
||||
frame->left_ref_poc_diff =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
|
||||
frame->right_ref_poc_diff =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
|
||||
|
||||
GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
|
||||
"frame type %s", gst_frame->system_frame_number, frame->poc,
|
||||
_slice_type_name (frame->type));
|
||||
|
||||
self->gop.cur_frame_index++;
|
||||
|
||||
g_queue_push_tail (&base->reorder_list,
|
||||
gst_video_codec_frame_ref (gst_frame));
|
||||
}
|
||||
|
||||
frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
|
||||
frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
|
||||
frame->pyramid_level =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
|
||||
frame->left_ref_poc_diff =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
|
||||
frame->right_ref_poc_diff =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
|
||||
|
||||
if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame)) {
|
||||
GST_DEBUG_OBJECT (self, "system_frame_number: %d, a force key frame,"
|
||||
" promote its type from %s to %s", gst_frame->system_frame_number,
|
||||
_slice_type_name (frame->type), _slice_type_name (GST_H264_I_SLICE));
|
||||
frame->type = GST_H264_I_SLICE;
|
||||
frame->is_ref = TRUE;
|
||||
} else if (self->gop.last_keyframe) {
|
||||
g_assert (self->gop.last_keyframe ==
|
||||
g_queue_peek_tail (&base->reorder_list));
|
||||
if (g_queue_get_length (&base->reorder_list) == 1) {
|
||||
/* The last cached key frame begins a new GOP */
|
||||
self->gop.cur_frame_index = 1;
|
||||
self->gop.cur_frame_num = 0;
|
||||
self->gop.last_keyframe = NULL;
|
||||
g_queue_clear_full (&base->ref_list,
|
||||
(GDestroyNotify) gst_video_codec_frame_unref);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
|
||||
"frame type %s", gst_frame->system_frame_number, frame->poc,
|
||||
_slice_type_name (frame->type));
|
||||
|
||||
self->gop.cur_frame_index++;
|
||||
g_queue_push_tail (&base->reorder_list,
|
||||
gst_video_codec_frame_ref (gst_frame));
|
||||
}
|
||||
|
||||
/* ensure the last one a non-B and end the GOP. */
|
||||
|
@ -1786,6 +1832,12 @@ _push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
|
|||
}
|
||||
}
|
||||
|
||||
/* Insert the cached next key frame after ending the current GOP. */
|
||||
if (add_cached_key_frame) {
|
||||
g_queue_push_tail (&base->reorder_list,
|
||||
gst_video_codec_frame_ref (gst_frame));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1807,7 +1859,7 @@ _count_backward_ref_num (gpointer data, gpointer user_data)
|
|||
}
|
||||
|
||||
static GstVideoCodecFrame *
|
||||
_pop_pyramid_b_frame (GstVaH264Enc * self)
|
||||
_pop_pyramid_b_frame (GstVaH264Enc * self, guint gop_len)
|
||||
{
|
||||
GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
|
||||
guint i;
|
||||
|
@ -1822,7 +1874,7 @@ _pop_pyramid_b_frame (GstVaH264Enc * self)
|
|||
b_vaframe = NULL;
|
||||
|
||||
/* Find the lowest level with smallest poc. */
|
||||
for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
|
||||
for (i = 0; i < gop_len; i++) {
|
||||
GstVaH264EncFrame *vaf;
|
||||
GstVideoCodecFrame *f;
|
||||
|
||||
|
@ -1854,7 +1906,7 @@ again:
|
|||
/* Check whether its refs are already poped. */
|
||||
g_assert (b_vaframe->left_ref_poc_diff != 0);
|
||||
g_assert (b_vaframe->right_ref_poc_diff != 0);
|
||||
for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
|
||||
for (i = 0; i < gop_len; i++) {
|
||||
GstVaH264EncFrame *vaf;
|
||||
GstVideoCodecFrame *f;
|
||||
|
||||
|
@ -1896,6 +1948,7 @@ _pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
|
|||
GstVaH264Enc *self = GST_VA_H264_ENC (base);
|
||||
GstVaH264EncFrame *vaframe;
|
||||
GstVideoCodecFrame *frame;
|
||||
guint gop_len;
|
||||
struct RefFramesCount count;
|
||||
|
||||
g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
|
||||
|
@ -1906,16 +1959,21 @@ _pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
|
|||
if (g_queue_is_empty (&base->reorder_list))
|
||||
return TRUE;
|
||||
|
||||
gop_len = g_queue_get_length (&base->reorder_list);
|
||||
|
||||
if (self->gop.last_keyframe && gop_len > 1)
|
||||
gop_len--;
|
||||
|
||||
/* Return the last pushed non-B immediately. */
|
||||
frame = g_queue_peek_tail (&base->reorder_list);
|
||||
frame = g_queue_peek_nth (&base->reorder_list, gop_len - 1);
|
||||
vaframe = _enc_frame (frame);
|
||||
if (vaframe->type != GST_H264_B_SLICE) {
|
||||
frame = g_queue_pop_tail (&base->reorder_list);
|
||||
frame = g_queue_pop_nth (&base->reorder_list, gop_len - 1);
|
||||
goto get_one;
|
||||
}
|
||||
|
||||
if (self->gop.b_pyramid) {
|
||||
frame = _pop_pyramid_b_frame (self);
|
||||
frame = _pop_pyramid_b_frame (self, gop_len);
|
||||
if (frame == NULL)
|
||||
return TRUE;
|
||||
goto get_one;
|
||||
|
@ -3065,6 +3123,7 @@ gst_va_h264_enc_flush (GstVideoEncoder * venc)
|
|||
/* begin from an IDR after flush. */
|
||||
self->gop.cur_frame_index = 0;
|
||||
self->gop.cur_frame_num = 0;
|
||||
self->gop.last_keyframe = NULL;
|
||||
|
||||
return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
|
||||
}
|
||||
|
|
|
@ -307,6 +307,8 @@ struct _GstVaH265Enc
|
|||
|
||||
guint num_reorder_frames;
|
||||
guint max_dpb_size;
|
||||
|
||||
GstVideoCodecFrame *last_keyframe;
|
||||
} gop;
|
||||
|
||||
struct
|
||||
|
@ -2028,55 +2030,96 @@ _h265_push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
|
|||
{
|
||||
GstVaH265Enc *self = GST_VA_H265_ENC (base);
|
||||
GstVaH265EncFrame *frame;
|
||||
gboolean add_cached_key_frame = FALSE;
|
||||
|
||||
g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
|
||||
FALSE);
|
||||
|
||||
if (gst_frame) {
|
||||
/* Begin a new GOP, should have a empty reorder_list. */
|
||||
if (self->gop.cur_frame_index == self->gop.idr_period) {
|
||||
g_assert (g_queue_is_empty (&base->reorder_list));
|
||||
self->gop.cur_frame_index = 0;
|
||||
}
|
||||
|
||||
frame = _enc_frame (gst_frame);
|
||||
frame->poc = self->gop.cur_frame_index;
|
||||
g_assert (self->gop.cur_frame_index <= self->gop.max_pic_order_cnt);
|
||||
|
||||
if (self->gop.cur_frame_index == 0) {
|
||||
g_assert (frame->poc == 0);
|
||||
GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
|
||||
" a new GOP", gst_frame->system_frame_number);
|
||||
/* Force to insert the key frame inside a GOP, just end the current
|
||||
GOP and start a new one. */
|
||||
if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame) &&
|
||||
!(self->gop.cur_frame_index == 0 ||
|
||||
self->gop.cur_frame_index == self->gop.idr_period)) {
|
||||
GST_DEBUG_OBJECT (base, "system_frame_number: %d is a force key "
|
||||
"frame(IDR), begin a new GOP.", gst_frame->system_frame_number);
|
||||
|
||||
frame->poc = 0;
|
||||
frame->type = self->gop.frame_types[0].slice_type;
|
||||
frame->is_ref = self->gop.frame_types[0].is_ref;
|
||||
frame->pyramid_level = self->gop.frame_types[0].pyramid_level;
|
||||
frame->left_ref_poc_diff = self->gop.frame_types[0].left_ref_poc_diff;
|
||||
frame->right_ref_poc_diff = self->gop.frame_types[0].right_ref_poc_diff;
|
||||
|
||||
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (gst_frame);
|
||||
|
||||
/* The previous key frame should be already be poped out. */
|
||||
g_assert (self->gop.last_keyframe == NULL);
|
||||
|
||||
/* An empty reorder list, start the new GOP immediately. */
|
||||
if (g_queue_is_empty (&base->reorder_list)) {
|
||||
self->gop.cur_frame_index = 1;
|
||||
g_queue_clear_full (&base->ref_list,
|
||||
(GDestroyNotify) gst_video_codec_frame_unref);
|
||||
last = FALSE;
|
||||
} else {
|
||||
/* Cache the key frame and end the current GOP.
|
||||
Next time calling this push() without frame, start the new GOP. */
|
||||
self->gop.last_keyframe = gst_frame;
|
||||
last = TRUE;
|
||||
}
|
||||
|
||||
add_cached_key_frame = TRUE;
|
||||
} else {
|
||||
/* Begin a new GOP, should have a empty reorder_list. */
|
||||
if (self->gop.cur_frame_index == self->gop.idr_period) {
|
||||
g_assert (g_queue_is_empty (&base->reorder_list));
|
||||
self->gop.cur_frame_index = 0;
|
||||
}
|
||||
|
||||
frame->poc = self->gop.cur_frame_index;
|
||||
g_assert (self->gop.cur_frame_index <= self->gop.max_pic_order_cnt);
|
||||
|
||||
if (self->gop.cur_frame_index == 0) {
|
||||
g_assert (frame->poc == 0);
|
||||
GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
|
||||
" a new GOP", gst_frame->system_frame_number);
|
||||
|
||||
g_queue_clear_full (&base->ref_list,
|
||||
(GDestroyNotify) gst_video_codec_frame_unref);
|
||||
|
||||
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (gst_frame);
|
||||
}
|
||||
|
||||
frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
|
||||
frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
|
||||
frame->pyramid_level =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
|
||||
frame->left_ref_poc_diff =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
|
||||
frame->right_ref_poc_diff =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
|
||||
|
||||
GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
|
||||
"frame type %s", gst_frame->system_frame_number, frame->poc,
|
||||
_h265_slice_type_name (frame->type));
|
||||
|
||||
self->gop.cur_frame_index++;
|
||||
g_queue_push_tail (&base->reorder_list,
|
||||
gst_video_codec_frame_ref (gst_frame));
|
||||
}
|
||||
} else if (self->gop.last_keyframe) {
|
||||
g_assert (self->gop.last_keyframe ==
|
||||
g_queue_peek_tail (&base->reorder_list));
|
||||
if (g_queue_get_length (&base->reorder_list) == 1) {
|
||||
/* The last cached key frame begins a new GOP */
|
||||
self->gop.cur_frame_index = 1;
|
||||
self->gop.last_keyframe = NULL;
|
||||
g_queue_clear_full (&base->ref_list,
|
||||
(GDestroyNotify) gst_video_codec_frame_unref);
|
||||
}
|
||||
|
||||
frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
|
||||
frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
|
||||
frame->pyramid_level =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
|
||||
frame->left_ref_poc_diff =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
|
||||
frame->right_ref_poc_diff =
|
||||
self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
|
||||
|
||||
if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame)) {
|
||||
GST_DEBUG_OBJECT (self, "system_frame_number: %d, a force key frame,"
|
||||
" promote its type from %s to %s", gst_frame->system_frame_number,
|
||||
_h265_slice_type_name (frame->type),
|
||||
_h265_slice_type_name (GST_H265_I_SLICE));
|
||||
frame->type = GST_H265_I_SLICE;
|
||||
frame->is_ref = TRUE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
|
||||
"frame type %s", gst_frame->system_frame_number, frame->poc,
|
||||
_h265_slice_type_name (frame->type));
|
||||
|
||||
self->gop.cur_frame_index++;
|
||||
g_queue_push_tail (&base->reorder_list,
|
||||
gst_video_codec_frame_ref (gst_frame));
|
||||
}
|
||||
|
||||
/* ensure the last one a non-B and end the GOP. */
|
||||
|
@ -2096,6 +2139,12 @@ _h265_push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
|
|||
}
|
||||
}
|
||||
|
||||
/* Insert the cached next key frame after ending the current GOP. */
|
||||
if (add_cached_key_frame) {
|
||||
g_queue_push_tail (&base->reorder_list,
|
||||
gst_video_codec_frame_ref (gst_frame));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2117,7 +2166,7 @@ _count_backward_ref_num (gpointer data, gpointer user_data)
|
|||
}
|
||||
|
||||
static GstVideoCodecFrame *
|
||||
_h265_pop_pyramid_b_frame (GstVaH265Enc * self)
|
||||
_h265_pop_pyramid_b_frame (GstVaH265Enc * self, guint gop_len)
|
||||
{
|
||||
GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
|
||||
guint i;
|
||||
|
@ -2132,7 +2181,7 @@ _h265_pop_pyramid_b_frame (GstVaH265Enc * self)
|
|||
b_vaframe = NULL;
|
||||
|
||||
/* Find the highest level with smallest poc. */
|
||||
for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
|
||||
for (i = 0; i < gop_len; i++) {
|
||||
GstVaH265EncFrame *vaf;
|
||||
GstVideoCodecFrame *f;
|
||||
|
||||
|
@ -2164,7 +2213,7 @@ again:
|
|||
/* Check whether its refs are already poped. */
|
||||
g_assert (b_vaframe->left_ref_poc_diff != 0);
|
||||
g_assert (b_vaframe->right_ref_poc_diff != 0);
|
||||
for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
|
||||
for (i = 0; i < gop_len; i++) {
|
||||
GstVaH265EncFrame *vaf;
|
||||
GstVideoCodecFrame *f;
|
||||
|
||||
|
@ -2206,6 +2255,7 @@ _h265_pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
|
|||
GstVaH265Enc *self = GST_VA_H265_ENC (base);
|
||||
GstVaH265EncFrame *vaframe;
|
||||
GstVideoCodecFrame *frame;
|
||||
guint gop_len;
|
||||
struct RefFramesCount count;
|
||||
|
||||
g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
|
||||
|
@ -2216,16 +2266,21 @@ _h265_pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
|
|||
if (g_queue_is_empty (&base->reorder_list))
|
||||
return TRUE;
|
||||
|
||||
gop_len = g_queue_get_length (&base->reorder_list);
|
||||
|
||||
if (self->gop.last_keyframe && gop_len > 1)
|
||||
gop_len--;
|
||||
|
||||
/* Return the last pushed non-B immediately. */
|
||||
frame = g_queue_peek_tail (&base->reorder_list);
|
||||
frame = g_queue_peek_nth (&base->reorder_list, gop_len - 1);
|
||||
vaframe = _enc_frame (frame);
|
||||
if (vaframe->type != GST_H265_B_SLICE) {
|
||||
frame = g_queue_pop_tail (&base->reorder_list);
|
||||
frame = g_queue_pop_nth (&base->reorder_list, gop_len - 1);
|
||||
goto get_one;
|
||||
}
|
||||
|
||||
if (self->gop.b_pyramid) {
|
||||
frame = _h265_pop_pyramid_b_frame (self);
|
||||
frame = _h265_pop_pyramid_b_frame (self, gop_len);
|
||||
if (frame == NULL)
|
||||
return TRUE;
|
||||
|
||||
|
@ -2529,6 +2584,7 @@ gst_va_h265_enc_reset_state (GstVaBaseEnc * base)
|
|||
self->gop.backward_ref_num = 0;
|
||||
self->gop.num_reorder_frames = 0;
|
||||
self->gop.max_dpb_size = 0;
|
||||
self->gop.last_keyframe = NULL;
|
||||
|
||||
self->rc.max_bitrate = 0;
|
||||
self->rc.target_bitrate = 0;
|
||||
|
@ -4657,6 +4713,7 @@ gst_va_h265_enc_flush (GstVideoEncoder * venc)
|
|||
|
||||
/* begin from an IDR after flush. */
|
||||
self->gop.cur_frame_index = 0;
|
||||
self->gop.last_keyframe = NULL;
|
||||
|
||||
return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ typedef struct
|
|||
|
||||
gint prev_width;
|
||||
gint prev_height;
|
||||
|
||||
guint force_keyframe_count;
|
||||
} TestCallbackData;
|
||||
|
||||
static gboolean
|
||||
|
@ -130,9 +132,10 @@ loop_rate_control (GstElement * encoder)
|
|||
g_object_set (encoder, "rate-control", enum_class->values[i].value, NULL);
|
||||
}
|
||||
|
||||
static gboolean force_key_frame;
|
||||
|
||||
static GstPadProbeReturn
|
||||
resolution_change_probe (GstPad * pad, GstPadProbeInfo * info,
|
||||
gpointer user_data)
|
||||
pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||
{
|
||||
GstPadProbeReturn ret = GST_PAD_PROBE_OK;
|
||||
TestCallbackData *data = (TestCallbackData *) user_data;
|
||||
|
@ -144,6 +147,17 @@ resolution_change_probe (GstPad * pad, GstPadProbeInfo * info,
|
|||
GstPad *peer = gst_pad_get_peer (pad);
|
||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||
|
||||
if (force_key_frame) {
|
||||
GstEvent *force_key_event;
|
||||
|
||||
force_key_frame = FALSE;
|
||||
|
||||
force_key_event = gst_video_event_new_downstream_force_key_unit
|
||||
(GST_BUFFER_PTS (buffer), GST_CLOCK_TIME_NONE,
|
||||
GST_CLOCK_TIME_NONE, FALSE, data->force_keyframe_count++);
|
||||
gst_pad_push_event (pad, force_key_event);
|
||||
}
|
||||
|
||||
ret = GST_PAD_PROBE_HANDLED;
|
||||
|
||||
if (peer) {
|
||||
|
@ -208,6 +222,7 @@ print_keyboard_help (void)
|
|||
"p", "Decrease QP-P (only in CQP)"}, {
|
||||
"B", "Increase QP-B (only in CQP)"}, {
|
||||
"b", "Decrease QP-B (only in CQP)"}, {
|
||||
"f", "Force to set a key frame"}, {
|
||||
"k", "show keyboard shortcuts"}
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
@ -418,6 +433,10 @@ keyboard_cb (gchar input, gboolean is_ascii, gpointer user_data)
|
|||
g_object_set (data->encoder, "qpb", qpb, NULL);
|
||||
break;
|
||||
}
|
||||
case 'f':{
|
||||
force_key_frame = TRUE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -541,7 +560,7 @@ main (gint argc, gchar ** argv)
|
|||
|
||||
pad = gst_element_get_static_pad (capsfilter, "src");
|
||||
data.probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
|
||||
resolution_change_probe, &data, NULL);
|
||||
pad_buffer_probe, &data, NULL);
|
||||
gst_object_unref (pad);
|
||||
data.prev_width = width;
|
||||
data.prev_height = height;
|
||||
|
|
|
@ -45,35 +45,53 @@ pylib_loc = get_option('libpython-dir')
|
|||
fsmod = import('fs')
|
||||
pylib_prefix = 'lib'
|
||||
pylib_suffix = 'so'
|
||||
pylib_ver = python_dep.version()
|
||||
pylib_locs = []
|
||||
if host_system == 'windows'
|
||||
if cc.get_argument_syntax() == 'msvc'
|
||||
pylib_prefix = ''
|
||||
endif
|
||||
pylib_suffix = 'dll'
|
||||
pylib_ver = pylib_ver.replace('.', '')
|
||||
elif host_system == 'darwin'
|
||||
pylib_suffix = 'dylib'
|
||||
endif
|
||||
pylib_fnames = []
|
||||
# Library name with soversion, non-devel package
|
||||
pylib_fnames += python.get_variable('INSTSONAME', [])
|
||||
if python.has_variable('INSTSONAME')
|
||||
# For example, libpython3.12.so.1.0 (Linux), libpython3.11.dll.a (MSYS2), etc.
|
||||
pylib_fnames += python.get_variable('INSTSONAME')
|
||||
endif
|
||||
# Library name without soversion, devel package, framework, etc.
|
||||
pylib_fnames += python.get_variable('LDLIBRARY', [])
|
||||
if python.has_variable('LDLIBRARY')
|
||||
# For example, libpython3.12.so (Linux), libpython3.11.dll.a (MSYS2), etc.
|
||||
pylib_fnames += python.get_variable('LDLIBRARY')
|
||||
endif
|
||||
# Manually construct name as a fallback
|
||||
pylib_fnames += [
|
||||
pylib_prefix + 'python' + python_dep.version() + python_abi_flags + '.' + pylib_suffix
|
||||
pylib_prefix + 'python' + pylib_ver + python_abi_flags + '.' + pylib_suffix
|
||||
]
|
||||
if pylib_loc != ''
|
||||
pylib_locs = [pylib_loc]
|
||||
else
|
||||
pylib_locs = [
|
||||
python.get_variable('LIBDIR', ''),
|
||||
python.get_variable('LIBPL', ''),
|
||||
]
|
||||
if python.has_variable('LIBDIR')
|
||||
pylib_locs += python.get_variable('LIBDIR')
|
||||
endif
|
||||
if python.has_variable('LIBPL')
|
||||
pylib_locs += python.get_variable('LIBPL')
|
||||
endif
|
||||
# On Windows, python312.dll is in the rootdir where Python is installed,
|
||||
# which is configured as the "prefix" in sysconfig.
|
||||
if host_system == 'windows'
|
||||
pylib_locs += python.get_variable('prefix')
|
||||
endif
|
||||
endif
|
||||
pylib_fname = ''
|
||||
foreach loc: pylib_locs
|
||||
foreach fname: pylib_fnames
|
||||
if fsmod.exists(loc / fname)
|
||||
fpath = loc / fname
|
||||
debug(f'Looking for Python library at: @fpath@')
|
||||
if fsmod.exists(fpath)
|
||||
pylib_fname = fname
|
||||
message(f'PY_LIB_FNAME = @fname@ (@loc@)')
|
||||
break
|
||||
|
@ -81,12 +99,7 @@ foreach loc: pylib_locs
|
|||
endforeach
|
||||
endforeach
|
||||
if pylib_fname == ''
|
||||
error_msg = 'Could not find python library to load'
|
||||
if python_opt.enabled()
|
||||
error(error_msg)
|
||||
else
|
||||
message(error_msg)
|
||||
endif
|
||||
message('Could not find python library to load, will try loading at runtime')
|
||||
endif
|
||||
|
||||
pygi_override_dir = get_option('pygi-overrides-dir')
|
||||
|
|
Loading…
Reference in a new issue