mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 10:40:34 +00:00
decoder: h264: add support for NALU "alignment" optimization.
We can avoid scanning for start codes again if the bitstream is fed in NALU chunks. Currently, we always scan for start codes, and keep track of remaining bits in a GstAdapter, even if, in practice, we are likely receiving one GstBuffer per NAL unit. i.e. h264parse with "nal" alignment. https://bugzilla.gnome.org/show_bug.cgi?id=723284 [use gst_adapter_available_fast() to determine the top buffer size] Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
parent
95c781c34f
commit
cb9f98f0d5
3 changed files with 93 additions and 22 deletions
|
@ -445,6 +445,7 @@ struct _GstVaapiDecoderH264Private {
|
||||||
GstH264NalParser *parser;
|
GstH264NalParser *parser;
|
||||||
guint parser_state;
|
guint parser_state;
|
||||||
guint decoder_state;
|
guint decoder_state;
|
||||||
|
GstVaapiStreamAlignH264 stream_alignment;
|
||||||
GstVaapiPictureH264 *current_picture;
|
GstVaapiPictureH264 *current_picture;
|
||||||
GstVaapiParserInfoH264 *sps[GST_H264_MAX_SPS_COUNT];
|
GstVaapiParserInfoH264 *sps[GST_H264_MAX_SPS_COUNT];
|
||||||
GstVaapiParserInfoH264 *active_sps;
|
GstVaapiParserInfoH264 *active_sps;
|
||||||
|
@ -3880,7 +3881,14 @@ gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder,
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
size = gst_adapter_available(adapter);
|
switch (priv->stream_alignment) {
|
||||||
|
case GST_VAAPI_STREAM_ALIGN_H264_NALU:
|
||||||
|
size = gst_adapter_available_fast(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
size = gst_adapter_available(adapter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->is_avcC) {
|
if (priv->is_avcC) {
|
||||||
if (size < priv->nal_length_size)
|
if (size < priv->nal_length_size)
|
||||||
|
@ -3902,30 +3910,34 @@ gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder,
|
||||||
if (size < 4)
|
if (size < 4)
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||||
|
|
||||||
ofs = scan_for_start_code(adapter, 0, size, NULL);
|
if (priv->stream_alignment == GST_VAAPI_STREAM_ALIGN_H264_NALU)
|
||||||
if (ofs < 0)
|
buf_size = size;
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
else {
|
||||||
|
ofs = scan_for_start_code(adapter, 0, size, NULL);
|
||||||
if (ofs > 0) {
|
if (ofs < 0)
|
||||||
gst_adapter_flush(adapter, ofs);
|
|
||||||
size -= ofs;
|
|
||||||
}
|
|
||||||
|
|
||||||
ofs2 = ps->input_offset2 - ofs - 4;
|
|
||||||
if (ofs2 < 4)
|
|
||||||
ofs2 = 4;
|
|
||||||
|
|
||||||
ofs = G_UNLIKELY(size < ofs2 + 4) ? -1 :
|
|
||||||
scan_for_start_code(adapter, ofs2, size - ofs2, NULL);
|
|
||||||
if (ofs < 0) {
|
|
||||||
// Assume the whole NAL unit is present if end-of-stream
|
|
||||||
if (!at_eos) {
|
|
||||||
ps->input_offset2 = size;
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||||
|
|
||||||
|
if (ofs > 0) {
|
||||||
|
gst_adapter_flush(adapter, ofs);
|
||||||
|
size -= ofs;
|
||||||
}
|
}
|
||||||
ofs = size;
|
|
||||||
|
ofs2 = ps->input_offset2 - ofs - 4;
|
||||||
|
if (ofs2 < 4)
|
||||||
|
ofs2 = 4;
|
||||||
|
|
||||||
|
ofs = G_UNLIKELY(size < ofs2 + 4) ? -1 :
|
||||||
|
scan_for_start_code(adapter, ofs2, size - ofs2, NULL);
|
||||||
|
if (ofs < 0) {
|
||||||
|
// Assume the whole NAL unit is present if end-of-stream
|
||||||
|
if (!at_eos) {
|
||||||
|
ps->input_offset2 = size;
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||||
|
}
|
||||||
|
ofs = size;
|
||||||
|
}
|
||||||
|
buf_size = ofs;
|
||||||
}
|
}
|
||||||
buf_size = ofs;
|
|
||||||
}
|
}
|
||||||
ps->input_offset2 = 0;
|
ps->input_offset2 = 0;
|
||||||
|
|
||||||
|
@ -4127,6 +4139,24 @@ gst_vaapi_decoder_h264_class(void)
|
||||||
return GST_VAAPI_DECODER_CLASS(&g_class);
|
return GST_VAAPI_DECODER_CLASS(&g_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_decoder_h264_set_alignment:
|
||||||
|
* @decoder: a #GstVaapiDecoderH264
|
||||||
|
* @alignment: the #GstVaapiStreamAlignH264
|
||||||
|
*
|
||||||
|
* Specifies how stream buffers are aligned / fed, i.e. the boundaries
|
||||||
|
* of each buffer that is supplied to the decoder. This could be no
|
||||||
|
* specific alignment, NAL unit boundaries, or access unit boundaries.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_vaapi_decoder_h264_set_alignment(GstVaapiDecoderH264 *decoder,
|
||||||
|
GstVaapiStreamAlignH264 alignment)
|
||||||
|
{
|
||||||
|
g_return_if_fail(decoder != NULL);
|
||||||
|
|
||||||
|
decoder->priv.stream_alignment = alignment;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_vaapi_decoder_h264_new:
|
* gst_vaapi_decoder_h264_new:
|
||||||
* @display: a #GstVaapiDisplay
|
* @display: a #GstVaapiDisplay
|
||||||
|
|
|
@ -27,11 +27,34 @@
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_VAAPI_DECODER_H264(decoder) \
|
||||||
|
((GstVaapiDecoderH264 *)(decoder))
|
||||||
|
|
||||||
typedef struct _GstVaapiDecoderH264 GstVaapiDecoderH264;
|
typedef struct _GstVaapiDecoderH264 GstVaapiDecoderH264;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstVaapiStreamAlignH264:
|
||||||
|
* @GST_VAAPI_STREAM_ALIGN_H264_NONE: Generic H.264 stream buffers
|
||||||
|
* @GST_VAAPI_STREAM_ALIGN_H264_NALU: H.264 stream buffers aligned NAL
|
||||||
|
* unit boundaries
|
||||||
|
* @GST_VAAPI_STREAM_ALIGN_H264_AU: H.264 stream buffers aligned on
|
||||||
|
* access unit boundaries
|
||||||
|
*
|
||||||
|
* Set of possible buffer alignments for H.264 streams.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
GST_VAAPI_STREAM_ALIGN_H264_NONE,
|
||||||
|
GST_VAAPI_STREAM_ALIGN_H264_NALU,
|
||||||
|
GST_VAAPI_STREAM_ALIGN_H264_AU
|
||||||
|
} GstVaapiStreamAlignH264;
|
||||||
|
|
||||||
GstVaapiDecoder *
|
GstVaapiDecoder *
|
||||||
gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps);
|
gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps);
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_vaapi_decoder_h264_set_alignment(GstVaapiDecoderH264 *decoder,
|
||||||
|
GstVaapiStreamAlignH264 alignment);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* GST_VAAPI_DECODER_H264_H */
|
#endif /* GST_VAAPI_DECODER_H264_H */
|
||||||
|
|
|
@ -644,6 +644,24 @@ gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
|
||||||
break;
|
break;
|
||||||
case GST_VAAPI_CODEC_H264:
|
case GST_VAAPI_CODEC_H264:
|
||||||
decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
|
decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
|
||||||
|
|
||||||
|
/* Set the stream buffer alignment for better optimizations */
|
||||||
|
if (decode->decoder && caps) {
|
||||||
|
GstStructure * const structure = gst_caps_get_structure(caps, 0);
|
||||||
|
const gchar *str = NULL;
|
||||||
|
|
||||||
|
if ((str = gst_structure_get_string(structure, "alignment"))) {
|
||||||
|
GstVaapiStreamAlignH264 alignment;
|
||||||
|
if (g_strcmp0(str, "au") == 0)
|
||||||
|
alignment = GST_VAAPI_STREAM_ALIGN_H264_AU;
|
||||||
|
else if (g_strcmp0(str, "nal") == 0)
|
||||||
|
alignment = GST_VAAPI_STREAM_ALIGN_H264_NALU;
|
||||||
|
else
|
||||||
|
alignment = GST_VAAPI_STREAM_ALIGN_H264_NONE;
|
||||||
|
gst_vaapi_decoder_h264_set_alignment(
|
||||||
|
GST_VAAPI_DECODER_H264(decode->decoder), alignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GST_VAAPI_CODEC_WMV3:
|
case GST_VAAPI_CODEC_WMV3:
|
||||||
case GST_VAAPI_CODEC_VC1:
|
case GST_VAAPI_CODEC_VC1:
|
||||||
|
|
Loading…
Reference in a new issue