音视频(42-48)

发布时间:2026/8/12 17:10:02

音视频(42-48)
注意本人的环境为qt6.11.1 ffmpeg-5.16.2 将dll拷贝到exe文件下进行调试#include stdio.h #include SDL2/SDL.h #undef main int main() { printf(Hello World!\n); SDL_Window *window NULL; // 声明窗口 SDL_Init(SDL_INIT_VIDEO); // 初始化SDL // 创建SDL Window window SDL_CreateWindow(Basic Window, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if(!window) // 检测是否创建成功 { printf(Cant create window, err:%s\n, SDL_GetError()); return 1; } SDL_Delay(10000); // 延迟10000ms SDL_DestroyWindow(window); // 消耗窗口 SDL_Quit(); // 释放资源 return 0; }#include stdio.h #include SDL2/SDL.h #undef main int main() { int run 1; SDL_Window *window NULL; SDL_Renderer *renderer NULL; SDL_Texture *texture NULL; SDL_Rect rect; // 长方形原点在左上角 rect.w 50; //方块大小 rect.h 50; SDL_Init(SDL_INIT_VIDEO);//初始化函数,可以确定希望激活的子系统 window SDL_CreateWindow(2 Window, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);// 创建窗口 if (!window) { return -1; } renderer SDL_CreateRenderer(window, -1, 0);//基于窗口创建渲染器 if (!renderer) { return -1; } texture SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 640, 480); //创建纹理 if (!texture) { return -1; } int show_count 0; while (run) { rect.x rand() % 600; rect.y rand() % 400; SDL_SetRenderTarget(renderer, texture); // 设置渲染目标为纹理 SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // 纹理背景为黑色 SDL_RenderClear(renderer); //清屏 SDL_RenderDrawRect(renderer, rect); //绘制一个长方形 SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); //长方形为白色 SDL_RenderFillRect(renderer, rect); SDL_SetRenderTarget(renderer, NULL); //恢复默认渲染目标为窗口 SDL_RenderCopy(renderer, texture, NULL, NULL); //拷贝纹理到CPU SDL_RenderPresent(renderer); //输出到目标窗口上 SDL_Delay(300); if(show_count 30) { run 0; // 不跑了 } } SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); //销毁窗口 SDL_Quit(); return 0; }#include SDL2/SDL.h #include stdio.h #define FF_QUIT_EVENT (SDL_USEREVENT 2) // 用户自定义事件 #undef main int main(int argc, char* argv[]) { SDL_Window *window NULL; // Declare a pointer SDL_Renderer *renderer NULL; SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2 // Create an application window with the following settings: window SDL_CreateWindow( An SDL2 window, // window title SDL_WINDOWPOS_UNDEFINED, // initial x position SDL_WINDOWPOS_UNDEFINED, // initial y position 640, // width, in pixels 480, // height, in pixels SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS// flags - see below ); // Check that the window was successfully created if (window NULL) { // In the case that the window could not be made... printf(Could not create window: %s\n, SDL_GetError()); return 1; } /* We must call SDL_CreateRenderer in order for draw calls to affect this window. */ renderer SDL_CreateRenderer(window, -1, 0); /* Select the color for drawing. It is set to red here. */ SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); /* Clear the entire screen to our selected color. */ SDL_RenderClear(renderer); /* Up until now everything was drawn behind the scenes. This will show the new, red contents of the window. */ SDL_RenderPresent(renderer); SDL_Event event; int b_exit 0; for (;;) { SDL_WaitEvent(event); switch (event.type) { case SDL_KEYDOWN: /* 键盘事件 */ switch (event.key.keysym.sym) { case SDLK_a: printf(key down a\n); break; case SDLK_s: printf(key down s\n); break; case SDLK_d: printf(key down d\n); break; case SDLK_q: printf(key down q and push quit event\n); SDL_Event event_q; event_q.type FF_QUIT_EVENT; SDL_PushEvent(event_q); break; default: printf(key down 0x%x\n, event.key.keysym.sym); break; } break; case SDL_MOUSEBUTTONDOWN: /* 鼠标按下事件 */ if (event.button.button SDL_BUTTON_LEFT) { printf(mouse down left\n); } else if(event.button.button SDL_BUTTON_RIGHT) { printf(mouse down right\n); } else { printf(mouse down %d\n, event.button.button); } break; case SDL_MOUSEMOTION: /* 鼠标移动事件 */ printf(mouse movie (%d,%d)\n, event.button.x, event.button.y); break; case FF_QUIT_EVENT: printf(receive quit event\n); b_exit 1; break; } if(b_exit) break; } //destory renderer if (renderer) SDL_DestroyRenderer(renderer); // Close and destroy the window if (window) SDL_DestroyWindow(window); // Clean up SDL_Quit(); return 0; }45#include SDL2/SDL.h #include stdio.h SDL_mutex *s_lock NULL; SDL_cond *s_cond NULL; int thread_work(void *arg) { SDL_LockMutex(s_lock); printf( thread_work sleep\n); sleep(10); // 用来测试获取锁 printf( thread_work wait\n); // 释放s_lock资源并等待signal。之所以释放s_lock是让别的线程能够获取到s_lock SDL_CondWait(s_cond, s_lock); //另一个线程(1)发送signal和(2)释放lock后这个函数退出 printf( thread_work receive signal, continue to do ~_~!!!\n); printf( thread_work end\n); SDL_UnlockMutex(s_lock); return 0; } #undef main int main() { s_lock SDL_CreateMutex(); s_cond SDL_CreateCond(); SDL_Thread * t SDL_CreateThread(thread_work,thread_work,NULL); if(!t) { printf( %s,SDL_GetError); return -1; } for(int i 0;i 2;i) { sleep(2); printf(main execute \n); } printf(main SDL_LockMutex(s_lock) before \n); SDL_LockMutex(s_lock); // 获取锁但是子线程还拿着锁 printf(main ready send signal\n); printf(main SDL_CondSignal(s_cond) before \n); SDL_CondSignal(s_cond); // 发送信号唤醒等待的线程 printf(main SDL_CondSignal(s_cond) after \n); sleep(10); SDL_UnlockMutex(s_lock);// 释放锁让其他线程可以拿到锁 printf(main SDL_UnlockMutex(s_lock) after \n); SDL_WaitThread(t, NULL); SDL_DestroyMutex(s_lock); SDL_DestroyCond(s_cond); return 0; }#include stdio.h #include string.h #include SDL2/SDL.h //自定义消息类型 #define REFRESH_EVENT (SDL_USEREVENT 1) // 请求画面刷新事件 #define QUIT_EVENT (SDL_USEREVENT 2) // 退出事件 //定义分辨率 // YUV像素分辨率 #define YUV_WIDTH 320 #define YUV_HEIGHT 240 //定义YUV格式 #define YUV_FORMAT SDL_PIXELFORMAT_IYUV int s_thread_exit 0; // 退出标志 1则退出 int refresh_video_timer(void *data) { while (!s_thread_exit) { SDL_Event event; event.type REFRESH_EVENT; SDL_PushEvent(event); SDL_Delay(40); } s_thread_exit 0; //push quit event SDL_Event event; event.type QUIT_EVENT; SDL_PushEvent(event); return 0; } #undef main int main(int argc, char* argv[]) { //初始化 SDL if(SDL_Init(SDL_INIT_VIDEO)) { fprintf( stderr, Could not initialize SDL - %s\n, SDL_GetError()); return -1; } // SDL SDL_Event event; // 事件 SDL_Rect rect; // 矩形 SDL_Window *window NULL; // 窗口 SDL_Renderer *renderer NULL; // 渲染 SDL_Texture *texture NULL; // 纹理 SDL_Thread *timer_thread NULL; // 请求刷新线程 uint32_t pixformat YUV_FORMAT; // YUV420P即是SDL_PIXELFORMAT_IYUV // 分辨率 // 1. YUV的分辨率 int video_width YUV_WIDTH; int video_height YUV_HEIGHT; // 2.显示窗口的分辨率 int win_width YUV_WIDTH; int win_height YUV_WIDTH; // YUV文件句柄 FILE *video_fd NULL; const char *yuv_path E:/2025/ffmpeg/05-sdl-yuv/yuv420p_320x240.yuv; size_t video_buff_len 0; uint8_t *video_buf NULL; //读取数据后先把放到buffer里面 // 我们测试的文件是YUV420P格式 uint32_t y_frame_len video_width * video_height; uint32_t u_frame_len video_width * video_height / 4; uint32_t v_frame_len video_width * video_height / 4; uint32_t yuv_frame_len y_frame_len u_frame_len v_frame_len; //创建窗口 window SDL_CreateWindow(Simplest 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; } // 基于窗口创建渲染器 renderer SDL_CreateRenderer(window, -1, 0); // 基于渲染器创建纹理 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; } // 打开YUV文件 video_fd fopen(yuv_path, rb); if( !video_fd ) { fprintf(stderr, Failed to open yuv file\n); goto _FAIL; } // 创建请求刷新线程 timer_thread SDL_CreateThread(refresh_video_timer, NULL, NULL); while (1) { // 收取SDL系统里面的事件 SDL_WaitEvent(event); if(event.type REFRESH_EVENT) // 画面刷新事件 { 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; } // 设置纹理的数据 video_width 320 plane SDL_UpdateTexture(texture, NULL, video_buf, video_width); // 显示区域可以通过修改w和h进行缩放 rect.x 0; rect.y 0; float w_ratio win_width * 1.0 /video_width; float h_ratio win_height * 1.0 /video_height; // 320x240 怎么保持原视频的宽高比例 rect.w video_width * w_ratio; rect.h video_height * h_ratio; // rect.w video_width * 0.5; // rect.h video_height * 0.5; // 清除当前显示 SDL_RenderClear(renderer); // 将纹理的数据拷贝给渲染器 SDL_RenderCopy(renderer, texture, NULL, rect); // 显示 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) //退出事件 { s_thread_exit 1; } else if(event.type QUIT_EVENT) { break; } } _FAIL: s_thread_exit 1; // 保证线程能够退出 // 释放资源 if(timer_thread) SDL_WaitThread(timer_thread, NULL); // 等待线程退出 if(video_buf) free(video_buf); if(video_fd) fclose(video_fd); if(texture) SDL_DestroyTexture(texture); if(renderer) SDL_DestroyRenderer(renderer); if(window) SDL_DestroyWindow(window); SDL_Quit(); return 0; }/** * SDL2播放PCM * * Darren 326873713 * 326873713qq.com * 腾讯课堂-零声学院https://ke.qq.com/course/468797 * * 本程序使用SDL2播放PCM音频采样数据。SDL实际上是对底层绘图 * APIDirect3DOpenGL的封装使用起来明显简单于直接调用底层 * API。 * 测试的PCM数据采用采样率44.1k, 采用精度S16SYS, 通道数2 * * 函数调用步骤如下: * * [初始化] * SDL_Init(): 初始化SDL。 * SDL_OpenAudio(): 根据参数存储于SDL_AudioSpec打开音频设备。 * SDL_PauseAudio(): 播放音频数据。 * * [循环播放数据] * SDL_Delay(): 延时等待播放完成。 * */ #include stdio.h #include SDL2/SDL.h // 每次读取2帧数据, 以1024个采样点一帧 2通道 16bit采样点为例 #define PCM_BUFFER_SIZE (1024*2*2*2) // 音频PCM数据缓存 static Uint8 *s_audio_buf NULL; // 目前读取的位置 static Uint8 *s_audio_pos NULL; // 缓存结束位置 static Uint8 *s_audio_end NULL; //音频设备回调函数 void fill_audio_pcm(void *udata, Uint8 *stream, int len) { SDL_memset(stream, 0, len); if(s_audio_pos s_audio_end) // 数据读取完毕 { return; } // 数据够了就读预设长度数据不够就只读部分不够的时候剩多少就读取多少 int remain_buffer_len s_audio_end - s_audio_pos; len (len remain_buffer_len) ? len : remain_buffer_len; // 拷贝数据到stream并调整音量 SDL_MixAudio(stream, s_audio_pos, len, SDL_MIX_MAXVOLUME/8); printf(len %d\n, len); s_audio_pos len; // 移动缓存指针 } // 提取PCM文件 // ffmpeg -i input.mp4 -t 20 -codec:a pcm_s16le -ar 44100 -ac 2 -f s16le 44100_16bit_2ch.pcm // 测试PCM文件 // ffplay -ar 44100 -ac 2 -f s16le 44100_16bit_2ch.pcm #undef main int main(int argc, char *argv[]) { int ret -1; FILE *audio_fd NULL; SDL_AudioSpec spec; const char *path E:/2025/ffmpeg/06-sdl-pcm/44100_16bit_2ch.pcm; // 每次缓存的长度 size_t read_buffer_len 0; //SDL initialize if(SDL_Init(SDL_INIT_AUDIO)) // 支持AUDIO { fprintf(stderr, Could not initialize SDL - %s\n, SDL_GetError()); return ret; } //打开PCM文件 audio_fd fopen(path, rb); if(!audio_fd) { fprintf(stderr, Failed to open pcm file!\n); goto _FAIL; } s_audio_buf (uint8_t *)malloc(PCM_BUFFER_SIZE); // 音频参数设置SDL_AudioSpec spec.freq 44100; // 采样频率 spec.format AUDIO_S16SYS; // 采样点格式 spec.channels 2; // 2通道 spec.silence 0; spec.samples 1024; // 23.2ms - 46.4ms 每次读取的采样数量多久产生一次回调和 samples 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) { // 从文件读取PCM数据 read_buffer_len fread(s_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); s_audio_end s_audio_buf read_buffer_len; // 更新buffer的结束位置 s_audio_pos s_audio_buf; // 更新buffer的起始位置 //the main thread wait for a moment while(s_audio_pos s_audio_end) { SDL_Delay(10); // 等待PCM数据消耗 } } printf(play PCM finish\n); // 关闭音频设备 SDL_CloseAudio(); _FAIL: //release some resources if(s_audio_buf) free(s_audio_buf); if(audio_fd) fclose(audio_fd); //quit SDL SDL_Quit(); return 0; }48

