看到很多同行需要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()));
}