linux 摄像头传输,Linux下摄像头采集图像的帧格式从YUYV转换成MJPEG(转)

在做网络视频监控系统时,摄像头有的不支持v4l2_pix_fmt_mjpeg格式,只能支持v4l2_pix_fmt_yuyv格式,这样的话,不适合于在网络上的传输。为了将YUYV转换成MJPEG,我借助于jpeg库。

)jpeg源码包通过下面这个网址下载

http://www.ijg.org/files/jpegsrc.v8b.tar.gz

2)解压源码包

$ tar xzvf

jpegsrc.v8b.tar.gz

$ cd jpeg-8b

$

./configure --prefix=/usr/local/jpeg

$ make

$ make install

2)具体用法:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "print.h"

#define OUTPUT_BUF_SIZE  4096

#define WIDTH 640

#define HEIGHT 480

struct buffer {

void *  start;

size_t  length;

};

typedef struct {

struct jpeg_destination_mgr

pub;

JOCTET *

buffer;

unsigned char *outbuffer;

int outbuffer_size;

unsigned char

*outbuffer_cursor;

int

*written;

}mjpg_destination_mgr;

typedef mjpg_destination_mgr *mjpg_dest_ptr;

static int  fd= -1;

struct buffer *buffers= NULL;

static unsigned int  n_buffers= 0;

char *temp_buffer  =NULL;

METHODDEF(void) init_destination(j_compress_ptr cinfo)

