mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-09 10:59:39 +00:00
decoder: introduce lists of units to decode before/after frame.
Theory of operations: all units marked as "slice" are moved to the "units" list. Since this list only contains slice data units, the prev_slice pointer was removed. Besides, we now maintain two extra lists of units to be decoded before or after slice data units. In particular, all units in the "pre_units" list will be decoded before GstVaapiDecoder::start_frame() is called and units in the "post_units" list will be decoded after GstVaapiDecoder::end_frame() is called.
This commit is contained in:
parent
c727e5b6d6
commit
63a7e42484
4 changed files with 75 additions and 44 deletions
|
@ -150,6 +150,7 @@ do_parse(GstVaapiDecoder *decoder,
|
|||
GstVaapiDecoderFrame *frame;
|
||||
GstVaapiDecoderUnit *unit;
|
||||
GstVaapiDecoderStatus status;
|
||||
GSList **unit_list_ptr;
|
||||
|
||||
*got_unit_size_ptr = 0;
|
||||
*got_frame_ptr = FALSE;
|
||||
|
@ -178,23 +179,48 @@ do_parse(GstVaapiDecoder *decoder,
|
|||
return status;
|
||||
}
|
||||
|
||||
if (GST_VAAPI_DECODER_UNIT_IS_FRAME_START(unit) && frame->prev_slice) {
|
||||
if (GST_VAAPI_DECODER_UNIT_IS_FRAME_START(unit) && frame->units) {
|
||||
parser_state_set_pending_unit(ps, adapter, unit);
|
||||
goto got_frame;
|
||||
}
|
||||
|
||||
got_unit:
|
||||
unit->offset = frame->output_offset;
|
||||
frame->units = g_slist_prepend(frame->units, unit);
|
||||
frame->output_offset += unit->size;
|
||||
|
||||
if (GST_VAAPI_DECODER_UNIT_IS_SLICE(unit))
|
||||
frame->prev_slice = unit;
|
||||
unit_list_ptr = &frame->units;
|
||||
else if (GST_VAAPI_DECODER_UNIT_IS_FRAME_END(unit))
|
||||
unit_list_ptr = &frame->post_units;
|
||||
else
|
||||
unit_list_ptr = &frame->pre_units;
|
||||
*unit_list_ptr = g_slist_prepend(*unit_list_ptr, unit);
|
||||
|
||||
*got_unit_size_ptr = unit->size;
|
||||
if (GST_VAAPI_DECODER_UNIT_IS_FRAME_END(unit)) {
|
||||
got_frame:
|
||||
frame->units = g_slist_reverse(frame->units);
|
||||
*got_frame_ptr = TRUE;
|
||||
frame->units = g_slist_reverse(frame->units);
|
||||
frame->pre_units = g_slist_reverse(frame->pre_units);
|
||||
frame->post_units = g_slist_reverse(frame->post_units);
|
||||
*got_frame_ptr = TRUE;
|
||||
}
|
||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static GstVaapiDecoderStatus
|
||||
do_decode_list(GstVaapiDecoder *decoder, GSList *units)
|
||||
{
|
||||
GstVaapiDecoderClass * const klass = GST_VAAPI_DECODER_GET_CLASS(decoder);
|
||||
GstVaapiDecoderStatus status;
|
||||
GSList *l;
|
||||
|
||||
for (l = units; l != NULL; l = l->next) {
|
||||
GstVaapiDecoderUnit * const unit = l->data;
|
||||
if (GST_VAAPI_DECODER_UNIT_IS_SKIPPED(unit))
|
||||
continue;
|
||||
status = klass->decode(decoder, unit);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -206,33 +232,35 @@ do_decode(GstVaapiDecoder *decoder, GstVideoCodecFrame *base_frame)
|
|||
GstVaapiParserState * const ps = &decoder->priv->parser_state;
|
||||
GstVaapiDecoderFrame * const frame = base_frame->user_data;
|
||||
GstVaapiDecoderStatus status;
|
||||
GSList *l;
|
||||
|
||||
ps->current_frame = base_frame;
|
||||
|
||||
if (klass->start_frame) {
|
||||
for (l = frame->units; l != NULL; l = l->next) {
|
||||
GstVaapiDecoderUnit * const unit = l->data;
|
||||
if (GST_VAAPI_DECODER_UNIT_IS_SLICE(unit)) {
|
||||
status = klass->start_frame(decoder, unit);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (l = frame->units; l != NULL; l = l->next) {
|
||||
GstVaapiDecoderUnit * const unit = l->data;
|
||||
if (GST_VAAPI_DECODER_UNIT_IS_SKIPPED(unit))
|
||||
continue;
|
||||
status = klass->decode(decoder, unit);
|
||||
if (frame->pre_units) {
|
||||
status = do_decode_list(decoder, frame->pre_units);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (klass->end_frame) {
|
||||
status = klass->end_frame(decoder);
|
||||
if (frame->units) {
|
||||
if (klass->start_frame) {
|
||||
status = klass->start_frame(decoder, frame->units->data);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = do_decode_list(decoder, frame->units);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (klass->end_frame) {
|
||||
status = klass->end_frame(decoder);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame->post_units) {
|
||||
status = do_decode_list(decoder, frame->post_units);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,17 @@ gst_vaapi_decoder_frame_class(void)
|
|||
return &GstVaapiDecoderFrameClass;
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_units(GSList **units_ptr)
|
||||
{
|
||||
GSList * const units = *units_ptr;
|
||||
|
||||
if (units) {
|
||||
g_slist_free_full(units, (GDestroyNotify)gst_vaapi_mini_object_unref);
|
||||
*units_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vaapi_decoder_frame_new:
|
||||
*
|
||||
|
@ -47,17 +58,8 @@ gst_vaapi_decoder_frame_class(void)
|
|||
GstVaapiDecoderFrame *
|
||||
gst_vaapi_decoder_frame_new(void)
|
||||
{
|
||||
GstVaapiDecoderFrame *frame;
|
||||
|
||||
frame = (GstVaapiDecoderFrame *)
|
||||
gst_vaapi_mini_object_new(gst_vaapi_decoder_frame_class());
|
||||
if (!frame)
|
||||
return NULL;
|
||||
|
||||
frame->output_offset = 0;
|
||||
frame->units = NULL;
|
||||
frame->prev_slice = NULL;
|
||||
return frame;
|
||||
return (GstVaapiDecoderFrame *)
|
||||
gst_vaapi_mini_object_new0(gst_vaapi_decoder_frame_class());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,9 +75,7 @@ gst_vaapi_decoder_frame_new(void)
|
|||
void
|
||||
gst_vaapi_decoder_frame_free(GstVaapiDecoderFrame *frame)
|
||||
{
|
||||
if (frame->units) {
|
||||
g_slist_free_full(frame->units,
|
||||
(GDestroyNotify)gst_vaapi_mini_object_unref);
|
||||
frame->units = NULL;
|
||||
}
|
||||
free_units(&frame->units);
|
||||
free_units(&frame->pre_units);
|
||||
free_units(&frame->post_units);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,9 @@ typedef enum {
|
|||
* @output_offset: current offset to the reconstructed #GstBuffer for
|
||||
* this #GstVideoCodecFrame. This is used to initialize the decoder
|
||||
* unit offset
|
||||
* @units: list of #GstVaapiDecoderUnit objects
|
||||
* @units: list of #GstVaapiDecoderUnit objects (slice data)
|
||||
* @pre_units: list of units to decode before GstVaapiDecoder:start_frame()
|
||||
* @post_units: list of units to decode after GstVaapiDecoder:end_frame()
|
||||
* @prev_slice: previous #GstVaapiDecoderUnit that was a slice, or NULL
|
||||
* if no slice data unit was received yet
|
||||
*
|
||||
|
@ -68,7 +70,8 @@ struct _GstVaapiDecoderFrame {
|
|||
|
||||
guint output_offset;
|
||||
GSList *units;
|
||||
GstVaapiDecoderUnit *prev_slice;
|
||||
GSList *pre_units;
|
||||
GSList *post_units;
|
||||
};
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
|
|
|
@ -40,7 +40,7 @@ typedef struct _GstVaapiDecoderUnit GstVaapiDecoderUnit;
|
|||
* @GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START: marks the start of a frame.
|
||||
* @GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END: marks the end of a frame.
|
||||
* @GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END: marks the end of a stream.
|
||||
* @GST_VAAPI_DECODER_UNIT_FLAG_SLICE: marks the unit contains slice data.
|
||||
* @GST_VAAPI_DECODER_UNIT_FLAG_SLICE: the unit contains slice data.
|
||||
* @GST_VAAPI_DECODER_UNIT_FLAG_SKIP: marks the unit as unused/skipped.
|
||||
*
|
||||
* Flags for #GstVaapiDecoderUnit.
|
||||
|
|
Loading…
Reference in a new issue