summaryrefslogtreecommitdiffstats
path: root/ext/dv
diff options
context:
space:
mode:
authorWim Taymans <wim@fluendo.com>2007-03-09 17:32:32 +0000
committerJan Schmidt <thaytan@mad.scientist.com>2007-03-09 17:32:32 +0000
commit9d501ec355197f1487f2476f4572d7bca8f5188a (patch)
tree7ca7e8e730ce013792e6e3046f3283fd5b9c18d7 /ext/dv
parentbeef8e01365d8d1ac8257443686c9c734dff111d (diff)
ext/dv/gstdvdec.*: Infer pixel-aspect-ratio from the video frame format if it isn't provided by the container, as hap...
Original commit message from CVS: * ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_sink_setcaps), (gst_dvdec_src_negotiate), (gst_dvdec_chain), (gst_dvdec_change_state): * ext/dv/gstdvdec.h: Infer pixel-aspect-ratio from the video frame format if it isn't provided by the container, as happens when playing DV from AVI or Quicktime containers. Patch by: Wim Taymans <wim@fluendo.com> Fixes #380944
Diffstat (limited to 'ext/dv')
-rw-r--r--ext/dv/gstdvdec.c131
-rw-r--r--ext/dv/gstdvdec.h11
2 files changed, 116 insertions, 26 deletions
diff --git a/ext/dv/gstdvdec.c b/ext/dv/gstdvdec.c
index 11088c8a..575fe0ab 100644
--- a/ext/dv/gstdvdec.c
+++ b/ext/dv/gstdvdec.c
@@ -58,8 +58,25 @@ GST_ELEMENT_DETAILS ("DV video decoder",
"Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
/* sizes of one input buffer */
+#define NTSC_HEIGHT 480
#define NTSC_BUFFER 120000
+#define NTSC_FRAMERATE_NUMERATOR 30000
+#define NTSC_FRAMERATE_DENOMINATOR 1001
+
+#define PAL_HEIGHT 576
#define PAL_BUFFER 144000
+#define PAL_FRAMERATE_NUMERATOR 25
+#define PAL_FRAMERATE_DENOMINATOR 1
+
+#define PAL_NORMAL_PAR_X 59
+#define PAL_NORMAL_PAR_Y 54
+#define PAL_WIDE_PAR_X 118
+#define PAL_WIDE_PAR_Y 81
+
+#define NTSC_NORMAL_PAR_X 10
+#define NTSC_NORMAL_PAR_Y 11
+#define NTSC_WIDE_PAR_X 40
+#define NTSC_WIDE_PAR_Y 33
#define DV_DEFAULT_QUALITY DV_QUALITY_BEST
#define DV_DEFAULT_DECODE_NTH 1
@@ -217,7 +234,6 @@ gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class)
dvdec->framerate_numerator = 0;
dvdec->framerate_denominator = 0;
- dvdec->height = 0;
dvdec->wide = FALSE;
dvdec->drop_factor = 1;
@@ -242,8 +258,6 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
{
GstDVDec *dvdec;
GstStructure *s;
- GstCaps *othercaps;
- gboolean gotpar = FALSE;
const GValue *par = NULL, *rate = NULL;
dvdec = GST_DVDEC (gst_pad_get_parent (pad));
@@ -251,18 +265,67 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
/* first parse the caps */
s = gst_caps_get_structure (caps, 0);
- if (!gst_structure_get_int (s, "height", &dvdec->height))
- goto error;
- if ((par = gst_structure_get_value (s, "pixel-aspect-ratio")))
- gotpar = TRUE;
+ /* we allow framerate and PAR to be overwritten. framerate is mandatory. */
if (!(rate = gst_structure_get_value (s, "framerate")))
- goto error;
-
+ goto no_framerate;
+ par = gst_structure_get_value (s, "pixel-aspect-ratio");
+
+ if (par) {
+ dvdec->par_x = gst_value_get_fraction_numerator (par);
+ dvdec->par_y = gst_value_get_fraction_denominator (par);
+ dvdec->need_par = FALSE;
+ } else {
+ dvdec->par_x = 0;
+ dvdec->par_y = 0;
+ dvdec->need_par = TRUE;
+ }
dvdec->framerate_numerator = gst_value_get_fraction_numerator (rate);
dvdec->framerate_denominator = gst_value_get_fraction_denominator (rate);
+ dvdec->sink_negotiated = TRUE;
+ dvdec->src_negotiated = FALSE;
- /* ignoring rgb, bgr0 for now */
+ gst_object_unref (dvdec);
+
+ return TRUE;
+
+ /* ERRORS */
+no_framerate:
+ {
+ GST_DEBUG_OBJECT (dvdec, "no framerate specified in caps");
+ gst_object_unref (dvdec);
+ return FALSE;
+ }
+}
+static gboolean
+gst_dvdec_src_negotiate (GstDVDec * dvdec)
+{
+ GstCaps *othercaps;
+
+ /* no PAR was specified in input, derive from encoded data */
+ if (dvdec->need_par) {
+ if (dvdec->PAL) {
+ if (dvdec->wide) {
+ dvdec->par_x = PAL_WIDE_PAR_X;
+ dvdec->par_y = PAL_WIDE_PAR_Y;
+ } else {
+ dvdec->par_x = PAL_NORMAL_PAR_X;
+ dvdec->par_y = PAL_NORMAL_PAR_Y;
+ }
+ } else {
+ if (dvdec->wide) {
+ dvdec->par_x = NTSC_WIDE_PAR_X;
+ dvdec->par_y = NTSC_WIDE_PAR_Y;
+ } else {
+ dvdec->par_x = NTSC_NORMAL_PAR_X;
+ dvdec->par_y = NTSC_NORMAL_PAR_Y;
+ }
+ }
+ GST_DEBUG_OBJECT (dvdec, "Inferred PAR %d/%d from video format",
+ dvdec->par_x, dvdec->par_y);
+ }
+
+ /* ignoring rgb, bgr0 for now */
dvdec->bpp = 2;
othercaps = gst_caps_new_simple ("video/x-raw-yuv",
@@ -270,25 +333,16 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
"width", G_TYPE_INT, 720,
"height", G_TYPE_INT, dvdec->height,
"framerate", GST_TYPE_FRACTION, dvdec->framerate_numerator,
- dvdec->framerate_denominator, NULL);
- if (gotpar)
- gst_structure_set_value (gst_caps_get_structure (othercaps, 0),
- "pixel-aspect-ratio", par);
+ dvdec->framerate_denominator,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION, dvdec->par_x,
+ dvdec->par_y, NULL);
gst_pad_set_caps (dvdec->srcpad, othercaps);
-
gst_caps_unref (othercaps);
- gst_object_unref (dvdec);
+ dvdec->src_negotiated = TRUE;
return TRUE;
-
-error:
- {
- gst_object_unref (dvdec);
-
- return FALSE;
- }
}
static gboolean
@@ -342,6 +396,7 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
GstFlowReturn ret = GST_FLOW_OK;
guint length;
gint64 cstart, cstop;
+ gboolean PAL, wide;
dvdec = GST_DVDEC (gst_pad_get_parent (pad));
inframe = GST_BUFFER_DATA (buf);
@@ -362,9 +417,13 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
if (G_UNLIKELY (dv_parse_header (dvdec->decoder, inframe) < 0))
goto parse_header_error;
+ /* get size */
+ PAL = dv_system_50_fields (dvdec->decoder);
+ wide = dv_format_wide (dvdec->decoder);
+
/* check the buffer is of right size after we know if we are
* dealing with PAL or NTSC */
- length = (dvdec->PAL ? PAL_BUFFER : NTSC_BUFFER);
+ length = (PAL ? PAL_BUFFER : NTSC_BUFFER);
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < length))
goto wrong_size;
@@ -373,6 +432,22 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
if (dvdec->video_offset % dvdec->drop_factor != 0)
goto skip;
+ /* renegotiate on change */
+ if (PAL != dvdec->PAL || wide != dvdec->wide) {
+ dvdec->src_negotiated = FALSE;
+ dvdec->PAL = PAL;
+ dvdec->wide = wide;
+ }
+
+ dvdec->height = (dvdec->PAL ? PAL_HEIGHT : NTSC_HEIGHT);
+
+
+ /* negotiate if not done yet */
+ if (!dvdec->src_negotiated) {
+ if (!gst_dvdec_src_negotiate (dvdec))
+ goto not_negotiated;
+ }
+
ret =
gst_pad_alloc_buffer_and_set_caps (dvdec->srcpad, 0,
(720 * dvdec->height) * dvdec->bpp,
@@ -429,6 +504,12 @@ parse_header_error:
ret = GST_FLOW_ERROR;
goto done;
}
+not_negotiated:
+ {
+ GST_DEBUG_OBJECT (dvdec, "could not negotiate output");
+ ret = GST_FLOW_NOT_NEGOTIATED;
+ goto done;
+ }
no_buffer:
{
GST_DEBUG_OBJECT (dvdec, "could not allocate buffer");
@@ -459,6 +540,8 @@ gst_dvdec_change_state (GstElement * element, GstStateChange transition)
dvdec->decoder->quality = qualities[dvdec->quality];
dv_set_error_log (dvdec->decoder, NULL);
gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED);
+ dvdec->src_negotiated = FALSE;
+ dvdec->sink_negotiated = FALSE;
/*
* Enable this function call when libdv2 0.100 or higher is more
* common
diff --git a/ext/dv/gstdvdec.h b/ext/dv/gstdvdec.h
index ffc8a24a..5f166a14 100644
--- a/ext/dv/gstdvdec.h
+++ b/ext/dv/gstdvdec.h
@@ -56,16 +56,23 @@ struct _GstDVDec {
gboolean clamp_chroma;
gint quality;
- gint frame_len;
gboolean PAL;
+ gboolean wide;
+ gint frame_len;
+
+ /* input caps */
+ gboolean sink_negotiated;
gint framerate_numerator;
gint framerate_denominator;
gint height;
- gboolean wide;
+ gint par_x;
+ gint par_y;
+ gboolean need_par;
/* negotiated output */
dv_color_space_t space;
gint bpp;
+ gboolean src_negotiated;
gint video_offset;
gint drop_factor;