相关新闻

Adrenorphin (free Acid) ;YGGFMRRV‑OH

Adrenorphin (free Acid) ;YGGFMRRV‑OH

2026/8/12 17:10:02

一、基本信息中文名称:肾上腺啡(游离羧基型,C 端‑COOH,非酰胺化)来源:哺乳动物肾上腺髓质,固相人工合成线性八肽,C 端为游离羧酸,无酰胺修饰序列:Tyr‑Gly‑…

Dev-C++ 2024下载安装与配置全指南:轻量IDE在Windows开发中的价值

Dev-C++ 2024下载安装与配置全指南:轻量IDE在Windows开发中的价值

2026/8/12 17:10:02

1. 项目概述:为什么Dev-C在Windows开发中依然有一席之地 看到这个标题,你可能会想,都2024年了,Visual Studio、VS Code、CLion这些现代IDE功能强大、生态丰富,为什么还有人要折腾一个看起来有些“复古”的Dev-C&#x…

DSL到Vue代码转换:构建低代码平台核心引擎的设计与实现

DSL到Vue代码转换:构建低代码平台核心引擎的设计与实现

2026/8/12 17:00:02

1. 项目概述:从DSL到Vue代码的“翻译官”在构建一个现代化的、AI驱动的Vue3应用开发平台时,我们总会遇到一个核心矛盾:如何让非专业开发者或业务专家也能高效地参与应用构建,同时又保证产出的代码具备专业水准、易于维护&#xff…

