d3d11: Add h264 decoder element

New decoder implementation based on dxva2 on d3d11 APIs. The DPB
management implementation is taken from Chromium.
This commit is contained in:
Seungha Yang 2019-12-26 14:24:46 +09:00 committed by GStreamer Merge Bot
parent 7bfdeaf161
commit 586390b1ba
11 changed files with 5124 additions and 0 deletions

View file

@ -72,6 +72,13 @@ typedef struct _GstD3D11DownloadClass GstD3D11DownloadClass;
typedef struct _GstD3D11ColorConvert GstD3D11ColorConvert;
typedef struct _GstD3D11ColorConvertClass GstD3D11ColorConvertClass;
typedef struct _GstD3D11Decoder GstD3D11Decoder;
typedef struct _GstD3D11DecoderClass GstD3D11DecoderClass;
typedef struct _GstD3D11DecoderPrivate GstD3D11DecoderPrivate;
typedef struct _GstD3D11H264Dec GstD3D11H264Dec;
typedef struct _GstD3D11H264DecClass GstD3D11H264DecClass;
G_END_DECLS
#endif /* __GST_D3D11_FWD_H__ */

1014
sys/d3d11/gstd3d11decoder.c Normal file

File diff suppressed because it is too large Load diff

129
sys/d3d11/gstd3d11decoder.h Normal file
View file

@ -0,0 +1,129 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_D3D11_DECODER_H__
#define __GST_D3D11_DECODER_H__
#include <gst/gst.h>
#include <gst/video/video.h>
#include <d3d9.h>
#include <dxva.h>
#include <dxva2api.h>
#include "gstd3d11_fwd.h"
#include "gstd3d11device.h"
#include "gstd3d11utils.h"
G_BEGIN_DECLS
#define GST_TYPE_D3D11_DECODER \
(gst_d3d11_decoder_get_type())
#define GST_D3D11_DECODER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_D3D11_DECODER,GstD3D11Decoder))
#define GST_D3D11_DECODER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_D3D11_DECODER,GstD3D11DecoderClass))
#define GST_D3D11_DECODER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_D3D11_DECODER,GstD3D11DecoderClass))
#define GST_IS_D3D11_DECODER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_D3D11_DECODER))
#define GST_IS_D3D11_DECODER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D11_DECODER))
typedef struct _GstD3D11DecoderOutputView GstD3D11DecoderOutputView;
struct _GstD3D11DecoderOutputView
{
GstD3D11Device *device;
ID3D11VideoDecoderOutputView *handle;
guint view_id;
};
typedef enum
{
GST_D3D11_CODEC_NONE,
GST_D3D11_CODEC_H264,
/* the last of supported codec */
GST_D3D11_CODEC_LAST
} GstD3D11Codec;
struct _GstD3D11Decoder
{
GstObject parent;
/* TRUE if decoder was successfully opened ever */
gboolean opened;
/*< private >*/
GstD3D11DecoderPrivate *priv;
gpointer padding[GST_PADDING_LARGE];
};
struct _GstD3D11DecoderClass
{
GstObjectClass parent_class;
};
GType gst_d3d11_decoder_get_type (void);
GstD3D11Decoder * gst_d3d11_decoder_new (GstD3D11Device * device);
gboolean gst_d3d11_decoder_open (GstD3D11Decoder * decoder,
GstD3D11Codec codec,
GstVideoInfo * info,
guint pool_size,
const GUID ** decoder_profiles,
guint profile_size);
void gst_d3d11_decoder_reset (GstD3D11Decoder * decoder);
gboolean gst_d3d11_decoder_begin_frame (GstD3D11Decoder * decoder,
GstD3D11DecoderOutputView * output_view,
guint content_key_size,
gconstpointer content_key);
gboolean gst_d3d11_decoder_end_frame (GstD3D11Decoder * decoder);
gboolean gst_d3d11_decoder_get_decoder_buffer (GstD3D11Decoder * decoder,
D3D11_VIDEO_DECODER_BUFFER_TYPE type,
guint * buffer_size,
gpointer * buffer);
gboolean gst_d3d11_decoder_release_decoder_buffer (GstD3D11Decoder * decoder,
D3D11_VIDEO_DECODER_BUFFER_TYPE type);
gboolean gst_d3d11_decoder_submit_decoder_buffers (GstD3D11Decoder * decoder,
guint buffer_count,
const D3D11_VIDEO_DECODER_BUFFER_DESC * buffers);
GstBuffer * gst_d3d11_decoder_get_output_view_buffer (GstD3D11Decoder * decoder);
GstD3D11DecoderOutputView * gst_d3d11_decoder_get_output_view_from_buffer (GstD3D11Decoder * decoder,
GstBuffer * buffer);
guint gst_d3d11_decoder_get_output_view_index (GstD3D11Decoder * decoder,
ID3D11VideoDecoderOutputView * view_handle);
gboolean gst_d3d11_decoder_copy_decoder_buffer (GstD3D11Decoder * decoder,
GstVideoInfo * info,
GstBuffer * decoder_buffer,
GstBuffer * output);
G_END_DECLS
#endif /* __GST_D3D11_DECODER_H__ */

