capture_video_capturer.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. #include "capture_video_capturer.h"
  2. #include "../base/logger.h"
  3. #include "../base/media_common.h"
  4. #include <algorithm>
  5. #include <sstream>
  6. #ifdef _WIN32
  7. #include <windows.h>
  8. #include <dshow.h>
  9. #pragma comment(lib, "strmiids.lib")
  10. #endif
  11. extern "C" {
  12. #include <libavformat/avformat.h>
  13. #include <libavdevice/avdevice.h>
  14. #include <libswscale/swscale.h>
  15. #include <libavutil/imgutils.h>
  16. #include <libavutil/opt.h>
  17. }
  18. namespace av {
  19. namespace capture {
  20. VideoCapturer::VideoCapturer() : videoParams_(CapturerType::VIDEO_CAMERA) {
  21. AV_LOGGER_DEBUG("创建视频采集器");
  22. // 注册设备
  23. avdevice_register_all();
  24. }
  25. VideoCapturer::~VideoCapturer() {
  26. close();
  27. AV_LOGGER_DEBUG("视频采集器已销毁");
  28. }
  29. ErrorCode VideoCapturer::initialize(const CapturerParams& params) {
  30. if (params.mediaType != MediaType::VIDEO) {
  31. AV_LOGGER_ERROR("参数媒体类型不是视频");
  32. return ErrorCode::INVALID_ARGUMENT;
  33. }
  34. videoParams_ = static_cast<const VideoCaptureParams&>(params);
  35. if (!validateParams(videoParams_)) {
  36. return ErrorCode::INVALID_PARAMS;
  37. }
  38. ErrorCode result = ErrorCode::OK;
  39. if (videoParams_.type == CapturerType::VIDEO_CAMERA) {
  40. result = initializeCamera();
  41. } else if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  42. result = initializeScreen();
  43. } else {
  44. AV_LOGGER_ERROR("不支持的视频采集器类型");
  45. return ErrorCode::NOT_SUPPORTED;
  46. }
  47. if (result == ErrorCode::OK) {
  48. setState(CapturerState::INITIALIZED);
  49. AV_LOGGER_INFOF("视频采集器初始化成功: {}x{}@{}fps",
  50. videoParams_.width, videoParams_.height, videoParams_.fps);
  51. }
  52. return result;
  53. }
  54. ErrorCode VideoCapturer::start() {
  55. std::lock_guard<std::mutex> lock(captureMutex_);
  56. if (getState() != CapturerState::INITIALIZED) {
  57. AV_LOGGER_ERROR("采集器状态无效,无法启动");
  58. return ErrorCode::INVALID_STATE;
  59. }
  60. shouldStop_ = false;
  61. // 启动采集线程
  62. try {
  63. captureThread_ = std::thread(&VideoCapturer::captureThreadFunc, this);
  64. setState(CapturerState::STARTED);
  65. AV_LOGGER_INFO("视频采集已启动");
  66. return ErrorCode::OK;
  67. } catch (const std::exception& e) {
  68. AV_LOGGER_ERRORF("启动采集线程失败: {}", e.what());
  69. return ErrorCode::THREAD_ERROR;
  70. }
  71. }
  72. ErrorCode VideoCapturer::stop() {
  73. std::lock_guard<std::mutex> lock(captureMutex_);
  74. if (getState() != CapturerState::STARTED) {
  75. return ErrorCode::OK;
  76. }
  77. shouldStop_ = true;
  78. // 唤醒暂停的线程
  79. {
  80. std::lock_guard<std::mutex> pauseLock(pauseMutex_);
  81. paused_ = false;
  82. pauseCondition_.notify_all();
  83. }
  84. // 等待线程结束
  85. if (captureThread_.joinable()) {
  86. captureThread_.join();
  87. }
  88. setState(CapturerState::STOPPED);
  89. AV_LOGGER_INFO("视频采集已停止");
  90. return ErrorCode::OK;
  91. }
  92. ErrorCode VideoCapturer::pause() {
  93. if (getState() != CapturerState::STARTED) {
  94. return ErrorCode::INVALID_STATE;
  95. }
  96. paused_ = true;
  97. AV_LOGGER_INFO("视频采集已暂停");
  98. return ErrorCode::OK;
  99. }
  100. ErrorCode VideoCapturer::resume() {
  101. if (getState() != CapturerState::STARTED) {
  102. return ErrorCode::INVALID_STATE;
  103. }
  104. {
  105. std::lock_guard<std::mutex> lock(pauseMutex_);
  106. paused_ = false;
  107. pauseCondition_.notify_all();
  108. }
  109. AV_LOGGER_INFO("视频采集已恢复");
  110. return ErrorCode::OK;
  111. }
  112. ErrorCode VideoCapturer::reset() {
  113. ErrorCode result = stop();
  114. if (result != ErrorCode::OK) {
  115. return result;
  116. }
  117. // 清空帧队列
  118. {
  119. std::lock_guard<std::mutex> lock(queueMutex_);
  120. while (!frameQueue_.empty()) {
  121. frameQueue_.pop();
  122. }
  123. }
  124. resetStats();
  125. setState(CapturerState::INITIALIZED);
  126. AV_LOGGER_INFO("视频采集器已重置");
  127. return ErrorCode::OK;
  128. }
  129. ErrorCode VideoCapturer::close() {
  130. stop();
  131. // 清理资源
  132. cleanupConverter();
  133. if (codecCtx_) {
  134. avcodec_free_context(&codecCtx_);
  135. codecCtx_ = nullptr;
  136. }
  137. if (formatCtx_) {
  138. avformat_close_input(&formatCtx_);
  139. formatCtx_ = nullptr;
  140. }
  141. codec_ = nullptr;
  142. videoStreamIndex_ = -1;
  143. setState(CapturerState::IDLE);
  144. AV_LOGGER_INFO("视频采集器已关闭");
  145. return ErrorCode::OK;
  146. }
  147. std::vector<std::string> VideoCapturer::getAvailableDevices() const {
  148. std::vector<std::string> devices;
  149. auto deviceInfos = getDetailedDeviceInfo();
  150. for (const auto& info : deviceInfos) {
  151. devices.push_back(info.name);
  152. }
  153. return devices;
  154. }
  155. std::string VideoCapturer::getCurrentDevice() const {
  156. return videoParams_.deviceName;
  157. }
  158. std::vector<VideoDeviceInfo> VideoCapturer::getDetailedDeviceInfo() const {
  159. std::lock_guard<std::mutex> lock(deviceCacheMutex_);
  160. if (!devicesCached_) {
  161. if (videoParams_.type == CapturerType::VIDEO_CAMERA) {
  162. cachedDevices_ = enumerateCameras();
  163. } else if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  164. cachedDevices_ = enumerateScreens();
  165. }
  166. devicesCached_ = true;
  167. }
  168. return cachedDevices_;
  169. }
  170. ErrorCode VideoCapturer::setVideoParams(int width, int height, int fps) {
  171. if (getState() == CapturerState::STARTED) {
  172. AV_LOGGER_ERROR("无法在采集过程中修改参数");
  173. return ErrorCode::INVALID_STATE;
  174. }
  175. videoParams_.width = width;
  176. videoParams_.height = height;
  177. videoParams_.fps = fps;
  178. AV_LOGGER_INFOF("视频参数已更新: {}x{}@{}fps", width, height, fps);
  179. return ErrorCode::OK;
  180. }
  181. ErrorCode VideoCapturer::setPixelFormat(AVPixelFormat format) {
  182. if (getState() == CapturerState::STARTED) {
  183. AV_LOGGER_ERROR("无法在采集过程中修改像素格式");
  184. return ErrorCode::INVALID_STATE;
  185. }
  186. videoParams_.pixelFormat = format;
  187. AV_LOGGER_INFOF("像素格式已更新: {}", av_get_pix_fmt_name(format));
  188. return ErrorCode::OK;
  189. }
  190. VideoCaptureParams VideoCapturer::getCurrentParams() const {
  191. return videoParams_;
  192. }
  193. bool VideoCapturer::validateParams(const CapturerParams& params) {
  194. const auto& videoParams = static_cast<const VideoCaptureParams&>(params);
  195. if (videoParams.width <= 0 || videoParams.height <= 0) {
  196. AV_LOGGER_ERROR("视频分辨率无效");
  197. return false;
  198. }
  199. if (videoParams.fps <= 0 || videoParams.fps > 120) {
  200. AV_LOGGER_ERROR("帧率无效");
  201. return false;
  202. }
  203. if (videoParams.type == CapturerType::VIDEO_CAMERA) {
  204. if (videoParams.cameraIndex < 0) {
  205. AV_LOGGER_ERROR("摄像头索引无效");
  206. return false;
  207. }
  208. } else if (videoParams.type == CapturerType::VIDEO_SCREEN) {
  209. if (videoParams.screenIndex < 0) {
  210. AV_LOGGER_ERROR("屏幕索引无效");
  211. return false;
  212. }
  213. }
  214. return true;
  215. }
  216. ErrorCode VideoCapturer::initializeCamera() {
  217. AV_LOGGER_INFOF("初始化摄像头采集器: 索引={}", videoParams_.cameraIndex);
  218. #ifdef _WIN32
  219. return setupDirectShowCamera();
  220. #elif defined(__linux__)
  221. return setupV4L2Camera();
  222. #elif defined(__APPLE__)
  223. return setupAVFoundationCamera();
  224. #else
  225. AV_LOGGER_ERROR("当前平台不支持摄像头采集");
  226. return ErrorCode::NOT_SUPPORTED;
  227. #endif
  228. }
  229. ErrorCode VideoCapturer::initializeScreen() {
  230. AV_LOGGER_INFOF("初始化屏幕录制: 索引={}", videoParams_.screenIndex);
  231. #ifdef _WIN32
  232. return setupGDIScreenCapture();
  233. #elif defined(__linux__)
  234. return setupX11ScreenCapture();
  235. #elif defined(__APPLE__)
  236. return setupCoreGraphicsScreenCapture();
  237. #else
  238. AV_LOGGER_ERROR("当前平台不支持屏幕录制");
  239. return ErrorCode::NOT_SUPPORTED;
  240. #endif
  241. }
  242. ErrorCode VideoCapturer::openInputDevice() {
  243. const AVInputFormat* inputFormat = getPlatformInputFormat();
  244. if (!inputFormat) {
  245. AV_LOGGER_ERROR("获取输入格式失败");
  246. return ErrorCode::NOT_SUPPORTED;
  247. }
  248. std::string deviceName = getPlatformDeviceName();
  249. if (deviceName.empty()) {
  250. AV_LOGGER_ERROR("获取设备名称失败");
  251. return ErrorCode::DEVICE_NOT_FOUND;
  252. }
  253. AV_LOGGER_INFOF("打开输入设备: {} (格式: {})", deviceName, inputFormat->name);
  254. // 设置输入选项
  255. AVDictionary* options = nullptr;
  256. // 设置视频参数
  257. av_dict_set(&options, "video_size",
  258. (std::to_string(videoParams_.width) + "x" + std::to_string(videoParams_.height)).c_str(), 0);
  259. av_dict_set(&options, "framerate", std::to_string(videoParams_.fps).c_str(), 0);
  260. if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  261. // 屏幕录制特定选项
  262. if (videoParams_.captureCursor) {
  263. av_dict_set(&options, "draw_mouse", "1", 0);
  264. }
  265. if (videoParams_.offsetX != 0 || videoParams_.offsetY != 0) {
  266. av_dict_set(&options, "offset_x", std::to_string(videoParams_.offsetX).c_str(), 0);
  267. av_dict_set(&options, "offset_y", std::to_string(videoParams_.offsetY).c_str(), 0);
  268. }
  269. }
  270. // 打开输入
  271. int ret = avformat_open_input(&formatCtx_, deviceName.c_str(), inputFormat, &options);
  272. av_dict_free(&options);
  273. if (ret < 0) {
  274. AV_LOGGER_ERRORF("打开输入设备失败: {} (设备: {})",
  275. ffmpeg_utils::errorToString(ret), deviceName);
  276. return static_cast<ErrorCode>(ret);
  277. }
  278. // 查找流信息
  279. ret = avformat_find_stream_info(formatCtx_, nullptr);
  280. if (ret < 0) {
  281. AV_LOGGER_ERRORF("查找流信息失败: {}", ffmpeg_utils::errorToString(ret));
  282. return static_cast<ErrorCode>(ret);
  283. }
  284. // 查找视频流
  285. videoStreamIndex_ = av_find_best_stream(formatCtx_, AVMEDIA_TYPE_VIDEO, -1, -1, &codec_, 0);
  286. if (videoStreamIndex_ < 0) {
  287. AV_LOGGER_ERROR("未找到视频流");
  288. return ErrorCode::STREAM_NOT_FOUND;
  289. }
  290. // 创建解码上下文
  291. codecCtx_ = avcodec_alloc_context3(codec_);
  292. if (!codecCtx_) {
  293. AV_LOGGER_ERROR("分配解码上下文失败");
  294. return ErrorCode::OUT_OF_MEMORY;
  295. }
  296. // 复制流参数到解码上下文
  297. ret = avcodec_parameters_to_context(codecCtx_, formatCtx_->streams[videoStreamIndex_]->codecpar);
  298. if (ret < 0) {
  299. AV_LOGGER_ERRORF("复制流参数失败: {}", ffmpeg_utils::errorToString(ret));
  300. return static_cast<ErrorCode>(ret);
  301. }
  302. // 打开解码器
  303. ret = avcodec_open2(codecCtx_, codec_, nullptr);
  304. if (ret < 0) {
  305. AV_LOGGER_ERRORF("打开解码器失败: {}", ffmpeg_utils::errorToString(ret));
  306. return static_cast<ErrorCode>(ret);
  307. }
  308. // 设置像素格式转换
  309. return setupPixelFormatConversion();
  310. }
  311. ErrorCode VideoCapturer::setupPixelFormatConversion() {
  312. AVPixelFormat srcFormat = codecCtx_->pix_fmt;
  313. AVPixelFormat dstFormat = videoParams_.pixelFormat;
  314. needConversion_ = (srcFormat != dstFormat);
  315. if (needConversion_) {
  316. AV_LOGGER_INFOF("需要像素格式转换: {} -> {}",
  317. av_get_pix_fmt_name(srcFormat),
  318. av_get_pix_fmt_name(dstFormat));
  319. swsCtx_ = sws_getContext(
  320. codecCtx_->width, codecCtx_->height, srcFormat,
  321. videoParams_.width, videoParams_.height, dstFormat,
  322. SWS_BILINEAR, nullptr, nullptr, nullptr
  323. );
  324. if (!swsCtx_) {
  325. AV_LOGGER_ERROR("创建像素格式转换上下文失败");
  326. return ErrorCode::CONVERSION_ERROR;
  327. }
  328. // 创建转换后的帧
  329. convertedFrame_ = makeAVFrame();
  330. if (!convertedFrame_) {
  331. return ErrorCode::OUT_OF_MEMORY;
  332. }
  333. convertedFrame_->format = dstFormat;
  334. convertedFrame_->width = videoParams_.width;
  335. convertedFrame_->height = videoParams_.height;
  336. int ret = av_frame_get_buffer(convertedFrame_.get(), 32);
  337. if (ret < 0) {
  338. AV_LOGGER_ERRORF("分配转换帧缓冲区失败: {}", ffmpeg_utils::errorToString(ret));
  339. return static_cast<ErrorCode>(ret);
  340. }
  341. }
  342. return ErrorCode::OK;
  343. }
  344. void VideoCapturer::captureThreadFunc() {
  345. AV_LOGGER_INFO("视频采集线程已启动");
  346. while (!shouldStop_) {
  347. // 检查暂停状态
  348. {
  349. std::unique_lock<std::mutex> lock(pauseMutex_);
  350. pauseCondition_.wait(lock, [this] { return !paused_ || shouldStop_; });
  351. }
  352. if (shouldStop_) {
  353. break;
  354. }
  355. ErrorCode result = captureFrame();
  356. if (result != ErrorCode::OK) {
  357. onError(result, "采集帧失败");
  358. // 短暂休眠后重试
  359. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  360. }
  361. }
  362. AV_LOGGER_INFO("视频采集线程已退出");
  363. }
  364. ErrorCode VideoCapturer::captureFrame() {
  365. AVPacket packet;
  366. av_init_packet(&packet);
  367. // 读取包
  368. int ret = av_read_frame(formatCtx_, &packet);
  369. if (ret < 0) {
  370. if (ret == AVERROR_EOF) {
  371. AV_LOGGER_WARNING("到达文件末尾");
  372. return ErrorCode::END_OF_STREAM;
  373. } else {
  374. AV_LOGGER_ERRORF("读取帧失败: {}", ffmpeg_utils::errorToString(ret));
  375. return static_cast<ErrorCode>(ret);
  376. }
  377. }
  378. // 检查是否是视频包
  379. if (packet.stream_index != videoStreamIndex_) {
  380. av_packet_unref(&packet);
  381. return ErrorCode::OK;
  382. }
  383. // 发送包到解码器
  384. ret = avcodec_send_packet(codecCtx_, &packet);
  385. av_packet_unref(&packet);
  386. if (ret < 0) {
  387. AV_LOGGER_ERRORF("发送包到解码器失败: {}", ffmpeg_utils::errorToString(ret));
  388. return static_cast<ErrorCode>(ret);
  389. }
  390. // 接收解码后的帧
  391. AVFramePtr frame = makeAVFrame();
  392. if (!frame) {
  393. return ErrorCode::OUT_OF_MEMORY;
  394. }
  395. ret = avcodec_receive_frame(codecCtx_, frame.get());
  396. if (ret == AVERROR(EAGAIN)) {
  397. return ErrorCode::OK; // 需要更多输入
  398. } else if (ret < 0) {
  399. AV_LOGGER_ERRORF("接收解码帧失败: {}", ffmpeg_utils::errorToString(ret));
  400. return static_cast<ErrorCode>(ret);
  401. }
  402. // 像素格式转换
  403. AVFramePtr outputFrame;
  404. if (needConversion_) {
  405. outputFrame = convertPixelFormat(frame);
  406. if (!outputFrame) {
  407. return ErrorCode::CONVERSION_ERROR;
  408. }
  409. } else {
  410. outputFrame = frame;
  411. }
  412. // 添加到队列或直接回调
  413. onFrameCaptured(outputFrame);
  414. return ErrorCode::OK;
  415. }
  416. AVFramePtr VideoCapturer::convertPixelFormat(const AVFramePtr& srcFrame) {
  417. if (!srcFrame || !swsCtx_ || !convertedFrame_) {
  418. return nullptr;
  419. }
  420. // 执行像素格式转换
  421. int ret = sws_scale(swsCtx_,
  422. srcFrame->data, srcFrame->linesize, 0, srcFrame->height,
  423. convertedFrame_->data, convertedFrame_->linesize);
  424. if (ret < 0) {
  425. AV_LOGGER_ERRORF("像素格式转换失败: {}", ffmpeg_utils::errorToString(ret));
  426. return nullptr;
  427. }
  428. // 复制时间戳等信息
  429. av_frame_copy_props(convertedFrame_.get(), srcFrame.get());
  430. return convertedFrame_;
  431. }
  432. void VideoCapturer::cleanupConverter() {
  433. if (swsCtx_) {
  434. sws_freeContext(swsCtx_);
  435. swsCtx_ = nullptr;
  436. }
  437. convertedFrame_.reset();
  438. needConversion_ = false;
  439. }
  440. std::vector<VideoDeviceInfo> VideoCapturer::enumerateCameras() const {
  441. #ifdef _WIN32
  442. return enumerateDirectShowDevices();
  443. #elif defined(__linux__)
  444. return enumerateV4L2Devices();
  445. #elif defined(__APPLE__)
  446. return enumerateAVFoundationDevices();
  447. #else
  448. return {};
  449. #endif
  450. }
  451. std::vector<VideoDeviceInfo> VideoCapturer::enumerateScreens() const {
  452. std::vector<VideoDeviceInfo> screens;
  453. // 简单的屏幕枚举实现
  454. VideoDeviceInfo screen;
  455. screen.id = "desktop";
  456. screen.name = "桌面";
  457. screen.description = "主显示器";
  458. // 添加常见分辨率
  459. screen.supportedResolutions = {
  460. {1920, 1080}, {1680, 1050}, {1600, 900}, {1440, 900},
  461. {1366, 768}, {1280, 1024}, {1280, 800}, {1024, 768}
  462. };
  463. // 添加常见帧率
  464. screen.supportedFps = {15, 24, 30, 60};
  465. // 添加支持的像素格式
  466. screen.supportedFormats = {
  467. AV_PIX_FMT_BGR24, AV_PIX_FMT_BGRA, AV_PIX_FMT_YUV420P
  468. };
  469. screens.push_back(screen);
  470. return screens;
  471. }
  472. const AVInputFormat* VideoCapturer::getPlatformInputFormat() const {
  473. #ifdef _WIN32
  474. if (videoParams_.type == CapturerType::VIDEO_CAMERA) {
  475. return av_find_input_format("dshow");
  476. } else if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  477. return av_find_input_format("gdigrab");
  478. }
  479. #elif defined(__linux__)
  480. if (videoParams_.type == CapturerType::VIDEO_CAMERA) {
  481. return av_find_input_format("v4l2");
  482. } else if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  483. return av_find_input_format("x11grab");
  484. }
  485. #elif defined(__APPLE__)
  486. if (videoParams_.type == CapturerType::VIDEO_CAMERA) {
  487. return av_find_input_format("avfoundation");
  488. } else if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  489. return av_find_input_format("avfoundation");
  490. }
  491. #endif
  492. return nullptr;
  493. }
  494. std::string VideoCapturer::getPlatformDeviceName() const {
  495. #ifdef _WIN32
  496. if (videoParams_.type == CapturerType::VIDEO_CAMERA) {
  497. if (!videoParams_.deviceName.empty()) {
  498. return "video=" + videoParams_.deviceName;
  499. } else {
  500. return "video=" + std::to_string(videoParams_.cameraIndex);
  501. }
  502. } else if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  503. return "desktop";
  504. }
  505. #elif defined(__linux__)
  506. if (videoParams_.type == CapturerType::VIDEO_CAMERA) {
  507. if (!videoParams_.deviceName.empty()) {
  508. return videoParams_.deviceName;
  509. } else {
  510. return "/dev/video" + std::to_string(videoParams_.cameraIndex);
  511. }
  512. } else if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  513. return ":0.0";
  514. }
  515. #elif defined(__APPLE__)
  516. if (videoParams_.type == CapturerType::VIDEO_CAMERA) {
  517. return std::to_string(videoParams_.cameraIndex);
  518. } else if (videoParams_.type == CapturerType::VIDEO_SCREEN) {
  519. return "Capture screen 0";
  520. }
  521. #endif
  522. return "";
  523. }
  524. #ifdef _WIN32
  525. std::vector<VideoDeviceInfo> VideoCapturer::enumerateDirectShowDevices() const {
  526. std::vector<VideoDeviceInfo> devices;
  527. // 简化的DirectShow设备枚举
  528. // 实际实现需要使用COM接口
  529. VideoDeviceInfo device;
  530. device.id = "0";
  531. device.name = "默认摄像头";
  532. device.description = "DirectShow摄像头设备";
  533. // 添加常见分辨率
  534. device.supportedResolutions = {
  535. {1920, 1080}, {1280, 720}, {960, 540}, {640, 480}, {320, 240}
  536. };
  537. // 添加常见帧率
  538. device.supportedFps = {15, 24, 30, 60};
  539. // 添加支持的像素格式
  540. device.supportedFormats = {
  541. AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUYV422, AV_PIX_FMT_BGR24
  542. };
  543. devices.push_back(device);
  544. return devices;
  545. }
  546. ErrorCode VideoCapturer::setupDirectShowCamera() {
  547. AV_LOGGER_INFO("设置DirectShow摄像头");
  548. return openInputDevice();
  549. }
  550. ErrorCode VideoCapturer::setupGDIScreenCapture() {
  551. AV_LOGGER_INFO("设置GDI屏幕录制");
  552. return openInputDevice();
  553. }
  554. #endif
  555. // VideoCaptureFactory 实现
  556. std::unique_ptr<VideoCapturer> VideoCapturer::VideoCaptureFactory::createCamera(int cameraIndex) {
  557. auto capturer = std::make_unique<VideoCapturer>();
  558. VideoCaptureParams params(CapturerType::VIDEO_CAMERA);
  559. params.cameraIndex = cameraIndex;
  560. ErrorCode result = capturer->initialize(params);
  561. if (result != ErrorCode::OK) {
  562. AV_LOGGER_ERRORF("创建摄像头采集器失败: {}", static_cast<int>(result));
  563. return nullptr;
  564. }
  565. return capturer;
  566. }
  567. std::unique_ptr<VideoCapturer> VideoCapturer::VideoCaptureFactory::createScreen(int screenIndex) {
  568. auto capturer = std::make_unique<VideoCapturer>();
  569. VideoCaptureParams params(CapturerType::VIDEO_SCREEN);
  570. params.screenIndex = screenIndex;
  571. ErrorCode result = capturer->initialize(params);
  572. if (result != ErrorCode::OK) {
  573. AV_LOGGER_ERRORF("创建屏幕录制采集器失败: {}", static_cast<int>(result));
  574. return nullptr;
  575. }
  576. return capturer;
  577. }
  578. std::unique_ptr<VideoCapturer> VideoCapturer::VideoCaptureFactory::createBestCamera() {
  579. return createCamera(0); // 默认使用第一个摄像头
  580. }
  581. } // namespace capture
  582. } // namespace av