Exemple #1
0
/*
 * jpeg_data:       Buffer with jpeg data to decode
 * len:             Length of buffer
 * itype:           0: Not interlaced
 *                  1: Interlaced, Top field first
 *                  2: Interlaced, Bottom field first
 * ctype            Chroma format for decompression.
 *                  Currently only Y4M_CHROMA_{420JPEG,422} are available
 * returns:
 *    -1 on fatal error
 *    0 on success
 *    1 if jpeg lib threw a "corrupt jpeg data" warning.
 *        in this case, "a damaged output image is likely."
 *
 */
int decode_jpeg_raw (unsigned char *jpeg_data, int len,
                     int itype, int ctype, unsigned int width,
                     unsigned int height, unsigned char *raw0,
                     unsigned char *raw1, unsigned char *raw2)
{
    int numfields, hsf[3], field, yl, yc;
    int i, xsl, xsc, xs, hdown;
    unsigned int x, y = 0, vsf[3], xd;

    JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3],
                          buf0[4], buf0[5], buf0[6], buf0[7],
                          buf0[8], buf0[9], buf0[10], buf0[11],
                          buf0[12], buf0[13], buf0[14], buf0[15]};

    JSAMPROW row1[8] = { buf1[0], buf1[1], buf1[2], buf1[3],
                         buf1[4], buf1[5], buf1[6], buf1[7]};

    JSAMPROW row2[16] = { buf2[0], buf2[1], buf2[2], buf2[3],
                          buf2[4], buf2[5], buf2[6], buf2[7]};

    JSAMPROW row1_444[16], row2_444[16];

    JSAMPARRAY scanarray[3] = { row0, row1, row2};

    struct jpeg_decompress_struct dinfo;
    struct my_error_mgr jerr;

    /* We set up the normal JPEG error routines, then override error_exit. */
    dinfo.err = jpeg_std_error (&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    /* Also hook the emit_message routine to note corrupt-data warnings. */
    jerr.original_emit_message = jerr.pub.emit_message;
    jerr.pub.emit_message = my_emit_message;
    jerr.warning_seen = 0;

    /* Establish the setjmp return context for my_error_exit to use. */
    if (setjmp (jerr.setjmp_buffer)) {
        /* If we get here, the JPEG code has signaled an error. */
        jpeg_destroy_decompress (&dinfo);
        return -1;
    }

    jpeg_create_decompress (&dinfo);

    jpeg_buffer_src (&dinfo, jpeg_data, len);

    /*
     * Read header, make some checks and try to figure out what the
     * user really wants.
     */
    jpeg_read_header (&dinfo, TRUE);
    dinfo.raw_data_out = TRUE;
#if JPEG_LIB_VERSION >= 70    
    dinfo.do_fancy_upsampling = FALSE;
#endif    
    dinfo.out_color_space = JCS_YCbCr;
    dinfo.dct_method = JDCT_IFAST;
    guarantee_huff_tables(&dinfo);
    jpeg_start_decompress (&dinfo);

    if (dinfo.output_components != 3) {
        MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: Output components of JPEG image"
                   " = %d, must be 3", dinfo.output_components);
        goto ERR_EXIT;
    }

    for (i = 0; i < 3; i++) {
        hsf[i] = dinfo.comp_info[i].h_samp_factor;
        vsf[i] = dinfo.comp_info[i].v_samp_factor;
    }

    if ((hsf[0] != 2 && hsf[0] != 1) || hsf[1] != 1 || hsf[2] != 1 ||
        (vsf[0] != 1 && vsf[0] != 2) || vsf[1] != 1 || vsf[2] != 1) {
        MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: Unsupported sampling factors,"
                   " hsf=(%d, %d, %d) vsf=(%d, %d, %d) !", hsf[0], hsf[1],
                   hsf[2], vsf[0], vsf[1], vsf[2]);
        goto ERR_EXIT;
    }

    if (hsf[0] == 1) {
        if (height % 8 != 0) {
            MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: YUV 4:4:4 sampling, but image"
                       " height %d not dividable by 8 !", height);
            goto ERR_EXIT;
        }

        for (y = 0; y < 16; y++) { // Allocate a special buffer for the extra sampling depth.
            row1_444[y] = (unsigned char *)malloc(dinfo.output_width * sizeof(char));
            row2_444[y] = (unsigned char *)malloc(dinfo.output_width * sizeof(char));
        }
        scanarray[1] = row1_444;
        scanarray[2] = row2_444;
    }

    /* Height match image height or be exact twice the image height. */

    if (dinfo.output_height == height) {
        numfields = 1;
    } else if (2 * dinfo.output_height == height) {
        numfields = 2;
    } else {
        MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: Read JPEG: requested height = %d, "
                   "height of image = %d", height, dinfo.output_height);
        goto ERR_EXIT;
    }

    /* Width is more flexible */

    if (dinfo.output_width > MAX_LUMA_WIDTH) {
        MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: Image width of %d exceeds max",
                   dinfo.output_width);
        goto ERR_EXIT;
    }

    if (width < 2 * dinfo.output_width / 3) {
        /* Downsample 2:1 */
        hdown = 1;
        if (2 * width < dinfo.output_width)
            xsl = (dinfo.output_width - 2 * width) / 2;
        else
            xsl = 0;
    } else if (width == 2 * dinfo.output_width / 3) {
        /* Special case of 3:2 downsampling */
      hdown = 2;
      xsl = 0;
    } else {
        /* No downsampling */
        hdown = 0;
        if (width < dinfo.output_width)
            xsl = (dinfo.output_width - width) / 2;
        else
            xsl = 0;
   }

    /* Make xsl even, calculate xsc */

    xsl = xsl & ~1;
    xsc = xsl / 2;

    yl = yc = 0;

    for (field = 0; field < numfields; field++) {
        if (field > 0) {
            jpeg_read_header (&dinfo, TRUE);
            dinfo.raw_data_out = TRUE;
#if JPEG_LIB_VERSION >= 70            
            dinfo.do_fancy_upsampling = FALSE;
#endif            
            dinfo.out_color_space = JCS_YCbCr;
            dinfo.dct_method = JDCT_IFAST;
            jpeg_start_decompress (&dinfo);
        }

        if (numfields == 2) {
            switch (itype) {
            case Y4M_ILACE_TOP_FIRST:
                yl = yc = field;
                break;
            case Y4M_ILACE_BOTTOM_FIRST:
                yl = yc = (1 - field);
                break;
            default:
                MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: Input is interlaced but"
                           " no interlacing set");
                goto ERR_EXIT;
            }
        } else {
            yl = yc = 0;
        }

        while (dinfo.output_scanline < dinfo.output_height) {
            /* Read raw data */
            jpeg_read_raw_data (&dinfo, scanarray, 8 * vsf[0]);

            for (y = 0; y < 8 * vsf[0]; yl += numfields, y++) {
                xd = yl * width;
                xs = xsl;

                if (hdown == 0) {
                    for (x = 0; x < width; x++)
                        raw0[xd++] = row0[y][xs++];
                } else if (hdown == 1) {
                    for (x = 0; x < width; x++, xs += 2)
                        raw0[xd++] = (row0[y][xs] + row0[y][xs + 1]) >> 1;
                } else {
                    for (x = 0; x < width / 2; x++, xd += 2, xs += 3) {
                        raw0[xd] = (2 * row0[y][xs] + row0[y][xs + 1]) / 3;
                        raw0[xd + 1] = (2 * row0[y][xs + 2] + row0[y][xs + 1]) / 3;
                    }
                }
            }

            /* Horizontal downsampling of chroma */

            for (y = 0; y < 8; y++) {
                xs = xsc;

                if (hsf[0] == 1)
                    for (x = 0; x < width / 2; x++, xs++) {
                        row1[y][xs] = (row1_444[y][2*x] + row1_444[y][2*x + 1]) >> 1;
                        row2[y][xs] = (row2_444[y][2*x] + row2_444[y][2*x + 1]) >> 1;
                    }

                xs = xsc;
                if (hdown == 0) {
                    for (x = 0; x < width / 2; x++, xs++) {
                        chr1[y][x] = row1[y][xs];
                        chr2[y][x] = row2[y][xs];
                    }
                } else if (hdown == 1) {
                    for (x = 0; x < width / 2; x++, xs += 2) {
                        chr1[y][x] = (row1[y][xs] + row1[y][xs + 1]) >> 1;
                        chr2[y][x] = (row2[y][xs] + row2[y][xs + 1]) >> 1;
                    }
                } else {
                    for (x = 0; x < width / 2; x += 2, xs += 3) {
                        chr1[y][x] = (2 * row1[y][xs] + row1[y][xs + 1]) / 3;
                        chr1[y][x + 1] = (2 * row1[y][xs + 2] + row1[y][xs + 1]) / 3;
                        chr2[y][x] = (2 * row2[y][xs] + row2[y][xs + 1]) / 3;
                        chr2[y][x + 1] = (2 * row2[y][xs + 2] + row2[y][xs + 1]) / 3;
                    }
                }
            }

            /* Vertical resampling of chroma */

            switch (ctype) {
            case Y4M_CHROMA_422:
                if (vsf[0] == 1) {
                    /* Just copy */
                    for (y = 0; y < 8 /*&& yc < height */; y++, yc += numfields) {
                        xd = yc * width / 2;

                        for (x = 0; x < width / 2; x++, xd++) {
                            raw1[xd] = chr1[y][x];
                            raw2[xd] = chr2[y][x];
                        }
                    }
                } else {
                    /* upsample */
                    for (y = 0; y < 8 /*&& yc < height */; y++) {
                        xd = yc * width / 2;

                        for (x = 0; x < width / 2; x++, xd++) {
                            raw1[xd] = chr1[y][x];
                            raw2[xd] = chr2[y][x];
                        }

                        yc += numfields;
                        xd = yc * width / 2;

                        for (x = 0; x < width / 2; x++, xd++) {
                            raw1[xd] = chr1[y][x];
                            raw2[xd] = chr2[y][x];
                        }

                        yc += numfields;
                    }
                }
                break;
            default:
            /*
             * Should be case Y4M_CHROMA_420JPEG: but use default: for compatibility. Some
             * pass things like '420' in with the expectation that anything other than
             * Y4M_CHROMA_422 will default to 420JPEG.
             */
                if (vsf[0] == 1) {
                    /* Really downsample */
                    for (y = 0; y < 8 /*&& yc < height/2*/; y += 2, yc += numfields) {
                        xd = yc * width / 2;

                        for (x = 0; x < width / 2; x++, xd++) {
                            assert(xd < (width * height / 4));
                            raw1[xd] = (chr1[y][x] + chr1[y + 1][x]) >> 1;
                            raw2[xd] = (chr2[y][x] + chr2[y + 1][x]) >> 1;
                        }
                    }

                } else {
                    /* Just copy */
                    for (y = 0; y < 8 /* && yc < height / 2 */; y++, yc += numfields) {
                        xd = yc * width / 2;

                        for (x = 0; x < width / 2; x++, xd++) {
                            raw1[xd] = chr1[y][x];
                            raw2[xd] = chr2[y][x];
                        }
                    }
                }
                break;
            }
Exemple #2
0
int read_JPEG_buffer(struct jpeg_decompress_struct *cinfo, //header
                     unsigned char*jpgbuffer, //src buffer, stores mjpeg
                     long buffersize, //src buffer size
                     unsigned char* destbuffer, //destination buffer, rgb
                     long destbuffersize,//buffer size
                     struct img_info* image_info , //image info
                     int format)
{
    int row_stride;		/* physical row width in output buffer */


    if (DEBUG)printf("come in\n");
    /* Step 2: specify data source (eg, a file) */

    if (DEBUG)printf("----------------jpeg_buffer_src--------------\n");
    jpeg_buffer_src(cinfo, jpgbuffer,buffersize);
    if (DEBUG)printf("----------------after jpeg_buffer_src--------------\n");

    /* Step 3: read file parameters with jpeg_read_header() */
    if (DEBUG)printf("read header...\n");
    int headerret= jpeg_read_header(cinfo, TRUE);
    if (DEBUG)printf("jpeg_read_header %d %d\n",headerret,JPEG_HEADER_OK);
    if (DEBUG)printf("read header end...\n");
    /* We can ignore the return value from jpeg_read_header since
     *   (a) suspension is not possible with the stdio data source, and
     *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
     * See libjpeg.doc for more info.
     */

    //debug info: output header information
    /*
    if(DEBUG)printf("JPEG PARAMETERS:\n");
    if(DEBUG)printf("Width Height %d %d\n",cinfo->image_width,
      cinfo->image_height);
    if(DEBUG)printf("COLOR SPACE %d %d\n",cinfo->jpeg_color_space,JCS_YCbCr);

    if(DEBUG)printf("OUT COLOR SPCAE: %d\n",cinfo->out_color_space);

    if(DEBUG)printf("QUANTIZE COLORS: %d\n",cinfo->quantize_colors);
    */
    if (format==1)
        cinfo->out_color_space=JCS_YCbCr;
    if (image_info!=NULL) {
        image_info->width=cinfo->image_width;
        image_info->height=cinfo->image_height;
        if (DEBUG)printf("Width Height %d %d\n",cinfo->image_width,
                             cinfo->image_height);
    }

    if (fatal_error) {
        if (DEBUG)printf("fatal error %d\n",fatal_error);
        return -1;
    }
    //for mjpeg pictures, huffman table must be added.
    //extracted from libquicktime
    if (DEBUG)printf("guarantee_huff_tables\n");
    guarantee_huff_tables(cinfo);


    /* Step 4: set parameters for decompression */

    /* In this example, we don't need to change any of the defaults set by
     * jpeg_read_header(), so we do nothing here.
     */

    /* Step 5: Start decompressor */

    (void) jpeg_start_decompress(cinfo);
    /* We can ignore the return value since suspension is not possible
     * with the stdio data source.
     */

    /* We may need to do some setup of our own at this point before reading
     * the data.  After jpeg_start_decompress() we have the correct scaled
     * output image dimensions available, as well as the output colormap
     * if we asked for color quantization.
     * In this example, we need to make an output work buffer of the right size.
     */
    /* JSAMPLEs per row in output buffer */
    row_stride = cinfo->output_width * cinfo->output_components;

    //debug info: output_components must be 3, yuv or rgb
    //	if(DEBUG)printf("row_stride: %d output component:%d \n",
    //		row_stride,cinfo->output_components);
    /* Make a one-row-high sample array that will go away when done with image */
    //buffer = (*cinfo->mem->alloc_sarray)
    //		((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1);


    //output rgb buffer
    long offset=0;
    //long offset=200;
    //unsigned char* filebuf=malloc(row_stride*cinfo->output_height+offset);
    //sif(DEBUG)printf(filebuf,"%d %d %d\ntype rgb, offset 0, width 1, height 2\n",offset,cinfo->output_width,cinfo->output_height);
    long start=0;
    /* Step 6: while (scan lines remain to be read) */
    /*           jpeg_read_scanlines(...); */

    /* Here we use the library's state variable cinfo.output_scanline as the
     * loop counter, so that we don't have to keep track ourselves.
     */
    int read_line=0;
    while (cinfo->output_scanline < cinfo->output_height) {
        /* jpeg_read_scanlines expects an array of pointers to scanlines.
         * Here the array is only one element long, but you could ask for
         * more than one scanline at a time if that's more convenient.
         */
        read_line=jpeg_read_scanlines(cinfo, buffer,1);// cinfo.image_height);

        //debug info
        //if(DEBUG)printf("output_scan line %d height %d read lines: %d\n",
        //	cinfo->output_scanline,
        //	cinfo->output_height,read_line);

        /* Assume put_scanline_someplace wants a pointer and sample count. */
        //put_scanline_someplace(buffer[0], row_stride);
        memcpy(destbuffer+offset+start,buffer[0],row_stride);
        start+=row_stride;
        if (start>destbuffersize) {
            if (DEBUG)fprintf(stderr,"destination buffer overflow while decompressing jpeg files.\n");
            exit(-1);
        }
    }

    //debug
    //msave("1.tmp",filebuf,start);
    /* Step 7: Finish decompression */

    (void) jpeg_finish_decompress(cinfo);
    /* We can ignore the return value since suspension is not possible
     * with the stdio data source.
     */

    /* And we're done! */
    return 1;
}
Exemple #3
0
static GstFlowReturn
gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstJpegDec *dec = (GstJpegDec *) bdec;
  GstVideoFrame vframe;
  gint width, height;
  gint r_h, r_v;
  guint code, hdr_ok;
  gboolean need_unmap = TRUE;
  GstVideoCodecState *state = NULL;

  dec->current_frame = frame;
  gst_buffer_map (frame->input_buffer, &dec->current_frame_map, GST_MAP_READ);
  gst_jpeg_dec_fill_input_buffer (&dec->cinfo);

  if (setjmp (dec->jerr.setjmp_buffer)) {
    code = dec->jerr.pub.msg_code;

    if (code == JERR_INPUT_EOF) {
      GST_DEBUG ("jpeg input EOF error, we probably need more data");
      goto need_more_data;
    }
    goto decode_error;
  }

  /* read header */
  hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
  if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
    GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
  }

  GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
  GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);

  if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
    goto components_not_supported;

  r_h = dec->cinfo.comp_info[0].h_samp_factor;
  r_v = dec->cinfo.comp_info[0].v_samp_factor;

  GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);

  if (dec->cinfo.num_components > 3)
    goto components_not_supported;

  /* verify color space expectation to avoid going *boom* or bogus output */
  if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
      dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
      dec->cinfo.jpeg_color_space != JCS_RGB)
    goto unsupported_colorspace;

