首页 » 网站建设 » php视频播放器技巧_音视频开拓SDL播放器实战

php视频播放器技巧_音视频开拓SDL播放器实战

访客 2024-10-30 0

扫一扫用手机浏览

文章目录 [+]

2 SDL音视频播放根本API2.1 SDL根本组成

SDL将功能分成下列数个子系统,不同的子系统包含特定功能本文关注的几个模块包括音频、视频和事宜等子系统:

- SDL_INIT_TIMER:定时器- SDL_INIT_AUDIO:音频- SDL_INIT_VIDEO:视频- SDL_INIT_JOYSTICK:摇杆- SDL_INIT_HAPTIC:触摸屏- SDL_INIT_GAMECONTROLLER:游戏掌握器- SDL_INIT_EVENTS:事宜- SDL_INIT_EVERYTHING:包含上述所有选项

2.2 SDL视频模块

php视频播放器技巧_音视频开拓SDL播放器实战

2.2.1 视频API

php视频播放器技巧_音视频开拓SDL播放器实战
(图片来自网络侵删)

视频API三大控件窗口(window)、渲染器(renderer)、纹理(texture)。
窗口作为所有界面的载体卖力根本的窗口事宜的捕获和相应;渲染器则是将图像数据渲染成图像;纹理紧张是用来管理图像将图像数据加入到纹理,方便后续加载到渲染器。

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

2.2.2 视频构造体

视频根本:窗口、渲染器、纹理和矩形等工具。

- SDL_Window // 窗口 - SDL_Renderer // 渲染 - SDL_Texture // 纹理 - SDL_Rect // 矩形

2.2.2 音频API

音频API根本流程比较大略,首先是打开音频设备SDL_OpenAudio,并开启音频播放SDL_PauseAudio,利用音频回调函数SDL_AudioCallback将数据写入音频播放缓冲区播放SDL_MixAudio,末了关闭音频播放SDL_CloseAudio。

- SDL_Init():初始化SDL系统- SDL_OpenAudio():打开音频设备- SDL_AudioCallback():音频播放回调函数- SDL_PauseAudio():开启或者停息播放- SDL_MixAudio():将音频数据写入播放缓冲区- SDL_CloseAudio():关闭音频设备- SDL_Quit():退出SDL系统

3 SDL开拓环境构建3.1 SDL源码下载与编译

本文先容的是Linux下的环境搭建,紧张通过源码进行编译获取SDL动态库。
下载路径:https://www.libsdl.org/download-2.0.php

mkdir SDLcd SDLwget https://www.libsdl.org/release/SDL2-2.0.22.tar.gztar -xvf SDL2-2.0.22.tar.gzcd SDL2-2.0.22mkdir buildcmake ..make -j4

全体编译过程很顺利,终极会得到编译文件如下图,这里会用到个中libSDL2-2.0.so动态库文件和根目录下的include文件夹。

3.2 工程构建

得到SDL2动态库后,接下来便是进行工程构建,创建一个SDL_project工程目录,包含该标准bin、build、include、lib、src目录文件。
并且将依赖库拷贝到工程目录下。
基本框架就构建好了。

粉丝福利, 免费领取C++音视频学习资料包+学习路线大纲、技能视频/代码,内容包括(音视频开拓,口试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs),有须要的可以进企鹅裙927239107领取哦~

mkdir SDL_projectcd SDL_projectmkdir bin build include lib srccp ../SDL2-2.0.22/build/libSDL2-2.0.so ./lib/cp ../SDL2-2.0.22/include/ ./src/ -rftouch CMakeLists.txttouch ./src/CMakeLists.txt4 SDL大略单纯视频播放器

这里截取部分源码进行描述;

第一初始化根本构造;

创建窗口:SDL_CreateWindow创建渲染器:SDL_CreateRenderer创建纹理:SDL_CreateTexture创建刷新线程:SDL_CreateThread

第二是利用SDL_WaitEvent,相应不同SDL事宜,包括视频显示流程:

读取yuv文件

将视频缓冲数据更新到纹理:SDL_UpdateTexture;

清理渲染器:SDL_RenderClear

纹理拷贝到渲染器:SDL_RenderCopy

显示视频画面:SDL_RenderPresent