Web安全实战:用户输入处理中的转义、验证与清理机制详解

Web安全实战:用户输入处理中的转义、验证与清理机制详解

2026/8/12 18:10:05

最近在开发一个需要处理用户上传内容的项目时,遇到了一个棘手的问题:如何安全、高效地处理用户提交的文本,特别是当文本中包含一些特殊字符或潜在风险内容时。这让我深入研究了字符串处理中的转义、验证和清理机制。本文将围绕这个主题&#…

AI模型竞技场:基于世界杯场景的模型评测与工程实践

AI模型竞技场:基于世界杯场景的模型评测与工程实践

2026/8/12 18:10:05

1. 项目缘起:当世界杯遇上AI模型,一场“另类”的竞技开始了最近几年,AI模型的发展速度,用“日新月异”来形容都显得有点保守。从大语言模型到多模态模型,从闭源巨头到开源社区,各种模型层出不穷&#xff0c…

递归与迭代:C++编程中的性能与选择

递归与迭代:C++编程中的性能与选择

2026/8/12 18:10:05

1. 编程范式之争:递归与迭代的本质差异 在C开发中,递归和迭代就像武林中的两大门派,各有独门绝技。最近在优化一个路径查找算法时,我不得不在两者之间做出选择。递归写法简洁优雅,但迭代版本运行效率更高。这让我意识到…

