SDL播放视频

SDL视频播放

SDL视频显示的流程

这里写图片描述

SDL视频显示函数简介

SDL_Init():初始化SDL系统
SDL_GreateWindow():创建窗口SDL_Window
SDL_GreateRenderer():创建渲染器SDL_Renderer
SDL_GreateTexture():创建纹理SDL_Texture
SDL_UpdateTexture():设置纹理的数据
SDL_RenderCopy():将纹理的数据拷贝给渲染器
SDL_RenderPresent():显示
SDL_Delay():工具函数,用于延时。
SDL_Quit():退出SDL系统

视频显示的数据结构

这里写图片描述

SDL数据结构简介

SDL_Window:代表了一个“窗口”
SDL_Renderer:代表了一个“渲染器”
SDL_Texture:代表了一个“纹理”
SDL_Rect:一个简单的矩形结构

SDL多线程
函数
SDL_GreateThread():创建一个线程
数据结构
SDL_Thread:线程的句柄
SDL事件
函数
SDL_WaitEvent():等待一个事件
SDL_PushEvent():发送一个事件
数据结构
SDL_Event:代表一个事件

代码

#include <jni.h>
#include <android/log.h>

#define  LOG_I(...) __android_log_print(ANDROID_LOG_ERROR,"main",__VA_ARGS__)

#include "SDL.h"

//测试SDL环境
//int main(int argc, char *argv[]){
//    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == -1){
//        LOG_I("SDL_Init failed %s",SDL_GetError());
//        return 0;
//    }
//    LOG_I("SDL_Init Success!");
//
//    SDL_Quit();
//    return 0;
//}

//利用SDL播放YUV视频像素数据
int main(int argc, char *argv[]){
    //初始化SDL组件
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == -1){
        LOG_I("SDL_Init failed %s",SDL_GetError());
        return 0;
    }
    LOG_I("SDL_Init Success!");
    int screen_width = 3130;
    int screen_height = 1914;
    int frame_width = screen_width;
    int frame_height = screen_height;
    //创建SDL_Window
    //参数一:The title of the window, in UTF-8 encoding.窗口的标题
    //参数二:The x position of the window, ::SDL_WINDOWPOS_CENTERED, or ::SDL_WINDOWPOS_UNDEFINED.窗口出现的位置X
    //参数三:The y position of the window, ::SDL_WINDOWPOS_CENTERED, or  ::SDL_WINDOWPOS_UNDEFINED.窗口出现的位置Y
    //参数四:The width of the window, in screen coordinates.窗口的大小宽
    //参数五:The height of the window, in screen coordinates.窗口的大小高
    //参数六:The flags for the window, a mask of any of the following:  窗口的 状态,支持下列标识。包括了窗口的是否最大化、最小化,能否调整边界等等属性
    //SDL_WINDOW_SHOWN,表示显示窗口;不过我更喜欢SDL_WINDOW_BORDERLESS,这样。。SDL2创建的窗口就没有那些标题和窗口的最大化之类的按键了 ;最后一个参数是可选参数,
    //::SDL_WINDOW_FULLSCREEN,    ::SDL_WINDOW_OPENGL,
    //::SDL_WINDOW_HIDDEN,        ::SDL_WINDOW_BORDERLESS,
    //::SDL_WINDOW_RESIZABLE,     ::SDL_WINDOW_MAXIMIZED,
    //::SDL_WINDOW_MINIMIZED,     ::SDL_WINDOW_INPUT_GRABBED,
    //::SDL_WINDOW_ALLOW_HIGHDPI.
    SDL_Window *sdl_window = SDL_CreateWindow(
            "SDL_Window_Title"
            ,SDL_WINDOWPOS_CENTERED
            ,SDL_WINDOWPOS_CENTERED
            ,screen_width
            ,screen_height
            ,SDL_WINDOW_OPENGL|SDL_WINDOW_BORDERLESS);
    if(sdl_window == NULL){
        LOG_I("SDL_window创建失败");
        return -1;
    }
    //创建SDL_Renderer渲染器
//    参数含义如下:
//    window : 渲染的目标窗口。
//    index:打算初始化的渲染设备的索引。设置“-1”则初始化默认的渲染设备。
//    flags :支持以下值(位于SDL_RendererFlags定义中)
//    SDL_RENDERER_SOFTWARE :使用软件渲染
//    SDL_RENDERER_ACCELERATED :使用硬件加速
//    SDL_RENDERER_PRESENTVSYNC:和显示器的刷新率同步
//    SDL_RENDERER_TARGETTEXTURE :不太懂
//    返回创建完成的渲染器的ID。如果创建失败则返回NULL。
    SDL_Renderer *sdl_renderer = SDL_CreateRenderer(sdl_window
            ,-1
            ,SDL_RENDERER_ACCELERATED);

    //SDL_Texture创建纹理