#ifndef GST_DISABLE_GST_DEBUG
  {
    gint i;

    for (i = 0; i < dec->cinfo.num_components; ++i) {
      GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
          i, dec->cinfo.comp_info[i].h_samp_factor,
          dec->cinfo.comp_info[i].v_samp_factor,
          dec->cinfo.comp_info[i].component_id);
    }
  }
#endif

  /* prepare for raw output */
  dec->cinfo.do_fancy_upsampling = FALSE;
  dec->cinfo.do_block_smoothing = FALSE;
  dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
  dec->cinfo.dct_method = dec->idct_method;
  dec->cinfo.raw_data_out = TRUE;

  GST_LOG_OBJECT (dec, "starting decompress");
  guarantee_huff_tables (&dec->cinfo);
  if (!jpeg_start_decompress (&dec->cinfo)) {
    GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
  }

  /* sanity checks to get safe and reasonable output */
  switch (dec->cinfo.jpeg_color_space) {
    case JCS_GRAYSCALE:
      if (dec->cinfo.num_components != 1)
        goto invalid_yuvrgbgrayscale;
      break;
    case JCS_RGB:
      if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
          dec->cinfo.max_h_samp_factor > 1)
        goto invalid_yuvrgbgrayscale;
      break;
    case JCS_YCbCr:
      if (dec->cinfo.num_components != 3 ||
          r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
          r_v < dec->cinfo.comp_info[1].v_samp_factor ||
          r_h < dec->cinfo.comp_info[0].h_samp_factor ||
          r_h < dec->cinfo.comp_info[1].h_samp_factor)
        goto invalid_yuvrgbgrayscale;
      break;
    default:
      g_assert_not_reached ();
      break;
  }

  width = dec->cinfo.output_width;
  height = dec->cinfo.output_height;

  if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
          height < MIN_HEIGHT || height > MAX_HEIGHT))
    goto wrong_size;

  gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);

  state = gst_video_decoder_get_output_state (bdec);
  ret = gst_video_decoder_alloc_output_frame (bdec, frame);
  if (G_UNLIKELY (ret != GST_FLOW_OK))
    goto alloc_failed;

  if (!gst_video_frame_map (&vframe, &state->info, frame->output_buffer,
          GST_MAP_READWRITE))
    goto alloc_failed;

  GST_LOG_OBJECT (dec, "width %d, height %d", width, height);

  if (dec->cinfo.jpeg_color_space == JCS_RGB) {
    gst_jpeg_dec_decode_rgb (dec, &vframe);
  } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
    gst_jpeg_dec_decode_grayscale (dec, &vframe);
  } else {
    GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
        dec->cinfo.rec_outbuf_height);

    /* For some widths jpeglib requires more horizontal padding than I420 
     * provides. In those cases we need to decode into separate buffers and then
     * copy over the data into our final picture buffer, otherwise jpeglib might
     * write over the end of a line into the beginning of the next line,
     * resulting in blocky artifacts on the left side of the picture. */
    if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
            || dec->cinfo.comp_info[0].h_samp_factor != 2
            || dec->cinfo.comp_info[1].h_samp_factor != 1
            || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
      GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
          "indirect decoding using extra buffer copy");
      gst_jpeg_dec_decode_indirect (dec, &vframe, r_v, r_h,
          dec->cinfo.num_components);
    } else {
      ret = gst_jpeg_dec_decode_direct (dec, &vframe);

      if (G_UNLIKELY (ret != GST_FLOW_OK))
        goto decode_direct_failed;
    }
  }

  gst_video_frame_unmap (&vframe);

  GST_LOG_OBJECT (dec, "decompressing finished");
  jpeg_finish_decompress (&dec->cinfo);

  /* reset error count on successful decode */
  dec->error_count = 0;

  gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
  ret = gst_video_decoder_finish_frame (bdec, frame);
  need_unmap = FALSE;