汇正财经:政策持续托底,把握地产结构性行情

汇正财经:政策持续托底,把握地产结构性行情

2026/8/12 18:10:05

一、背景8月以来房地产政策密集加码,需求端宽松持续向一线城市深化。北京出台新政将非京籍购房社保年限降至1年、五环外取消套数限制,公积金首套最高贷款额度提至340万元,政策力度超出市场预期,带动二手房带看量与成交量明显回升&…

鼻基底自填2.0:分层定点支撑技术解析与材料选择指南

鼻基底自填2.0:分层定点支撑技术解析与材料选择指南

2026/8/12 18:10:05

在实际的面部美学和微整形领域,鼻基底凹陷是影响面部立体度、侧脸轮廓和整体气质的一个关键因素。很多求美者发现,即使鼻子本身高度足够,但面中部的“洼地”依然会让人显得疲惫、苍老,甚至出现“法令纹”假象。传统的填充方式可能…

【2026年】女性读MBA,择校有什么特别建议?

【2026年】女性读MBA,择校有什么特别建议?

2026/8/12 18:00:05

越来越多的女性职场人把MBA列入成长规划,但真正择校时,很多人发现网上针对"女性MBA"的讨论要么泛泛而谈,要么充斥刻板印象。这篇文章从女性在职读MBA的真实痛点出发,给出可落地的择校参考:选什么样的学校&am…

