mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
h264: fix slice_data_bit_offset calculation.
Unlike what VA-API documentation defines, the slice_data_bit_offset represents the offset to the first macroblock in the slice data, minus any emulation prevention bytes in the slice_header(). This fix copes with binary-only VA drivers that won't be fixed any time soon. Besides, this aligns with the current FFmpeg behaviour that was based on those proprietary drivers implementing the API incorrectly.
This commit is contained in:
parent
c979d51da6
commit
63e29adbf5
2 changed files with 65 additions and 3 deletions
24
configure.ac
24
configure.ac
|
@ -247,6 +247,30 @@ AC_DEFINE_UNQUOTED(USE_CODEC_PARSERS, $USE_CODEC_PARSERS,
|
|||
[Defined to 1 if GStreamer codec parsers are used])
|
||||
AM_CONDITIONAL(USE_CODEC_PARSERS, test $USE_CODEC_PARSERS -eq 1)
|
||||
|
||||
if test "$enable_codecparsers" = "yes"; then
|
||||
AC_CACHE_CHECK([for GstH264SliceHdr::n_emulation_prevention_bytes],
|
||||
ac_cv_have_gst_h264_slice_hdr_epb_count, [
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $GST_CFLAGS $GST_CODEC_PARSERS_CFLAGS"
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS="$LIBS $GST_LIBS $GST_CODEC_PARSERS_LIBS"
|
||||
AC_TRY_COMPILE(
|
||||
[#include <gst/codecparsers/gsth264parser.h>],
|
||||
[GstH264SliceHdr slice_hdr;
|
||||
slice_hdr.n_emulation_prevention_bytes = 0;],
|
||||
[ac_cv_have_gst_h264_slice_hdr_epb_count="yes"],
|
||||
[ac_cv_have_gst_h264_slice_hdr_epb_count="no"]
|
||||
)
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
LIBS="$saved_LIBS"
|
||||
])
|
||||
fi
|
||||
|
||||
if test "$ac_cv_have_gst_h264_slice_hdr_epb_count" = "yes"; then
|
||||
AC_DEFINE_UNQUOTED(HAVE_GST_H264_SLICE_HDR_EPB_COUNT, 1,
|
||||
[Defined to 1 if GstH264SliceHdr::n_emulation_prevention_bytes exists.])
|
||||
fi
|
||||
|
||||
dnl Check for GStreamer interfaces
|
||||
PKG_CHECK_MODULES([GST_INTERFACES],
|
||||
[gstreamer-interfaces-$GST_MAJORMINOR >= $GST_PLUGINS_BASE_VERSION_REQUIRED]
|
||||
|
|
|
@ -1965,6 +1965,40 @@ decode_picture_end(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef HAVE_GST_H264_SLICE_HDR_EPB_COUNT
|
||||
static guint
|
||||
get_epb_count(const guint8 *buf, guint buf_size, guint header_size)
|
||||
{
|
||||
guint i, n = 0;
|
||||
|
||||
if (buf_size > header_size)
|
||||
buf_size = header_size;
|
||||
|
||||
for (i = 2; i < buf_size; i++) {
|
||||
if (!buf[i - 2] && !buf[i - 1] && buf[i] == 0x03)
|
||||
i += 2, n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline guint
|
||||
get_slice_data_bit_offset(GstH264SliceHdr *slice_hdr, GstH264NalUnit *nalu)
|
||||
{
|
||||
guint epb_count;
|
||||
|
||||
#ifdef HAVE_GST_H264_SLICE_HDR_EPB_COUNT
|
||||
epb_count = slice_hdr->n_emulation_prevention_bytes;
|
||||
#else
|
||||
epb_count = get_epb_count(
|
||||
nalu->data + nalu->offset,
|
||||
nalu->size,
|
||||
slice_hdr->header_size / 8
|
||||
);
|
||||
#endif
|
||||
return 8 /* nal_unit_type */ + slice_hdr->header_size - epb_count * 8;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fill_pred_weight_table(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
|
||||
{
|
||||
|
@ -2074,13 +2108,17 @@ fill_RefPicList(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
fill_slice(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
|
||||
fill_slice(
|
||||
GstVaapiDecoderH264 *decoder,
|
||||
GstVaapiSliceH264 *slice,
|
||||
GstH264NalUnit *nalu
|
||||
)
|
||||
{
|
||||
GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
|
||||
VASliceParameterBufferH264 * const slice_param = slice->base.param;
|
||||
|
||||
/* Fill in VASliceParameterBufferH264 */
|
||||
slice_param->slice_data_bit_offset = 8 /* nal_unit_type */ + slice_hdr->header_size;
|
||||
slice_param->slice_data_bit_offset = get_slice_data_bit_offset(slice_hdr, nalu);
|
||||
slice_param->first_mb_in_slice = slice_hdr->first_mb_in_slice;
|
||||
slice_param->slice_type = slice_hdr->type % 5;
|
||||
slice_param->direct_spatial_mv_pred_flag = slice_hdr->direct_spatial_mv_pred_flag;
|
||||
|
@ -2137,7 +2175,7 @@ decode_slice(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
|
|||
priv->mb_x = slice_hdr->first_mb_in_slice % priv->mb_width;
|
||||
priv->mb_y = slice_hdr->first_mb_in_slice / priv->mb_width; // FIXME: MBAFF or field
|
||||
|
||||
if (!fill_slice(decoder, slice)) {
|
||||
if (!fill_slice(decoder, slice, nalu)) {
|
||||
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
goto error;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue