我们这里采用SDL(本文所用版本为SDL2.0.5)来进行图像输出,SDL在进行图像渲染时一般采用的会是direct3D或者opengl,SDL对它们进行了封装,不过我们这里只讨论SDL的使用,并不会去涉及这些底层实现。尽管如此,我们还是有必要了解其中一些基本概念,这些概念能帮助我们很好地理解所使用的SDL api的实际作用。

其中最重要的一个概念就是render,中文译为渲染,rendering在计算机图像领域指的就是图像合成(image synthesis)。通俗一点的解释就是:render指的是把2D图像(图形)或者3D模型变成所展示出来的图像的过程,实际进行这种转换操作的物件被称为renderer(渲染器)。在SDL中,renderer主要处理的是2D的数据,其中包括

  1. 图形:画点画线画面笔触上色填充颜色等。
  2. 图像:裁剪旋转等。

不过本文只用到renderer最基本的功能,即把图像输出到窗口。在SDL中,为了方便renderer的实现,renderer所处理的对象被规定为texture(纹理),因此图像需要先被包装成texture,texture会被render成rendered image,然后就可以输出到window。

初始化

在使用SDL的函数之前,需要先调用SDL_Init来进行初始化,由于本文的目的是进行视频图像输出,因此需要指定flag为SDL_INIT_VIDEO来初始化视频子系统。

    if(SDL_Init(SDL_INIT_VIDEO)){
fprintf(stderr, "SDL init video failed\n");
return -1;
}

接下来创建window、renderer、texture。在创建texture时需要指定输入的图像像素格式,通常视频的像素格式都是yuv420p,对应的flag为SDL_PIXELFORMAT_IYUV。对于会频繁更换的视频图像,还需要指定texture为SDL_TEXTUREACCESS_STREAMING。

    window = SDL_CreateWindow("Simple Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DEF_WIDTH, DEF_HEIGHT, 0);
if(!window){
fprintf(stderr, "SDL create window failed\n");
return -1;
} renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(!renderer){
fprintf(stderr, "SDL create renderer failed\n");
return -1;
} texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, DEF_WIDTH, DEF_HEIGHT);
if(!renderer){
fprintf(stderr, "SDL create renderer failed\n");
return -1;
}
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);

创建用于存储图像像素数据的缓冲区,并打开yuv文件,以供后续读取图像

    YPlane = (unsigned char *)malloc(DEF_WIDTH*DEF_HEIGHT);
UPlane = (unsigned char *)malloc(DEF_WIDTH*DEF_HEIGHT/4);
VPlane = (unsigned char *)malloc(DEF_WIDTH*DEF_HEIGHT/4); pFile = fopen(argv[1], "rb");
if(pFile==NULL)
return -1;

显示

循环读取图像进入缓冲区,然后把图像传入texture进行包装、渲染、最后输出,每帧间隔为1/24秒。对于视频子系统来说,还有一个必不可少的步骤,就是在循环中调用SDL_PumpEvents。SDL_PumpEvents如其名称,主要的功能是推动event队列以进行队列状态的更新,不过它还有一个作用是进行视频子系统的设备状态更新,如果不调用这个函数,所显示的视频会在大约10秒后丢失色彩。

    while(1){
sizeY = fread(YPlane, 1, DEF_WIDTH*DEF_HEIGHT, pFile);
sizeU = fread(UPlane, 1, DEF_WIDTH*DEF_HEIGHT/4, pFile);
sizeV = fread(VPlane, 1, DEF_WIDTH*DEF_HEIGHT/4, pFile);
if(!sizeY||!sizeU||!sizeV)
break;
if(0!=SDL_UpdateYUVTexture(texture, NULL, YPlane, DEF_WIDTH, UPlane, DEF_WIDTH/2, VPlane, DEF_WIDTH/2)){
fprintf(stdout, "Render Update Texture failed, reason: %s\n", SDL_GetError());
}
SDL_RenderCopyEx(renderer, texture, NULL, NULL, 0, NULL, 0);
SDL_RenderPresent(renderer);
SDL_Delay(1000/FRAMERATE); SDL_PumpEvents();
}

退出

退出前的收尾处理

    SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
free(YPlane);
free(UPlane);
free(VPlane);
fclose(pFile);

