android4.0 USB Camera实例(五)jpg压缩

最近大部分时间都在研究usb 摄像头顺便把jpg编码也写上 下面大部分函数都是我在网上找的 然后稍微的改一点就可以使用了 不过找这些函数费了不少时间 jpg编码网上有很多说明 大致流程都是一样的 我也没深入研究这里就不说了 接前面几篇Camera的文章 这里主要同把获取到的yuv数据通过jpg压缩 以及压缩成mjpeg视频流 首先说明下摄像头获取到的数据格式是yuv422(p16) 这个是在你初始化摄像头设置pixelformat我们当初设置的是V4L2_PIX_FMT_YUYV它的实际格式就是yuv422了 具体的格式你就上网找吧 具体过程是 首先将yuv422转换成rgb888然后在将rgb888转换成jpg 其实是可以直接将yuv422转成jpg的但是我没实现后面我们也放上相关的代码 下面我就直接上代码了

首先yuv422转rgb888

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static void YUV422toRGB888(int width, int height, unsigned char *src, unsigned char *dst)  
  2. {  
  3.     int line, column;  
  4.     unsigned char *py, *pu, *pv;  
  5.     unsigned char *tmp = dst;  
  6.     /* In this format each four bytes is two pixels. Each four bytes is two Y's, aCb  
  7.     and a Cr.Each Y goes to one of the pixels, and the Cb and Cr belong to bothpixels. */  
  8.     py = src;  
  9.     pu = src + 1;  
  10.     pv = src + 3;  
  11.     #define CLIP(x) ( (x)>=0xFF ? 0xFF : ( (x) <= 0x00 ? 0x00 : (x) ) )  
  12.     for (line = 0; line < height; ++line) {  
  13.         for (column = 0; column < width; ++column) {  
  14.             *tmp++ = CLIP((double)*py + 1.402*((double)*pv-128.0));  
  15.             *tmp++ = CLIP((double)*py - 0.344*((double)*pu-128.0) -0.714*((double)*pv-128.0));  
  16.             *tmp++ = CLIP((double)*py + 1.772*((double)*pu-128.0));  
  17.             // increase py every time  
  18.             py += 2;  
  19.             // increase pu,pv every second time  
  20.             if ((column & 1)==1) {  
  21.                 pu += 4;  
  22.                 pv += 4;  
  23.             }  
  24.         }  
  25.     }  
  26. }  

然后将rgb888转成jpg

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static int jpeg_mem_copy(unsigned char* img,unsigned char *dest)  
  2. {  
  3.     struct jpeg_compress_struct cinfo;  
  4.     struct jpeg_error_mgr jerr;  
  5.     JSAMPROW row_pointer[1];  
  6.     unsigned char *pbuf = NULL;  
  7.     int jpglen = 0;  
  8.     // create jpeg data  
  9.     cinfo.err = jpeg_std_error( &jerr );  
  10.     jpeg_create_compress(&cinfo);  
  11.     //jpeg_stdio_dest(&cinfo, fp);  
  12.     jpeg_mem_dest(&cinfo, &pbuf, &jpglen);  
  13.     // set image parameters  
  14.     cinfo.image_width = mwidth;  
  15.     cinfo.image_height = mheight;  
  16.     cinfo.input_components = 3;  
  17.     cinfo.in_color_space = JCS_RGB;  
  18.     // set jpeg compression parameters to default  
  19.     jpeg_set_defaults(&cinfo);  
  20.     // and then adjust quality setting  
  21.     jpeg_set_quality(&cinfo, 80, TRUE);  
  22.     // start compress  
  23.     jpeg_start_compress(&cinfo, TRUE);  
  24.     // feed data  
  25.     while (cinfo.next_scanline < cinfo.image_height) {  
  26.         row_pointer[0] = &img[cinfo.next_scanline * cinfo.image_width *   
  27.         cinfo.input_components];  
  28.         jpeg_write_scanlines(&cinfo, row_pointer, 1);  
  29.     }  
  30.     // finish compression  
  31.     jpeg_finish_compress(&cinfo);  
  32.     // destroy jpeg data  
  33.     jpeg_destroy_compress(&cinfo);  
  34.     memcpy(dest,pbuf,jpglen);  
  35.     //LOGD("++++++++++++++++len is %d\n",jpglen);  
  36.     if(pbuf)  
  37.         free(pbuf);  
  38.     return jpglen;  
  39. }  
