/*
* GStreamer
* Copyright (c) 2010, Texas Instruments Incorporated
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation
* version 2.1 of the License.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* SECTION:element-ducatih264dec
*
* FIXME:Describe ducatih264dec here.
*
*
* Example launch line
* |[
* gst-launch -v -m fakesrc ! ducatih264dec ! fakesink silent=TRUE
* ]|
*
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include "gstducatih264dec.h"
#define GST_BUFFER_FLAG_B_FRAME (GST_BUFFER_FLAG_LAST << 0)
#define PADX 32
#define PADY 24
GST_BOILERPLATE (GstDucatiH264Dec, gst_ducati_h264dec, GstDucatiVidDec,
GST_TYPE_DUCATIVIDDEC);
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-h264, "
"stream-format = byte-stream, " /* only byte-stream */
"align = au, " /* only entire frames */
"width = (int)[ 16, 2048 ], "
"height = (int)[ 16, 2048 ], "
"framerate = (fraction)[ 0, max ],"
"profile = (string){constrained-baseline, baseline, main, extended};"
"video/x-h264, "
"stream-format = byte-stream, " /* only byte-stream */
"align = au, " /* only entire frames */
"width = (int)[ 16, 2048 ], "
"height = (int)[ 16, 2048 ], "
"framerate = (fraction)[ 0, max ],"
"profile = (string) {high, high-10-intra, high-10, high-4:2:2-intra, "
"high-4:2:2, high-4:4:4-intra, high-4:4:4, cavlc-4:4:4-intra}, "
"level = (string) {1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2};"
)
);
/* GstDucatiVidDec vmethod implementations */
static void
gst_ducati_h264dec_update_buffer_size (GstDucatiVidDec * self)
{
gint w = self->width;
gint h = self->height;
/* calculate output buffer parameters: */
self->padded_width = ALIGN2 (w + (2 * PADX), 7);
self->padded_height = h + 4 * PADY;
self->min_buffers = MIN (16, 32768 / ((w / 16) * (h / 16))) + 3;
}
static gboolean
gst_ducati_h264dec_allocate_params (GstDucatiVidDec * self, gint params_sz,
gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz)
{
gboolean ret = parent_class->allocate_params (self,
sizeof (IH264VDEC_Params), sizeof (IH264VDEC_DynamicParams),
sizeof (IH264VDEC_Status), sizeof (IH264VDEC_InArgs),
sizeof (IH264VDEC_OutArgs));
if (ret) {
IH264VDEC_Params *params = (IH264VDEC_Params *) self->params;
self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1;
params->maxNumRefFrames = IH264VDEC_NUM_REFFRAMES_AUTO;
params->pConstantMemory = 0;
params->presetLevelIdc = IH264VDEC_LEVEL41;
params->errConcealmentMode = IH264VDEC_APPLY_CONCEALMENT;
params->temporalDirModePred = TRUE;
}
return ret;
}
static gint
gst_ducati_h264dec_handle_error (GstDucatiVidDec * self, gint ret,
gint extended_error, gint status_extended_error)
{
if (extended_error & 0x00000001) {
/* No valid slice. This seems to be bad enough that it's better to flush and
* skip to the next keyframe.
*/
gst_ducati_viddec_codec_flush (self, FALSE);
}
ret = parent_class->handle_error (self, ret, extended_error,
status_extended_error);
return ret;
}
static gboolean
gst_ducati_h264dec_query (GstDucatiVidDec * vdec, GstPad * pad,
GstQuery * query, gboolean * forward)
{
GstDucatiH264Dec * self = GST_DUCATIH264DEC (vdec);
gboolean res = TRUE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_LATENCY:
{
gboolean live;
GstClockTime min, max, latency;
if (vdec->fps_d == 0) {
GST_INFO_OBJECT (self, "not ready to report latency");
res = FALSE;
break;
}
gst_query_parse_latency (query, &live, &min, &max);
if (vdec->fps_n != 0)
latency = gst_util_uint64_scale (GST_SECOND,
vdec->fps_d, vdec->fps_n);
else
latency = 0;
if (min == GST_CLOCK_TIME_NONE)
min = latency;
else
min += latency;
if (max != GST_CLOCK_TIME_NONE)
max += latency;
GST_INFO_OBJECT (self, "latency %"GST_TIME_FORMAT " ours %"GST_TIME_FORMAT,
GST_TIME_ARGS (min), GST_TIME_ARGS (latency));
gst_query_set_latency (query, live, min, max);
break;
}
default:
break;
}
if (res)
res = parent_class->query (vdec, pad, query, forward);
return res;
}
static gboolean
gst_ducati_h264dec_drop_frame (GstDucatiVidDec * self, GstBuffer * buf,
gint64 diff)
{
gboolean is_bframe = GST_BUFFER_FLAG_IS_SET (buf,
GST_BUFFER_FLAG_B_FRAME);
if (diff >= 0 && is_bframe)
return TRUE;
return FALSE;
}
/* GObject vmethod implementations */
static void
gst_ducati_h264dec_base_init (gpointer gclass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_set_details_simple (element_class,
"DucatiH264Dec",
"Codec/Decoder/Video",
"Decodes video in H.264/bytestream format with ducati",
"Rob Clark ");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
}
static void
gst_ducati_h264dec_class_init (GstDucatiH264DecClass * klass)
{
GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
bclass->codec_name = "ivahd_h264dec";
bclass->update_buffer_size =
GST_DEBUG_FUNCPTR (gst_ducati_h264dec_update_buffer_size);
bclass->allocate_params =
GST_DEBUG_FUNCPTR (gst_ducati_h264dec_allocate_params);
bclass->handle_error = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_handle_error);
bclass->drop_frame = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_drop_frame);
bclass->query = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_query);
}
static void
gst_ducati_h264dec_init (GstDucatiH264Dec * self,
GstDucatiH264DecClass * gclass)
{
}