1186
sys/d3d11/gstd3d11h264dec.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,87 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_D3D11_H264_DEC_H__
#define __GST_D3D11_H264_DEC_H__
#include "gsth264decoder.h"
#include "gsth264picture.h"
#include "gstd3d11decoder.h"
G_BEGIN_DECLS
#define GST_TYPE_D3D11_H264_DEC \
(gst_d3d11_h264_dec_get_type())
#define GST_D3D11_H264_DEC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_D3D11_H264_DEC,GstD3D11H264Dec))
#define GST_D3D11_H264_DEC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_D3D11_H264_DEC,GstD3D11H264DecClass))
#define GST_D3D11_H264_DEC_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_D3D11_H264_DEC,GstD3D11H264DecClass))
#define GST_IS_D3D11_H264_DEC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_D3D11_H264_DEC))
#define GST_IS_D3D11_H264_DEC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D11_H264_DEC))
struct _GstD3D11H264Dec
{
GstH264Decoder parent;
GstVideoCodecState *output_state;
GstD3D11Device *device;
gint adapter;
guint width, height;
guint coded_width, coded_height;
guint bitdepth;
guint chroma_format_idc;
GstVideoFormat out_format;
DXVA_PicEntry_H264 ref_frame_list[16];
INT field_order_cnt_list[16][2];
USHORT frame_num_list[16];
UINT used_for_reference_flags;
USHORT non_existing_frame_flags;
/* Array of DXVA_Slice_H264_Short */
GArray *slice_list;
GstD3D11Decoder *d3d11_decoder;
GstH264Picture *current_picture;
/* Pointing current bitstream buffer */
guint current_offset;
guint bitstream_buffer_size;
guint8 * bitstream_buffer_bytes;
gboolean use_d3d11_output;
};
struct _GstD3D11H264DecClass
{
GstH264DecoderClass parent_class;
};
GType gst_d3d11_h264_dec_get_type (void);
G_END_DECLS
#endif /* __GST_D3D11_H264_DEC_H__ */

1829
sys/d3d11/gsth264decoder.c Normal file

File diff suppressed because it is too large Load diff

112
sys/d3d11/gsth264decoder.h Normal file
View file

