diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c index 1e709b5952..68c2b8192a 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c @@ -445,6 +445,7 @@ struct _GstVaapiDecoderH264Private { GstH264NalParser *parser; guint parser_state; guint decoder_state; + GstVaapiStreamAlignH264 stream_alignment; GstVaapiPictureH264 *current_picture; GstVaapiParserInfoH264 *sps[GST_H264_MAX_SPS_COUNT]; GstVaapiParserInfoH264 *active_sps; @@ -3880,7 +3881,14 @@ gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder, if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) 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 (size < priv->nal_length_size) @@ -3902,30 +3910,34 @@ gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder, if (size < 4) return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; - ofs = scan_for_start_code(adapter, 0, size, NULL); - if (ofs < 0) - return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; - - 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; + if (priv->stream_alignment == GST_VAAPI_STREAM_ALIGN_H264_NALU) + buf_size = size; + else { + ofs = scan_for_start_code(adapter, 0, size, NULL); + if (ofs < 0) 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; @@ -4127,6 +4139,24 @@ gst_vaapi_decoder_h264_class(void) 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: * @display: a #GstVaapiDisplay diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h264.h b/gst-libs/gst/vaapi/gstvaapidecoder_h264.h index 05c010b685..f9949dd126 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_h264.h +++ b/gst-libs/gst/vaapi/gstvaapidecoder_h264.h @@ -27,11 +27,34 @@ G_BEGIN_DECLS +#define GST_VAAPI_DECODER_H264(decoder) \ + ((GstVaapiDecoderH264 *)(decoder)) + 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 * gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps); +void +gst_vaapi_decoder_h264_set_alignment(GstVaapiDecoderH264 *decoder, + GstVaapiStreamAlignH264 alignment); + G_END_DECLS #endif /* GST_VAAPI_DECODER_H264_H */ diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c index 8ccc169d21..49df98422d 100644 --- a/gst/vaapi/gstvaapidecode.c +++ b/gst/vaapi/gstvaapidecode.c @@ -644,6 +644,24 @@ gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps) break; case GST_VAAPI_CODEC_H264: 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; case GST_VAAPI_CODEC_WMV3: case GST_VAAPI_CODEC_VC1: