vdpau: more work on h264 decoder
This commit is contained in:
parent
686d2d2303
commit
f8846a463d
@ -12,6 +12,7 @@ libgstvdpau_la_SOURCES = \
|
|||||||
h264/gstnalreader.c \
|
h264/gstnalreader.c \
|
||||||
h264/gsth264parser.c \
|
h264/gsth264parser.c \
|
||||||
h264/gstvdph264frame.c \
|
h264/gstvdph264frame.c \
|
||||||
|
h264/gsth264dpb.c \
|
||||||
h264/gstvdph264dec.c
|
h264/gstvdph264dec.c
|
||||||
|
|
||||||
libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS)
|
libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS)
|
||||||
@ -34,4 +35,5 @@ noinst_HEADERS = \
|
|||||||
h264/gstnalreader.h \
|
h264/gstnalreader.h \
|
||||||
h264/gsth264parser.h \
|
h264/gsth264parser.h \
|
||||||
h264/gstvdph264frame.h \
|
h264/gstvdph264frame.h \
|
||||||
|
h264/gsth264dpb.h \
|
||||||
h264/gstvdph264dec.h
|
h264/gstvdph264dec.h
|
@ -124,8 +124,6 @@ gst_base_video_decoder_new_frame (GstBaseVideoDecoder * base_video_decoder)
|
|||||||
static void
|
static void
|
||||||
gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder)
|
gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder)
|
||||||
{
|
{
|
||||||
GList *g;
|
|
||||||
|
|
||||||
GST_DEBUG ("reset");
|
GST_DEBUG ("reset");
|
||||||
|
|
||||||
base_video_decoder->discont = TRUE;
|
base_video_decoder->discont = TRUE;
|
||||||
@ -152,13 +150,6 @@ gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder)
|
|||||||
|
|
||||||
base_video_decoder->have_src_caps = FALSE;
|
base_video_decoder->have_src_caps = FALSE;
|
||||||
|
|
||||||
for (g = g_list_first (base_video_decoder->frames); g; g = g_list_next (g)) {
|
|
||||||
GstVideoFrame *frame = g->data;
|
|
||||||
gst_video_frame_unref (frame);
|
|
||||||
}
|
|
||||||
g_list_free (base_video_decoder->frames);
|
|
||||||
base_video_decoder->frames = NULL;
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (base_video_decoder);
|
GST_OBJECT_LOCK (base_video_decoder);
|
||||||
base_video_decoder->earliest_time = GST_CLOCK_TIME_NONE;
|
base_video_decoder->earliest_time = GST_CLOCK_TIME_NONE;
|
||||||
base_video_decoder->proportion = 0.5;
|
base_video_decoder->proportion = 0.5;
|
||||||
@ -1022,9 +1013,6 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
|
|||||||
GST_DEBUG ("pushing frame %" GST_TIME_FORMAT,
|
GST_DEBUG ("pushing frame %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (frame->presentation_timestamp));
|
GST_TIME_ARGS (frame->presentation_timestamp));
|
||||||
|
|
||||||
base_video_decoder->frames =
|
|
||||||
g_list_remove (base_video_decoder->frames, frame);
|
|
||||||
|
|
||||||
gst_base_video_decoder_set_src_caps (base_video_decoder);
|
gst_base_video_decoder_set_src_caps (base_video_decoder);
|
||||||
|
|
||||||
if (base_video_decoder->sink_clipping) {
|
if (base_video_decoder->sink_clipping) {
|
||||||
@ -1137,9 +1125,6 @@ gst_base_video_decoder_skip_frame (GstBaseVideoDecoder * base_video_decoder,
|
|||||||
GST_DEBUG ("skipping frame %" GST_TIME_FORMAT,
|
GST_DEBUG ("skipping frame %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (frame->presentation_timestamp));
|
GST_TIME_ARGS (frame->presentation_timestamp));
|
||||||
|
|
||||||
base_video_decoder->frames =
|
|
||||||
g_list_remove (base_video_decoder->frames, frame);
|
|
||||||
|
|
||||||
gst_video_frame_unref (frame);
|
gst_video_frame_unref (frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1171,9 +1156,6 @@ gst_base_video_decoder_have_frame (GstBaseVideoDecoder * base_video_decoder,
|
|||||||
GST_DEBUG ("dts %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->decode_timestamp));
|
GST_DEBUG ("dts %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->decode_timestamp));
|
||||||
GST_DEBUG ("dist %d", frame->distance_from_sync);
|
GST_DEBUG ("dist %d", frame->distance_from_sync);
|
||||||
|
|
||||||
base_video_decoder->frames = g_list_append (base_video_decoder->frames,
|
|
||||||
frame);
|
|
||||||
|
|
||||||
running_time = gst_segment_to_running_time (&base_video_decoder->segment,
|
running_time = gst_segment_to_running_time (&base_video_decoder->segment,
|
||||||
GST_FORMAT_TIME, frame->presentation_timestamp);
|
GST_FORMAT_TIME, frame->presentation_timestamp);
|
||||||
|
|
||||||
@ -1234,37 +1216,6 @@ gst_base_video_decoder_get_current_frame (GstBaseVideoDecoder *
|
|||||||
return base_video_decoder->current_frame;
|
return base_video_decoder->current_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GstVideoFrame *
|
|
||||||
gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder *
|
|
||||||
base_video_decoder)
|
|
||||||
{
|
|
||||||
GList *g;
|
|
||||||
|
|
||||||
g = g_list_first (base_video_decoder->frames);
|
|
||||||
|
|
||||||
if (g == NULL)
|
|
||||||
return NULL;
|
|
||||||
return (GstVideoFrame *) (g->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
GstVideoFrame *
|
|
||||||
gst_base_video_decoder_get_frame (GstBaseVideoDecoder * base_video_decoder,
|
|
||||||
int frame_number)
|
|
||||||
{
|
|
||||||
GList *g;
|
|
||||||
|
|
||||||
for (g = g_list_first (base_video_decoder->frames); g; g = g_list_next (g)) {
|
|
||||||
GstVideoFrame *frame = g->data;
|
|
||||||
|
|
||||||
if (frame->system_frame_number == frame_number) {
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_base_video_decoder_update_src_caps (GstBaseVideoDecoder *
|
gst_base_video_decoder_update_src_caps (GstBaseVideoDecoder *
|
||||||
base_video_decoder)
|
base_video_decoder)
|
||||||
@ -1295,7 +1246,6 @@ gst_base_video_decoder_get_property (GObject * object, guint property_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GObject vmethod implementations */
|
|
||||||
static void
|
static void
|
||||||
gst_base_video_decoder_set_property (GObject * object, guint property_id,
|
gst_base_video_decoder_set_property (GObject * object, guint property_id,
|
||||||
const GValue * value, GParamSpec * pspec)
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
@ -95,8 +95,6 @@ struct _GstBaseVideoDecoder
|
|||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
GstAdapter *input_adapter;
|
GstAdapter *input_adapter;
|
||||||
|
|
||||||
GList *frames;
|
|
||||||
|
|
||||||
gboolean have_sync;
|
gboolean have_sync;
|
||||||
gboolean discont;
|
gboolean discont;
|
||||||
|
|
||||||
|
263
sys/vdpau/h264/gsth264dpb.c
Normal file
263
sys/vdpau/h264/gsth264dpb.c
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.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., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gsth264dpb.h"
|
||||||
|
|
||||||
|
/* Properties */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_NUM_REF_FRAMES
|
||||||
|
};
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (h264dpb_debug);
|
||||||
|
#define GST_CAT_DEFAULT h264dpb_debug
|
||||||
|
|
||||||
|
#define DEBUG_INIT \
|
||||||
|
GST_DEBUG_CATEGORY_INIT (h264dpb_debug, "h264dpb", 0, \
|
||||||
|
"H264 DPB");
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (GstH264DPB, gst_h264_dpb, G_TYPE_OBJECT, DEBUG_INIT);
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_h264_dpb_fill_reference_frames (GstH264DPB * dpb,
|
||||||
|
VdpReferenceFrameH264 reference_frames[16])
|
||||||
|
{
|
||||||
|
GstVdpH264Frame **frames;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
frames = dpb->frames;
|
||||||
|
for (i = 0; i < dpb->n_frames; i++) {
|
||||||
|
GstVdpH264Frame *frame = frames[i];
|
||||||
|
|
||||||
|
reference_frames[i].surface =
|
||||||
|
GST_VDP_VIDEO_BUFFER (GST_VIDEO_FRAME_CAST (frame)->src_buffer)->
|
||||||
|
surface;
|
||||||
|
|
||||||
|
reference_frames[i].is_long_term = frame->is_long_term;
|
||||||
|
reference_frames[i].top_is_reference = frame->is_reference;
|
||||||
|
reference_frames[i].bottom_is_reference = frame->is_reference;
|
||||||
|
reference_frames[i].field_order_cnt[0] = frame->poc;
|
||||||
|
reference_frames[i].field_order_cnt[1] = frame->poc;
|
||||||
|
reference_frames[i].frame_idx = frame->frame_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_h264_dpb_output (GstH264DPB * dpb, guint idx)
|
||||||
|
{
|
||||||
|
GstVdpH264Frame *frame = dpb->frames[idx];
|
||||||
|
|
||||||
|
gst_video_frame_ref (GST_VIDEO_FRAME_CAST (frame));
|
||||||
|
dpb->output (dpb, frame);
|
||||||
|
|
||||||
|
if (!frame->is_reference) {
|
||||||
|
GstVdpH264Frame **frames;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
gst_video_frame_unref (GST_VIDEO_FRAME_CAST (frame));
|
||||||
|
dpb->n_frames--;
|
||||||
|
|
||||||
|
frames = dpb->frames;
|
||||||
|
for (i = idx; i < dpb->n_frames; i++)
|
||||||
|
frames[i] = frames[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_h264_dpb_bump (GstH264DPB * dpb, guint poc)
|
||||||
|
{
|
||||||
|
GstVdpH264Frame **frames;
|
||||||
|
guint i;
|
||||||
|
gint bump_idx;
|
||||||
|
|
||||||
|
frames = dpb->frames;
|
||||||
|
bump_idx = -1;
|
||||||
|
for (i = 0; i < dpb->n_frames; i++) {
|
||||||
|
if (frames[i]->output_needed) {
|
||||||
|
bump_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bump_idx != -1) {
|
||||||
|
for (i = bump_idx + 1; i < dpb->n_frames; i++) {
|
||||||
|
if (frames[i]->output_needed && (frames[i]->poc < frames[bump_idx]->poc)) {
|
||||||
|
bump_idx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frames[bump_idx]->poc < poc) {
|
||||||
|
gst_h264_dpb_output (dpb, bump_idx);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_h264_dpb_add (GstH264DPB * dpb, GstVdpH264Frame * h264_frame)
|
||||||
|
{
|
||||||
|
GstVdpH264Frame **frames;
|
||||||
|
|
||||||
|
GST_DEBUG ("add frame with poc: %d", h264_frame->poc);
|
||||||
|
|
||||||
|
frames = dpb->frames;
|
||||||
|
|
||||||
|
if (h264_frame->is_reference) {
|
||||||
|
|
||||||
|
while (dpb->n_frames == dpb->max_frames) {
|
||||||
|
if (!gst_h264_dpb_bump (dpb, G_MAXUINT)) {
|
||||||
|
GST_ERROR_OBJECT (dpb, "Couldn't make room in DPB");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dpb->frames[dpb->n_frames++] = h264_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
if (dpb->n_frames == dpb->max_frames) {
|
||||||
|
while (gst_h264_dpb_bump (dpb, h264_frame->poc));
|
||||||
|
|
||||||
|
dpb->output (dpb, h264_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
dpb->frames[dpb->n_frames++] = h264_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_h264_dpb_flush (GstH264DPB * dpb, gboolean output)
|
||||||
|
{
|
||||||
|
GstVideoFrame **frames;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
while (gst_h264_dpb_bump (dpb, G_MAXUINT));
|
||||||
|
|
||||||
|
frames = (GstVideoFrame **) dpb->frames;
|
||||||
|
for (i = 0; i < dpb->n_frames; i++)
|
||||||
|
gst_video_frame_unref (frames[i]);
|
||||||
|
|
||||||
|
dpb->n_frames = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_h264_dpb_mark_sliding (GstH264DPB * dpb)
|
||||||
|
{
|
||||||
|
GstVdpH264Frame **frames;
|
||||||
|
guint i;
|
||||||
|
gint mark_idx;
|
||||||
|
|
||||||
|
frames = dpb->frames;
|
||||||
|
for (i = 0; i < dpb->n_frames; i++) {
|
||||||
|
if (frames[i]->is_reference && !frames[i]->is_long_term) {
|
||||||
|
mark_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mark_idx != -1) {
|
||||||
|
for (i = mark_idx; i < dpb->n_frames; i++) {
|
||||||
|
if (frames[i]->is_reference && !frames[i]->is_long_term &&
|
||||||
|
frames[i]->frame_num < frames[mark_idx]->frame_num)
|
||||||
|
mark_idx = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
frames[mark_idx]->is_reference = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GObject vmethod implementations */
|
||||||
|
static void
|
||||||
|
gst_h264_dpb_get_property (GObject * object, guint property_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstH264DPB *dpb = GST_H264_DPB (object);
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_NUM_REF_FRAMES:
|
||||||
|
g_value_set_uint (value, dpb->max_frames);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_h264_dpb_set_property (GObject * object, guint property_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstH264DPB *dpb = GST_H264_DPB (object);
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_NUM_REF_FRAMES:
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
dpb->max_frames = g_value_get_uint (value);
|
||||||
|
for (i = dpb->n_frames; i > dpb->max_frames; i--)
|
||||||
|
gst_h264_dpb_bump (dpb, G_MAXUINT);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_h264_dpb_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
/* TODO: Add deinitalization code here */
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gst_h264_dpb_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_h264_dpb_init (GstH264DPB * dpb)
|
||||||
|
{
|
||||||
|
dpb->n_frames = 0;
|
||||||
|
dpb->max_frames = MAX_DPB_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_h264_dpb_class_init (GstH264DPBClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gst_h264_dpb_finalize;
|
||||||
|
object_class->set_property = gst_h264_dpb_set_property;
|
||||||
|
object_class->get_property = gst_h264_dpb_get_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class, PROP_NUM_REF_FRAMES,
|
||||||
|
g_param_spec_uint ("num-ref-frames", "Num Ref Frames",
|
||||||
|
"How many reference frames the DPB should hold ",
|
||||||
|
0, 16, 16, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
}
|
74
sys/vdpau/h264/gsth264dpb.h
Normal file
74
sys/vdpau/h264/gsth264dpb.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.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., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GST_H264_DPB_H_
|
||||||
|
#define _GST_H264_DPB_H_
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "../gstvdp/gstvdpvideobuffer.h"
|
||||||
|
|
||||||
|
#include "gstvdph264frame.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MAX_DPB_SIZE 16
|
||||||
|
|
||||||
|
|
||||||
|
#define GST_TYPE_H264_DPB (gst_h264_dpb_get_type ())
|
||||||
|
#define GST_H264_DPB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_H264_DPB, GstH264DPB))
|
||||||
|
#define GST_H264_DPB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_H264_DPB, GstH264DPBClass))
|
||||||
|
#define GST_IS_H264_DPB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_H264_DPB))
|
||||||
|
#define GST_IS_H264_DPB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_H264_DPB))
|
||||||
|
#define GST_H264_DPB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_H264_DPB, GstH264DPBClass))
|
||||||
|
|
||||||
|
typedef struct _GstH264DPB GstH264DPB;
|
||||||
|
typedef struct _GstH264DPBClass GstH264DPBClass;
|
||||||
|
|
||||||
|
struct _GstH264DPB
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GstVdpH264Frame *frames[MAX_DPB_SIZE];
|
||||||
|
guint n_frames;
|
||||||
|
|
||||||
|
guint max_frames;
|
||||||
|
|
||||||
|
void (*output) (GstH264DPB *dpb, GstVdpH264Frame *h264_frame);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264DPBClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_h264_dpb_fill_reference_frames (GstH264DPB *dpb, VdpReferenceFrameH264 reference_frames[16]);
|
||||||
|
|
||||||
|
gboolean gst_h264_dpb_add (GstH264DPB *dpb, GstVdpH264Frame *h264_frame);
|
||||||
|
void gst_h264_dpb_flush (GstH264DPB *dpb, gboolean output);
|
||||||
|
|
||||||
|
void gst_h264_dpb_mark_sliding (GstH264DPB *dpb);
|
||||||
|
|
||||||
|
GType gst_h264_dpb_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* _GST_H264_DPB_H_ */
|
@ -374,6 +374,7 @@ gst_h264_parser_parse_sequence (GstH264Parser * parser, guint8 * data,
|
|||||||
seq->bit_depth_chroma_minus8 = 0;
|
seq->bit_depth_chroma_minus8 = 0;
|
||||||
memset (seq->scaling_lists_4x4, 16, 96);
|
memset (seq->scaling_lists_4x4, 16, 96);
|
||||||
memset (seq->scaling_lists_8x8, 16, 384);
|
memset (seq->scaling_lists_8x8, 16, 384);
|
||||||
|
seq->mb_adaptive_frame_field_flag = 0;
|
||||||
seq->frame_crop_left_offset = 0;
|
seq->frame_crop_left_offset = 0;
|
||||||
seq->frame_crop_right_offset = 0;
|
seq->frame_crop_right_offset = 0;
|
||||||
seq->frame_crop_top_offset = 0;
|
seq->frame_crop_top_offset = 0;
|
||||||
@ -417,7 +418,7 @@ gst_h264_parser_parse_sequence (GstH264Parser * parser, guint8 * data,
|
|||||||
|
|
||||||
READ_UE_ALLOWED (&reader, seq->log2_max_frame_num_minus4, 0, 12);
|
READ_UE_ALLOWED (&reader, seq->log2_max_frame_num_minus4, 0, 12);
|
||||||
/* calculate MaxFrameNum */
|
/* calculate MaxFrameNum */
|
||||||
seq->MaxFrameNum = pow (2, seq->log2_max_frame_num_minus4 + 4);
|
seq->MaxFrameNum = 1 << (seq->log2_max_frame_num_minus4 + 4);
|
||||||
|
|
||||||
READ_UE_ALLOWED (&reader, seq->pic_order_cnt_type, 0, 2);
|
READ_UE_ALLOWED (&reader, seq->pic_order_cnt_type, 0, 2);
|
||||||
if (seq->pic_order_cnt_type == 0) {
|
if (seq->pic_order_cnt_type == 0) {
|
||||||
@ -753,40 +754,39 @@ gst_h264_slice_parse_dec_ref_pic_marking (GstH264Slice * slice,
|
|||||||
|
|
||||||
m = &slice->dec_ref_pic_marking;
|
m = &slice->dec_ref_pic_marking;
|
||||||
|
|
||||||
if (slice->nal_unit.IdrPicFlag) {
|
if (slice->nal_unit.IdrPicFlag == 0) {
|
||||||
READ_UINT8 (reader, m->no_output_of_prior_pics_flag, 1);
|
READ_UINT8 (reader, m->no_output_of_prior_pics_flag, 1);
|
||||||
READ_UINT8 (reader, m->long_term_reference_flag, 1);
|
READ_UINT8 (reader, m->long_term_reference_flag, 1);
|
||||||
} else {
|
} else {
|
||||||
READ_UINT8 (reader, m->adaptive_ref_pic_marking_mode_flag, 1);
|
READ_UINT8 (reader, m->adaptive_ref_pic_marking_mode_flag, 1);
|
||||||
if (m->adaptive_ref_pic_marking_mode_flag) {
|
if (m->adaptive_ref_pic_marking_mode_flag) {
|
||||||
guint8 memory_management_control_operation;
|
guint8 memory_management_control_operation;
|
||||||
|
guint i = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
READ_UE_ALLOWED (reader, memory_management_control_operation, 0, 6);
|
READ_UE_ALLOWED (reader, memory_management_control_operation, 0, 6);
|
||||||
|
m->ref_pic_marking[i].memory_management_control_operation =
|
||||||
|
memory_management_control_operation;
|
||||||
|
|
||||||
if (memory_management_control_operation == 1 ||
|
if (memory_management_control_operation == 1 ||
|
||||||
memory_management_control_operation == 3) {
|
memory_management_control_operation == 3)
|
||||||
guint32 difference_of_pic_nums_minus1;
|
READ_UE (reader, m->ref_pic_marking[i].difference_of_pic_nums_minus1);
|
||||||
|
|
||||||
READ_UE (reader, difference_of_pic_nums_minus1);
|
if (memory_management_control_operation == 2)
|
||||||
}
|
READ_UE (reader, m->ref_pic_marking[i].long_term_pic_num);
|
||||||
if (memory_management_control_operation == 2) {
|
|
||||||
guint32 long_term_pic_num;
|
|
||||||
|
|
||||||
READ_UE (reader, long_term_pic_num);
|
|
||||||
}
|
|
||||||
if (memory_management_control_operation == 3 ||
|
if (memory_management_control_operation == 3 ||
|
||||||
memory_management_control_operation == 6) {
|
memory_management_control_operation == 6)
|
||||||
guint32 long_term_frame_idx;
|
READ_UE (reader, m->ref_pic_marking[i].long_term_frame_idx);
|
||||||
|
|
||||||
READ_UE (reader, long_term_frame_idx);
|
if (memory_management_control_operation == 4)
|
||||||
}
|
READ_UE (reader, m->ref_pic_marking[i].max_long_term_frame_idx_plus1);
|
||||||
if (memory_management_control_operation == 4) {
|
|
||||||
guint32 max_long_term_frame_idx_plus1;
|
|
||||||
|
|
||||||
READ_UE (reader, max_long_term_frame_idx_plus1);
|
i++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (memory_management_control_operation != 0);
|
while (memory_management_control_operation != 0);
|
||||||
|
|
||||||
|
m->n_ref_pic_marking = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +183,6 @@ struct _GstH264Sequence
|
|||||||
guint32 pic_height_in_map_units_minus1;
|
guint32 pic_height_in_map_units_minus1;
|
||||||
guint8 frame_mbs_only_flag;
|
guint8 frame_mbs_only_flag;
|
||||||
|
|
||||||
/* if !frame_mbs_only_flag */
|
|
||||||
guint8 mb_adaptive_frame_field_flag;
|
guint8 mb_adaptive_frame_field_flag;
|
||||||
|
|
||||||
guint8 direct_8x8_inference_flag;
|
guint8 direct_8x8_inference_flag;
|
||||||
@ -256,6 +255,18 @@ struct _GstH264DecRefPicMarking
|
|||||||
|
|
||||||
/* else */
|
/* else */
|
||||||
guint8 adaptive_ref_pic_marking_mode_flag;
|
guint8 adaptive_ref_pic_marking_mode_flag;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
guint8 memory_management_control_operation;
|
||||||
|
|
||||||
|
union {
|
||||||
|
guint32 difference_of_pic_nums_minus1;
|
||||||
|
guint32 long_term_pic_num;
|
||||||
|
guint32 long_term_frame_idx;
|
||||||
|
guint32 max_long_term_frame_idx_plus1;
|
||||||
|
};
|
||||||
|
} ref_pic_marking[10];
|
||||||
|
guint8 n_ref_pic_marking;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstH264PredWeightTable
|
struct _GstH264PredWeightTable
|
||||||
|
@ -72,6 +72,21 @@ GST_BOILERPLATE_FULL (GstVdpH264Dec, gst_vdp_h264_dec, GstBaseVideoDecoder,
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vdp_h264_dec_alloc_buffer (GstVdpH264Dec * h264_dec,
|
||||||
|
GstVdpVideoBuffer ** outbuf)
|
||||||
|
{
|
||||||
|
GstVdpVideoSrcPad *vdp_pad;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
vdp_pad = (GstVdpVideoSrcPad *) GST_BASE_VIDEO_DECODER_SRC_PAD (h264_dec);
|
||||||
|
ret = gst_vdp_video_src_pad_alloc_buffer (vdp_pad, outbuf);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vdp_h264_dec_set_sink_caps (GstBaseVideoDecoder * base_video_decoder,
|
gst_vdp_h264_dec_set_sink_caps (GstBaseVideoDecoder * base_video_decoder,
|
||||||
GstCaps * caps)
|
GstCaps * caps)
|
||||||
@ -165,25 +180,354 @@ gst_vdp_h264_dec_shape_output (GstBaseVideoDecoder * base_video_decoder,
|
|||||||
return gst_vdp_video_src_pad_push (vdp_pad, GST_VDP_VIDEO_BUFFER (buf));
|
return gst_vdp_video_src_pad_push (vdp_pad, GST_VDP_VIDEO_BUFFER (buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_dec_output (GstH264DPB * dpb, GstVdpH264Frame * h264_frame)
|
||||||
|
{
|
||||||
|
GST_DEBUG ("poc: %d", h264_frame->poc);
|
||||||
|
|
||||||
|
gst_video_frame_unref (GST_VIDEO_FRAME_CAST (h264_frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
gst_vdp_h264_dec_calculate_poc (GstVdpH264Dec * h264_dec, GstH264Slice * slice)
|
||||||
|
{
|
||||||
|
GstH264Picture *pic;
|
||||||
|
GstH264Sequence *seq;
|
||||||
|
|
||||||
|
guint poc;
|
||||||
|
|
||||||
|
pic = slice->picture;
|
||||||
|
seq = pic->sequence;
|
||||||
|
|
||||||
|
if (seq->pic_order_cnt_type == 0) {
|
||||||
|
guint32 max_poc_cnt_lsb = 1 << (seq->log2_max_pic_order_cnt_lsb_minus4 + 4);
|
||||||
|
|
||||||
|
if ((slice->pic_order_cnt_lsb < h264_dec->prev_poc_lsb) &&
|
||||||
|
((h264_dec->prev_poc_lsb - slice->pic_order_cnt_lsb) >=
|
||||||
|
(max_poc_cnt_lsb / 2)))
|
||||||
|
h264_dec->poc_msb = h264_dec->poc_msb + max_poc_cnt_lsb;
|
||||||
|
|
||||||
|
else if ((slice->pic_order_cnt_lsb > h264_dec->prev_poc_lsb) &&
|
||||||
|
((slice->pic_order_cnt_lsb - h264_dec->prev_poc_lsb) >
|
||||||
|
(max_poc_cnt_lsb / 2)))
|
||||||
|
h264_dec->poc_msb = h264_dec->poc_msb - max_poc_cnt_lsb;
|
||||||
|
|
||||||
|
poc = h264_dec->poc_msb + slice->pic_order_cnt_lsb;
|
||||||
|
|
||||||
|
h264_dec->prev_poc_lsb = slice->pic_order_cnt_lsb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return poc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_dec_init_frame_info (GstVdpH264Dec * h264_dec,
|
||||||
|
GstVdpH264Frame * h264_frame)
|
||||||
|
{
|
||||||
|
GstH264Slice *slice;
|
||||||
|
|
||||||
|
slice = &h264_frame->slice_hdr;
|
||||||
|
|
||||||
|
h264_frame->poc = gst_vdp_h264_dec_calculate_poc (h264_dec, slice);
|
||||||
|
|
||||||
|
h264_frame->is_long_term = FALSE;
|
||||||
|
|
||||||
|
/* is reference */
|
||||||
|
if (slice->nal_unit.ref_idc == 0)
|
||||||
|
h264_frame->is_reference = FALSE;
|
||||||
|
else if (slice->nal_unit.IdrPicFlag) {
|
||||||
|
h264_frame->is_reference = TRUE;
|
||||||
|
h264_frame->is_long_term =
|
||||||
|
slice->dec_ref_pic_marking.long_term_reference_flag;
|
||||||
|
} else {
|
||||||
|
if (slice->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag)
|
||||||
|
GST_ERROR ("FIXME: implement adaptive ref pic marking");
|
||||||
|
else
|
||||||
|
h264_frame->is_reference = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vdp_h264_dec_idr (GstVdpH264Dec * h264_dec, GstVdpH264Frame * h264_frame)
|
||||||
|
{
|
||||||
|
GstH264Slice *slice;
|
||||||
|
GstH264Sequence *seq;
|
||||||
|
|
||||||
|
h264_dec->poc_msb = 0;
|
||||||
|
h264_dec->prev_poc_lsb = 0;
|
||||||
|
|
||||||
|
slice = &h264_frame->slice_hdr;
|
||||||
|
if (slice->dec_ref_pic_marking.no_output_of_prior_pics_flag)
|
||||||
|
gst_h264_dpb_flush (h264_dec->dpb, FALSE);
|
||||||
|
else
|
||||||
|
gst_h264_dpb_flush (h264_dec->dpb, TRUE);
|
||||||
|
|
||||||
|
|
||||||
|
seq = slice->picture->sequence;
|
||||||
|
if (seq != h264_dec->sequence) {
|
||||||
|
GstVdpDevice *device;
|
||||||
|
|
||||||
|
gst_base_video_decoder_update_src_caps (GST_BASE_VIDEO_DECODER (h264_dec));
|
||||||
|
|
||||||
|
device = gst_vdp_video_src_pad_get_device
|
||||||
|
(GST_VDP_VIDEO_SRC_PAD (GST_BASE_VIDEO_DECODER_SRC_PAD (h264_dec)));
|
||||||
|
|
||||||
|
if (device) {
|
||||||
|
GstVideoState *state;
|
||||||
|
VdpDecoderProfile profile;
|
||||||
|
VdpStatus status;
|
||||||
|
|
||||||
|
if (h264_dec->decoder != VDP_INVALID_HANDLE) {
|
||||||
|
device->vdp_decoder_destroy (h264_dec->decoder);
|
||||||
|
h264_dec->decoder = VDP_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
state =
|
||||||
|
gst_base_video_decoder_get_state (GST_BASE_VIDEO_DECODER (h264_dec));
|
||||||
|
|
||||||
|
switch (seq->profile_idc) {
|
||||||
|
case 66:
|
||||||
|
profile = VDP_DECODER_PROFILE_H264_BASELINE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 77:
|
||||||
|
profile = VDP_DECODER_PROFILE_H264_MAIN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 100:
|
||||||
|
profile = VDP_DECODER_PROFILE_H264_HIGH;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = device->vdp_decoder_create (device->device, profile,
|
||||||
|
state->width, state->height, seq->num_ref_frames, &h264_dec->decoder);
|
||||||
|
if (status != VDP_STATUS_OK) {
|
||||||
|
GST_ELEMENT_ERROR (h264_dec, RESOURCE, READ,
|
||||||
|
("Could not create vdpau decoder"),
|
||||||
|
("Error returned from vdpau was: %s",
|
||||||
|
device->vdp_get_error_string (status)));
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_object_set (h264_dec->dpb, "num-ref-frames", seq->num_ref_frames, NULL);
|
||||||
|
|
||||||
|
h264_dec->sequence = seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VdpPictureInfoH264
|
||||||
|
gst_vdp_h264_dec_fill_info (GstVdpH264Dec * h264_dec,
|
||||||
|
GstVdpH264Frame * h264_frame)
|
||||||
|
{
|
||||||
|
GstH264Slice *slice;
|
||||||
|
GstH264Picture *pic;
|
||||||
|
GstH264Sequence *seq;
|
||||||
|
VdpPictureInfoH264 info;
|
||||||
|
|
||||||
|
slice = &h264_frame->slice_hdr;
|
||||||
|
pic = slice->picture;
|
||||||
|
seq = pic->sequence;
|
||||||
|
|
||||||
|
info.slice_count = h264_frame->slices->len;
|
||||||
|
|
||||||
|
/* FIXME: we only handle frames for now */
|
||||||
|
info.field_order_cnt[0] = h264_frame->poc;
|
||||||
|
info.field_order_cnt[1] = h264_frame->poc;
|
||||||
|
|
||||||
|
info.is_reference = h264_frame->is_reference;
|
||||||
|
|
||||||
|
info.field_pic_flag = slice->field_pic_flag;
|
||||||
|
info.bottom_field_flag = slice->bottom_field_flag;
|
||||||
|
|
||||||
|
info.num_ref_frames = seq->num_ref_frames;
|
||||||
|
info.frame_mbs_only_flag = seq->frame_mbs_only_flag;
|
||||||
|
info.mb_adaptive_frame_field_flag = seq->mb_adaptive_frame_field_flag;
|
||||||
|
info.log2_max_frame_num_minus4 = seq->log2_max_frame_num_minus4;
|
||||||
|
info.pic_order_cnt_type = seq->pic_order_cnt_type;
|
||||||
|
info.log2_max_pic_order_cnt_lsb_minus4 =
|
||||||
|
seq->log2_max_pic_order_cnt_lsb_minus4;
|
||||||
|
info.delta_pic_order_always_zero_flag = seq->delta_pic_order_always_zero_flag;
|
||||||
|
info.direct_8x8_inference_flag = seq->direct_8x8_inference_flag;
|
||||||
|
|
||||||
|
|
||||||
|
info.constrained_intra_pred_flag = pic->constrained_intra_pred_flag;
|
||||||
|
info.weighted_pred_flag = pic->weighted_pred_flag;
|
||||||
|
info.weighted_bipred_idc = pic->weighted_bipred_idc;
|
||||||
|
info.transform_8x8_mode_flag = pic->transform_8x8_mode_flag;
|
||||||
|
info.chroma_qp_index_offset = pic->chroma_qp_index_offset;
|
||||||
|
info.second_chroma_qp_index_offset = pic->second_chroma_qp_index_offset;
|
||||||
|
info.pic_init_qp_minus26 = pic->pic_init_qp_minus26;
|
||||||
|
info.num_ref_idx_l0_active_minus1 = pic->num_ref_idx_l0_active_minus1;
|
||||||
|
info.num_ref_idx_l1_active_minus1 = pic->num_ref_idx_l1_active_minus1;
|
||||||
|
info.entropy_coding_mode_flag = pic->entropy_coding_mode_flag;
|
||||||
|
info.pic_order_present_flag = pic->pic_order_present_flag;
|
||||||
|
info.deblocking_filter_control_present_flag =
|
||||||
|
pic->deblocking_filter_control_present_flag;
|
||||||
|
info.redundant_pic_cnt_present_flag = pic->redundant_pic_cnt_present_flag;
|
||||||
|
|
||||||
|
memcpy (&info.scaling_lists_4x4, &pic->scaling_lists_4x4, 96);
|
||||||
|
memcpy (&info.scaling_lists_8x8, &pic->scaling_lists_8x8, 128);
|
||||||
|
|
||||||
|
gst_h264_dpb_fill_reference_frames (h264_dec->dpb, info.referenceFrames);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VdpBitstreamBuffer *
|
||||||
|
gst_vdp_h264_dec_create_bitstream_buffers (GstVdpH264Dec * h264_dec,
|
||||||
|
GstVdpH264Frame * h264_frame, guint * n_bufs)
|
||||||
|
{
|
||||||
|
VdpBitstreamBuffer *bufs;
|
||||||
|
|
||||||
|
if (h264_dec->packetized) {
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
bufs = g_new (VdpBitstreamBuffer, h264_frame->slices->len * 2);
|
||||||
|
*n_bufs = h264_frame->slices->len * 2;
|
||||||
|
|
||||||
|
for (i = 0; i < h264_frame->slices->len; i++) {
|
||||||
|
static const guint8 start_code[] = { 0x00, 0x00, 0x01 };
|
||||||
|
guint idx;
|
||||||
|
GstBuffer *buf;
|
||||||
|
|
||||||
|
idx = i * 2;
|
||||||
|
bufs[idx].bitstream = start_code;
|
||||||
|
bufs[idx].bitstream_bytes = 3;
|
||||||
|
bufs[idx].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
|
||||||
|
|
||||||
|
idx = idx + 1;
|
||||||
|
buf = GST_BUFFER_CAST (g_ptr_array_index (h264_frame->slices, i));
|
||||||
|
bufs[idx].bitstream = GST_BUFFER_DATA (buf) + h264_dec->nal_length_size;
|
||||||
|
bufs[idx].bitstream_bytes = GST_BUFFER_SIZE (buf) -
|
||||||
|
h264_dec->nal_length_size;
|
||||||
|
bufs[idx].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
bufs = g_new (VdpBitstreamBuffer, h264_frame->slices->len * 2);
|
||||||
|
*n_bufs = h264_frame->slices->len * 2;
|
||||||
|
|
||||||
|
for (i = 0; i < h264_frame->slices->len; i++) {
|
||||||
|
GstBuffer *buf;
|
||||||
|
|
||||||
|
buf = GST_BUFFER_CAST (g_ptr_array_index (h264_frame->slices, i));
|
||||||
|
bufs[i].bitstream = GST_BUFFER_DATA (buf);
|
||||||
|
bufs[i].bitstream_bytes = GST_BUFFER_SIZE (buf);
|
||||||
|
bufs[i].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bufs;
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_vdp_h264_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder,
|
gst_vdp_h264_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder,
|
||||||
GstVideoFrame * frame, GstClockTimeDiff deadline)
|
GstVideoFrame * frame, GstClockTimeDiff deadline)
|
||||||
{
|
{
|
||||||
|
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
|
||||||
GstVdpH264Frame *h264_frame;
|
GstVdpH264Frame *h264_frame;
|
||||||
|
GstH264Slice *slice;
|
||||||
|
GstH264Picture *pic;
|
||||||
|
GstH264Sequence *seq;
|
||||||
|
|
||||||
|
GstFlowReturn ret;
|
||||||
|
GstVdpVideoBuffer *outbuf;
|
||||||
|
VdpPictureInfoH264 info;
|
||||||
|
GstVdpDevice *device;
|
||||||
|
VdpVideoSurface surface;
|
||||||
|
VdpBitstreamBuffer *bufs;
|
||||||
|
guint n_bufs;
|
||||||
|
VdpStatus status;
|
||||||
|
|
||||||
GST_DEBUG ("handle_frame");
|
GST_DEBUG ("handle_frame");
|
||||||
|
|
||||||
h264_frame = (GstVdpH264Frame *) frame;
|
h264_frame = (GstVdpH264Frame *) frame;
|
||||||
|
|
||||||
GST_DEBUG ("frame_num: %d", h264_frame->slice_hdr.frame_num);
|
slice = &h264_frame->slice_hdr;
|
||||||
GST_DEBUG ("pic_order_cnt_type: %d",
|
pic = slice->picture;
|
||||||
h264_frame->slice_hdr.picture->sequence->pic_order_cnt_type);
|
seq = pic->sequence;
|
||||||
GST_DEBUG ("pic_order_cnt_lsb: %d", h264_frame->slice_hdr.pic_order_cnt_lsb);
|
|
||||||
GST_DEBUG ("delta_pic_order_cnt_bottom: %d",
|
|
||||||
h264_frame->slice_hdr.delta_pic_order_cnt_bottom);
|
if (slice->nal_unit.IdrPicFlag) {
|
||||||
|
if (gst_vdp_h264_dec_idr (h264_dec, h264_frame))
|
||||||
|
h264_dec->got_idr = TRUE;
|
||||||
|
else {
|
||||||
|
gst_base_video_decoder_skip_frame (base_video_decoder, frame);
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we've got a IDR frame yet */
|
||||||
|
if (!h264_dec->got_idr) {
|
||||||
|
gst_base_video_decoder_skip_frame (base_video_decoder, frame);
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_vdp_h264_dec_init_frame_info (h264_dec, h264_frame);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* decoding */
|
||||||
|
if ((ret = gst_vdp_h264_dec_alloc_buffer (h264_dec, &outbuf) != GST_FLOW_OK))
|
||||||
|
goto alloc_error;
|
||||||
|
|
||||||
|
device = GST_VDP_VIDEO_BUFFER (outbuf)->device;
|
||||||
|
surface = GST_VDP_VIDEO_BUFFER (outbuf)->surface;
|
||||||
|
|
||||||
|
info = gst_vdp_h264_dec_fill_info (h264_dec, h264_frame);
|
||||||
|
bufs = gst_vdp_h264_dec_create_bitstream_buffers (h264_dec, h264_frame,
|
||||||
|
&n_bufs);
|
||||||
|
|
||||||
|
status = device->vdp_decoder_render (h264_dec->decoder, surface,
|
||||||
|
(VdpPictureInfo *) & info, n_bufs, bufs);
|
||||||
|
|
||||||
|
g_free (bufs);
|
||||||
|
if (status != VDP_STATUS_OK)
|
||||||
|
goto decode_error;
|
||||||
|
|
||||||
|
frame->src_buffer = GST_BUFFER_CAST (outbuf);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* DPB handling */
|
||||||
|
if (slice->nal_unit.ref_idc != 0 && !slice->nal_unit.IdrPicFlag) {
|
||||||
|
if (slice->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag)
|
||||||
|
GST_ERROR ("FIXME: implement adaptive ref pic marking");
|
||||||
|
else
|
||||||
|
gst_h264_dpb_mark_sliding (h264_dec->dpb);
|
||||||
|
}
|
||||||
|
gst_h264_dpb_add (h264_dec->dpb, h264_frame);
|
||||||
|
|
||||||
gst_base_video_decoder_skip_frame (base_video_decoder, frame);
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
alloc_error:
|
||||||
|
GST_ERROR_OBJECT (h264_dec, "Could not allocate output buffer");
|
||||||
|
gst_base_video_decoder_skip_frame (base_video_decoder, frame);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
decode_error:
|
||||||
|
GST_ELEMENT_ERROR (h264_dec, RESOURCE, READ,
|
||||||
|
("Could not decode"),
|
||||||
|
("Error returned from vdpau was: %s",
|
||||||
|
device->vdp_get_error_string (status)));
|
||||||
|
|
||||||
|
gst_buffer_unref (GST_BUFFER_CAST (outbuf));
|
||||||
|
gst_base_video_decoder_skip_frame (base_video_decoder, frame);
|
||||||
|
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
@ -445,6 +789,11 @@ gst_vdp_h264_dec_create_srcpad (GstBaseVideoDecoder * base_video_decoder,
|
|||||||
static gboolean
|
static gboolean
|
||||||
gst_vdp_h264_dec_flush (GstBaseVideoDecoder * base_video_decoder)
|
gst_vdp_h264_dec_flush (GstBaseVideoDecoder * base_video_decoder)
|
||||||
{
|
{
|
||||||
|
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
|
||||||
|
h264_dec->got_idr = FALSE;
|
||||||
|
gst_h264_dpb_flush (h264_dec->dpb, FALSE);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,8 +804,15 @@ gst_vdp_h264_dec_start (GstBaseVideoDecoder * base_video_decoder)
|
|||||||
|
|
||||||
h264_dec->packetized = FALSE;
|
h264_dec->packetized = FALSE;
|
||||||
h264_dec->nal_length_size = SYNC_CODE_SIZE;
|
h264_dec->nal_length_size = SYNC_CODE_SIZE;
|
||||||
|
|
||||||
|
h264_dec->got_idr = FALSE;
|
||||||
|
h264_dec->sequence = NULL;
|
||||||
|
|
||||||
h264_dec->parser = g_object_new (GST_TYPE_H264_PARSER, NULL);
|
h264_dec->parser = g_object_new (GST_TYPE_H264_PARSER, NULL);
|
||||||
|
|
||||||
|
h264_dec->dpb = g_object_new (GST_TYPE_H264_DPB, NULL);
|
||||||
|
h264_dec->dpb->output = gst_vdp_h264_dec_output;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,7 +821,21 @@ gst_vdp_h264_dec_stop (GstBaseVideoDecoder * base_video_decoder)
|
|||||||
{
|
{
|
||||||
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
|
||||||
|
GstVdpVideoSrcPad *vdp_pad;
|
||||||
|
GstVdpDevice *device;
|
||||||
|
|
||||||
g_object_unref (h264_dec->parser);
|
g_object_unref (h264_dec->parser);
|
||||||
|
g_object_unref (h264_dec->dpb);
|
||||||
|
|
||||||
|
vdp_pad =
|
||||||
|
GST_VDP_VIDEO_SRC_PAD (GST_BASE_VIDEO_DECODER_SRC_PAD
|
||||||
|
(base_video_decoder));
|
||||||
|
|
||||||
|
if ((device = gst_vdp_video_src_pad_get_device (vdp_pad))) {
|
||||||
|
|
||||||
|
if (h264_dec->decoder != VDP_INVALID_HANDLE)
|
||||||
|
device->vdp_decoder_destroy (h264_dec->decoder);
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "../basevideodecoder/gstbasevideodecoder.h"
|
#include "../basevideodecoder/gstbasevideodecoder.h"
|
||||||
|
|
||||||
#include "gsth264parser.h"
|
#include "gsth264parser.h"
|
||||||
|
#include "gsth264dpb.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -44,10 +45,18 @@ typedef struct _GstVdpH264DecClass GstVdpH264DecClass;
|
|||||||
struct _GstVdpH264Dec {
|
struct _GstVdpH264Dec {
|
||||||
GstBaseVideoDecoder base_video_decoder;
|
GstBaseVideoDecoder base_video_decoder;
|
||||||
|
|
||||||
GstBuffer *codec_data;
|
|
||||||
gboolean packetized;
|
gboolean packetized;
|
||||||
guint8 nal_length_size;
|
guint8 nal_length_size;
|
||||||
|
|
||||||
GstH264Parser *parser;
|
GstH264Parser *parser;
|
||||||
|
GstH264DPB *dpb;
|
||||||
|
|
||||||
|
GstH264Sequence *sequence;
|
||||||
|
gboolean got_idr;
|
||||||
|
VdpDecoder decoder;
|
||||||
|
|
||||||
|
guint poc_msb;
|
||||||
|
guint prev_poc_lsb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVdpH264DecClass {
|
struct _GstVdpH264DecClass {
|
||||||
|
@ -42,8 +42,13 @@ struct _GstVdpH264Frame
|
|||||||
GstVideoFrame video_frame;
|
GstVideoFrame video_frame;
|
||||||
|
|
||||||
GstH264Slice slice_hdr;
|
GstH264Slice slice_hdr;
|
||||||
|
|
||||||
GPtrArray *slices;
|
GPtrArray *slices;
|
||||||
|
|
||||||
|
guint poc;
|
||||||
|
guint16 frame_num;
|
||||||
|
gboolean is_reference;
|
||||||
|
gboolean is_long_term;
|
||||||
|
gboolean output_needed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVdpH264FrameClass
|
struct _GstVdpH264FrameClass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user