比较好的亚太EMBA,问了6位校友师资差别真的挺大

比较好的亚太EMBA,问了6位校友师资差别真的挺大

2026/8/12 7:11:29

比较好的亚太EMBA核心差异先看什么?对于希望兼顾工作与系统管理能力提升的亚太区高管而言,筛选匹配度高的EMBA项目时,师资配置是决定学习体验与实际收获的核心要素之一。我们结合3-4个公开信息透明、办学历史较长的亚太区主流EMBA项目特点&am…

备考3个月对比6份资料 海外游学的亚洲EMBA面试注意点

备考3个月对比6份资料 海外游学的亚洲EMBA面试注意点

2026/8/11 8:44:43

备考海外游学的亚洲EMBA面试,核心要围绕项目国际化设计逻辑、个人跨文化管理经验匹配度两个维度准备,避免把游学模块等同于普通旅游参访的认知偏差。不少备考者花3个月对比6份资料,却容易忽略面试官对“国际视野落地能力”的考察——比如香港…

比较好的国内EMBA,问了二十位校友聊透人脉价值

比较好的国内EMBA,问了二十位校友聊透人脉价值

2026/8/11 15:57:54

比较好的国内EMBA核心差异体现在哪些方面?比较好的国内EMBA的核心长期价值,很大程度上依托于校友网络的连接质量与资源生态的活跃度,这也是不少高管在择校时优先考量的因素。我们结合3-4个市场关注度较高的项目公开信息,从课程、师…

告别模组冲突!5步掌握《神界:原罪2》模组管理的终极秘诀

告别模组冲突!5步掌握《神界:原罪2》模组管理的终极秘诀

2026/8/12 9:39:37

告别模组冲突!5步掌握《神界:原罪2》模组管理的终极秘诀 【免费下载链接】DivinityModManager A mod manager for Divinity: Original Sin - Definitive Edition. 项目地址: https://gitcode.com/gh_mirrors/di/DivinityModManager 你是否曾经为《…

如何用Charge Limiter延长MacBook电池寿命:终极保护指南

如何用Charge Limiter延长MacBook电池寿命:终极保护指南

2026/8/12 9:39:37

如何用Charge Limiter延长MacBook电池寿命:终极保护指南 【免费下载链接】charge-limiter macOS app to set battery charge limit for Intel MacBooks 项目地址: https://gitcode.com/gh_mirrors/ch/charge-limiter 还在为MacBook电池健康度下降而烦恼吗&am…

推三返一模式5.0版本系统开发

推三返一模式5.0版本系统开发

2026/8/12 9:39:37

推三返一模式5.0版本系统开发要点编辑:araolin(私域邦网络土土哥)模式核心逻辑 推三返一是一种促销或分销机制,用户推荐三人完成特定行为(如购买、注册),推荐人可获得返利或奖励。5.0版本通常在…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/8 5:07:31

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/9 13:42:46

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/8 2:30:15

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…