diff options
| -rw-r--r-- | ChangeLog | 7 | ||||
| -rw-r--r-- | ext/jpeg/gstjpegdec.c | 150 | ||||
| -rw-r--r-- | ext/jpeg/gstjpegdec.h | 5 | 
3 files changed, 103 insertions, 59 deletions
@@ -1,3 +1,10 @@ +2005-10-28  Wim Taymans  <wim@fluendo.com> + +	* ext/jpeg/gstjpegdec.c: (gst_jpeg_dec_init), (gst_jpeg_dec_chain), +	(gst_jpeg_dec_change_state): +	* ext/jpeg/gstjpegdec.h: +	Cleanups. Don't create caps for every chain. +  2005-10-27  Edgard Lima  Edgard Lima  <edgard.lima@indt.org.br>  	* gst/law/alaw-encode.c: (gst_alawenc_init), diff --git a/ext/jpeg/gstjpegdec.c b/ext/jpeg/gstjpegdec.c index 382e457c..e1a456f7 100644 --- a/ext/jpeg/gstjpegdec.c +++ b/ext/jpeg/gstjpegdec.c @@ -54,7 +54,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",      GST_STATIC_CAPS ("image/jpeg, "          "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)          " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", " -        G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (double) [ 1, MAX ]") +        G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (double) [ 0, MAX ]")      );  GST_DEBUG_CATEGORY (jpeg_dec_debug); @@ -243,10 +243,6 @@ gst_jpeg_dec_init (GstJpegDec * dec)        (&gst_jpeg_dec_src_pad_template), "src");    gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); -  dec->packetized = FALSE; -  dec->next_ts = 0; -  dec->fps = 1.0; -    /* setup jpeglib */    memset (&dec->cinfo, 0, sizeof (dec->cinfo));    memset (&dec->jerr, 0, sizeof (dec->jerr)); @@ -696,7 +692,6 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)    GstFlowReturn ret;    GstJpegDec *dec;    GstBuffer *outbuf; -  GstCaps *caps;    gulong size;    guchar *data, *outdata;    guchar *base[3], *last[3]; @@ -704,11 +699,15 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)    gint width, height;    gint r_h, r_v;    gint i; +  guint code; +  GstClockTime timestamp, duration;    dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad)); -  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) { -    dec->next_ts = GST_BUFFER_TIMESTAMP (buf); +  timestamp = GST_BUFFER_TIMESTAMP (buf); + +  if (GST_CLOCK_TIME_IS_VALID (timestamp)) { +    dec->next_ts = timestamp;    }    if (dec->tempbuf) { @@ -719,7 +718,7 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)    buf = NULL;    if (!gst_jpeg_dec_ensure_header (dec)) -    return GST_FLOW_OK;         /* need more data */ +    goto need_more_data;    /* If we know that each input buffer contains data     * for a whole jpeg image (e.g. MJPEG streams), just  @@ -727,25 +726,13 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)     * the jpeg data */    if (dec->packetized) {      img_len = GST_BUFFER_SIZE (dec->tempbuf); -#if 0 -    /* This does not work, e.g. avidemux adds an  -     * extra 0 at the end of the buffer */ -    if (!gst_jpeg_dec_have_end_marker (dec)) { -      gst_util_dump_mem (GST_BUFFER_DATA (dec->tempbuf), -          GST_BUFFER_SIZE (dec->tempbuf)); -      GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("JPEG input without EOI marker"), -          (NULL)); -      ret = GST_FLOW_ERROR; -      goto done; -    } -#endif    } else {      /* Parse jpeg image to handle jpeg input that       * is not aligned to buffer boundaries */      img_len = gst_jpeg_dec_parse_image_data (dec);      if (img_len == 0) -      return GST_FLOW_OK;       /* need more data */ +      goto need_more_data;    }    data = (guchar *) GST_BUFFER_DATA (dec->tempbuf); @@ -756,17 +743,13 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)    dec->jsrc.pub.bytes_in_buffer = size;    if (setjmp (dec->jerr.setjmp_buffer)) { -    guint code = dec->jerr.pub.msg_code; +    code = dec->jerr.pub.msg_code;      if (code == JERR_INPUT_EOF) {        GST_DEBUG ("jpeg input EOF error, we probably need more data"); -      return GST_FLOW_OK; +      goto need_more_data;      } -    GST_ELEMENT_ERROR (dec, STREAM, DECODE, -        (_("Failed to decode JPEG image")), -        ("Error #%u: %s", code, dec->jerr.pub.jpeg_message_table[code])); -    ret = GST_FLOW_ERROR; -    goto done; +    goto decode_error;    }    GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1], @@ -796,41 +779,52 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)    height = dec->cinfo.output_height;    if (width < MIN_WIDTH || width > MAX_WIDTH || -      height < MIN_HEIGHT || height > MAX_HEIGHT) { -    GST_ELEMENT_ERROR (dec, STREAM, DECODE, -        ("Picture is too small or too big (%ux%u)", width, height), -        ("Picture is too small or too big (%ux%u)", width, height)); -    ret = GST_FLOW_ERROR; -    goto done; -  } +      height < MIN_HEIGHT || height > MAX_HEIGHT) +    goto wrong_size; + +  if (width != dec->caps_width || height != dec->caps_height || +      dec->fps != dec->caps_fps) { +    GstCaps *caps; -  caps = gst_caps_new_simple ("video/x-raw-yuv", -      "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), -      "width", G_TYPE_INT, width, -      "height", G_TYPE_INT, height, -      "framerate", G_TYPE_DOUBLE, (double) dec->fps, NULL); +    /* framerate == 0.0 is a still frame */ +    caps = gst_caps_new_simple ("video/x-raw-yuv", +        "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), +        "width", G_TYPE_INT, width, +        "height", G_TYPE_INT, height, +        "framerate", G_TYPE_DOUBLE, (double) dec->fps, NULL); -  GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps); -  GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor); +    GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps); +    GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", +        dec->cinfo.max_v_samp_factor); -  if (gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE, -          I420_SIZE (width, height), caps, &outbuf) != GST_FLOW_OK) { -    GST_DEBUG_OBJECT (dec, "failed to alloc buffer"); +    gst_pad_set_caps (dec->srcpad, caps);      gst_caps_unref (caps); -    return GST_FLOW_ERROR; + +    dec->caps_width = width; +    dec->caps_height = height; +    dec->caps_fps = dec->fps;    } -  gst_caps_unref (caps); -  caps = NULL; +  ret = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE, +      I420_SIZE (width, height), GST_PAD_CAPS (dec->srcpad), &outbuf); +  if (ret != GST_FLOW_OK) +    goto alloc_failed;    outdata = GST_BUFFER_DATA (outbuf);    GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts; -  GST_BUFFER_DURATION (outbuf) = GST_SECOND / dec->fps; + +  if (dec->packetized) { +    duration = GST_SECOND / dec->fps; +    dec->next_ts += duration; +  } else { +    duration = GST_CLOCK_TIME_NONE; +    dec->next_ts = GST_CLOCK_TIME_NONE; +  } +  GST_BUFFER_DURATION (outbuf) = duration; +    GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",        width, height, GST_BUFFER_SIZE (outbuf), I420_SIZE (width, height)); -  dec->next_ts += GST_BUFFER_DURATION (outbuf); -    /* mind the swap, jpeglib outputs blue chroma first */    base[0] = outdata + I420_Y_OFFSET (width, height);    base[1] = outdata + I420_U_OFFSET (width, height); @@ -864,9 +858,7 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)    jpeg_finish_decompress (&dec->cinfo);    GST_LOG_OBJECT (dec, "pushing buffer"); -  gst_pad_push (dec->srcpad, outbuf); - -  ret = GST_FLOW_OK; +  ret = gst_pad_push (dec->srcpad, outbuf);  done:    if (GST_BUFFER_SIZE (dec->tempbuf) == img_len) { @@ -879,8 +871,45 @@ done:      gst_buffer_unref (dec->tempbuf);      dec->tempbuf = buf;    } -    return ret; + +  /* special cases */ +need_more_data: +  { +    GST_LOG_OBJECT (dec, "we need more data"); +    return GST_FLOW_OK; +  } +  /* ERRORS */ +wrong_size: +  { +    GST_ELEMENT_ERROR (dec, STREAM, DECODE, +        ("Picture is too small or too big (%ux%u)", width, height), +        ("Picture is too small or too big (%ux%u)", width, height)); +    ret = GST_FLOW_ERROR; +    goto done; +  } +decode_error: +  { +    GST_ELEMENT_ERROR (dec, STREAM, DECODE, +        (_("Failed to decode JPEG image")), +        ("Error #%u: %s", code, dec->jerr.pub.jpeg_message_table[code])); +    ret = GST_FLOW_ERROR; +    goto done; +  } +alloc_failed: +  { +    const gchar *reason; + +    reason = gst_flow_get_name (ret); + +    GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason); +    if (GST_FLOW_IS_FATAL (ret)) { +      GST_ELEMENT_ERROR (dec, STREAM, DECODE, +          ("Buffer allocation failed, reason: %s", reason), +          ("Buffer allocation failed, reason: %s", reason)); +    } +    return ret; +  }  }  static GstStateChangeReturn @@ -892,10 +921,13 @@ gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)    dec = GST_JPEG_DEC (element);    switch (transition) { -    case GST_STATE_CHANGE_NULL_TO_READY: -      dec->next_ts = 0; +    case GST_STATE_CHANGE_READY_TO_PAUSED: +      dec->fps = 0.0; +      dec->caps_fps = 0.0; +      dec->caps_width = -1; +      dec->caps_height = -1;        dec->packetized = FALSE; -      break; +      dec->next_ts = 0;      default:        break;    } diff --git a/ext/jpeg/gstjpegdec.h b/ext/jpeg/gstjpegdec.h index 8bfe8287..4d8f42c0 100644 --- a/ext/jpeg/gstjpegdec.h +++ b/ext/jpeg/gstjpegdec.h @@ -78,6 +78,11 @@ struct _GstJpegDec {    /* video state */    gdouble  fps; +  /* negotiated state */ +  gdouble  caps_fps; +  gint 	   caps_width; +  gint 	   caps_height; +    struct jpeg_decompress_struct cinfo;    struct GstJpegDecErrorMgr     jerr;    struct GstJpegDecSourceMgr    jsrc;  | 