@ -0,0 +1,112 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_H264_DECODER_H__
#define __GST_H264_DECODER_H__
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/codecparsers/gsth264parser.h>
#include "gsth264picture.h"
G_BEGIN_DECLS
#define GST_TYPE_H264_DECODER (gst_h264_decoder_get_type())
#define GST_H264_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_H264_DECODER,GstH264Decoder))
#define GST_H264_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_H264_DECODER,GstH264DecoderClass))
#define GST_H264_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_H264_DECODER,GstH264DecoderClass))
#define GST_IS_H264_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_H264_DECODER))
#define GST_IS_H264_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_H264_DECODER))
#define GST_H264_DECODER_CAST(obj) ((GstH264Decoder*)obj)
typedef struct _GstH264Decoder GstH264Decoder;
typedef struct _GstH264DecoderClass GstH264DecoderClass;
typedef struct _GstH264DecoderPrivate GstH264DecoderPrivate;
/**
* GstH264Decoder:
*
* The opaque #GstH264Decoder data structure.
*/
struct _GstH264Decoder
{
/*< private >*/
GstVideoDecoder parent;
/*< protected >*/
GstVideoCodecState * input_state;
/*< private >*/
GstH264DecoderPrivate *priv;
gpointer padding[GST_PADDING_LARGE];
};
/**
* GstH264DecoderClass:
* @new_sequence: Notifies subclass of SPS update
* @new_picture: Optional.
* Called whenever new #GstH264Picture is created.
* Subclass can set implementation specific user data
* on the #GstH264Picture via gst_h264_picture_set_user_data()
* @output_picture: Optional.
* Called just before gst_video_decoder_have_frame().
* Subclass should be prepared for handle_frame()
* @start_picture: Optional.
* Called per one #GstH264Picture to notify subclass to prepare
* decoding process for the #GstH264Picture
* @decode_slice: Provides per slice data with parsed slice header and
* required raw bitstream for subclass to decode it
* @end_picture: Optional.
* Called per one #GstH264Picture to notify subclass to finish
* decoding process for the #GstH264Picture
*/
struct _GstH264DecoderClass
{
GstVideoDecoderClass parent_class;
gboolean (*new_sequence) (GstH264Decoder * decoder,
const GstH264SPS * sps);
gboolean (*new_picture) (GstH264Decoder * decoder,
GstH264Picture * picture);
GstFlowReturn (*output_picture) (GstH264Decoder * decoder,
GstH264Picture * picture);
gboolean (*start_picture) (GstH264Decoder * decoder,
GstH264Picture * picture,
GstH264Slice * slice,
GstH264Dpb * dpb);
gboolean (*decode_slice) (GstH264Decoder * decoder,
GstH264Picture * picture,
GstH264Slice * slice);
gboolean (*end_picture) (GstH264Decoder * decoder,
GstH264Picture * picture);
/*< private >*/
gpointer padding[GST_PADDING_LARGE];
};
GType gst_h264_decoder_get_type (void);
G_END_DECLS
#endif /* __GST_H264_DECODER_H__ */

510
sys/d3d11/gsth264picture.c Normal file
View file

