V4L2+QT视频会议系统源码


转自: http://hi.baidu.com/__barrett__/item/5e75aaf17c26f8dc6225d263

V4L2+QT视频会议系统源码

看到很多同行需要qt的视频显示源码,于是就写出来和大家分享了,高手请跳过.......需要全部源码的请加QQ576514651

#include <QObject>
#include <QMessageBox>
#include <QStringList>
#include <sys/ioctl.h>
#include <signal.h>
#include <QApplication>

#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "image.h"
#include "SsbSipH264Encode.h"
#include "lcd.h"
#include "post.h"

//#define JPG_SIZE 8192

//#define PORT 28000
//#define ADDR "234.5.8."

//static void *encoding_thread(void *arg);
//unsigned char *image_buffer;
int image_height;
int image_width;

#pragma pack(2)

typedef struct
{
unsigned char b : 5;
unsigned char g : 6;
unsigned char r : 5;
}RGB565;

#pragma pack(4)

//初始化摄像头 
static int cam_p_init(void) 
{
int dev_fp = -1;

dev_fp = open(PREVIEW_NODE, O_RDWR);

if (dev_fp < 0) {
perror(PREVIEW_NODE);
return -1;
}
return dev_fp;
}

//初始化硬件编码器
static int cam_c_init(void)
{
int dev_fp = -1;

dev_fp = open(CODEC_NODE, O_RDWR);

if (dev_fp < 0) {
perror(CODEC_NODE);
printf("CODEC : Open Failed \n");
return -1;
}
return dev_fp;
}

//退出
static void exit_from_app() 
{
// int start;
// int fb_size;
// int ret;

/* Stop previewing */
/*
start = 0;
ret = ioctl(cam_p_fp, VIDIOC_OVERLAY, &start);
if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_OVERLAY failed\n");
exit(1);
}
*/
close(cam_p_fp);
close(cam_c_fp);
printf("2222222222222222222\n");
mfc_encoder_free(handle);
}

//设置编码器参数
void *mfc_encoder_init(int width, int height, int frame_rate, int bitrate, int gop_num)
{
int frame_size;
// void *handle;
int ret;


frame_size = (width * height * 3) >> 1;

handle = SsbSipH264EncodeInit(width, height, frame_rate, bitrate, gop_num);
if (handle == NULL) {
//LOG_MSG(LOG_ERROR, "Test_Encoder", "SsbSipH264EncodeInit Failed\n");
return NULL;
}

ret = SsbSipH264EncodeExe(handle);

return handle;
}

//编码
void *mfc_encoder_exe(void *handle, unsigned char *yuv_buf, int frame_size, int first_frame, long *size)
{
unsigned char *p_inbuf, *p_outbuf;
int hdr_size;
int ret;


p_inbuf = (unsigned char *)SsbSipH264EncodeGetInBuf(handle, 0);

memcpy(p_inbuf, yuv_buf, frame_size);

ret = SsbSipH264EncodeExe(handle);
if (first_frame) {
SsbSipH264EncodeGetConfig(handle, H264_ENC_GETCONF_HEADER_SIZE, &hdr_size);
//printf("Header Size : %d\n", hdr_size);
}

p_outbuf = (unsigned char *)SsbSipH264EncodeGetOutBuf(handle, size);

return p_outbuf;
}

void mfc_encoder_free(void *handle)
{
SsbSipH264EncodeDeInit(handle);
}

//初始化摄像头
int init()
{
int ret, start, found = 0;
// unsigned int addr = 0;
// char rgb_for_preview[LCD_WIDTH * LCD_HEIGHT * 4]; // MAX
char file_name[100];
struct v4l2_capability cap;
struct v4l2_input chan;
struct v4l2_framebuffer preview;
struct v4l2_pix_format preview_fmt;
struct v4l2_format codec_fmt;

int pp_fd;

printf("==== Camera Preview & Encode to H264 Test ====\n");
printf(" liyutai, v0.1 (2009-10-30) \n"); 
/* Camera preview initialization */
if ((cam_p_fp = cam_p_init()) < 0)
exit_from_app();

/* Camera codec initialization */
if ((cam_c_fp = cam_c_init()) < 0)
exit_from_app();

pp_params pp_param;
pp_fd = open(PP_DEV_NAME, O_RDWR|O_NDELAY);

if(pp_fd < 0)
{
printf("Post processor open error\n");
return -1;
}

memset(&pp_param, 0, sizeof(pp_params));
pp_param.OutPath = POST_DMA;
ioctl(pp_fd, PPROC_SET_PARAMS, &pp_param);

// signal_ctrl_c();


/* Get capability */
ret = ioctl(cam_p_fp , VIDIOC_QUERYCAP, &cap);
if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_QUERYCAP failled\n");
exit(1);
}
//printf("V4L2 : Name of the interface is %s\n", cap.driver);


