Index: plugins/jpeg/gstjpeg.c =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/plugins/jpeg/gstjpeg.c,v retrieving revision 1.13 diff -u -r1.13 gstjpeg.c --- plugins/jpeg/gstjpeg.c 2001/04/22 12:30:15 1.13 +++ plugins/jpeg/gstjpeg.c 2001/05/01 09:16:34 @@ -53,6 +53,8 @@ ), "width", GST_PROPS_INT_RANGE (16, 4096), "height", GST_PROPS_INT_RANGE (16, 4096), + "endianness", GST_PROPS_INT(G_LITTLE_ENDIAN), + "depth", GST_PROPS_INT(24), NULL)); } Index: plugins/jpeg/gstjpegenc.c =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/plugins/jpeg/gstjpegenc.c,v retrieving revision 1.11 diff -u -r1.11 gstjpegenc.c --- plugins/jpeg/gstjpegenc.c 2001/04/24 19:04:50 1.11 +++ plugins/jpeg/gstjpegenc.c 2001/05/01 09:16:34 @@ -22,6 +22,8 @@ #include "gstjpegenc.h" +static void gst_jpegenc_pushbuf(GstJpegEnc *); + /* elementfactory information */ GstElementDetails gst_jpegenc_details = { "jpeg image encoder", @@ -43,18 +45,19 @@ ARG_0, /* FILL ME */ }; + +extern GstPadTemplate *jpegenc_sink_template; static void gst_jpegenc_class_init (GstJpegEnc *klass); static void gst_jpegenc_init (GstJpegEnc *jpegenc); static void gst_jpegenc_chain (GstPad *pad,GstBuffer *buf); -static GstBuffer *gst_jpegenc_get (GstPad *pad); - -static void gst_jpegenc_resync (GstJpegEnc *jpegenc); static GstElementClass *parent_class = NULL; static guint gst_jpegenc_signals[LAST_SIGNAL] = { 0 }; +static int debugnum = 1; + GtkType gst_jpegenc_get_type (void) { @@ -94,148 +97,136 @@ gtk_object_class_add_signals (gtkobject_class, gst_jpegenc_signals, LAST_SIGNAL); + } static void gst_jpegenc_init_destination (j_compress_ptr cinfo) { + GstJpegEnc *g = cinfo->client_data; + g->buf = NULL; + gst_jpegenc_pushbuf(g); GST_DEBUG (0,"gst_jpegenc_chain: init_destination\n"); + } static gboolean gst_jpegenc_flush_destination (j_compress_ptr cinfo) { + GstJpegEnc *g = cinfo->client_data; + gst_jpegenc_pushbuf(g); GST_DEBUG (0,"gst_jpegenc_chain: flush_destination: buffer too small !!!\n"); + return TRUE; } static void gst_jpegenc_term_destination (j_compress_ptr cinfo) { + GstJpegEnc *g = cinfo->client_data; + GstJpegEncChunk *ptr = g->buf; + int lastchunk, size, copied; + guchar *outbuf; + + size = lastchunk = GSTJPEGENCCHUNKSIZE - cinfo->dest->free_in_buffer; + copied = 0; GST_DEBUG (0,"gst_jpegenc_chain: term_source\n"); + while(ptr->prev) { + size += GSTJPEGENCCHUNKSIZE; + ptr = ptr->prev; + } + GST_BUFFER_SIZE(g->buffer) = size; + GST_BUFFER_DATA(g->buffer) = outbuf = g_malloc(size); + while(ptr->next) { + memcpy(outbuf + copied, ptr->data, GSTJPEGENCCHUNKSIZE); + copied += GSTJPEGENCCHUNKSIZE; + ptr = ptr->next; + g_free(ptr->prev); + } + memcpy(outbuf + copied, ptr->data, lastchunk); + g_free(ptr); + ptr = NULL; +} + +static GstPadNegotiateReturn +gst_jpegenc_negotiate(GstPad *pad, GstCaps **caps, gpointer *data) { + + GST_DEBUG(0, "gst_jpegenc_negotiate pad %p *caps %p *data %p\n", pad, *caps, *data); + if(*caps == NULL) { + GstCaps *newcaps = GST_PADTEMPLATE_CAPS(jpegenc_sink_template); + + *data = (void *)-1; + gst_caps_set(newcaps, "width", GST_PROPS_INT(320)); + gst_caps_set(newcaps, "height", GST_PROPS_INT(240)); + gst_caps_set(newcaps, "format", GST_PROPS_FOURCC(GST_MAKE_FOURCC('R', 'G', 'B', ' '))); + gst_caps_set(newcaps, "depth", GST_PROPS_INT(24)); + gst_caps_set(newcaps, "endianness", GST_PROPS_INT(G_LITTLE_ENDIAN)); + *caps = newcaps; + return GST_PAD_NEGOTIATE_TRY; + } else { + gulong format; + gint width, height; + + format = gst_caps_get_fourcc_int (*caps, "format"); + width = gst_caps_get_int (*caps, "width"); + height = gst_caps_get_int (*caps, "height"); + + GST_DEBUG(0, "gst_jpegenc_negotiate: got format %ld width %d height %d. What the hell.\n", + format, width, height); + return GST_PAD_NEGOTIATE_AGREE; + } + GST_DEBUG(0, "gst_jpegenc_negotiate fallthru?\n"); + return GST_PAD_NEGOTIATE_FAIL; +} + +static void gst_jpegenc_pushbuf(GstJpegEnc *jpegenc) { + GstJpegEncChunk *b = g_malloc(sizeof(*b)); + memset(b, 0, sizeof(*b)); + GST_DEBUG(0, "Initializing %p to prev %p\n", b, jpegenc->buf); + b->prev = jpegenc->buf; + b->done = 23; + if(jpegenc->buf) + jpegenc->buf->next = b; + jpegenc->buf = b; + jpegenc->jdest.next_output_byte = b->data; + jpegenc->jdest.free_in_buffer = GSTJPEGENCCHUNKSIZE; } static void gst_jpegenc_init (GstJpegEnc *jpegenc) { /* create the sink and src pads */ - jpegenc->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + jpegenc->sinkpad = gst_pad_new_from_template + (jpegenc_sink_template, "sink"); + gst_pad_set_negotiate_function(jpegenc->sinkpad, gst_jpegenc_negotiate); gst_element_add_pad(GST_ELEMENT(jpegenc),jpegenc->sinkpad); gst_pad_set_chain_function(jpegenc->sinkpad,gst_jpegenc_chain); - gst_pad_set_get_function(jpegenc->sinkpad,gst_jpegenc_get); jpegenc->srcpad = gst_pad_new("src",GST_PAD_SRC); gst_element_add_pad(GST_ELEMENT(jpegenc),jpegenc->srcpad); // reset the initial video state - jpegenc->width = -1; - jpegenc->height = -1; + jpegenc->width = 320; + jpegenc->height = 240; + + jpegenc->buf = NULL; /* setup jpeglib */ memset(&jpegenc->cinfo, 0, sizeof(jpegenc->cinfo)); memset(&jpegenc->jerr, 0, sizeof(jpegenc->jerr)); + jpegenc->cinfo.client_data = jpegenc; jpegenc->cinfo.err = jpeg_std_error(&jpegenc->jerr); jpeg_create_compress(&jpegenc->cinfo); - GST_DEBUG (0,"gst_jpegenc_init: setting line buffers\n"); - jpegenc->line[0] = NULL; - jpegenc->line[1] = NULL; - jpegenc->line[2] = NULL; - gst_jpegenc_resync(jpegenc); - + jpegenc->cinfo.image_width = 320; + jpegenc->cinfo.image_height = 240; + jpegenc->cinfo.input_components = 3; + jpegenc->cinfo.in_color_space = JCS_RGB; + jpeg_set_defaults(&jpegenc->cinfo); + jpegenc->jdest.init_destination = gst_jpegenc_init_destination; jpegenc->jdest.empty_output_buffer = gst_jpegenc_flush_destination; jpegenc->jdest.term_destination = gst_jpegenc_term_destination; jpegenc->cinfo.dest = &jpegenc->jdest; - -} - -static void -gst_jpegenc_resync (GstJpegEnc *jpegenc) -{ - guint size = 0; - gint width, height; - - GST_DEBUG (0,"gst_jpegenc_resync: resync\n"); - - jpegenc->cinfo.image_width = width = jpegenc->width; - jpegenc->cinfo.image_height = height = jpegenc->height; - jpegenc->cinfo.input_components = 3; - - GST_DEBUG (0,"gst_jpegenc_resync: wdith %d, height %d\n", width, height); - - jpeg_set_defaults(&jpegenc->cinfo); - jpegenc->cinfo.dct_method = JDCT_FASTEST; - //jpegenc->cinfo.dct_method = JDCT_DEFAULT; - //jpegenc->cinfo.smoothing_factor = 10; - jpeg_set_quality(&jpegenc->cinfo, 85, TRUE); - - /* - switch (jpegenc->format) { - case GST_COLORSPACE_RGB24: - size = 3; - GST_DEBUG (0,"gst_jpegenc_resync: setting format to RGB24\n"); - jpegenc->cinfo.in_color_space = JCS_RGB; - jpegenc->cinfo.raw_data_in = FALSE; - break; - case GST_COLORSPACE_YUV420P: - size = 2; - jpegenc->cinfo.raw_data_in = TRUE; - jpegenc->cinfo.in_color_space = JCS_YCbCr; - GST_DEBUG (0,"gst_jpegenc_resync: setting format to YUV420P\n"); - jpegenc->cinfo.comp_info[0].h_samp_factor = 2; - jpegenc->cinfo.comp_info[0].v_samp_factor = 2; - jpegenc->cinfo.comp_info[1].h_samp_factor = 1; - jpegenc->cinfo.comp_info[1].v_samp_factor = 1; - jpegenc->cinfo.comp_info[2].h_samp_factor = 1; - jpegenc->cinfo.comp_info[2].v_samp_factor = 1; - - if (height != -1) { - jpegenc->line[0] = g_realloc(jpegenc->line[0], height*sizeof(char*)); - jpegenc->line[1] = g_realloc(jpegenc->line[1], height*sizeof(char*)/2); - jpegenc->line[2] = g_realloc(jpegenc->line[2], height*sizeof(char*)/2); - } - - GST_DEBUG (0,"gst_jpegenc_resync: setting format done\n"); - break; - default: - printf("gst_jpegenc_resync: unsupported colorspace, using RGB\n"); - size = 3; - jpegenc->cinfo.in_color_space = JCS_RGB; - break; - } -*/ - jpegenc->bufsize = jpegenc->width*jpegenc->height*size; - jpegenc->row_stride = width * size; - - jpeg_suppress_tables(&jpegenc->cinfo, TRUE); - - jpegenc->buffer = NULL; - GST_DEBUG (0,"gst_jpegenc_resync: resync done\n"); -} - -static GstBuffer* -gst_jpegenc_get (GstPad *pad) -{ - GstJpegEnc *jpegenc; - GstBuffer *newbuf; - - GST_DEBUG (0,"gst_jpegenc_chain: pull buffer\n"); - - g_return_val_if_fail (pad != NULL, NULL); - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - jpegenc = GST_JPEGENC (GST_OBJECT_PARENT (pad)); - - if (jpegenc->buffer == NULL || GST_BUFFER_REFCOUNT(jpegenc->buffer) != 1) { - if (jpegenc->buffer) gst_buffer_unref(jpegenc->buffer); - GST_DEBUG (0,"gst_jpegenc_chain: new buffer\n"); - newbuf = jpegenc->buffer = gst_buffer_new(); - GST_BUFFER_DATA(newbuf) = g_malloc(jpegenc->bufsize); - GST_BUFFER_SIZE(newbuf) = jpegenc->bufsize; - } - gst_buffer_ref(jpegenc->buffer); - - return jpegenc->buffer; } static void @@ -250,6 +241,9 @@ guchar *base[3]; gint i,j, k; + // straight out of the manual + JSAMPROW row[1]; + g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); g_return_if_fail (buf != NULL); @@ -260,64 +254,23 @@ data = GST_BUFFER_DATA(buf); size = GST_BUFFER_SIZE(buf); - + GST_DEBUG (0,"gst_jpegenc_chain: got buffer of %ld bytes in '%s'\n",size, GST_OBJECT_NAME (jpegenc)); - - /* first deal with video metadata */ - /* - meta = gst_buffer_get_first_meta(buf); - if (meta) { - if (jpegenc->format != ((MetaVideoRaw *)meta)->format || - jpegenc->width != ((MetaVideoRaw *)meta)->width || - jpegenc->height != ((MetaVideoRaw *)meta)->height) { - - jpegenc->format = ((MetaVideoRaw *)meta)->format; - jpegenc->width = ((MetaVideoRaw *)meta)->width; - jpegenc->height = ((MetaVideoRaw *)meta)->height; - if (jpegenc->buffer) gst_buffer_unref(jpegenc->buffer); - - gst_jpegenc_resync(jpegenc); - } - } - */ + jpegenc->buffer = gst_buffer_new(); + GST_BUFFER_TIMESTAMP(jpegenc->buffer) = GST_BUFFER_TIMESTAMP(buf); - outbuf = gst_buffer_new(); - outsize = GST_BUFFER_SIZE(outbuf) = jpegenc->bufsize; - outdata = GST_BUFFER_DATA(outbuf) = g_malloc(outsize); - GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf); - - width = jpegenc->width; - height = jpegenc->height; - - base[0] = data; - base[1] = base[0]+width*height; - base[2] = base[1]+width*height/4; - - jpegenc->jdest.next_output_byte = outdata; - jpegenc->jdest.free_in_buffer = outsize; - jpeg_start_compress(&jpegenc->cinfo, TRUE); - width2 = width>>1; - GST_DEBUG (0,"gst_jpegdec_chain: compressing\n"); - - for (i = 0; i < height; i += 2*DCTSIZE) { - for (j=0, k=0; j<2*DCTSIZE;j+=2, k++) { - jpegenc->line[0][j] = base[0]; base[0] += width; - jpegenc->line[0][j+1] = base[0]; base[0] += width; - jpegenc->line[1][k] = base[1]; base[1] += width2; - jpegenc->line[2][k] = base[2]; base[2] += width2; - } - jpeg_write_raw_data(&jpegenc->cinfo, jpegenc->line, 2*DCTSIZE); - } - jpeg_finish_compress(&jpegenc->cinfo); - GST_DEBUG (0,"gst_jpegdec_chain: compressing done\n"); + while(jpegenc->cinfo.next_scanline < jpegenc->height) { + row[0] = data + jpegenc->cinfo.next_scanline * jpegenc->width * 3; + jpeg_write_scanlines(&jpegenc->cinfo, row, 1); + } - GST_BUFFER_SIZE(outbuf) = (((outsize - jpegenc->jdest.free_in_buffer)+3)&~3); + jpeg_finish_compress(&jpegenc->cinfo); - gst_pad_push(jpegenc->srcpad, outbuf); + gst_pad_push(jpegenc->srcpad, jpegenc->buffer); gtk_signal_emit(GTK_OBJECT(jpegenc),gst_jpegenc_signals[FRAME_ENCODED]); Index: plugins/jpeg/gstjpegenc.h =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/plugins/jpeg/gstjpegenc.h,v retrieving revision 1.6 diff -u -r1.6 gstjpegenc.h --- plugins/jpeg/gstjpegenc.h 2001/04/02 14:21:07 1.6 +++ plugins/jpeg/gstjpegenc.h 2001/05/01 09:16:35 @@ -45,7 +45,16 @@ typedef struct _GstJpegEnc GstJpegEnc; typedef struct _GstJpegEncClass GstJpegEncClass; +typedef struct _GstJpegEncChunk GstJpegEncChunk; +#define GSTJPEGENCCHUNKSIZE 8192 +struct _GstJpegEncChunk { + guchar data[GSTJPEGENCCHUNKSIZE]; + int done; + struct _GstJpegEncChunk *prev; + struct _GstJpegEncChunk *next; +}; + struct _GstJpegEnc { GstElement element; @@ -67,6 +76,7 @@ struct jpeg_error_mgr jerr; struct jpeg_destination_mgr jdest; + GstJpegEncChunk *buf; }; struct _GstJpegEncClass {