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
This commit is contained in:
Wim Taymans 2007-03-09 17:32:32 +00:00 committed by Jan Schmidt
parent beef8e0136
commit 9d501ec355
3 changed files with 128 additions and 25 deletions

View file

@ -1,3 +1,16 @@
2007-03-09 Jan Schmidt <thaytan@mad.scientist.com>
* 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
2007-03-09 Wim Taymans <wim@fluendo.com> 2007-03-09 Wim Taymans <wim@fluendo.com>
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_activate_streams): * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_activate_streams):

View file

@ -58,8 +58,25 @@ GST_ELEMENT_DETAILS ("DV video decoder",
"Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>"); "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
/* sizes of one input buffer */ /* sizes of one input buffer */
#define NTSC_HEIGHT 480
#define NTSC_BUFFER 120000 #define NTSC_BUFFER 120000
#define NTSC_FRAMERATE_NUMERATOR 30000
#define NTSC_FRAMERATE_DENOMINATOR 1001
#define PAL_HEIGHT 576
#define PAL_BUFFER 144000 #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_QUALITY DV_QUALITY_BEST
#define DV_DEFAULT_DECODE_NTH 1 #define DV_DEFAULT_DECODE_NTH 1
@ -217,7 +234,6 @@ gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class)
dvdec->framerate_numerator = 0; dvdec->framerate_numerator = 0;
dvdec->framerate_denominator = 0; dvdec->framerate_denominator = 0;
dvdec->height = 0;
dvdec->wide = FALSE; dvdec->wide = FALSE;
dvdec->drop_factor = 1; dvdec->drop_factor = 1;
@ -242,8 +258,6 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
{ {
GstDVDec *dvdec; GstDVDec *dvdec;
GstStructure *s; GstStructure *s;
GstCaps *othercaps;
gboolean gotpar = FALSE;
const GValue *par = NULL, *rate = NULL; const GValue *par = NULL, *rate = NULL;
dvdec = GST_DVDEC (gst_pad_get_parent (pad)); dvdec = GST_DVDEC (gst_pad_get_parent (pad));
@ -251,18 +265,67 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
/* first parse the caps */ /* first parse the caps */
s = gst_caps_get_structure (caps, 0); s = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (s, "height", &dvdec->height)) /* we allow framerate and PAR to be overwritten. framerate is mandatory. */
goto error;
if ((par = gst_structure_get_value (s, "pixel-aspect-ratio")))
gotpar = TRUE;
if (!(rate = gst_structure_get_value (s, "framerate"))) 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_numerator = gst_value_get_fraction_numerator (rate);
dvdec->framerate_denominator = gst_value_get_fraction_denominator (rate); dvdec->framerate_denominator = gst_value_get_fraction_denominator (rate);
dvdec->sink_negotiated = TRUE;
dvdec->src_negotiated = FALSE;
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 */ /* ignoring rgb, bgr0 for now */
dvdec->bpp = 2; dvdec->bpp = 2;
othercaps = gst_caps_new_simple ("video/x-raw-yuv", 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, "width", G_TYPE_INT, 720,
"height", G_TYPE_INT, dvdec->height, "height", G_TYPE_INT, dvdec->height,
"framerate", GST_TYPE_FRACTION, dvdec->framerate_numerator, "framerate", GST_TYPE_FRACTION, dvdec->framerate_numerator,
dvdec->framerate_denominator, NULL); dvdec->framerate_denominator,
if (gotpar) "pixel-aspect-ratio", GST_TYPE_FRACTION, dvdec->par_x,
gst_structure_set_value (gst_caps_get_structure (othercaps, 0), dvdec->par_y, NULL);
"pixel-aspect-ratio", par);
gst_pad_set_caps (dvdec->srcpad, othercaps); gst_pad_set_caps (dvdec->srcpad, othercaps);
gst_caps_unref (othercaps); gst_caps_unref (othercaps);
gst_object_unref (dvdec); dvdec->src_negotiated = TRUE;
return TRUE; return TRUE;
error:
{
gst_object_unref (dvdec);
return FALSE;
}
} }
static gboolean static gboolean
@ -342,6 +396,7 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
guint length; guint length;
gint64 cstart, cstop; gint64 cstart, cstop;
gboolean PAL, wide;
dvdec = GST_DVDEC (gst_pad_get_parent (pad)); dvdec = GST_DVDEC (gst_pad_get_parent (pad));
inframe = GST_BUFFER_DATA (buf); 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)) if (G_UNLIKELY (dv_parse_header (dvdec->decoder, inframe) < 0))
goto parse_header_error; 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 /* check the buffer is of right size after we know if we are
* dealing with PAL or NTSC */ * 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)) if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < length))
goto wrong_size; goto wrong_size;
@ -373,6 +432,22 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
if (dvdec->video_offset % dvdec->drop_factor != 0) if (dvdec->video_offset % dvdec->drop_factor != 0)
goto skip; 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 = ret =
gst_pad_alloc_buffer_and_set_caps (dvdec->srcpad, 0, gst_pad_alloc_buffer_and_set_caps (dvdec->srcpad, 0,
(720 * dvdec->height) * dvdec->bpp, (720 * dvdec->height) * dvdec->bpp,
@ -429,6 +504,12 @@ parse_header_error:
ret = GST_FLOW_ERROR; ret = GST_FLOW_ERROR;
goto done; goto done;
} }
not_negotiated:
{
GST_DEBUG_OBJECT (dvdec, "could not negotiate output");
ret = GST_FLOW_NOT_NEGOTIATED;
goto done;
}
no_buffer: no_buffer:
{ {
GST_DEBUG_OBJECT (dvdec, "could not allocate 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]; dvdec->decoder->quality = qualities[dvdec->quality];
dv_set_error_log (dvdec->decoder, NULL); dv_set_error_log (dvdec->decoder, NULL);
gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED); 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 * Enable this function call when libdv2 0.100 or higher is more
* common * common

View file

@ -56,16 +56,23 @@ struct _GstDVDec {
gboolean clamp_chroma; gboolean clamp_chroma;
gint quality; gint quality;
gint frame_len;
gboolean PAL; gboolean PAL;
gboolean wide;
gint frame_len;
/* input caps */
gboolean sink_negotiated;
gint framerate_numerator; gint framerate_numerator;
gint framerate_denominator; gint framerate_denominator;
gint height; gint height;
gboolean wide; gint par_x;
gint par_y;
gboolean need_par;
/* negotiated output */ /* negotiated output */
dv_color_space_t space; dv_color_space_t space;
gint bpp; gint bpp;
gboolean src_negotiated;
gint video_offset; gint video_offset;
gint drop_factor; gint drop_factor;