@ -0,0 +1,510 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "gsth264picture.h"
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_h264_dec_debug);
#define GST_CAT_DEFAULT gst_d3d11_h264_dec_debug
GST_DEFINE_MINI_OBJECT_TYPE (GstH264Picture, gst_h264_picture);
static void
_gst_h264_picture_free (GstH264Picture * picture)
{
if (picture->notify)
picture->notify (picture->user_data);
g_free (picture);
}
/**
* gst_h264_picture_new:
*
* Create new #GstH264Picture
*
* Returns: a new #GstH264Picture
*/
GstH264Picture *
gst_h264_picture_new (void)
{
GstH264Picture *pic;
pic = g_new0 (GstH264Picture, 1);
pic->pts = GST_CLOCK_TIME_NONE;
pic->top_field_order_cnt = G_MAXINT32;
pic->bottom_field_order_cnt = G_MAXINT32;
pic->field = GST_H264_PICTURE_FIELD_FRAME;
gst_mini_object_init (GST_MINI_OBJECT_CAST (pic), 0,
GST_TYPE_H264_PICTURE, NULL, NULL,
(GstMiniObjectFreeFunction) _gst_h264_picture_free);
return pic;
}
/**
* gst_h264_picture_set_user_data:
* @picture: a #GstH264Picture
* @user_data: private data
* @notify: (closure user_data): a #GDestroyNotify
*
* Sets @user_data on the picture and the #GDestroyNotify that will be called when
* the picture is freed.
*
* If a @user_data was previously set, then the previous set @notify will be called
* before the @user_data is replaced.
*/
void
gst_h264_picture_set_user_data (GstH264Picture * picture, gpointer user_data,
GDestroyNotify notify)
{
g_return_if_fail (GST_IS_H264_PICTURE (picture));
if (picture->notify)
picture->notify (picture->user_data);
picture->user_data = user_data;
picture->notify = notify;
}
/**
* gst_h264_picture_get_user_data:
* @picture: a #GstH264Picture
*
* Gets private data set on the picture via
* gst_h264_picture_set_user_data() previously.
*
* Returns: (transfer none): The previously set user_data
*/
gpointer
gst_h264_picture_get_user_data (GstH264Picture * picture)
{
return picture->user_data;
}
struct _GstH264Dpb
{
GArray *pic_list;
gint max_num_pics;
};
/**
* gst_h264_dpb_new:
*
* Create new #GstH264Dpb
*
* Returns: a new #GstH264Dpb
*/
GstH264Dpb *
gst_h264_dpb_new (void)
{
GstH264Dpb *dpb;
dpb = g_new0 (GstH264Dpb, 1);
dpb->pic_list =
g_array_sized_new (FALSE, TRUE, sizeof (GstH264Picture *),
GST_H264_DPB_MAX_SIZE);
g_array_set_clear_func (dpb->pic_list,
(GDestroyNotify) gst_h264_picture_clear);
return dpb;
}
/**
* gst_h264_dpb_set_max_num_pics:
* @dpb: a #GstH264Dpb
* @max_num_pics: the maximum number of picture
*
* Set the number of maximum allowed pictures to store
*/
void
gst_h264_dpb_set_max_num_pics (GstH264Dpb * dpb, gint max_num_pics)
{
g_return_if_fail (dpb != NULL);
dpb->max_num_pics = max_num_pics;
}
/**
* gst_h264_dpb_get_max_num_pics:
* @dpb: a #GstH264Dpb
*
* Returns: the number of maximum pictures
*/
gint
gst_h264_dpb_get_max_num_pics (GstH264Dpb * dpb)
{
g_return_val_if_fail (dpb != NULL, 0);
return dpb->max_num_pics;
}
/**
* gst_h264_dpb_free:
* @dpb: a #GstH264Dpb to free
*
* Free the @dpb
*/
void
gst_h264_dpb_free (GstH264Dpb * dpb)
{
g_return_if_fail (dpb != NULL);
gst_h264_dpb_clear (dpb);
g_free (dpb);
}
/**
* gst_h264_dpb_clear:
* @dpb: a #GstH264Dpb
*
* Clear all stored #GstH264Picture
*/
void
gst_h264_dpb_clear (GstH264Dpb * dpb)
{
g_return_if_fail (dpb != NULL);
g_array_set_size (dpb->pic_list, 0);
}
/**
* gst_h264_dpb_add:
* @dpb: a #GstH264Dpb
* @picture: (transfer full): a #GstH264Picture
*
* Store the @picture
*/
void
gst_h264_dpb_add (GstH264Dpb * dpb, GstH264Picture * picture)
{
g_return_if_fail (dpb != NULL);
g_return_if_fail (GST_IS_H264_PICTURE (picture));
g_array_append_val (dpb->pic_list, picture);
}
/**
* gst_h264_dpb_delete_unused:
* @dpb: a #GstH264Dpb
*
* Delete already outputted and not referenced all pictures from dpb
*/
void
gst_h264_dpb_delete_unused (GstH264Dpb * dpb)
{
gint i;
g_return_if_fail (dpb != NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (picture->outputted && !picture->ref) {
GST_TRACE ("remove picture %p (frame num %d) from dpb",
picture, picture->frame_num);
g_array_remove_index (dpb->pic_list, i);
i--;
}
}
}
/**
* gst_h264_dpb_delete_by_poc:
* @dpb: a #GstH264Dpb
* @poc: a poc of #GstH264Picture to remove
*
* Delete a #GstH264Dpb by @poc
*/
void
gst_h264_dpb_delete_by_poc (GstH264Dpb * dpb, gint poc)
{
gint i;
g_return_if_fail (dpb != NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (picture->pic_order_cnt == poc) {
g_array_remove_index (dpb->pic_list, i);
return;
}
}
GST_WARNING ("Couldn't find picture with poc %d", poc);
}
/**
* gst_h264_dpb_num_ref_pictures:
* @dpb: a #GstH264Dpb
*
* Returns: The number of referenced pictures
*/
gint
gst_h264_dpb_num_ref_pictures (GstH264Dpb * dpb)
{
gint i;
gint ret = 0;
g_return_val_if_fail (dpb != NULL, -1);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (picture->ref)
ret++;
}
return ret;
}
/**
* gst_h264_dpb_mark_all_non_ref:
* @dpb: a #GstH264Dpb
*
* Mark all pictures are not referenced
*/
void
gst_h264_dpb_mark_all_non_ref (GstH264Dpb * dpb)
{
gint i;
g_return_if_fail (dpb != NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
picture->ref = FALSE;
}
}
/**
* gst_h264_dpb_get_short_ref_by_pic_num:
* @dpb: a #GstH264Dpb
* @pic_num: a picture number
*
* Find a short term reference picture which has matching picture number
*
* Returns: (nullable) (transfer full): a #GstH264Picture
*/
GstH264Picture *
gst_h264_dpb_get_short_ref_by_pic_num (GstH264Dpb * dpb, gint pic_num)
{
gint i;
g_return_val_if_fail (dpb != NULL, NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (picture->ref && !picture->long_term && picture->pic_num == pic_num)
return gst_h264_picture_ref (picture);
}
GST_WARNING ("No short term reference picture for %d", pic_num);
return NULL;
}
/**
* gst_h264_dpb_get_long_ref_by_pic_num:
* @dpb: a #GstH264Dpb
* @pic_num: a picture number
*
* Find a long term reference picture which has matching picture number
*
* Returns: (nullable) (transfer full): a #GstH264Picture
*/
GstH264Picture *
gst_h264_dpb_get_long_ref_by_pic_num (GstH264Dpb * dpb, gint pic_num)
{
gint i;
g_return_val_if_fail (dpb != NULL, NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (picture->ref && picture->long_term && picture->pic_num == pic_num)
return gst_h264_picture_ref (picture);
}
GST_WARNING ("No long term reference picture for %d", pic_num);
return NULL;
}
/**
* gst_h264_dpb_get_lowest_frame_num_short_ref:
* @dpb: a #GstH264Dpb
* @pic_num: a picture number
*
* Find a short term reference picture which has the lowest frame_num_wrap
*
* Returns: (transfer full): a #GstH264Picture
*/
GstH264Picture *
gst_h264_dpb_get_lowest_frame_num_short_ref (GstH264Dpb * dpb)
{
gint i;
GstH264Picture *ret = NULL;
g_return_val_if_fail (dpb != NULL, NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (picture->ref && !picture->long_term &&
(!ret || picture->frame_num_wrap < ret->frame_num_wrap))
ret = picture;
}
if (ret)
gst_h264_picture_ref (ret);
return ret;
}
/**
* gst_h264_dpb_get_pictures_not_outputted:
* @dpb: a #GstH264Dpb
* @out: (out): a list of #GstH264Dpb
*
* Retrieve all not-outputted pictures from @dpb
*/
void
gst_h264_dpb_get_pictures_not_outputted (GstH264Dpb * dpb, GList ** out)
{
gint i;
g_return_if_fail (dpb != NULL);
g_return_if_fail (out != NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (!picture->outputted)
*out = g_list_append (*out, gst_h264_picture_ref (picture));
}
}
/**
* gst_h264_dpb_get_pictures_short_term_ref:
* @dpb: a #GstH264Dpb
* @out: (out): a list of #GstH264Dpb
*
* Retrieve all short-term reference pictures from @dpb
*/
void
gst_h264_dpb_get_pictures_short_term_ref (GstH264Dpb * dpb, GList ** out)
{
gint i;
g_return_if_fail (dpb != NULL);
g_return_if_fail (out != NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (picture->ref && !picture->long_term)
*out = g_list_append (*out, gst_h264_picture_ref (picture));
}
}
/**
* gst_h264_dpb_get_pictures_long_term_ref:
* @dpb: a #GstH264Dpb
* @out: (out): a list of #GstH264Dpb
*
* Retrieve all long-term reference pictures from @dpb
*/
void
gst_h264_dpb_get_pictures_long_term_ref (GstH264Dpb * dpb, GList ** out)
{
gint i;
g_return_if_fail (dpb != NULL);
g_return_if_fail (out != NULL);
for (i = 0; i < dpb->pic_list->len; i++) {
GstH264Picture *picture =
g_array_index (dpb->pic_list, GstH264Picture *, i);
if (picture->ref && picture->long_term)
*out = g_list_append (*out, gst_h264_picture_ref (picture));
}
}
/**
* gst_h264_dpb_get_pictures_all:
* @dpb: a #GstH264Dpb
*
* Return: (transfer full): a #GArray of #GstH264Picture stored in @dpb
*/
GArray *
gst_h264_dpb_get_pictures_all (GstH264Dpb * dpb)
{
g_return_val_if_fail (dpb != NULL, NULL);
return g_array_ref (dpb->pic_list);
}
/**
* gst_h264_dpb_get_size:
* @dpb: a #GstH264Dpb
*
* Return: the length of stored dpb array
*/
gint
gst_h264_dpb_get_size (GstH264Dpb * dpb)
{
g_return_val_if_fail (dpb != NULL, -1);
return dpb->pic_list->len;
}
/**
* gst_h264_dpb_is_full:
* @dpb: a #GstH264Dpb
*
* Return: %TRUE if @dpb is full
*/
gboolean
gst_h264_dpb_is_full (GstH264Dpb * dpb)
{
g_return_val_if_fail (dpb != NULL, -1);
return dpb->pic_list->len >= dpb->max_num_pics;
}

