播放摄像头 sdl2.0 显示v4l2

#include <sys/ioctl.h>
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <SDL2/SDL.h>

#define LOAD_BGRA    0
#define LOAD_RGB24   0
#define LOAD_BGR24   0
#define LOAD_YUV422P 1  

//Bit per Pixel
#if LOAD_BGRA
const int bpp=32;
#elif LOAD_RGB24|LOAD_BGR24
const int bpp=24;
#elif LOAD_YUV422P
const int bpp=16;
#endif
int screen_w=640,screen_h=480;
const int pixel_w=640,pixel_h=480;
unsigned char buffer[pixel_w*pixel_h*bpp/8];
unsigned char buffer_convert[pixel_w*pixel_h*4];
struct buffers
{
void* start;
unsigned int length;
}*buffers;
void errmsg(const char* fun_name)
{
        printf("%s error\n",fun_name);
        exit(-1);
}
int main()
{

     int fd = open("/dev/video0",O_RDWR);
          if(fd < 0)
         errmsg("open");
         int ret = -1;
    struct v4l2_capability cap;
         ret = ioctl(fd,VIDIOC_QUERYCAP,&cap);
         if(ret < 0 )
             {
        perror("ioctl");
        return -1;
             }
     printf("%s \n%s\n%s\n %08x %08x\n",cap.driver,cap.card,cap.bus_info,cap.version,cap.capabilities);
          printf("V4L2_CAP_VIDEO_CAPTURE = %08x    %d \n",V4L2_CAP_VIDEO_CAPTURE,V4L2_CAP_VIDEO_CAPTURE&cap.capabilities);

           if(!(V4L2_CAP_VIDEO_CAPTURE&cap.capabilities))
           {
                 errmsg( "capture not support");
        exit(-1);
           }
//
    struct v4l2_fmtdesc fmtdesc;
    fmtdesc.index=0;
    fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    printf("Support format:\n");
         while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1)
        {
         printf("%d.%s type=%08x  flags=%08x pixelformat=%08x\n",fmtdesc.index+1,fmtdesc.description,fmtdesc.type,fmtdesc.flags,fmtdesc.pixelformat);
          fmtdesc.index++;
           }
    struct v4l2_requestbuffers req;
          req.count=4; req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
          req.memory=V4L2_MEMORY_MMAP;
        ret =  ioctl(fd,VIDIOC_REQBUFS,&req);
        if(ret < 0 )
        {
            perror("ioctl23");
                  exit(-1);
        }
     buffers = (struct buffers*)calloc (req.count, sizeof (*buffers));
     if (!buffers) {
     fprintf (stderr, "Out of memory/n");
     exit (-1);
     }
     struct v4l2_buffer buf;
     for (unsigned int n_buffers = 0; n_buffers < req.count; ++n_buffers)
     {
     memset(&buf,0,sizeof(buf));
     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     buf.memory = V4L2_MEMORY_MMAP;
     buf.index = n_buffers;
     if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf))
         {
            perror("ioctl33");
                exit(-1);
         }
     buffers[n_buffers].length = buf.length;
     buffers[n_buffers].start =mmap (NULL,buf.length,PROT_READ | PROT_WRITE ,MAP_SHARED,fd, buf.m.offset);
     if (MAP_FAILED == buffers[n_buffers].start)
         {
          perror("mmap");
            exit(-1);
         }
     }
     unsigned int i;
     enum v4l2_buf_type type;
     for (i = 0; i < 4; ++i)
     {
     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     buf.memory = V4L2_MEMORY_MMAP;
     buf.index = i;
    ret  =  ioctl (fd, VIDIOC_QBUF, &buf);
    if(ret < 0)
    {
     perror("ioctl 44");
        exit(-1);
    }
     }
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     ret = ioctl (fd, VIDIOC_STREAMON, &type);
     if(ret < 0)
    {
     perror("ioctl 44");
        exit(-1);
    }
    if(SDL_Init(SDL_INIT_VIDEO)) {
        printf( "Could not initialize SDL - %s\n", SDL_GetError());
        return -1;
    }
    SDL_Window *screen;
    //SDL 2.0 Support for multiple windows
    screen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        screen_w, screen_h,SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
    if(!screen) {
        printf("SDL: could not create window - exiting:%s\n",SDL_GetError());
        return -1;
    }
    SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
    Uint32 pixformat=0;