这里我使用的是最新的jpeg库9a的里面已经集成了jpeg_mem_dest函数 libjpeg移植网上也有很多说明

下面是我提供给上层调用的一个接口

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. JNIEXPORT jint JNICALL Java_com_hclydao_usbcamera_Fimcgzsd_writefile(JNIEnv * env, jclass obj,jbyteArray yuvdata,jbyteArray filename)//jintArray rgbdata  
  2. {  
  3.     jbyte *ydata = (jbyte*)(*env)->GetByteArrayElements(env, yuvdata, 0);  
  4.     jbyte *filedir = (jbyte*)(*env)->GetByteArrayElements(env, filename, 0);  
  5.   
  6.     FILE * outfile;  
  7.     if ((outfile = fopen(filedir, "wb")) == NULL) {  
  8.         LOGE("++++++++++++open %s failed\n",filedir);  
  9.         return -1;  
  10.     }  
  11.     //yuv422_to_jpeg(ydata,mwidth,mheight,outfile,80);  
  12.     unsigned char* src = (unsigned char*)ydata;  
  13.     unsigned char* dst = malloc(mwidth*mheight*3*sizeof(char));  
  14.     unsigned char* jpgdata = malloc(mwidth*mheight*3*sizeof(char));  
  15.     YUV422toRGB888(mwidth,mheight,src,dst);  
  16.     int size=jpeg_mem_copy(dst,jpgdata);  
  17.     fwrite(jpgdata,size,1,outfile);  
  18.     if(dst)free(dst);  
  19.     if(jpgdata)free(jpgdata);  
  20.     fclose(outfile);  
  21.     (*env)->ReleaseByteArrayElements(env, yuvdata, ydata, 0);  
  22.     (*env)->ReleaseByteArrayElements(env, filename, filedir, 0);  
  23. }  
这个传入的是获取到的yuv数据以及要保存的jpg文件的路径 里面有一些参数是我声明的全局变量 具体可以去看我前面几篇文章


以下是视频流的相关接口

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. FILE * video_file;  
  2. /* 
  3.  *put in frame buffer to queue 
  4.  */  
  5. JNIEXPORT jint JNICALL Java_com_hclydao_usbcamera_Fimcgzsd_videoopen(JNIEnv * env, jclass obj,jbyteArray filename)  
  6. {  
  7.     jbyte *filedir = (jbyte*)(*env)->GetByteArrayElements(env, filename, 0);  
  8.   
  9.     if ((video_file = fopen(filedir, "wb")) == NULL) {  
  10.         LOGE("++++++++++++open %s failed\n",filedir);  
  11.         return -1;  
  12.     }  
  13.   
  14.     (*env)->ReleaseByteArrayElements(env, filename, filedir, 0);  
  15. }  
  16.   
  17. JNIEXPORT jint JNICALL Java_com_hclydao_usbcamera_Fimcgzsd_videostart(JNIEnv * env, jclass obj,jbyteArray yuvdata)  
  18. {  
  19.     jbyte *ydata = (jbyte*)(*env)->GetByteArrayElements(env, yuvdata, 0);  
  20.     unsigned char* src = (unsigned char*)ydata;  
  21.     unsigned char* dst = malloc(mwidth*mheight*3*sizeof(char));  
  22.     unsigned char* jpgdata = malloc(mwidth*mheight*3*sizeof(char));  
  23.     YUV422toRGB888(mwidth,mheight,src,dst);  
  24.     int size=jpeg_mem_copy(dst,jpgdata);  
  25.     fwrite(jpgdata,size,1,video_file);  
  26.     //fwrite(dst,(mwidth*mheight*3*sizeof(char)),1,video_file);  
  27.     if(dst)free(dst);  
  28.     if(jpgdata)free(jpgdata);  
  29.     (*env)->ReleaseByteArrayElements(env, yuvdata, ydata, 0);  
  30. }  
  31.   
  32. JNIEXPORT jint JNICALL Java_com_hclydao_usbcamera_Fimcgzsd_videoclose(JNIEnv * env, jclass obj)  
  33. {  
  34.     fclose(video_file);  
  35. }  