done:

exit:

  if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
    jpeg_abort_decompress (&dec->cinfo);
    ret = gst_jpeg_dec_post_error_or_warning (dec);
  }

  if (need_unmap)
    gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);

  if (state)
    gst_video_codec_state_unref (state);

  return ret;

  /* special cases */
need_more_data:
  {
    GST_LOG_OBJECT (dec, "we need more data");
    ret = GST_FLOW_OK;
    goto exit;
  }
  /* ERRORS */
wrong_size:
  {
    gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
        "Picture is too small or too big (%ux%u)", width, height);
    ret = GST_FLOW_ERROR;
    goto done;
  }
decode_error:
  {
    gchar err_msg[JMSG_LENGTH_MAX];

    dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);

    gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
        "Decode error #%u: %s", code, err_msg);

    gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
    gst_video_decoder_drop_frame (bdec, frame);
    need_unmap = FALSE;

    ret = GST_FLOW_ERROR;
    goto done;
  }
decode_direct_failed:
  {
    /* already posted an error message */
    jpeg_abort_decompress (&dec->cinfo);
    goto done;
  }
alloc_failed:
  {
    const gchar *reason;

    reason = gst_flow_get_name (ret);

    GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
    /* Reset for next time */
    jpeg_abort_decompress (&dec->cinfo);
    if (ret != GST_FLOW_EOS && ret != GST_FLOW_FLUSHING &&
        ret != GST_FLOW_NOT_LINKED) {
      gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
          "Buffer allocation failed, reason: %s", reason);
    }
    goto exit;
  }