[SimplePlayer] 2. 在屏幕上显示视频图像的更多相关文章

  1. 在屏幕上显示C盘根目录下的所有文件和文件夹

    1 import java.io.File; //在屏幕上显示C盘根目录下的所有文件和文件夹 public class ListDemo { public static void main(Strin ...

  2. 怎样在屏幕上显示多个alv

    本文解说怎样在屏幕上显示多个alv. 实现这种需求关键是下面几点(举例:在屏幕上显示4个alv): 1.须要定义4个alv control 2.由于有4个alv control,于是就须要定义4个容器 ...

  3. Android视频录制从不入门到入门系列教程(二)————显示视频图像

    1.创建一个空的工程,注意声明下列权限: <uses-permission android:name="android.permission.CAMERA"/> < ...

  4. linux tail-在屏幕上显示指定文件的末尾若干行

    博主推荐:获取更多 linux文件内容查看命令 收藏:linux命令大全 tail命令用于输入文件中的尾部内容.tail命令默认在屏幕上显示指定文件的末尾10行.如果给定的文件不止一个,则在显示的每个 ...

  5. 【opengl】OpenGL中三维物体显示在二维屏幕上显示的变换过程

    转自:http://blog.sina.com.cn/s/blog_957b9fdb0100zesv.html 为了说明在三维物体到二维图象之间,需要经过什么样的变换,我们引入了相机(Camera)模 ...

  6. Droid@screen:在PC屏幕上显示Android手机屏幕

    这里介绍一款工具——Droid@screen,用来获取手机屏幕,显示在PC屏幕上.它集截图.录像等多种功能于一体. 安装 1.    下载地址:http://droid-at-screen.org/d ...

  7. iOS开发中获取视图在屏幕上显示的位置

    在iOS开发中,我们会经常遇到一个问题,例如,点击一个按钮,弹出一个遮罩层,上面显示一个弹框,弹框显示的位置在按钮附近.如果这个按钮的位置相对于屏幕边缘的距离是固定的,那就容易了,可以直接写死位置.可 ...

  8. 30、在LCD上显示摄像头图像

    1. 准备虚拟机2.安装工具链sudo tar xjf arm-linux-gcc-4.3.2.tar.bz2 -C /设置环境变量:sudo vi /etc/environment : PATH=& ...

  9. ProgressDialog(三)——代号为中心的屏幕上显示ProgressDialog(ProgressBar)

    MainActivity如下面: package cc.testprogressdialog; import android.os.Bundle; import android.view.Gravit ...

随机推荐

  1. HTML的概念和三大基石以及标准文档结构

    HTML的概念: 概念:  HTML:超文本标记语言 作用:  需要将java在后台根据用户请求处理的请求结果在浏览器中显示给用户.  在浏览器中数据需要使用友好的格式展示给用户.  HTML是告诉浏 ...

  2. Html5: Drawing with text

    <!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...

  3. splay详解(二)

    前言 在上一节中,我们讲述了Splay的核心操作rotate与splay 本节我会教大家如何用这两个函数实现各种强大的功能 为了方便讲解,我们拿这道题做例题来慢慢分析 利用splay实现各种功能 首先 ...

  4. 42.Odoo产品分析 (四) – 工具板块(10) – 问卷(2)

    查看Odoo产品分析系列--目录 接上一篇Odoo产品分析 (四) – 工具板块(10) – 问卷(1) 4 页面 即问卷,点开一项查看:  可以看出,网页就是问卷本身的子目录,其中指明了该目录包括哪 ...

  5. Vysor Pro破解助手

    Vysor更新到1.7.7版本后,原来提供的VysorPro助手无法正常破解了. 针对新版本的改动,更新了一下Vysor破解助手,支持破解Vysor 1.6.6和Vysor1.7.7之间的版本. Vy ...

  6. Dagger2源码浅析

    dagger2是目前android端比较火的一款依赖注入框架,先来看下基本的用法吧: 首先提供module,类似于工厂: @Module public class ApiServiceModule { ...

  7. 操作系统:修改VirtualBox for Mac的虚拟硬盘大小

    我安装的是Mac版的VirtualBox,不能从GUI上修改硬盘大小,但是实在是大小不够用了. 百度后得知,可以用命令行修改. 1.打开终端,输入sudo su,取得管理员权限 $ sudo su P ...

  8. AngularJS学习之旅—AngularJS Scope作用域(五)

    1.AngularJS Scope(作用域) Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带. Scope 是一个对象,有可用的方法和属性. Sco ...

  9. c/c++ 网络编程 UDP 发送端 bind 作用

    网络编程 UDP 发送端 bind 作用 upd 发送端 调用bind函数的效果:把socket特定到一个指定的端口,如果不调用bind,内核会随机分配一个端口. upd 发送端 调用bind函数的目 ...

  10. iOS中Realm数据库的基本用法

      原文  http://git.devzeng.com/blog/simple-usage-of-realm-in-ios.html 主题 RealmiOS开发 Realm是由 Y Combinat ...