就是连续保存jpg文件到同一个文件 保存的文件直接播放不了 用格式工厂转换成avi以后就可以放了


下面是一个直接将yuv转jpg的函数 这是将yuv420p转成jpg的 我的是yuv422的 改了很多次发现保存的图片不对 看来还是要研究下这些格式之间的区别

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* put_jpeg_yuv420p_memory converts an input image in the YUV420P format into a jpeg image and puts 
  2.  * it in a memory buffer. 
  3.  * Inputs: 
  4.  * - input_image is the image in YUV420P format. 
  5.  * - width and height are the dimensions of the image 
  6.  * Output: 
  7.  * - dest_image is a pointer to the jpeg image buffer 
  8.  * Returns buffer size of jpeg image      
  9.  */  
  10. static int put_jpeg_yuv420p_memory(unsigned char *dest_image,  
  11.                                    unsigned char *input_image, int width, int height)  
  12. {  
  13.     int i, j, jpeg_image_size;  
  14.     
  15.     JSAMPROW y[16],cb[16],cr[16]; // y[2][5] = color sample of row 2 and pixel column 5; (one plane)  
  16.     JSAMPARRAY data[3]; // t[0][2][5] = color sample 0 of row 2 and column 5  
  17.     
  18.     struct jpeg_compress_struct cinfo;  
  19.     struct jpeg_error_mgr jerr;  
  20.     char *pbuf = NULL;  
  21.     int jpglen = 0;  
  22.     data[0] = y;  
  23.     data[1] = cb;  
  24.     data[2] = cr;  
  25.     
  26.     cinfo.err = jpeg_std_error(&jerr);  // errors get written to stderr   
  27.         
  28.     jpeg_create_compress(&cinfo);  
  29.     cinfo.image_width = width;  
  30.     cinfo.image_height = height;  
  31.     cinfo.input_components = 3;  
  32.     jpeg_set_defaults (&cinfo);  
  33.     
  34.     jpeg_set_colorspace(&cinfo, JCS_YCbCr);  
  35.     
  36.     cinfo.raw_data_in = TRUE;                  // supply downsampled data  
  37.     cinfo.do_fancy_downsampling = FALSE;       // fix segfaulst with v7  
  38.     cinfo.comp_info[0].h_samp_factor = 2;  
  39.     cinfo.comp_info[0].v_samp_factor = 2;  
  40.     cinfo.comp_info[1].h_samp_factor = 1;  
  41.     cinfo.comp_info[1].v_samp_factor = 1;  
  42.     cinfo.comp_info[2].h_samp_factor = 1;  
  43.     cinfo.comp_info[2].v_samp_factor = 1;  
  44.     
  45.     jpeg_set_quality(&cinfo, 80, TRUE);  
  46.     cinfo.dct_method = JDCT_FASTEST;  
  47.     
  48.     jpeg_mem_dest(&cinfo, &pbuf, &jpglen);    // data written to mem  
  49.         
  50.     jpeg_start_compress (&cinfo, TRUE);  
  51.     
  52.     for (j = 0; j < height; j += 16) {  
  53.         for (i = 0; i < 16; i++) {  
  54.             y[i] = input_image + width * (i + j);  
  55.             if (i%2 == 0) {  
  56.                 cb[i/2] = input_image + width * height + width / 2 * ((i + j) / 2);  
  57.                 cr[i/2] = input_image + width * height + width * height / 4 + width / 2 * ((i + j) / 2);  
  58.             }  
  59.         }  
  60.         jpeg_write_raw_data(&cinfo, data, 16);  
  61.     }  
  62.     
  63.     jpeg_finish_compress(&cinfo);  
  64.     jpeg_destroy_compress(&cinfo);  
  65.     memcpy(dest_image,pbuf,jpglen);  
  66.     if(pbuf)  
  67.         free(pbuf);  
  68.     return jpglen;  
  69. }  

最近比较迷茫 所以没有深入研究这些 同时我也一直在想 有些东西到底有没有深入研究的必要 纠结 接下来接着准备看下ffmpeg h264压缩

============================================
作者:hclydao
http://blog.csdn.net/hclydao
版权没有,但是转载请保留此段声明

============================================


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值