/* Check the type - preview(OVERLAY) */
if (!(cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)) {
printf("V4L2 : Can not capture(V4L2_CAP_VIDEO_OVERLAY is false)\n");
exit(1);
}

chan.index = 0;
found = 0;
while(1) {
ret = ioctl(cam_p_fp, VIDIOC_ENUMINPUT, &chan);
if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_ENUMINPUT failled !!!!\n");fflush(stdout);
break;
}

//printf("[%d] : Name of this channel is %s\n", chan.index, chan.name);

/* Test channel.type */
if (chan.type & V4L2_INPUT_TYPE_CAMERA ) {
printf("V4L2 : Camera Input(V4L2_INPUT_TYPE_CAMERA )\n");
found = 1;
break;
}
chan.index++;
}

if(!found) 
exit_from_app();

/* Settings for input channel 0 which is channel of webcam */
chan.type = V4L2_INPUT_TYPE_CAMERA;
ret = ioctl(cam_p_fp, VIDIOC_S_INPUT, &chan);

if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_S_INPUT failed\n");fflush(stdout);
exit(1);
}

preview_fmt.width = LCD_WIDTH;
preview_fmt.height = LCD_HEIGHT;
preview_fmt.pixelformat = LCD_BPP_V4L2;

preview.capability = 0;
preview.flags = 0;
preview.fmt = preview_fmt;

/* Set up for preview */
ret = ioctl(cam_p_fp, VIDIOC_S_FBUF, &preview);


if (ret< 0) {
printf("V4L2 : ioctl on VIDIOC_S_BUF failed\n");
exit(1);
}

/* Preview start */
start = 1;
ret = ioctl(cam_p_fp, VIDIOC_OVERLAY, &start);

if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_OVERLAY failed\n");
exit(1);
}

/* Codec set */
/* Get capability */
ret = ioctl(cam_c_fp , VIDIOC_QUERYCAP, &cap);

if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_QUERYCAP failled\n");
exit(1);
}
//printf("V4L2 : Name of the interface is %s\n", cap.driver);


/* Check the type - preview(OVERLAY) */
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
printf("V4L2 : Can not capture(V4L2_CAP_VIDEO_CAPTURE is false)\n");
exit(1);
}

/* Set format */
codec_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
codec_fmt.fmt.pix.width = LCD_WIDTH; 
codec_fmt.fmt.pix.height = LCD_HEIGHT; 
codec_fmt.fmt.pix.pixelformat= V4L2_PIX_FMT_YUV420; 
ret = ioctl(cam_c_fp , VIDIOC_S_FMT, &codec_fmt);
if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_S_FMT failled\n");
exit(1);
}

printf("\n[8. Camera preview & MFC encoding]\n");
printf("Using IP : MFC, Post processor, LCD, Camera\n");
printf("Display size : VGA(640x480)\n");

handle = mfc_encoder_init(LCD_WIDTH, LCD_HEIGHT, 30, 1000, 30); 

sprintf(&file_name[0], "Cam_encoding_%dx%d-%d.264", LCD_WIDTH, LCD_HEIGHT, ++film_cnt);
printf("Name of encoded file : Cam_encoding_%dx%d-%d.264\n", LCD_WIDTH, LCD_HEIGHT, film_cnt);
fflush(stdout);

/* file create/open, note to "wb" */
// encoded_fp = fopen(&file_name[0], "wb");
// if (!encoded_fp) {
// perror(&file_name[0]);
// }

/* Codec start */
start = 1;
ret = ioctl(cam_c_fp, VIDIOC_STREAMON, &start);
if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_STREAMON failed\n");
exit(1);
}
return 0;
}

void startEncode()
{
/* Encoding and decoding threads creation */
// int k_id ; 
// k_id = pthread_create(&pth, 0, encoding_thread, 0);
// pthread_join(pth, NULL);
// exit_from_app();
}

//编码函数
unsigned char *encoding_thread()
{

// int yuv_cnt = 0;
// int start, 
int ret;
// int frame_num = YUV_FRAME_NUM;
// int key;
unsigned char g_yuv[YUV_FRAME_BUFFER_SIZE];
unsigned char *encoded_buf;

/* read from camera device */
if ((ret = read(cam_c_fp, g_yuv, YUV_FRAME_BUFFER_SIZE)) < 0) {
perror("read()");
}

// printf("read:%d\n", ret);
if(frame_count == 1)
encoded_buf = (unsigned char *)mfc_encoder_exe(handle, g_yuv, YUV_FRAME_BUFFER_SIZE, 1, &encoded_size);
else
encoded_buf = (unsigned char *)mfc_encoder_exe(handle, g_yuv, YUV_FRAME_BUFFER_SIZE, 0, &encoded_size); 
// printf("frame_count:%d\n", frame_count);
// printf("encoded_buf:%d\n", strlen((const char *)encoded_buf));
// printf("write:%d\n", 
// fwrite(encoded_buf, 1, encoded_size, encoded_fp);
frame_count++; 
return encoded_buf;

}