//    renderer:目标渲染器。
//    format :纹理的格式。后面会详述。
//    其中用了一个宏SDL_DEFINE_PIXELFORMAT用于将几种属性合并到一个格式中。下面我们看看一个格式都包含哪些属性:
    //    SDL_PIXELTYPE_PACKED32:代表了像素分量的存储方式。PACKED代表了像素的几个分量是一起存储的,内存中存储方式如下:R1|G1|B1,R2|G2|B2…;ARRAY则代表了像素的几个分量是分开存储的,内存中存储方式如下:R1|R2|R3…,G1|G2|G3…,B1|B2|B3…
    //    SDL_PACKEDORDER_ARGB:代表了PACKED存储方式下像素分量的顺序。注意,这里所说的顺序涉及到了一个“大端”和“小端”的问题。这个问题在《最简单的视音频播放示例2:GDI播放YUV, RGB》中已经叙述,不再重复记录。对于Windows这样的“小端”系统,“ARGB”格式在内存中的存储顺序是B|G|R|A。
    //    SDL_PACKEDLAYOUT_8888:说明了每个分量占据的比特数。例如ARGB格式每个分量分别占据了8bit。
    //    32:每个像素占用的比特数。例如ARGB格式占用了32bit(每个分量占据8bit)。
    //    4:每个像素占用的字节数。例如ARGB格式占用了4Byte(每个分量占据1Byte)。
//    access :可以取以下值(定义位于SDL_TextureAccess中)
//    SDL_TEXTUREACCESS_STATIC   :变化极少
//    SDL_TEXTUREACCESS_STREAMING:变化频繁
//    SDL_TEXTUREACCESS_TARGET   :暂时没有理解
//    w :纹理的宽
//    h :纹理的高
//    创建成功则返回纹理的ID,失败返回0。
    SDL_Texture *sdl_texture = SDL_CreateTexture(sdl_renderer
            ,SDL_PIXELFORMAT_IYUV
            ,SDL_TEXTUREACCESS_TARGET
            ,screen_width
            ,screen_height);

    //设置纹理的数据
    FILE *file_yuv = fopen("/storage/emulated/0/qq_video.yuv","rb+");
    if(file_yuv == NULL){
        LOG_I("打开文件失败!");
        return -1;
    }

    SDL_Rect sdl_rect;
    char buffer_pixels[screen_width*screen_height*3/2];

    //循环读取YUV文件视频像素数据每一帧画面,进行渲染
    while (true){
        //判断文件是否读取完毕(视频是否播放完成)
        if(feof(file_yuv)){
            break;
        }
//        buffer 用于接收数据的内存地址
//        size 要读的每个数据项的字节数,单位是字节
//        count 要读count个数据项,每个数据项size个字节.
//        stream file输入流
        fread(buffer_pixels,1,screen_width*screen_height*3/2,file_yuv);
//        texture:目标纹理。
//        rect:更新像素的矩形区域。设置为NULL的时候更新整个区域。
//        pixels:像素数据。
//        pitch:一行像素数据的字节数。
//        成功的话返回0,失败的话返回-1。
        SDL_UpdateTexture(sdl_texture,NULL,buffer_pixels,frame_width);
        //将纹理数据拷贝给渲染器
        sdl_rect.x = 0;
        sdl_rect.y = 0;
        sdl_rect.w = screen_width;
        sdl_rect.h = screen_height;
        //先清空帧画面,再重新绘制
        SDL_RenderClear(sdl_renderer);

//        renderer:渲染目标。
//        texture:输入纹理。
//        srcrect:选择输入纹理的一块矩形区域作为输入。设置为NULL的时候整个纹理作为输入。
//        dstrect:选择渲染目标的一块矩形区域作为输出。设置为NULL的时候整个渲染目标作为输出。
//        成功的话返回0,失败的话返回-1。
        SDL_RenderCopy(sdl_renderer,sdl_texture,NULL,&sdl_rect);
        //显示帧画面
        SDL_RenderPresent(sdl_renderer);
        //延时渲染
        SDL_Delay(50);//延时50ms
    }
    //释放资源
    fclose(file_yuv);
    SDL_DestroyTexture(sdl_texture);
    SDL_DestroyRenderer(sdl_renderer);

    //退出SDL系统
    SDL_Quit();
    return 0;
}

代码地址:CSDN地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值