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;
}

FFMPEG学习----使用SDL播放YUV数据

命令行下:

FFMPEG学习----使用SDL播放YUV数据

多线程版本:

#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;
}
上一篇:【Java面试题】30 子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。


下一篇:FFmpeg学习3:播放音频