//初始化网络
void Image::initNetwork()
{
int seatNo = getSeatNo(); 
int port = seatNo + 28000;
sendAddr.sin_family = AF_INET;
sendAddr.sin_port = htons(port);
QString addr = QString("234.5.8.") + QString::number(seatNo);
QByteArray arr = addr.toLatin1();
char *address = arr.data();
sendAddr.sin_addr.s_addr = inet_addr(address);
// QMessageBox::about(this, "xxx", QString::number(port) + addr);
socketFd = socket(AF_INET, SOCK_DGRAM, 0);
if(socketFd < 0)
{
perror("socket:");
return ;
}
}

//暂时不使用的函数,RGB16转换RGB24
void rgb565To24(const unsigned short *src, unsigned char *dst)
{
RGB565 *p = (RGB565 *)src;
int i;

for(i = 0; i < image_height * image_width * 2; i++)
{
*(dst + i * 3) = (((p + i)->r) << 3) | 0x07;
*(dst + i * 3 + 1) = (((p + i)->g) << 3) | 0x03;
*(dst + i * 3 + 2) = (((p + i)->b) << 3) | 0x07;
}
}

//视频刷新
void Image::updateImageSlot()
{

int ret;
if((ret = read(cam_p_fp, &rgbData, LCD_WIDTH * LCD_HEIGHT * 2)) < 0)
{
perror("read");
return ;
}

// FILE *fp = fopen("jpeg_rgb.264", "wb");
// printf("write:%d\n", fwrite(rgbData, 1, LCD_WIDTH * LCD_HEIGHT * 4, fp)); 
// return ;
 QImage image(rgbData, LCD_WIDTH, LCD_HEIGHT, QImage::Format_RGB16);//RGB转换成QImage显示
QPixmap pixmap;
pixmap = pixmap.fromImage(image);
// label->setMinimumSize(LCD_WIDTH, LCD_HEIGHT);
label->setPixmap(pixmap);
label->setMinimumSize(LCD_WIDTH, LCD_HEIGHT);
label->setMaximumSize(LCD_WIDTH, LCD_HEIGHT);

// disconnect(timer, SIGNAL(timeout()),
// this, SLOT(updateImageSlot()));
// sleep(2);
// bzero(rgbData, sizeof(rgbData));
// delete timer;
// timer = NULL;

unsigned char *h264Data = encoding_thread();
int length = sizeof(struct sockaddr);
if((ret = sendto(socketFd, h264Data, encoded_size,
0, (struct sockaddr *)&sendAddr, (socklen_t)length)) < 0)
{
perror("sendto:::"); 
}
// printf("sendto : %d\n", ret);
h264Data = NULL;

}


void Image::timerEvent(QTimerEvent *e)
{

}

void Image::sendH264Slot()
{
}

//开始视频采集
void Image::start()
{
initNetwork();
init();
// pthread_t pth;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()),
this, SLOT(updateImageSlot()));
// connect(timer, SIGNAL(timeout()),
// this, SLOT(sendH264Slot()));
timerId = timer->timerId();
timer->start(40);
startEncode();
// image_buffer = (unsigned char *)malloc(LCD_HEIGHT * LCD_WIDTH * 4);
// jpgData = (unsigned char *)malloc(JPG_SIZE);
}

//结束视频采集
void Image::end()
{
if(timer)
{
killTimer(timerId);
delete timer;
timer = NULL;
}
QString pth = QCoreApplication::applicationDirPath();
pth += "/img/logo.png";
label->setPixmap(QPixmap(pth));
// free(image_buffer);
// free(jpgData);
// image_buffer = NULL;
// jpgData = NULL;
exit_from_app();
}

Image::Image(QWidget *parent)
:QWidget(parent)
{
label = new QLabel(this);
QString pth = QCoreApplication::applicationDirPath();
pth += "/img/logo.png";
// QMessageBox::about(this, "xxx", pth);
label->setPixmap(QPixmap(pth));
image_height = LCD_HEIGHT;
image_width = LCD_WIDTH;
// encode = new Encode;
// encode->start();
// timer = new QTimer(this);
// timerId = timer->timerId();
// connect(timer, SIGNAL(timeout()),
// this, SLOT(updateImageSlot()));
}

 

你可能感兴趣的:(V4L2+QT视频会议系统源码)