216
sys/d3d11/gsth264picture.h Normal file
View file

@ -0,0 +1,216 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_H264_PICTURE_H__
#define __GST_H264_PICTURE_H__
#include <gst/gst.h>
#include <gst/codecparsers/gsth264parser.h>
G_BEGIN_DECLS
#define GST_TYPE_H264_PICTURE (gst_h264_picture_get_type())
#define GST_IS_H264_PICTURE(obj) (GST_IS_MINI_OBJECT_TYPE(obj, GST_TYPE_H264_PICTURE))
#define GST_H264_PICTURE(obj) ((GstH264Picture *)obj)
#define GST_H264_PICTURE_CAST(obj) (GST_H264_PICTURE(obj))
typedef struct _GstH264Slice GstH264Slice;
typedef struct _GstH264Picture GstH264Picture;
#define GST_H264_DPB_MAX_SIZE 32
struct _GstH264Slice
{
GstH264SliceHdr header;
/* parsed nal unit (doesn't take ownership of raw data) */
GstH264NalUnit nalu;
};
typedef enum
{
GST_H264_PICTURE_FIELD_FRAME,
GST_H264_PICTURE_FILED_TOP_FIELD,
GST_H264_PICTURE_FIELD_BOTTOM_FIELD,
} GstH264PictureField;
struct _GstH264Picture
{
GstMiniObject parent;
GstH264SliceType type;
GstClockTime pts;
guint8 pic_order_cnt_type; /* SPS */
gint32 top_field_order_cnt;
gint32 bottom_field_order_cnt;
gint pic_order_cnt;
gint pic_order_cnt_msb;
gint pic_order_cnt_lsb;
gint delta_pic_order_cnt_bottom;
gint delta_pic_order_cnt0;
gint delta_pic_order_cnt1;
gint pic_num;
gint long_term_pic_num;
gint frame_num;
gint frame_num_offset;
gint frame_num_wrap;
gint long_term_frame_idx;
gint nal_ref_idc;
gboolean idr;
gint idr_pic_id;
gboolean ref;
gboolean long_term;
gboolean outputted;
gboolean mem_mgmt_5;
gboolean nonexisting;
GstH264PictureField field;
GstH264DecRefPicMarking dec_ref_pic_marking;
gpointer user_data;
GDestroyNotify notify;
};
G_GNUC_INTERNAL
GType gst_h264_picture_get_type (void);
G_GNUC_INTERNAL
GstH264Picture * gst_h264_picture_new (void);
G_GNUC_INTERNAL
static inline GstH264Picture *
gst_h264_picture_ref (GstH264Picture * picture)
{
return (GstH264Picture *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (picture));
}
G_GNUC_INTERNAL
static inline void
gst_h264_picture_unref (GstH264Picture * picture)
{
gst_mini_object_unref (GST_MINI_OBJECT_CAST (picture));
}
G_GNUC_INTERNAL
static inline gboolean
gst_h264_picture_replace (GstH264Picture ** old_picture,
GstH264Picture * new_picture)
{
return gst_mini_object_replace ((GstMiniObject **) old_picture,
(GstMiniObject *) new_picture);
}
G_GNUC_INTERNAL
static inline void
gst_h264_picture_clear (GstH264Picture ** picture)
{
if (picture && *picture) {
gst_h264_picture_unref (*picture);
*picture = NULL;
}
}
G_GNUC_INTERNAL
void gst_h264_picture_set_user_data (GstH264Picture * picture,
gpointer user_data,
GDestroyNotify notify);
G_GNUC_INTERNAL
gpointer gst_h264_picture_get_user_data (GstH264Picture * picture);
/*******************
* GstH264Dpb *
*******************/
typedef struct _GstH264Dpb GstH264Dpb;
G_GNUC_INTERNAL
GstH264Dpb * gst_h264_dpb_new (void);
G_GNUC_INTERNAL
void gst_h264_dpb_set_max_num_pics (GstH264Dpb * dpb,
gint max_num_pics);
G_GNUC_INTERNAL
gint gst_h264_dpb_get_max_num_pics (GstH264Dpb * dpb);
G_GNUC_INTERNAL
void gst_h264_dpb_free (GstH264Dpb * dpb);
G_GNUC_INTERNAL
void gst_h264_dpb_clear (GstH264Dpb * dpb);
G_GNUC_INTERNAL
void gst_h264_dpb_add (GstH264Dpb * dpb,
GstH264Picture * picture);
G_GNUC_INTERNAL
void gst_h264_dpb_delete_unused (GstH264Dpb * dpb);
G_GNUC_INTERNAL
void gst_h264_dpb_delete_by_poc (GstH264Dpb * dpb,
gint poc);
G_GNUC_INTERNAL
gint gst_h264_dpb_num_ref_pictures (GstH264Dpb * dpb);
G_GNUC_INTERNAL
void gst_h264_dpb_mark_all_non_ref (GstH264Dpb * dpb);
G_GNUC_INTERNAL
GstH264Picture * gst_h264_dpb_get_short_ref_by_pic_num (GstH264Dpb * dpb,
gint pic_num);
G_GNUC_INTERNAL
GstH264Picture * gst_h264_dpb_get_long_ref_by_pic_num (GstH264Dpb * dpb,
gint pic_num);
G_GNUC_INTERNAL
GstH264Picture * gst_h264_dpb_get_lowest_frame_num_short_ref (GstH264Dpb * dpb);
G_GNUC_INTERNAL
void gst_h264_dpb_get_pictures_not_outputted (GstH264Dpb * dpb,
GList ** out);
G_GNUC_INTERNAL
void gst_h264_dpb_get_pictures_short_term_ref (GstH264Dpb * dpb,
GList ** out);
G_GNUC_INTERNAL
void gst_h264_dpb_get_pictures_long_term_ref (GstH264Dpb * dpb,
GList ** out);
G_GNUC_INTERNAL
GArray * gst_h264_dpb_get_pictures_all (GstH264Dpb * dpb);
G_GNUC_INTERNAL
gint gst_h264_dpb_get_size (GstH264Dpb * dpb);
G_GNUC_INTERNAL
gboolean gst_h264_dpb_is_full (GstH264Dpb * dpb);
G_END_DECLS
#endif /* __GST_H264_PICTURE_H__ */