#if LOAD_BGRA
    //Note: ARGB8888 in "Little Endian" system stores as B|G|R|A
    pixformat= SDL_PIXELFORMAT_ARGB8888;
#elif LOAD_RGB24
    pixformat= SDL_PIXELFORMAT_RGB888;
#elif LOAD_BGR24
    pixformat= SDL_PIXELFORMAT_BGR888;
#elif LOAD_YUV422P
    //IYUV: Y + U + V  (3 planes)
    //YV12: Y + V + U  (3 planes)
    pixformat= SDL_PIXELFORMAT_YUY2; // SDL_PIXELFORMAT_IYUV;
#endif
    SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer,pixformat, SDL_TEXTUREACCESS_STREAMING,pixel_w,pixel_h);
SDL_Rect sdlRect;
//     struct v4l2_buffer buf; CLEAR (buf);
while(1)
{
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ioctl (fd, VIDIOC_DQBUF, &buf);
 if(ret < 0)
{
 perror("ioctl 56");
    exit(-1);
}
//process_image (buffers[buf.index.]start); //
printf("%d\n",buffers[buf.index].length);
#if LOAD_BGRA
            //We don‘t need to change Endian
            //Because input BGRA pixel data(B|G|R|A) is same as ARGB8888 in Little Endian (B|G|R|A)
            SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w*4);
#elif LOAD_RGB24|LOAD_BGR24
            //change 24bit to 32 bit
            //and in Windows we need to change Endian
            CONVERT_24to32(buffer,buffer_convert,pixel_w,pixel_h);
            SDL_UpdateTexture( sdlTexture, NULL, buffer_convert, pixel_w*4);
#elif LOAD_YUV422P
            SDL_UpdateTexture( sdlTexture, NULL, buffers[buf.index].start, pixel_w*2);
#endif
            //FIX: If window is resize
            sdlRect.x = 0;
            sdlRect.y = 0;
            sdlRect.w = screen_w;
            sdlRect.h = screen_h;
            SDL_RenderClear( sdlRenderer );
            SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect);
            SDL_RenderPresent( sdlRenderer );
            //Delay 40ms
            SDL_Delay(40);
ret = ioctl (fd,VIDIOC_QBUF,&buf);
 if(ret < 0)
{
 perror("ioctl 67");
    exit(-1);
}
}
close(fd);
return  0 ;
}

笔记本的摄像头640*480  yuv422    g++ video0.c -std=c++0x   -lSDL2 /usr/local/lib/libSDL2_image.a

时间: 2024-08-01 22:44:21

播放摄像头 sdl2.0 显示v4l2的相关文章

[原]零基础学习SDL开发之在Android使用SDL2.0显示BMP图

关于如何移植SDL2.0到安卓上面来参考我的上一篇文章:[原]零基础学习SDL开发之移植SDL2.0到Android 在一篇文章我们主要使用SDL2.0来加载一张BMP图来渲染显示. 博主的开发环境:Ubuntu 14.04 64位,Eclipse + CDT + ADT+NDK 博主曾经自己使用NDK编译出了libSDL2.so,然后使用共享库的方式来调用libSDL2中的函数,结果发现SDL\src\core\android\SDL_android.c 这个jni函数写的实在是不够自己另外做

[原]零基础学习SDL开发之在Android使用SDL2.0显示BMP叠加图

关于如何移植在android上使用SDL,可以参考[原]零基础学习SDL开发之移植SDL2.0到Android 和 [原]零基础学习SDL开发之在Android使用SDL2.0显示BMP图 . 在一篇文章我们主要使用SDL2.0来加载一张BMP图来渲染显示,同时叠加一张图作为背景图. 博主的开发环境:Ubuntu 14.04 64位,Eclipse + CDT + ADT+NDK 在前面两篇文章我们知道了如何移植SDL2.0到android上面来,并且可以在Android上面来显示一张图片,这篇

