最近大部分时间都在研究usb 摄像头顺便把jpg编码也写上 下面大部分函数都是我在网上找的 然后稍微的改一点就可以使用了 不过找这些函数费了不少时间 jpg编码网上有很多说明 大致流程都是一样的 我也没深入研究这里就不说了 接前面几篇Camera的文章 这里主要同把获取到的yuv数据通过jpg压缩 以及压缩成mjpeg视频流 首先说明下摄像头获取到的数据格式是yuv422(p16) 这个是在你初始化摄像头设置pixelformat我们当初设置的是V4L2_PIX_FMT_YUYV它的实际格式就是yuv422了 具体的格式你就上网找吧 具体过程是 首先将yuv422转换成rgb888然后在将rgb888转换成jpg 其实是可以直接将yuv422转成jpg的但是我没实现后面我们也放上相关的代码 下面我就直接上代码了
首先yuv422转rgb888
- static void YUV422toRGB888(int width, int height, unsigned char *src, unsigned char *dst)
- {
- int line, column;
- unsigned char *py, *pu, *pv;
- unsigned char *tmp = dst;
- /* In this format each four bytes is two pixels. Each four bytes is two Y's, aCb
- and a Cr.Each Y goes to one of the pixels, and the Cb and Cr belong to bothpixels. */
- py = src;
- pu = src + 1;
- pv = src + 3;
- #define CLIP(x) ( (x)>=0xFF ? 0xFF : ( (x) <= 0x00 ? 0x00 : (x) ) )
- for (line = 0; line < height; ++line) {
- for (column = 0; column < width; ++column) {
- *tmp++ = CLIP((double)*py + 1.402*((double)*pv-128.0));
- *tmp++ = CLIP((double)*py - 0.344*((double)*pu-128.0) -0.714*((double)*pv-128.0));
- *tmp++ = CLIP((double)*py + 1.772*((double)*pu-128.0));
- // increase py every time
- py += 2;
- // increase pu,pv every second time
- if ((column & 1)==1) {
- pu += 4;
- pv += 4;
- }
- }
- }
- }
然后将rgb888转成jpg
- static int jpeg_mem_copy(unsigned char* img,unsigned char *dest)
- {
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- JSAMPROW row_pointer[1];
- unsigned char *pbuf = NULL;
- int jpglen = 0;
- // create jpeg data
- cinfo.err = jpeg_std_error( &jerr );
- jpeg_create_compress(&cinfo);
- //jpeg_stdio_dest(&cinfo, fp);
- jpeg_mem_dest(&cinfo, &pbuf, &jpglen);
- // set image parameters
- cinfo.image_width = mwidth;
- cinfo.image_height = mheight;
- cinfo.input_components = 3;
- cinfo.in_color_space = JCS_RGB;
- // set jpeg compression parameters to default
- jpeg_set_defaults(&cinfo);
- // and then adjust quality setting
- jpeg_set_quality(&cinfo, 80, TRUE);
- // start compress
- jpeg_start_compress(&cinfo, TRUE);
- // feed data
- while (cinfo.next_scanline < cinfo.image_height) {
- row_pointer[0] = &img[cinfo.next_scanline * cinfo.image_width *
- cinfo.input_components];
- jpeg_write_scanlines(&cinfo, row_pointer, 1);
- }
- // finish compression
- jpeg_finish_compress(&cinfo);
- // destroy jpeg data
- jpeg_destroy_compress(&cinfo);
- memcpy(dest,pbuf,jpglen);
- //LOGD("++++++++++++++++len is %d\n",jpglen);
- if(pbuf)
- free(pbuf);
- return jpglen;
- }
下面是我提供给上层调用的一个接口
- JNIEXPORT jint JNICALL Java_com_hclydao_usbcamera_Fimcgzsd_writefile(JNIEnv * env, jclass obj,jbyteArray yuvdata,jbyteArray filename)//jintArray rgbdata
- {
- jbyte *ydata = (jbyte*)(*env)->GetByteArrayElements(env, yuvdata, 0);
- jbyte *filedir = (jbyte*)(*env)->GetByteArrayElements(env, filename, 0);
- FILE * outfile;
- if ((outfile = fopen(filedir, "wb")) == NULL) {
- LOGE("++++++++++++open %s failed\n",filedir);
- return -1;
- }
- //yuv422_to_jpeg(ydata,mwidth,mheight,outfile,80);
- unsigned char* src = (unsigned char*)ydata;
- unsigned char* dst = malloc(mwidth*mheight*3*sizeof(char));
- unsigned char* jpgdata = malloc(mwidth*mheight*3*sizeof(char));
- YUV422toRGB888(mwidth,mheight,src,dst);
- int size=jpeg_mem_copy(dst,jpgdata);
- fwrite(jpgdata,size,1,outfile);
- if(dst)free(dst);
- if(jpgdata)free(jpgdata);
- fclose(outfile);
- (*env)->ReleaseByteArrayElements(env, yuvdata, ydata, 0);
- (*env)->ReleaseByteArrayElements(env, filename, filedir, 0);
- }
以下是视频流的相关接口
- FILE * video_file;
- /*
- *put in frame buffer to queue
- */
- JNIEXPORT jint JNICALL Java_com_hclydao_usbcamera_Fimcgzsd_videoopen(JNIEnv * env, jclass obj,jbyteArray filename)
- {
- jbyte *filedir = (jbyte*)(*env)->GetByteArrayElements(env, filename, 0);
- if ((video_file = fopen(filedir, "wb")) == NULL) {
- LOGE("++++++++++++open %s failed\n",filedir);
- return -1;
- }
- (*env)->ReleaseByteArrayElements(env, filename, filedir, 0);
- }
- JNIEXPORT jint JNICALL Java_com_hclydao_usbcamera_Fimcgzsd_videostart(JNIEnv * env, jclass obj,jbyteArray yuvdata)
- {
- jbyte *ydata = (jbyte*)(*env)->GetByteArrayElements(env, yuvdata, 0);
- unsigned char* src = (unsigned char*)ydata;
- unsigned char* dst = malloc(mwidth*mheight*3*sizeof(char));
- unsigned char* jpgdata = malloc(mwidth*mheight*3*sizeof(char));
- YUV422toRGB888(mwidth,mheight,src,dst);
- int size=jpeg_mem_copy(dst,jpgdata);
- fwrite(jpgdata,size,1,video_file);
- //fwrite(dst,(mwidth*mheight*3*sizeof(char)),1,video_file);
- if(dst)free(dst);
- if(jpgdata)free(jpgdata);
- (*env)->ReleaseByteArrayElements(env, yuvdata, ydata, 0);
- }
- JNIEXPORT jint JNICALL Java_com_hclydao_usbcamera_Fimcgzsd_videoclose(JNIEnv * env, jclass obj)
- {
- fclose(video_file);
- }
下面是一个直接将yuv转jpg的函数 这是将yuv420p转成jpg的 我的是yuv422的 改了很多次发现保存的图片不对 看来还是要研究下这些格式之间的区别
- /* put_jpeg_yuv420p_memory converts an input image in the YUV420P format into a jpeg image and puts
- * it in a memory buffer.
- * Inputs:
- * - input_image is the image in YUV420P format.
- * - width and height are the dimensions of the image
- * Output:
- * - dest_image is a pointer to the jpeg image buffer
- * Returns buffer size of jpeg image
- */
- static int put_jpeg_yuv420p_memory(unsigned char *dest_image,
- unsigned char *input_image, int width, int height)
- {
- int i, j, jpeg_image_size;
- JSAMPROW y[16],cb[16],cr[16]; // y[2][5] = color sample of row 2 and pixel column 5; (one plane)
- JSAMPARRAY data[3]; // t[0][2][5] = color sample 0 of row 2 and column 5
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- char *pbuf = NULL;
- int jpglen = 0;
- data[0] = y;
- data[1] = cb;
- data[2] = cr;
- cinfo.err = jpeg_std_error(&jerr); // errors get written to stderr
- jpeg_create_compress(&cinfo);
- cinfo.image_width = width;
- cinfo.image_height = height;
- cinfo.input_components = 3;
- jpeg_set_defaults (&cinfo);
- jpeg_set_colorspace(&cinfo, JCS_YCbCr);
- cinfo.raw_data_in = TRUE; // supply downsampled data
- cinfo.do_fancy_downsampling = FALSE; // fix segfaulst with v7
- cinfo.comp_info[0].h_samp_factor = 2;
- cinfo.comp_info[0].v_samp_factor = 2;
- cinfo.comp_info[1].h_samp_factor = 1;
- cinfo.comp_info[1].v_samp_factor = 1;
- cinfo.comp_info[2].h_samp_factor = 1;
- cinfo.comp_info[2].v_samp_factor = 1;
- jpeg_set_quality(&cinfo, 80, TRUE);
- cinfo.dct_method = JDCT_FASTEST;
- jpeg_mem_dest(&cinfo, &pbuf, &jpglen); // data written to mem
- jpeg_start_compress (&cinfo, TRUE);
- for (j = 0; j < height; j += 16) {
- for (i = 0; i < 16; i++) {
- y[i] = input_image + width * (i + j);
- if (i%2 == 0) {
- cb[i/2] = input_image + width * height + width / 2 * ((i + j) / 2);
- cr[i/2] = input_image + width * height + width * height / 4 + width / 2 * ((i + j) / 2);
- }
- }
- jpeg_write_raw_data(&cinfo, data, 16);
- }
- jpeg_finish_compress(&cinfo);
- jpeg_destroy_compress(&cinfo);
- memcpy(dest_image,pbuf,jpglen);
- if(pbuf)
- free(pbuf);
- return jpglen;
- }
最近比较迷茫 所以没有深入研究这些 同时我也一直在想 有些东西到底有没有深入研究的必要 纠结 接下来接着准备看下ffmpeg h264压缩
============================================
作者:hclydao
http://blog.csdn.net/hclydao
版权没有,但是转载请保留此段声明
============================================