View file

@ -17,6 +17,13 @@ d3d11_sources = [
'gstd3d11overlaycompositor.c',
]
d3d11_dec_sources = [
'gsth264picture.c',
'gsth264decoder.c',
'gstd3d11decoder.c',
'gstd3d11h264dec.c',
]
dxgi_headers = [
['dxgi1_6.h', 6],
['dxgi1_5.h', 5],
@ -91,6 +98,14 @@ endif
d3d11_conf.set10('HAVE_D3D11SDKLAYERS_H', have_d3d11sdk_h)
d3d11_conf.set10('HAVE_DXGIDEBUG_H', have_dxgidebug_h)
# d3d11 video api uses dxva structure for decoding, and dxva.h needs d3d9 types
if cc.has_header('dxva.h') and cc.has_header('d3d9.h')
d3d11_conf.set('HAVE_DXVA_H', 1)
d3d11_sources += d3d11_dec_sources
extra_c_args += ['-DGST_USE_UNSTABLE_API']
extra_dep += [gstcodecparsers_dep]
endif
configure_file(
output: 'd3d11config.h',
configuration: d3d11_conf,

View file

@ -29,6 +29,10 @@
#include "gstd3d11download.h"
#include "gstd3d11colorconvert.h"
#include "gstd3d11videosinkbin.h"
#ifdef HAVE_DXVA_H
#include "gstd3d11utils.h"
#include "gstd3d11h264dec.h"
#endif
GST_DEBUG_CATEGORY (gst_d3d11_shader_debug);
GST_DEBUG_CATEGORY (gst_d3d11_colorconverter_debug);
@ -41,6 +45,10 @@ GST_DEBUG_CATEGORY (gst_d3d11_overlay_compositor_debug);
GST_DEBUG_CATEGORY (gst_d3d11_debug_layer_debug);
#endif
#ifdef HAVE_DXVA_H
GST_DEBUG_CATEGORY (gst_d3d11_h264_dec_debug);
#endif
static gboolean
plugin_init (GstPlugin * plugin)
{
@ -74,6 +82,17 @@ plugin_init (GstPlugin * plugin)
gst_element_register (plugin,
"d3d11videosink", GST_RANK_SECONDARY - 1, GST_TYPE_D3D11_VIDEO_SINK_BIN);
#ifdef HAVE_DXVA_H
/* DXVA2 API is availble since Windows 8 */
if (gst_d3d11_is_windows_8_or_greater ()) {
GST_DEBUG_CATEGORY_INIT (gst_d3d11_h264_dec_debug,
"d3d11h264dec", 0, "Direct3D11 H.264 Video Decoder");
gst_element_register (plugin,
"d3d11h264dec", GST_RANK_SECONDARY, GST_TYPE_D3D11_H264_DEC);
}
#endif
return TRUE;
}