FFMPEG学习----使用SDL播放YUV数据
命令行下配置:
G:\Coding\Video\SDL\proj>tree /F
文件夹 PATH 列表
卷序列号为 0FD5-0CC8
G:.
│ sdl.cpp
│ SDL2.dll
│ SDL2.lib
│ SDL2main.lib
│ sintel_640_360.yuv
│ test_yuv420p_320x180.yuv
│
└─sdl
begin_code.h
close_code.h
SDL.h
SDL_assert.h
SDL_atomic.h
SDL_audio.h
SDL_bits.h
SDL_blendmode.h
SDL_clipboard.h
SDL_config.h
SDL_cpuinfo.h
SDL_egl.h
SDL_endian.h
SDL_error.h
SDL_events.h
SDL_filesystem.h
SDL_gamecontroller.h
SDL_gesture.h
SDL_haptic.h
SDL_hints.h
SDL_joystick.h
SDL_keyboard.h
SDL_keycode.h
SDL_loadso.h
SDL_log.h
SDL_main.h
SDL_messagebox.h
SDL_mouse.h
SDL_mutex.h
SDL_name.h
SDL_opengl.h
SDL_opengles.h
SDL_opengles2.h
SDL_opengles2_gl2.h
SDL_opengles2_gl2ext.h
SDL_opengles2_gl2platform.h
SDL_opengles2_khrplatform.h
SDL_opengl_glext.h
SDL_pixels.h
SDL_platform.h
SDL_power.h
SDL_quit.h
SDL_rect.h
SDL_render.h
SDL_revision.h
SDL_rwops.h
SDL_scancode.h
SDL_shape.h
SDL_stdinc.h
SDL_surface.h
SDL_system.h
SDL_syswm.h
SDL_test.h
SDL_test_assert.h
SDL_test_common.h
SDL_test_compare.h
SDL_test_crc32.h
SDL_test_font.h
SDL_test_fuzzer.h
SDL_test_harness.h
SDL_test_images.h
SDL_test_log.h
SDL_test_md5.h
SDL_test_random.h
SDL_thread.h
SDL_timer.h
SDL_touch.h
SDL_types.h
SDL_version.h
SDL_video.h G:\Coding\Video\SDL\proj>dir
驱动器 G 中的卷没有标签。
卷的序列号是 0FD5-0CC8 G:\Coding\Video\SDL\proj 的目录 2016/08/20 09:19 <DIR> .
2016/08/20 09:19 <DIR> ..
2016/01/02 11:39 <DIR> sdl
2016/08/20 09:17 1,757 sdl.cpp
2016/01/02 11:58 1,047,552 SDL2.dll
2016/01/02 11:39 120,400 SDL2.lib
2016/01/02 11:39 37,594 SDL2main.lib
2015/07/03 01:39 34,560,000 sintel_640_360.yuv
2014/10/13 15:50 4,320,000 test_yuv420p_320x180.yuv
6 个文件 40,087,303 字节
3 个目录 10,272,571,392 可用字节 G:\Coding\Video\SDL\proj>
源码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h> extern "C"
{
#include "SDL.h"
}; int main(int argc, char* argv[])
{
//窗口
SDL_Window *sdlScreen;
//渲染器
SDL_Renderer* sdlRenderer;
//纹理
SDL_Texture* sdlTexture;
//矩形结构
SDL_Rect sdlRect; const int bpp = 12;
//屏幕宽高
int screen_w = 640, screen_h = 360;
const int pixel_w = 640, pixel_h = 360;
unsigned char buffer[pixel_w * pixel_h * bpp / 8];
char filename[] = "sintel_640_360.yuv"; FILE *fp = NULL;
fp = fopen(filename, "rb+"); if (fp == NULL)
{
printf("cannot open this file\n");
return -1;
} //初始化SDL系统
if (SDL_Init(SDL_INIT_VIDEO))
{
printf("Could not initialize SDL - %s\n", SDL_GetError());
return -1;
} //创建窗口SDL_Window
/**
* 函数声明:extern DECLSPEC SDL_Window * SDLCALL
* SDL_CreateWindow(const char *title,int x, int y, int w, int h, Uint32 flags);
* \brief Create a window with the specified position, dimensions, and flags.
*
* \param title The title of the window, in UTF-8 encoding.
* \param x The x position of the window, ::SDL_WINDOWPOS_CENTERED, or
* ::SDL_WINDOWPOS_UNDEFINED.
* \param y The y position of the window, ::SDL_WINDOWPOS_CENTERED, or
* ::SDL_WINDOWPOS_UNDEFINED.
* \param w The width of the window, in screen coordinates.
* \param h The height of the window, in screen coordinates.
* \param flags The flags for the window, a mask of any of the following:
* ::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.
*
* \return The id of the window created, or zero if window creation failed.
*
* If the window is created with the SDL_WINDOW_ALLOW_HIGHDPI flag, its size
* in pixels may differ from its size in screen coordinates on platforms with
* high-DPI support (e.g. iOS and Mac OS X). Use SDL_GetWindowSize() to query
* the client area's size in screen coordinates, and SDL_GL_GetDrawableSize()
* or SDL_GetRendererOutputSize() to query the drawable size in pixels.
*
* \sa SDL_DestroyWindow()
*/
sdlScreen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (sdlScreen == 0)
{
printf("SDL: could not create SDL_Window - exiting:%s\n", SDL_GetError());
return -1;
}
//创建渲染器SDL_Renderer
/**
* 函数声明:extern DECLSPEC SDL_Renderer * SDLCALL
* SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags);
* \brief Create a 2D rendering context for a window.
*
* \param window The window where rendering is displayed.
* \param index The index of the rendering driver to initialize, or -1 to
* initialize the first one supporting the requested flags.
* \param flags ::SDL_RendererFlags.
*
* \return A valid rendering context or NULL if there was an error.
*
* \sa SDL_CreateSoftwareRenderer()
* \sa SDL_GetRendererInfo()
* \sa SDL_DestroyRenderer()
*/
sdlRenderer = SDL_CreateRenderer(sdlScreen, -1, SDL_RENDERER_ACCELERATED);
if (sdlRenderer == NULL)
{
printf("SDL: could not create SDL_Renderer - exiting:%s\n", SDL_GetError());
return -1;
} //IYUV: Y + U + V (3 planes)
//YV12: Y + V + U (3 planes) //创建纹理SDL_Texture
/**
* 函数声明:extern DECLSPEC SDL_Texture * SDLCALL
* SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h);
* \brief Create a texture for a rendering context.
*
* \param renderer The renderer.
* \param format The format of the texture.
* \param access One of the enumerated values in ::SDL_TextureAccess.
* \param w The width of the texture in pixels.
* \param h The height of the texture in pixels.
*
* \return The created texture is returned, or NULL if no rendering context was
* active, the format was unsupported, or the width or height were out
* of range.
*
* \sa SDL_QueryTexture()
* \sa SDL_UpdateTexture()
* \sa SDL_DestroyTexture()
*/
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);
if (sdlTexture == NULL)
{
printf("SDL: could not create SDL_Texture - exiting:%s\n", SDL_GetError());
return -1;
} while (1)
{ //读取一帧数据
if (fread(buffer, 1, pixel_w * pixel_h * bpp / 8, fp) != pixel_w * pixel_h * bpp / 8)
{
//循环播放
fseek(fp, 0, SEEK_SET);
fread(buffer, 1, pixel_w * pixel_h * bpp / 8, fp);
} //设置纹理数据
/**
* 函数声明:extern DECLSPEC int SDLCALL
* SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch);
* \brief Update the given texture rectangle with new pixel data.
*
* \param texture The texture to update
* \param rect A pointer to the rectangle of pixels to update, or NULL to
* update the entire texture.
* \param pixels The raw pixel data.
* \param pitch The number of bytes in a row of pixel data, including padding between lines.
*
* \return 0 on success, or -1 if the texture is not valid.
*
* \note This is a fairly slow function.
*/
SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w); sdlRect.x = 0;
sdlRect.y = 0;
sdlRect.w = screen_w;
sdlRect.h = screen_h; /**
* 函数声明:extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer * renderer);
* \brief Clear the current rendering target with the drawing color
*
* This function clears the entire rendering target, ignoring the viewport.
*
* \return 0 on success, or -1 on error
*/
SDL_RenderClear(sdlRenderer); //将纹理数据拷贝给渲染器
/**
* 函数声明:extern DECLSPEC int SDLCALL
* SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect);
* \brief Copy a portion of the texture to the current rendering target.
*
* \param renderer The renderer which should copy parts of a texture.
* \param texture The source texture.
* \param srcrect A pointer to the source rectangle, or NULL for the entire
* texture.
* \param dstrect A pointer to the destination rectangle, or NULL for the
* entire rendering target.
*
* \return 0 on success, or -1 on error
*/
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect); //显示数据
/**
* 函数声明:extern DECLSPEC void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);
* \brief Update the screen with rendering performed.
*/
SDL_RenderPresent(sdlRenderer); //工具函数,用于延时,视频一般一秒播放25帧
/**
* 函数声明:extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms);
* \brief Wait a specified number of milliseconds before returning.
*/
SDL_Delay(40); } SDL_DestroyTexture(sdlTexture);
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow(sdlScreen);
SDL_Quit();
return 0;
}
命令行下:
多线程版本:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h> extern "C"
{
#include "SDL.h"
}; //Refresh Event
#define REFRESH_EVENT (SDL_USEREVENT + 1)
//Break
#define BREAK_EVENT (SDL_USEREVENT + 2) bool thread_exit = false; int RefreshVideo(void *opaque)
{
thread_exit = false;
while (!thread_exit)
{
SDL_Event event;
event.type = REFRESH_EVENT;
SDL_PushEvent(&event);
SDL_Delay(40);
}
thread_exit = false;
//Break
SDL_Event event;
event.type = BREAK_EVENT;
SDL_PushEvent(&event);
return 0;
} int main(int argc, char* argv[])
{
//窗口
SDL_Window *sdlScreen = NULL;
//渲染器
SDL_Renderer* sdlRenderer = NULL;
//纹理
SDL_Texture* sdlTexture = NULL;
//矩形结构
SDL_Rect sdlRect;
SDL_Thread *sdlThread = NULL;
SDL_Event event; //屏幕宽高
int screen_w = 640, screen_h = 360;
const int pixel_w = 640, pixel_h = 272;
unsigned char buffer[pixel_w * pixel_h * 3 / 2];
char filename[] = "film_640_272.yuv";
int i = 1; FILE *fp = NULL;
fp = fopen(filename, "rb+"); if (fp == NULL)
{
printf("cannot open this file\n");
return -1;
} //初始化SDL系统
if (SDL_Init(SDL_INIT_VIDEO))
{
printf("Could not initialize SDL - %s\n", SDL_GetError());
return -1;
} //创建窗口SDL_Window
/**
* 函数声明:extern DECLSPEC SDL_Window * SDLCALL
* SDL_CreateWindow(const char *title,int x, int y, int w, int h, Uint32 flags);
* \brief Create a window with the specified position, dimensions, and flags.
*
* \param title The title of the window, in UTF-8 encoding.
* \param x The x position of the window, ::SDL_WINDOWPOS_CENTERED, or
* ::SDL_WINDOWPOS_UNDEFINED.
* \param y The y position of the window, ::SDL_WINDOWPOS_CENTERED, or
* ::SDL_WINDOWPOS_UNDEFINED.
* \param w The width of the window, in screen coordinates.
* \param h The height of the window, in screen coordinates.
* \param flags The flags for the window, a mask of any of the following:
* ::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.
*
* \return The id of the window created, or zero if window creation failed.
*
* If the window is created with the SDL_WINDOW_ALLOW_HIGHDPI flag, its size
* in pixels may differ from its size in screen coordinates on platforms with
* high-DPI support (e.g. iOS and Mac OS X). Use SDL_GetWindowSize() to query
* the client area's size in screen coordinates, and SDL_GL_GetDrawableSize()
* or SDL_GetRendererOutputSize() to query the drawable size in pixels.
*
* \sa SDL_DestroyWindow()
*/
sdlScreen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (sdlScreen == 0)
{
printf("SDL: could not create SDL_Window - exiting:%s\n", SDL_GetError());
return -1;
}
//创建渲染器SDL_Renderer
/**
* 函数声明:extern DECLSPEC SDL_Renderer * SDLCALL
* SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags);
* \brief Create a 2D rendering context for a window.
*
* \param window The window where rendering is displayed.
* \param index The index of the rendering driver to initialize, or -1 to
* initialize the first one supporting the requested flags.
* \param flags ::SDL_RendererFlags.
*
* \return A valid rendering context or NULL if there was an error.
*
* \sa SDL_CreateSoftwareRenderer()
* \sa SDL_GetRendererInfo()
* \sa SDL_DestroyRenderer()
*/
sdlRenderer = SDL_CreateRenderer(sdlScreen, -1, SDL_RENDERER_ACCELERATED);
if (sdlRenderer == NULL)
{
printf("SDL: could not create SDL_Renderer - exiting:%s\n", SDL_GetError());
return -1;
} //创建纹理SDL_Texture
/**
* 函数声明:extern DECLSPEC SDL_Texture * SDLCALL
* SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h);
* \brief Create a texture for a rendering context.
*
* \param renderer The renderer.
* \param format The format of the texture.
* \param access One of the enumerated values in ::SDL_TextureAccess.
* \param w The width of the texture in pixels.
* \param h The height of the texture in pixels.
*
* \return The created texture is returned, or NULL if no rendering context was
* active, the format was unsupported, or the width or height were out
* of range.
*
* \sa SDL_QueryTexture()
* \sa SDL_UpdateTexture()
* \sa SDL_DestroyTexture()
*/
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);
if (sdlTexture == NULL)
{
printf("SDL: could not create SDL_Texture - exiting:%s\n", SDL_GetError());
return -1;
} sdlThread = SDL_CreateThread(RefreshVideo, NULL, NULL); while (1)
{
SDL_WaitEvent(&event);
if (event.type == REFRESH_EVENT)
{
//读取一帧数据
int count = fread(buffer, 1, pixel_w * pixel_h * 3 / 2, fp);
if (count != pixel_w * pixel_h * 3 / 2)
{
break;
//循环播放
fseek(fp, 0, SEEK_SET);
i = 1;
fread(buffer, 1, pixel_w * pixel_h * 3 / 2, fp);
} //设置纹理数据
/**
* 函数声明:extern DECLSPEC int SDLCALL
* SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch);
* \brief Update the given texture rectangle with new pixel data.
*
* \param texture The texture to update
* \param rect A pointer to the rectangle of pixels to update, or NULL to
* update the entire texture.
* \param pixels The raw pixel data.
* \param pitch The number of bytes in a row of pixel data, including padding between lines.
*
* \return 0 on success, or -1 if the texture is not valid.
*
* \note This is a fairly slow function.
*/
SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w); sdlRect.x = 0;
sdlRect.y = 0;
sdlRect.w = screen_w;
sdlRect.h = screen_h; /**
* 函数声明:extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer * renderer);
* \brief Clear the current rendering target with the drawing color
*
* This function clears the entire rendering target, ignoring the viewport.
*
* \return 0 on success, or -1 on error
*/
SDL_RenderClear(sdlRenderer); //将纹理数据拷贝给渲染器
/**
* 函数声明:extern DECLSPEC int SDLCALL
* SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect);
* \brief Copy a portion of the texture to the current rendering target.
*
* \param renderer The renderer which should copy parts of a texture.
* \param texture The source texture.
* \param srcrect A pointer to the source rectangle, or NULL for the entire
* texture.
* \param dstrect A pointer to the destination rectangle, or NULL for the
* entire rendering target.
*
* \return 0 on success, or -1 on error
*/
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect); //显示数据
/**
* 函数声明:extern DECLSPEC void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);
* \brief Update the screen with rendering performed.
*/
SDL_RenderPresent(sdlRenderer);
printf("Play Frame %d\n", i++);
}
else if (event.type == SDL_WINDOWEVENT)
{
SDL_GetWindowSize(sdlScreen, &screen_w, &screen_h);
}
else if (event.type == BREAK_EVENT)
{
break;
}
else if (event.type == SDL_QUIT)
{
thread_exit = true;
}
} SDL_DestroyTexture(sdlTexture);
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow(sdlScreen);
SDL_Quit();
return 0;
}
FFMPEG学习----使用SDL播放YUV数据的更多相关文章
- FFMPEG学习----使用SDL播放PCM数据
参考雷神的代码: /** * 最简单的SDL2播放音频的例子(SDL2播放PCM) * Simplest Audio Play SDL2 (SDL2 play PCM) * * 本程序使用SDL2播放 ...
- FFmpeg学习3:播放音频
参考dranger tutorial,本文将介绍如何使用FFmpeg解码音频数据,并使用SDL将解码后的数据输出. 本文主要包含以下几方面的内容: 关于播放音频的需要的一些基础知识介绍 使用SDL2播 ...
- 【转载】使用SDL播放YUV图像数据(转)
SDL提供了针对YUV格式数据的直接写屏操作.废话不多说,直接上代码吧/** * file showyuv.c * author: rare * date: 2009/12/06 * email: d ...
- FFMPEG学习----使用SDL构建音频播放器
ffmpeg版本:ffmpeg-20160413-git-0efafc5 #include <stdio.h> #include <stdlib.h> #include < ...
- SDL播放YUV——循环
#include "SDL.h" #include "as_lesson_log.h" #define PATH_YUV420 "/sdcard/ou ...
- ffmpeg学习笔记-音频播放
前文讲到音频解码,将音频解码,并且输入到PCM文件,这里将音频通过AudioTrack直接输出 音频播放说明 在Android中自带的MediaPlayer也可以对音频播放,但其支持格式太少 使用ff ...
- FFMPEG学习----使用SDL构建视频播放器
#include <stdio.h> #include <string.h> extern "C" { #include "libavcodec/ ...
- ffplay播放YUV数据
播放器YUV系列的格式用ffplay很方便 免费的 播放NV21 ffplay -i d:/cap.yuv -pix_fmt nv21 -s 640x480 播放YUV420P ffplay -i d ...
- FFmpeg学习5:多线程播放视音频
在前面的学习中,视频和音频的播放是分开进行的.这主要是为了学习的方便,经过一段时间的学习,对FFmpeg的也有了一定的了解,本文就介绍了 如何使用多线程同时播放音频和视频(未实现同步),并对前面的学习 ...
随机推荐
- [gitHub实践] git基础:远程仓库的使用
[gitHub实践] git基础:远程仓库的使用 版权2019.6.2更新 git 基础 远程仓库的使用 git remote # 查看远程仓库 $ git remote # 克隆的仓库服务器默认名字 ...
- awsl
from enum import Enum, uniquefrom math import sqrtfrom random import randint import pygame @uniquecl ...
- LibreOJ 6278. 数列分块入门 2 题解
题目链接:https://loj.ac/problem/6278 题目描述 给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,询问区间内小于某个值 \(x\) 的元素个数. ...
- 使用Rancher Server部署本地多节点K8S集群
当我第一次开始我的Kubernetes之旅时,我一直在寻找一种设置本地部署环境的方式.很多人常常会使用minikube或microk8s,这两者非常适合新手在单节点集群环境下进行操作.但当我已经了解了 ...
- 交换机广播风暴,STP生成树协议,端口聚合
交换机(工作在数据链路层)具有学习功能: 一台刚重启的交换机上的mac地址表为空,根据数据包的来源,目的地来学习MAC地址与端口的映射关系映射关系,对于MAC地址表之中已有的就不管了,对未知端 ...
- 应届生/社招面试最爱问的几道Java基础问题
本文已经收录自笔者开源的 JavaGuide: https://github.com/Snailclimb ([Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识)如果觉得不错 ...
- js以当前时间为基础,便捷获取时间(最近2天,最近1周,最近2周,最近1月,最近2月,最近半年,最近一年,本周,本月,本年)
在开发公司管理后台系统时,遇到了需要根据不同的时间段如"近一年.近半年.近三月.近一月.近一周"来获取并展示不同图表数据的需求,很是繁琐,项目开发周期又非常的短,自己想了一下,虽然 ...
- js强制限制输入允许两位小数
<input type="text" value="@item.CostCash.Value.ToString("#0.00")" c ...
- Linux系统上安装配置MAVEN
1,下载maven 首先进入maven下载目录:http://maven.apache.org/download.cgi 2,上传maven到linux系统 以下操作路径都是本人习惯,目录可以随意更改 ...
- java jvm jre jdk三者的关系
jvm:java虚拟机器(跨平台的关键) jre:java运行环境 jdk:java 开发工具包(kit) jdk>jre>jvm 环境变量配置 https://www.cnblogs.c ...