最简单的基于FFMPEG+SDL的视频播放器 ver2 (採用SDL2.0)

===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x) 最简单的基于FFMPEG+SDL的视频播放器 ver2 (採用SDL2.0) 最简单的基于FFmpeg的解码器-纯净版(不包括libavformat) 最简单的基于FFMPEG+SDL的视频播放器:拆分-解码器和播放器 最简单的基于FFMPEG的Hellowor

最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)

简介 之前做过一个FFMPEG+SDL的简单播放器:<100行代码实现最简单的基于FFMPEG+SDL的视频播放器>.该播放器采用SDL1.2显示视频.最近有不少人反映SDL已经升级到2.0版本了,甚至官网的Wiki上都只有SDL2.0的文档了,因此下载了SDL 2.0 并且进行了简单的研究.随后对此前的播放器进行了修改,将SDL1.2换成了SDL2.0. 注:<100行代码实现最简单的基于FFMPEG+SDL的视频播放器>文章中提到的很多知识这里不再重复.本文重点记录SDL1.2

FFMPEG+SDL2.0流媒体开发3---简易MP4视频播放器,提取MP4的H264视频序列解码并且显示

简介 之前写了一遍提取MP4中的音视频并且解码,这一篇引入SDL2.0来显示解码后的视频序列 实现一个简易的 视频播放器. 我这里用的FFMPEG和SDL2.0都是最新版的 可能网上的资料不是很多,API接口也变了很多,不过大体的思路还是一样的. 分析几个FFMPEG函数 在这之前我们分析几个代码中可能引起疑问的FFMPEG几个函数的源代码,我已经尽我的能力添加了注释,因为实在没有文档可能有的地方也不是很详尽  不过大体还是能看懂的 av_image_alloc (分配图片缓冲区) 我们在FFM

演示基于SDL2.0+FFmpeg的播放器

SDL是一个跨平台的渲染组件,目前已经推出到2.0.3版本,支持Win/Linux/OSX/Android.网上很多介绍大多是基于SDL1.2版本的,与2.0版本有一定的差别,本文演示如何用SDL2.0版本播放视频(仅视频). SDL下载网站:http://libsdl.org 参考网址:http://blog.csdn.net/dawdo222/article/details/8692834 上代码: // 演示如何用SDL2进行播放 //可参考http://blog.csdn.net/daw

SDL2.0例子代码分析---循环播放wav loopwav

SDL2.0中循环播放一段声音文件 ,并且添加上注释. /* 加载并且循环播放一个WAV文件*/ /* loopwaves.c is much more robust in handling WAVE files -- This is only for simple WAVEs */ #include "SDL_config.h" #include <stdio.h> #include <stdlib.h> #if HAVE_SIGNAL_H #include

最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)

简介 之前做过一个简单的音频播放器:<最简单的基于FFMPEG+SDL的音频播放器>,采用的是SDL1.2.前两天刚把原先做的<最简单的基于FFMPEG+SDL的视频播放器>更新采用了SDL2.0,于是顺手也把音频播放器更新成为SDL2.0. SourceForge项目主页:https://sourceforge.net/projects/simplestffmpegaudioplayer/ 完整工程下载地址:http://download.csdn.net/detail/leix

[原]如何在Android用FFmpeg+SDL2.0解码图像线程

关于如何在Android上用FFmpeg+SDL2.0解码显示图像参考[原]如何在Android用FFmpeg+SDL2.0解码显示图像 ,关于如何在Android使用FFmpeg+SDL2.0解码声音参考[原]如何在Android用FFmpeg+SDL2.0解码声音.但是该文章有一个问题,就是解码出来的声音有很大的噪音,基本无法听清,这是由于对于声音的处理有问题.故本文参考ffmpeg-sdl音频播放分析声音解码的处理,解码出来的声音就正常了. 博主的开发环境:Ubuntu 14.04 64位