From c2319d8fa1d1e0c16094bd1ee402e0639b3f2399 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 21 Jun 2002 18:27:46 +0000 Subject: [PATCH] Added YV12 output format Original commit message from CVS: Added YV12 output format --- ext/mpeg2dec/gstmpeg2deccvs.c | 80 +++++++++++++++++++++++++++++------ ext/mpeg2dec/gstmpeg2deccvs.h | 40 +++++++++++------- 2 files changed, 92 insertions(+), 28 deletions(-) diff --git a/ext/mpeg2dec/gstmpeg2deccvs.c b/ext/mpeg2dec/gstmpeg2deccvs.c index 47947d293e..82be51bd12 100644 --- a/ext/mpeg2dec/gstmpeg2deccvs.c +++ b/ext/mpeg2dec/gstmpeg2deccvs.c @@ -23,7 +23,7 @@ #include #include -#include "gstmpeg2dec.h" +#include "gstmpeg2deccvs.h" /* elementfactory information */ static GstElementDetails gst_mpeg2dec_details = { @@ -51,6 +51,13 @@ GST_PAD_TEMPLATE_FACTORY (src_template_factory, "src", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "mpeg2dec_src", + "video/raw", + "format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','V','1','2')), + "width", GST_PROPS_INT_RANGE (16, 4096), + "height", GST_PROPS_INT_RANGE (16, 4096) + ), GST_CAPS_NEW ( "mpeg2dec_src", "video/raw", @@ -196,8 +203,14 @@ gst_mpeg2dec_alloc_buffer (GstMpeg2dec *mpeg2dec, mpeg2_info_t *info) out = GST_BUFFER_DATA (outbuf); buf[0] = out; - buf[1] = buf[0] + size; - buf[2] = buf[1] + size/4; + if (mpeg2dec->format == MPEG2DEC_FORMAT_I420) { + buf[1] = buf[0] + size; + buf[2] = buf[1] + size/4; + } + else { + buf[2] = buf[0] + size; + buf[1] = buf[2] + size/4; + } gst_buffer_ref (outbuf); mpeg2_set_buf (mpeg2dec->decoder, buf, outbuf); @@ -210,6 +223,53 @@ gst_mpeg2dec_alloc_buffer (GstMpeg2dec *mpeg2dec, mpeg2_info_t *info) return TRUE; } +static gboolean +gst_mpeg2dec_negotiate_format (GstMpeg2dec *mpeg2dec) +{ + GstCaps *allowed; + GstCaps *trylist; + + /* we what we are allowed to do */ + allowed = gst_pad_get_allowed_caps (mpeg2dec->srcpad); + + /* try to fix our height */ + trylist = gst_caps_intersect (allowed, + GST_CAPS_NEW ( + "mpeg2dec_negotiate", + "video/raw", + "width", GST_PROPS_INT (mpeg2dec->width), + "height", GST_PROPS_INT (mpeg2dec->height) + )); + /* prepare for looping */ + trylist = gst_caps_normalize (trylist); + + while (trylist) { + GstCaps *to_try = gst_caps_copy_1 (trylist); + + /* try each format */ + if (gst_pad_try_set_caps (mpeg2dec->srcpad, to_try)) { + guint32 fourcc; + + /* it worked, try to find what it was again */ + gst_caps_get_fourcc_int (to_try, "format", &fourcc); + + if (fourcc == GST_STR_FOURCC ("I420")) { + mpeg2dec->format = MPEG2DEC_FORMAT_I420; + } + else { + mpeg2dec->format = MPEG2DEC_FORMAT_YV12; + } + break; + } + trylist = trylist->next; + } + /* oops list exhausted an nothing was found... */ + if (!trylist) { + return FALSE; + } + return TRUE; +} + static void gst_mpeg2dec_chain (GstPad *pad, GstBuffer *buf) { @@ -270,14 +330,10 @@ gst_mpeg2dec_chain (GstPad *pad, GstBuffer *buf) mpeg2dec->height = info->sequence->height; mpeg2dec->total_frames = 0; - gst_pad_try_set_caps (mpeg2dec->srcpad, - GST_CAPS_NEW ( - "mpeg2dec_caps", - "video/raw", - "format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')), - "width", GST_PROPS_INT (mpeg2dec->width), - "height", GST_PROPS_INT (mpeg2dec->height) - )); + if (!gst_mpeg2dec_negotiate_format (mpeg2dec)) { + gst_element_error (GST_ELEMENT (mpeg2dec), "could not negotiate format"); + return; + } gst_mpeg2dec_alloc_buffer (mpeg2dec, info); break; @@ -605,7 +661,7 @@ gst_mpeg2dec_change_state (GstElement *element) mpeg2dec->closed = FALSE; /* reset the initial video state */ - mpeg2dec->format = -1; + mpeg2dec->format = MPEG2DEC_FORMAT_NONE; mpeg2dec->width = -1; mpeg2dec->height = -1; mpeg2dec->first = TRUE; diff --git a/ext/mpeg2dec/gstmpeg2deccvs.h b/ext/mpeg2dec/gstmpeg2deccvs.h index 609cc13394..d93f9a7e66 100644 --- a/ext/mpeg2dec/gstmpeg2deccvs.h +++ b/ext/mpeg2dec/gstmpeg2deccvs.h @@ -46,31 +46,39 @@ extern "C" { typedef struct _GstMpeg2dec GstMpeg2dec; typedef struct _GstMpeg2decClass GstMpeg2decClass; +typedef enum +{ + MPEG2DEC_FORMAT_NONE, + MPEG2DEC_FORMAT_I420, + MPEG2DEC_FORMAT_YV12, +} Mpeg2decFormat; + struct _GstMpeg2dec { - GstElement element; + GstElement element; /* pads */ - GstPad *sinkpad,*srcpad; + GstPad *sinkpad, + *srcpad; GstBufferPool *peerpool; - mpeg2dec_t *decoder; - guint32 accel; - gboolean closed; + mpeg2dec_t *decoder; + guint32 accel; + gboolean closed; /* the timestamp of the next frame */ - gboolean first; - gboolean discont_pending; - gint64 next_time; - gint64 last_PTS; - gint frames_per_PTS; - gint adjust; + gboolean first; + gboolean discont_pending; + gint64 next_time; + gint64 last_PTS; + gint frames_per_PTS; + gint adjust; /* video state */ - gint format; - gint width; - gint height; - gint frame_rate_code; - gint64 total_frames; + Mpeg2decFormat format; + gint width; + gint height; + gint frame_rate_code; + gint64 total_frames; }; struct _GstMpeg2decClass {