{

mjpg_dest_ptr dest = (mjpg_dest_ptr)

cinfo->dest;

dest->buffer = (JOCTET

*)(*cinfo->mem->alloc_small)

((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE *

sizeof(JOCTET));

*(dest->written) =

0;

dest->pub.next_output_byte =

dest->buffer;

dest->pub.free_in_buffer

= OUTPUT_BUF_SIZE;

}

METHODDEF(boolean) empty_output_buffer(j_compress_ptr

cinfo) {

mjpg_dest_ptr dest = (mjpg_dest_ptr)

cinfo->dest;

memcpy(dest->outbuffer_cursor,

dest->buffer, OUTPUT_BUF_SIZE);

dest->outbuffer_cursor

+= OUTPUT_BUF_SIZE;

*(dest->written) +=

OUTPUT_BUF_SIZE;

dest->pub.next_output_byte =

dest->buffer;

dest->pub.free_in_buffer

= OUTPUT_BUF_SIZE;

return TRUE;

}

METHODDEF(void) term_destination(j_compress_ptr cinfo)

{

mjpg_dest_ptr dest = (mjpg_dest_ptr)

cinfo->dest;

size_t datacount = OUTPUT_BUF_SIZE -

dest->pub.free_in_buffer;

memcpy(dest->outbuffer_cursor,

dest->buffer, datacount);

dest->outbuffer_cursor

+= datacount;

*(dest->written) +=

datacount;

}

void dest_buffer(j_compress_ptr cinfo, unsigned char

*buffer, int size, int *written) {

mjpg_dest_ptr dest;

if (cinfo->dest == NULL)

{

cinfo->dest = (struct jpeg_destination_mgr

*)(*cinfo->mem->alloc_small)

((j_common_ptr) cinfo, JPOOL_PERMANENT,

sizeof(mjpg_destination_mgr));

}

dest =

(mjpg_dest_ptr)cinfo->dest;

dest->pub.init_destination =

init_destination;

dest->pub.empty_output_buffer =

empty_output_buffer;

dest->pub.term_destination =

term_destination;

dest->outbuffer =

buffer;

dest->outbuffer_size =

size;

dest->outbuffer_cursor =

buffer;

dest->written =

written;

}

//摄像头采集帧图像的YUYV格式转换为JPEG格式

int compress_yuyv_to_jpeg(unsigned char *buf, unsigned

char *buffer, int size, int quality) {

struct jpeg_compress_struct

cinfo;

struct jpeg_error_mgr jerr;

JSAMPROW row_pointer[1];

unsigned char *line_buffer,

*yuyv;

int z;

static int written;

//int count = 0;

//printf("%s\n", buf);

line_buffer = calloc (WIDTH * 3,

1);

yuyv =

buf;//将YUYV格式的图片数据赋给YUYV指针

printf("compress

start...\n");

cinfo.err = jpeg_std_error

(&jerr);

jpeg_create_compress

(&cinfo);

dest_buffer(&cinfo,

buffer, size, &written);

cinfo.image_width = WIDTH;

cinfo.image_height = HEIGHT;

cinfo.input_components = 3;

cinfo.in_color_space =

JCS_RGB;

jpeg_set_defaults

(&cinfo);

jpeg_set_quality

(&cinfo, quality, TRUE);

jpeg_start_compress

(&cinfo, TRUE);

z = 0;

while (cinfo.next_scanline

< HEIGHT) {

int x;

unsigned char *ptr =

line_buffer;

for (x = 0; x

< WIDTH; x++) {

int r, g, b;

int y, u, v;

if (!z)

y = yuyv[0] <<

8;

else

y = yuyv[2] <<

8;

u

= yuyv[1] - 128;

v

= yuyv[3] - 128;

r

= (y + (359 * v)) >> 8;

g

= (y - (88 * u) - (183 * v)) >>

8;

b

= (y + (454 * u)) >> 8;

*(ptr++) = (r > 255) ? 255 : ((r < 0)

? 0 : r);

*(ptr++) = (g > 255) ? 255 : ((g < 0)

? 0 : g);

*(ptr++) = (b > 255) ? 255 : ((b < 0)

? 0 : b);

if (z++) {

z = 0;

yuyv += 4;

}

}

row_pointer[0] =

line_buffer;

jpeg_write_scanlines

(&cinfo, row_pointer, 1);

}

jpeg_finish_compress

(&cinfo);

jpeg_destroy_compress

(&cinfo);

free (line_buffer);

return (written);

}

....

....

....

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java摄像头通过v4l2采集YUYV格式图像数据,可以通过以下步骤将其换为YUV420P格式,然后再通过x26编码。 首先,我们需要了解YUYV和YUV420P这两种图像数据格式的特点。 YUYV格式是一种16位的颜色编码格式,它使用两个连续的像素点共享一个色度信息(Cb和Cr),以减少颜色信息的采样率。每个像素所占用的字节为YUYV。 YUV420P格式是一种带有Y、Cb和Cr三个分量的图像格式,它采用了4:2:0的采样比例。对于每个Y像素,只有一个Cb和一个Cr分量,但对于每4个连续的Y像素,只有一个对应的Cb和一个对应的Cr分量。 将YUYV格式换为YUV420P格式的步骤如下: 1. 首先,我们需要计算输出图像的分辨率(width和height)。假设输入图像的分辨率为inputWidth和inputHeight。 2. 创建一个大小为inputWidth * inputHeight * 3 / 2的字节数组,用来存储换后的YUV420P数据。 3. 遍历输入图像的每个YUYV像素对(Y1, U, Y2, V),根据下面的公式计算输出图像的Y、Cb和Cr分量: Y1 = YUYV[2 * i]; U = YUYV[2 * i + 1]; Y2 = YUYV[2 * i + 2]; V = YUYV[2 * i + 3]; 对于输出图像的每个像素,计算对应的索引: outputIndex = (i / 2) * 3; 将Y、Cb和Cr分量写入输出图像的字节数组中: output[outputIndex] = Y1; output[outputIndex + 1] = U; output[outputIndex + 2] = V; output[outputIndex + 3] = Y2; output[outputIndex + 4] = U; output[outputIndex + 5] = V; 4. 最后,你可以使用x26编码器将换后的YUV420P格式图像数据进行编码。 这样,你就可以通过Java摄像头采集YUYV格式图像数据,并将其换为YUV420P格式,然后使用x26进行编码处理。 ### 回答2: 首先,Java可以使用v4l2库来采集摄像头图像数据。v4l2是一个视频4 Linux 2 编程接口,允许开发者在Linux系统中访问和控制视频设备,包括摄像头。 在Java中,可以使用JNI(Java Native Interface)来使用v4l2库函数。通过JNI将Java程序与C/C++代码连接起来,实现通过v4l2采集yuyv格式图像数据。 其次,要将yuyv格式图像数据换为yuv420p格式,可以使用算法来进行处理。yuyv格式是一种颜色编码格式,它包含了亮度和色度信息。而yuv420p格式是一种通用的图像格式,其中亮度和色度信息被分离成两个平面。 换的算法可以根据yuyv和yuv420p的颜色编码规则进行处理。例如,可以使用色度抽取和亮度补偿的算法来实现换。具体的实现方式需要根据具体的编码规则进行相应的处理。 最后,将换后的yuv420p格式图像数据通过x264进行编码。x264是一个开源的H.264视频编码器库,可以将视频数据压缩为H.264格式。 通过调用x264库函数,可以将yuv420p格式图像数据输入到x264编码器中进行编码。编码器会根据H.264的编码规则进行图像压缩,并输出压缩后的视频数据。 以上是关于在Java中使用v4l2采集yuyv格式图像数据,将其换为yuv420p格式,再通过x264进行编码的基本流程的回答。具体的实现需要结合具体的编程环境和库函数使用来进行详细操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值