golang调用sdl2,播放yuv视频

    win10 x64下测试成功,其他操作系统下不保证成功。

    采用的是syscall方式,不是cgo方式。

    见地址

    代码如下:

    1. package main
    2. import (
    3. "fmt"
    4. "github.com/moonfdd/sdl2-go/sdl"
    5. "github.com/moonfdd/sdl2-go/sdlcommon"
    6. "io/ioutil"
    7. "time"
    8. "unsafe"
    9. )
    10. const REFRESH_EVENT = sdl.SDL_USEREVENT + 1 // 请求画面刷新事件
    11. const QUIT_EVENT = sdl.SDL_USEREVENT + 2 // 退出事件
    12. //定义分辨率
    13. // YUV像素分辨率
    14. const YUV_WIDTH = 320
    15. const YUV_HEIGHT = 240
    16. //定义YUV格式
    17. const YUV_FORMAT = sdl.SDL_PIXELFORMAT_IYUV
    18. var s_thread_exit = 0 // 退出标志 = 1则退出
    19. func main() {
    20. sdlcommon.SetSDL2Path("SDL2.dll")
    21. sdl.SDL_Init(sdl.SDL_INIT_VIDEO)
    22. pixformat := YUV_FORMAT
    23. // 分辨率
    24. // 1. YUV的分辨率
    25. video_width := int32(YUV_WIDTH)
    26. video_height := int32(YUV_HEIGHT)
    27. // 2.显示窗口的分辨率
    28. win_width := int32(YUV_WIDTH)
    29. win_height := int32(YUV_WIDTH)
    30. y_frame_len := video_width * video_height
    31. u_frame_len := video_width * video_height / 4
    32. v_frame_len := video_width * video_height / 4
    33. yuv_frame_len := y_frame_len + u_frame_len + v_frame_len
    34. window := sdl.SDL_CreateWindow("微信公众号:福大大架构师每日一题", sdl.SDL_WINDOWPOS_UNDEFINED, sdl.SDL_WINDOWPOS_UNDEFINED, video_width, video_height, sdl.SDL_WINDOW_OPENGL|sdl.SDL_WINDOW_RESIZABLE)
    35. if window == nil {
    36. fmt.Printf("Can't create window, err:%s", sdl.SDL_GetError())
    37. return
    38. }
    39. renderer := window.SDL_CreateRenderer(-1, 0)
    40. texture := renderer.SDL_CreateTexture(uint32(pixformat), sdl.SDL_TEXTUREACCESS_STREAMING, video_width, video_height)
    41. var event sdl.SDL_Event
    42. var rect sdl.SDL_Rect
    43. fileData, err := ioutil.ReadFile("yuv420p_320x240.yuv")
    44. if err != nil {
    45. fmt.Println("读取文件失败", err)
    46. return
    47. }
    48. //创建请求刷新线程
    49. go func() {
    50. for s_thread_exit == 0 {
    51. var event sdl.SDL_Event
    52. event.Type = REFRESH_EVENT
    53. event.SDL_PushEvent()
    54. time.Sleep(40 * time.Millisecond)
    55. }
    56. s_thread_exit = 0
    57. var event sdl.SDL_Event
    58. event.Type = QUIT_EVENT
    59. event.SDL_PushEvent()
    60. }()
    61. for {
    62. // 收取SDL系统里面的事件
    63. event.SDL_WaitEvent()
    64. if event.Type == REFRESH_EVENT { // 画面刷新事件
    65. if len(fileData) < int(yuv_frame_len) {
    66. break
    67. }
    68. video_buf := fileData[0:yuv_frame_len]
    69. fileData = fileData[yuv_frame_len:]
    70. // 设置纹理的数据 video_width = 320, plane
    71. texture.SDL_UpdateTexture(nil, uintptr(unsafe.Pointer(&video_buf[0])), video_width)
    72. // 显示区域,可以通过修改w和h进行缩放
    73. rect.X = 0
    74. rect.Y = 0
    75. //w_ratio := win_width * 1.0 / video_width
    76. //h_ratio := win_height * 1.0 / video_height
    77. //// 320x240 怎么保持原视频的宽高比例
    78. //rect.W = video_width * w_ratio
    79. //rect.H = video_height * h_ratio
    80. rect.W = win_width
    81. rect.H = win_height
    82. // 清除当前显示
    83. renderer.SDL_RenderClear()
    84. // 将纹理的数据拷贝给渲染器
    85. renderer.SDL_RenderCopy(texture, nil, &rect)
    86. // 显示
    87. renderer.SDL_RenderPresent()
    88. } else if event.Type == sdl.SDL_WINDOWEVENT {
    89. window.SDL_GetWindowSize(&win_width, &win_height)
    90. } else if event.Type == sdl.SDL_QUIT {
    91. s_thread_exit = 1
    92. } else if event.Type == QUIT_EVENT {
    93. break
    94. }
    95. }
    96. texture.SDL_DestroyTexture()
    97. renderer.SDL_DestroyRenderer()
    98. window.SDL_DestroyWindow()
    99. sdl.SDL_Quit()
    100. }

    执行结果如下:

    golang调用sdl2,播放yuv视频 - 图1