//SDL_CreateWindow window = SDL_CreateWindow("Simple YUV Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, video_width, video_height, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); if(!window) { fprintf(stderr, "SDL: could not create window, err:%s\n",SDL_GetError()); goto _FAIL; } // SDL_CreateRenderer renderer = SDL_CreateRenderer(window, -1, 0); // SDL_CreateTexture texture = SDL_CreateTexture(renderer, pixformat, SDL_TEXTUREACCESS_STREAMING, video_width, video_height); video_buf = (uint8_t)malloc(yuv_frame_len); if(!video_buf) { fprintf(stderr, "Failed to alloce yuv frame space!\n"); goto _FAIL; } // open yuv_path video_fd = fopen(yuv_path, "rb"); if( !video_fd ) { fprintf(stderr, "Failed to open yuv file:%s\n", yuv_path); goto _FAIL; } // SDL_CreateThread timer_thread = SDL_CreateThread(refresh_video_timer, NULL, NULL); while (1) { // SDL_WaitEvent SDL_WaitEvent(&event); if(event.type == SDL_REFRESH_EVENT) // update video frame { video_buff_len = fread(video_buf, 1, yuv_frame_len, video_fd); if(video_buff_len <= 0) { fprintf(stderr, "Failed to read data from yuv file!\n"); goto _FAIL; } // SDL_UpdateTexture SDL_UpdateTexture(texture, NULL, video_buf, video_width); // keep window scale rect.x = 0; rect.y = 0; float w_ratio = win_width 1.0 /video_width; float h_ratio = win_height 1.0 /video_height; rect.w = video_width w_ratio; rect.h = video_height h_ratio; // SDL_RenderClear SDL_RenderClear(renderer); // SDL_RenderCopy SDL_RenderCopy(renderer, texture, NULL, &rect); // SDL_RenderPresent SDL_RenderPresent(renderer); } else if(event.type == SDL_WINDOWEVENT) { //If Resize SDL_GetWindowSize(window, &win_width, &win_height); //printf("SDL_WINDOWEVENT win_width:%d, win_height:%d\n",win_width, // win_height ); } else if(event.type == SDL_QUIT) //退失事宜 { g_thread_exit = 1; } else if(event.type == SDL_QUIT_EVENT) { break; } }

yuv播放器测试,播放一个yuv文件,可以正常播放画面,调节画面大小。

5 SDL大略单纯音频播放器

SDL 音频播放相对视频播放器更为大略:

音频设备初始化并且读取音频数据:

打开音频设备:SDL_OpenAudio开启音频设备播放读取pcm文件,写入音频缓冲区

if(SDL_Init(SDL_INIT_AUDIO)) { fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); return ret; } //open pcmfile audio_fd = fopen(path, "rb"); if(!audio_fd) { fprintf(stderr, "Failed to open pcm file!\n"); goto _FAIL; } g_audio_buf = (uint8_t )malloc(PCM_BUFFER_SIZE); // SDL_AudioSpec spec.freq = 44100; spec.format = AUDIO_S16SYS; spec.channels = 2; spec.silence = 0; spec.samples = 1024; spec.callback = fill_audio_pcm; spec.userdata = NULL; if(SDL_OpenAudio(&spec, NULL)) { fprintf(stderr, "Failed to open audio device, %s\n", SDL_GetError()); goto _FAIL; } //play audio SDL_PauseAudio(0); int data_count = 0; while(1) { // read pcm read_buffer_len = fread(g_audio_buf, 1, PCM_BUFFER_SIZE, audio_fd); if(read_buffer_len == 0) { break; } data_count += read_buffer_len; printf("now playing %10d bytes data.\n",data_count); g_audio_end = g_audio_buf + read_buffer_len; g_audio_pos = g_audio_buf; //the main thread wait for a moment while(g_audio_pos < g_audio_end) { SDL_Delay(10); } } printf("play PCM finish\n"); // SDL_CloseAudio SDL_CloseAudio();

回调函数将音频数据写入播放缓冲区:

void mix_audio_pcm(void udata, Uint8 stream, int len){ SDL_memset(stream, 0, len); if(g_audio_pos >= g_audio_end) { return; } int remain_buffer_len = g_audio_end - g_audio_pos; len = (len < remain_buffer_len) ? len : remain_buffer_len; SDL_MixAudio(stream, g_audio_pos, len, SDL_MIX_MAXVOLUME/8); printf("len = %d\n", len); g_audio_pos += len; }

标签:

相关文章