components_not_supported:
  {
    gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
        "number of components not supported: %d (max 3)",
        dec->cinfo.num_components);
    ret = GST_FLOW_ERROR;
    goto done;
  }
unsupported_colorspace:
  {
    gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
        "Picture has unknown or unsupported colourspace");
    ret = GST_FLOW_ERROR;
    goto done;
  }
invalid_yuvrgbgrayscale:
  {
    gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
        "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
    ret = GST_FLOW_ERROR;
    goto done;
  }
}
Exemple #4
0
int decode_jpeg_raw(unsigned char *jpeg_data, int len,
		    int itype, int ctype, int width, int height,
		    unsigned char *raw0, unsigned char *raw1,
		    unsigned char *raw2)           
{
    int numfields, hsf[3], vsf[3], field, yl, yc, x, y =
	0, i, xsl, xsc, xs, xd, hdown;

    JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3],
	buf0[4], buf0[5], buf0[6], buf0[7],
	buf0[8], buf0[9], buf0[10], buf0[11],
	buf0[12], buf0[13], buf0[14], buf0[15]
    };
    JSAMPROW row1[8] = { buf1[0], buf1[1], buf1[2], buf1[3],
	buf1[4], buf1[5], buf1[6], buf1[7]
    };
    JSAMPROW row2[16] = { buf2[0], buf2[1], buf2[2], buf2[3],
	buf2[4], buf2[5], buf2[6], buf2[7]
    };
    JSAMPROW row1_444[16], row2_444[16];
    JSAMPARRAY scanarray[3] = { row0, row1, row2 };
    struct jpeg_decompress_struct dinfo;
    struct my_error_mgr jerr;

    /* We set up the normal JPEG error routines, then override error_exit. */
    dinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;

    /* Establish the setjmp return context for my_error_exit to use. */
    if (setjmp(jerr.setjmp_buffer)) {
	/* If we get here, the JPEG code has signaled an error. */
	jpeg_destroy_decompress(&dinfo);
	return -1;
    }

    jpeg_create_decompress(&dinfo);

    jpeg_buffer_src(&dinfo, jpeg_data, len);

    /* Read header, make some checks and try to figure out what the
       user really wants */

    jpeg_read_header(&dinfo, TRUE);
    dinfo.raw_data_out = TRUE;
    dinfo.out_color_space = JCS_YCbCr;
