SDL播放YUV——循环
#include "SDL.h"
#include "as_lesson_log.h"
#define PATH_YUV420 "/sdcard/output.yuv"
#define width 1280
#define height 720
extern "C" int yuv_main(int argc, char *argv[])
{
//根据分辨率计算Y,U,V的长度
int lenY = width * height;
int lenU = width * height / 4;
int lenV = width * height / 4;
Uint8 *pYBuf = (Uint8 *)malloc(lenY);
Uint8 *pUBuf = (Uint8 *)malloc(lenU);
Uint8 *pVBuf = (Uint8 *)malloc(lenV);
FILE *pFile = fopen(PATH_YUV420, "rb");
if (pFile == NULL) {
LOGE("%s %d load yuv failed", __FUNCTION__, __LINE__);
return -1;
}
//初始化SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == -1) {
LOGE("SDL_Init failed %s", SDL_GetError());
return -1;
}
SDL_Window *window = SDL_CreateWindow("SDL_WINDOW_TITLE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); //渲染器
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, width, height); //纹理是渲染的内容
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = width;
rect.h = height;
while (true) {
if ((fread((void *)pYBuf, 1, lenY, pFile) == 0 || fread((void *)pUBuf, 1, lenU, pFile) == 0 || fread((void *)pVBuf, 1, lenV, pFile) == 0)) {
LOGI("SDL_file-end");
break;
}
SDL_UpdateYUVTexture(texture, &rect, pYBuf, width, pUBuf, width / 2, pVBuf, width / 2);
//下面开始显示纹理
SDL_RenderClear(renderer);
// SDL_RenderCopy(renderer, texture, NULL, &rect);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
SDL_Delay(45);
}
fclose(pFile);
free((void *)pYBuf);
free((void *)pUBuf);
free((void *)pVBuf);
return 0;
}
思路:
while (true) {
如果YUV读取完,退出
YUV渲染
SDL_Delay(45); //加这个延时进行伪帧率控制。45ms放一帧。22.2帧每秒,167X45=7.5s放完
//Delay 40ms,25FPS 40X25 = 1000ms=1s
}
问题点:
1,播放时候,视频不能全屏。
有2个关键函数,SDL_UpdateYUVTexture和SDL_RenderCopy,
一个是设置纹理,一个是把纹理放到渲染器。
只需要把输出到目标渲染器的窗口设为null就行,之前设为原始视频的大小。
2,第一次可以放,第二次不行。
加了创建失败的调制信息后发现
那是c最后退出时候,没加SDL_Quit(); 所以窗口没回收,第二次创建时候,窗口创建失败。看日志
2019-04-18 16:02:18.741 29208-29208/com.gx123.net_wifi.leesoo V/SDL: Window size: 1920x1008
2019-04-18 16:02:18.748 29208-29674/com.gx123.net_wifi.leesoo I/SDL: SDL_Android_Init()
2019-04-18 16:02:18.748 29208-29674/com.gx123.net_wifi.leesoo I/SDL: SDL_Android_Init() finished!
2019-04-18 16:02:18.749 29208-29674/com.gx123.net_wifi.leesoo E/as_lesson: SDL_CreateWindow failed Android only supports one window
2019-04-18 16:02:18.749 29208-29674/com.gx123.net_wifi.leesoo E/as_lesson: SDL_CreateRenderer failed Invalid window
2019-04-18 16:02:18.749 29208-29674/com.gx123.net_wifi.leesoo E/as_lesson: yuv_main 47 createtexture failed Invalid renderer
疑惑点;
1, 渲染器和纹理的对应关系和显示大小比例。
纹理比喻画布? 没有存数据,只是把数据信息最后给渲染器 ?
纹理大,渲染器小,会显示不全,纹理小,渲染器大,会有黑边。
http://www.hewebgl.com/article/getarticle/108
2,怎么循环渲染每一帧。怎么知道这一帧渲染完了到下一帧
解决2:文件读取函数fread 发挥作用了。
size_t fread( void *buffer, size_t size, size_t count, FILE *stream )
buffer 是读取的数据存放的内存的指针
size 是每次读取的字节数
count 一共要读取次数
strean 是要读取的文件的指针
例如 从文件fp里读取100个字节 可用以下3个语句
fread(buffer,100,1,fp)
fread(buffer,50,2,fp)
fread(buffer,1,100,fp)
fread每调用一次,文件指针都会往下移动,缓冲区会更新。
A,本文的用法。
if ((fread((void *)pYBuf, 1, lenY, pFile) == 0 || fread((void *)pUBuf, 1, lenU, pFile) == 0 || fread((void *)pVBuf, 1, lenV, pFile) == 0))
YUV3个缓存分开,一次读3个缓存更新。 读取次数是一帧图像的YUV个数。
调用读Y数据,接着调用读U数据,再调用读V数据。
最终更新时候 pYBuf 有 W*H 个字节,pUBuf有 W*H/4个 字节,pVBuf有 W*H/4个 字节
然后把3个分量更新SDL_UpdateYUVTexture
下次再循环读取(fread((void *)pYBuf, 1, lenY, pFile 时候,pFile的文件指针已经指向下一帧了。
B,Tony用法
加载完YUV帧,还考虑数据对其。
C,其他文章
if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){
// Loop
fseek(fp, 0, SEEK_SET);
i--;
continue;
}
//更新纹理数据
SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w);
这个就是一次读取一帧,这帧包含YUV3个。 然后把这帧缓冲区放到纹理上去。
纹理一次渲染一帧,不是一个yuv3字节的点。
SDL播放YUV——循环的更多相关文章
- FFMPEG学习----使用SDL播放YUV数据
命令行下配置: G:\Coding\Video\SDL\proj>tree /F 文件夹 PATH 列表 卷序列号为 0FD5-0CC8 G:. │ sdl.cpp │ SDL2.dll │ S ...
- 【转载】使用SDL播放YUV图像数据(转)
SDL提供了针对YUV格式数据的直接写屏操作.废话不多说,直接上代码吧/** * file showyuv.c * author: rare * date: 2009/12/06 * email: d ...
- SDL 开发实战(六): 使用 SDL 实现 YUV 播放器
前面铺垫了这么多,现在终于进入核心的主题了,那就是使用SDL播放视频,本节我们将使用SDL播放YUV视频,也就是做一个YUV播放器. 下面说明一下使用SDL播放YUV视频的基本流程,主要分为两大部分: ...
- 最简单的视音频播放示例3:Direct3D播放YUV,RGB(通过Surface)
上一篇文章记录了GDI播放视频的技术.打算接下来写两篇文章记录Direct3D(简称D3D)播放视频的技术.Direct3D应该Windows下最常用的播放视频的技术.实际上视频播放只是Direct3 ...
- 最简单的视音频播放示例2:GDI播放YUV, RGB
前一篇文章对“Simplest Media Play”工程作了概括性介绍.后续几篇文章打算详细介绍每个子工程中的几种技术.在记录Direct3D,OpenGL这两种相对复杂的技术之前,打算先记录一种和 ...
- SDL播放YUV----单帧
用到的项目:Tocy-Android-SDLv2 C中的 入口: main.c as_lesson_XXX.c bmp_main : 在C中定义文件的路径: char *filepath = &quo ...
- 最简单的视音频播放演示样例3:Direct3D播放YUV,RGB(通过Surface)
===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频 ...
- SDL开发笔记(二):音频基础介绍、使用SDL播放音频
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- MFC中使用SDL播放音频没有声音的解决方法
本文所说的音频是指的纯音频,不包含视频的那种. 在控制台中使用SDL播放音频,一般情况下不会有问题. 但是在MFC中使用SDL播放音频的时候,会出现没有声音的情况.经过长时间探索,没有找到特别好的解决 ...
随机推荐
- Dubbo源码构建
代码签出 通过以下的这个命令签出最新的项目源码: git clone https://github.com/apache/incubator-dubbo.git dubbo 分支 我们使用 maste ...
- json、demjson
一.json 概述: json.dumps():将 Python 对象编码成 JSON 字符串, dic -> json str json.dump() :将 Python 对象保存成 JSO ...
- 【js高程学习笔记】关于变量值和函数参数
变量包含了两种不同类型的值: 基本类型 (Undefined.null.Boolean.Number.string都属于基本类型) 引用类型 (对象) 两种值在赋值上不同的是: 将一个引用类型的值(对 ...
- datatable 添加列之前判断是否存在该列
if (!dt.Columns.Contains("BDate")) { DataColumn dc1 = new DataColumn("BDate", ty ...
- Java多线程之线程状态总结
概述 线程大家肯定不陌生,对于线程中的运行状态,自己经常搞混淆,这边按照下图记录下: 线程一般来说有如下几种状态: 新建,可运行,超时阻塞,等待阻塞,同步阻塞,死亡 yeild:当线程执行了yield ...
- if -----if else语句
if语句是用来进行判断的,其使用格式如下: 单分支 if 判断的条件: 满足条件后要执行的代码 双分支 if 条件: 满足条件执行代码 else: if条件不满足就走这段 这里必须要插入这个缩进的知识 ...
- apk的api级别不要低于26
谷歌要求 api级别 最低26, 在用 xbuliber打包app的时候,可以在 manifest.json增加下面的代码. "plus": { "distribute& ...
- struts校验
Struts2 校验框架 Struts2 和Struts1同样也提供了校验框架,但在Struts2 已经不再把校验框架做为一个插件,而是已经内置到了Struts2中,而且配置起来更为简单方便,功能也更 ...
- pypyodbc 的坑
1, 你要先确认你自己的office的版本, 你要安装access dabase engine. 但是 sb 微软的驱动 32位的不让装, 64位的也不让装, 吐槽微软100次---MS个大SX. 最 ...
- 使用numpy与matplotlib.pyplot画图
使用numpy与matplotlib.pyplot画图 1. 折线图 1 # -*- enccoding:utf-8 -*- 2 import numpy as np 3 import matplot ...