//   dinfo.dct_method = (_dct_method == 0 ? JDCT_DEFAULT : JDCT_FLOAT);
    dinfo.dct_method = JDCT_DEFAULT;
    guarantee_huff_tables(&dinfo);
    jpeg_start_decompress(&dinfo);

    if (dinfo.output_components != 3) {
	veejay_msg(0,"Output components of JPEG image = %d, must be 3",
		    dinfo.output_components);
	goto ERR_EXIT;
    }

    for (i = 0; i < 3; i++) {
	hsf[i] = dinfo.comp_info[i].h_samp_factor;
	vsf[i] = dinfo.comp_info[i].v_samp_factor;
    }

    if ((hsf[0] != 2 && hsf[0] != 1) || hsf[1] != 1 || hsf[2] != 1 ||
	(vsf[0] != 1 && vsf[0] != 2) || vsf[1] != 1 || vsf[2] != 1) {
	veejay_msg
	    (0,"Unsupported sampling factors, hsf=(%d, %d, %d) vsf=(%d, %d, %d) !",
	     hsf[0], hsf[1], hsf[2], vsf[0], vsf[1], vsf[2]);
	goto ERR_EXIT;
    }

    if (hsf[0] == 1) {
	if (height % 8 != 0) {
	    veejay_msg
		(0,"YUV 4:4:4 sampling, but image height %d not dividable by 8 !\n",
		 height);
	    goto ERR_EXIT;
	}

	mjpeg_info
	    ("YUV 4:4:4 sampling encountered ! Allocating special row buffer\n");
	for (y = 0; y < 16; y++)	// allocate a special buffer for the extra sampling depth
	{
	    //mjpeg_info("YUV 4:4:4 %d.\n",y);
	    row1_444[y] =
		(unsigned char *) malloc(dinfo.output_width *
					 sizeof(char));
	    row2_444[y] =
		(unsigned char *) malloc(dinfo.output_width *
					 sizeof(char));
	}
	//mjpeg_info("YUV 4:4:4 sampling encountered ! Allocating done.\n");
	scanarray[1] = row1_444;
	scanarray[2] = row2_444;
    }

    /* Height match image height or be exact twice the image height */

    if (dinfo.output_height == height) {
	numfields = 1;
    } else if (2 * dinfo.output_height == height) {
	numfields = 2;
    } else {
	veejay_msg
	    (0,"Read JPEG: requested height = %d, height of image = %d",
	     height, dinfo.output_height);
	goto ERR_EXIT;
    }

    /* Width is more flexible */

    if (dinfo.output_width > MAX_LUMA_WIDTH) {
	veejay_msg(0,"Image width of %d exceeds max", dinfo.output_width);
	goto ERR_EXIT;
    }
    if (width < 2 * dinfo.output_width / 3) {
	/* Downclip 2:1 */

	hdown = 1;
	if (2 * width < dinfo.output_width)
	    xsl = (dinfo.output_width - 2 * width) / 2;
	else
	    xsl = 0;
    } else if (width == 2 * dinfo.output_width / 3) {
	/* special case of 3:2 downsampling */

	hdown = 2;
	xsl = 0;
    } else {
	/* No downsampling */

	hdown = 0;
	if (width < dinfo.output_width)
	    xsl = (dinfo.output_width - width) / 2;
	else
	    xsl = 0;
    }

    /* Make xsl even, calculate xsc */

    xsl = xsl & ~1;
    xsc = xsl / 2;

    yl = yc = 0;

    for (field = 0; field < numfields; field++) {
	if (field > 0) {
	    jpeg_read_header(&dinfo, TRUE);
	    dinfo.raw_data_out = TRUE;
	    dinfo.out_color_space = JCS_YCbCr;
	    dinfo.dct_method = JDCT_FLOAT; //JDCT_DEFAULT;            
	    jpeg_start_decompress(&dinfo);
	}

	if (numfields == 2) {
	    switch (itype) {
	    case LAV_INTER_TOP_FIRST:
		yl = yc = field;
		break;
	    case LAV_INTER_BOTTOM_FIRST:
		yl = yc = (1 - field);
		break;
	    default:
		veejay_msg(0,"Input is interlaced but no interlacing set");
		goto ERR_EXIT;
	    }
	} else
	    yl = yc = 0;

	while (dinfo.output_scanline < dinfo.output_height) {
	    /* read raw data */
	    jpeg_read_raw_data(&dinfo, scanarray, 8 * vsf[0]);

	    for (y = 0; y < 8 * vsf[0]; yl += numfields, y++) {
		xd = yl * width;
		xs = xsl;

		if (hdown == 0)
		    for (x = 0; x < width; x++)
			raw0[xd++] = row0[y][xs++];
		else if (hdown == 1)
		    for (x = 0; x < width; x++, xs += 2)
			raw0[xd++] = (row0[y][xs] + row0[y][xs + 1]) >> 1;
		else
		    for (x = 0; x < width / 2; x++, xd += 2, xs += 3) {
			raw0[xd] = (2 * row0[y][xs] + row0[y][xs + 1]) / 3;
			raw0[xd + 1] =
			    (2 * row0[y][xs + 2] + row0[y][xs + 1]) / 3;
		    }
	    }

	    /* Horizontal downsampling of chroma */

	    for (y = 0; y < 8; y++) {
		xs = xsc;

		if (hsf[0] == 1)
		    for (x = 0; x < width / 2; x++, xs++) {
			row1[y][xs] =
			    (row1_444[y][2 * x] +
			     row1_444[y][2 * x + 1]) >> 1;
			row2[y][xs] =
			    (row2_444[y][2 * x] +
			     row2_444[y][2 * x + 1]) >> 1;
		    }

		xs = xsc;
		if (hdown == 0)
		    for (x = 0; x < width / 2; x++, xs++) {
			chr1[y][x] = row1[y][xs];
			chr2[y][x] = row2[y][xs];
		} else if (hdown == 1)
		    for (x = 0; x < width / 2; x++, xs += 2) {
			chr1[y][x] = (row1[y][xs] + row1[y][xs + 1]) >> 1;
			chr2[y][x] = (row2[y][xs] + row2[y][xs + 1]) >> 1;
		} else
		    for (x = 0; x < width / 2; x += 2, xs += 3) {
			chr1[y][x] =
			    (2 * row1[y][xs] + row1[y][xs + 1]) / 3;
			chr1[y][x + 1] =
			    (2 * row1[y][xs + 2] + row1[y][xs + 1]) / 3;
			chr2[y][x] =
			    (2 * row2[y][xs] + row2[y][xs + 1]) / 3;
			chr2[y][x + 1] =
			    (2 * row2[y][xs + 2] + row2[y][xs + 1]) / 3;
		    }
	    }

	    /* Vertical downsampling of chroma */

	    if (vsf[0] == 1) {
		for (y = 0; y < 8 /*&& yc < height/2 */ ;
		     y += 2, yc += numfields) {
		    xd = yc * width / 2;
		    for (x = 0; x < width / 2; x++, xd++) {
			assert(xd < (width * height / 4));
			raw1[xd] = (chr1[y][x] + chr1[y + 1][x]) >> 1;
			raw2[xd] = (chr2[y][x] + chr2[y + 1][x]) >> 1;
		    }
		}

	    } else {
		/* Just copy */
		for (y = 0; y < 8 /*&& yc < height/2 */ ;
Exemple #5
0
/**
 * jpgutl_decode_jpeg
 *  Purpose:  Decompress the jpeg data_in into the img_out buffer.
 *
 *  Parameters:
 *  jpeg_data_in     The jpeg data sent in
 *  jpeg_data_len    The length of the jpeg data
 *  width            The width of the image
 *  height           The height of the image
 *  img_out          Pointer to the image output
 *
 *  Return Values
 *    Success 0, Failure -1
 */
int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len,
                     unsigned int width, unsigned int height, unsigned char *volatile img_out)
{
    JSAMPARRAY      line;           /* Array of decomp data lines */
    unsigned char  *wline;          /* Will point to line[0] */
    unsigned int    i;
    unsigned char  *img_y, *img_cb, *img_cr;
    unsigned char   offset_y;

    struct jpeg_decompress_struct dinfo;
    struct jpgutl_error_mgr jerr;

    /* We set up the normal JPEG error routines, then override error_exit. */
    dinfo.err = jpeg_std_error (&jerr.pub);
    jerr.pub.error_exit = jpgutl_error_exit;
    /* Also hook the emit_message routine to note corrupt-data warnings. */
    jerr.original_emit_message = jerr.pub.emit_message;
    jerr.pub.emit_message = jpgutl_emit_message;
    jerr.warning_seen = 0;

    jpeg_create_decompress (&dinfo);

    /* Establish the setjmp return context for jpgutl_error_exit to use. */
    if (setjmp (jerr.setjmp_buffer)) {
        /* If we get here, the JPEG code has signaled an error. */
        jpeg_destroy_decompress (&dinfo);
        return -1;
    }

    jpgutl_buffer_src (&dinfo, jpeg_data_in, jpeg_data_len);

    jpeg_read_header (&dinfo, TRUE);

    //420 sampling is the default for YCbCr so no need to override.
    dinfo.out_color_space = JCS_YCbCr;
    dinfo.dct_method = JDCT_DEFAULT;
    guarantee_huff_tables(&dinfo);  /* Required by older versions of the jpeg libs */
    jpeg_start_decompress (&dinfo);

    if ((dinfo.output_width == 0) || (dinfo.output_height == 0)) {
        MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO,_("Invalid JPEG image dimensions"));
        jpeg_destroy_decompress(&dinfo);
        return -1;
    }

    if ((dinfo.output_width != width) || (dinfo.output_height != height)) {
        MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO
            ,_("JPEG image size %dx%d, JPEG was %dx%d")
            ,width, height, dinfo.output_width, dinfo.output_height);
        jpeg_destroy_decompress(&dinfo);
        return -1;
    }

    img_y  = img_out;
    img_cb = img_y + dinfo.output_width * dinfo.output_height;
    img_cr = img_cb + (dinfo.output_width * dinfo.output_height) / 4;

    /* Allocate space for one line. */
    line = (*dinfo.mem->alloc_sarray)((j_common_ptr) &dinfo, JPOOL_IMAGE,
                                       dinfo.output_width * dinfo.output_components, 1);

    wline = line[0];
    offset_y = 0;

    while (dinfo.output_scanline < dinfo.output_height) {
        jpeg_read_scanlines(&dinfo, line, 1);

        for (i = 0; i < (dinfo.output_width * 3); i += 3) {
            img_y[i / 3] = wline[i];
            if (i & 1) {
                img_cb[(i / 3) / 2] = wline[i + 1];
                img_cr[(i / 3) / 2] = wline[i + 2];
            }
        }

        img_y += dinfo.output_width;

        if (offset_y++ & 1) {
            img_cb += dinfo.output_width / 2;
            img_cr += dinfo.output_width / 2;
        }
    }

    jpeg_finish_decompress(&dinfo);
    jpeg_destroy_decompress(&dinfo);

    /*
     * If there are too many warnings, this means that
     * only a partial image could be returned which would
     * trigger many false positive motion detections
    */
    if (jerr.warning_seen > 2) return -1;

    return 0;

}