#c #windows #uwp #windows-runtime #c -winrt
Вопрос:
Я хочу извлечь необработанные кадры или растровые изображения из видео, которое я воспроизводю в своем консольном приложении C , используя API C /WinRT. Я просто использую CopyFrameToVideoSurface
, чтобы скопировать кадр видео в a IDirect3DSurface
. Но это просто приводит к сбою моей программы (которая отлично работает, если я не настрою этот обратный вызов извлечения кадров). Моя цель состоит в том, чтобы отобразить этот буфер кадров где-нибудь в другом месте для отображения видео.
Код извлечения фрейма (см. Полный проект здесь: https://github.com/harmonoid/libwinmedia/tree/stackoverflow)
IDirect3DSurface surface = IDirect3DSurface();
Streams::IBuffer buffer = Streams::IBuffer();
DLLEXPORT void PlayerSetFrameEventHandler(
int32_t player_id, void (*callback)(uint8_t* buffer, int32_t size,
int32_t width, int32_t height)) {
g_media_players.at(player_id).IsVideoFrameServerEnabled(true);
g_media_players.at(player_id)
.VideoFrameAvailable([=](auto, const autoamp; args) -> void {
g_media_players.at(player_id).CopyFrameToVideoSurface(surface);
SoftwareBitmap bitmap =
SoftwareBitmap::CreateCopyFromSurfaceAsync(surface).get();
bitmap.CopyToBuffer(buffer);
(*callback)(buffer.data(), buffer.Length(), bitmap.PixelWidth(),
bitmap.PixelHeight());
});
}
Вы можете просто создать эту общую библиотеку, используя cmake --build .
Для тестирования сбоя вы можете скомпилировать следующий пример (также присутствует в репозитории ссылок): https://github.com/harmonoid/libwinmedia/blob/stackoverflow/examples/frame_extractor.cpp
#include <cstdio>
#include "../include/internal.hpp"
int32_t main() {
using namespace Internal;
// Create a list of medias.
const char* media_uris[] = {
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/"
"ForBiggerJoyrides.mp4"};
const int media_ids[] = {0};
// Create a player instance.
PlayerCreate(0);
// Set frame callback (comment out the code to prevent crash from happening).
PlayerSetFrameEventHandler(
0, [](uint8_t*, int32_t, int32_t width, int32_t height) {
printf("Video width: %d, Video height: %d.", width, height);
});
// Open list of medias.
PlayerOpen(0, 1, media_uris, media_ids);
// Start playing the player.
PlayerPlay(0);
// Prevent console from closing.
getchar();
return 0;
}
Мне действительно помогут, если я смогу получить помощь в исправлении кода или любого другого рабочего метода для извлечения кадров или растровых изображений видео с помощью winrt::Windows::Media::Playback::MediaPlayer
.
Спасибо..
Комментарии:
1. Вы копируете на нулевую поверхность
surface
. Вы можете видеть в окне «Локальные», чтоdestination
значение равно нулю. Обратите внимание, что вы никогда не создавали поверхность или буфер.2. @RaymondChen большое спасибо за ваш ответ. Я понимаю, что создание экземпляра raw
IBuffer
, возможно, неправильно, но как я должен получитьIDirect3DSurface
(или что-то, что реализуетIDirect3DSurface
) в консольном приложении C /WinRT. Спасибо.3. Надеюсь, есть несколько руководств по Direct3D, которые покажут, как создать поверхность idirect3d11. Если у вас есть IDXGISurface, вы можете преобразовать его в IDirect3D11Surface с помощью CreateDirect3D11SurfaceFromDXGISurface
4. @RaymondChen большое вам спасибо, я посмотрю.
5. Пример того, как создать объект, реализующий
IDirect3DSurface
интерфейс, можно найти в разделе Использование MediaPlayer в режиме фрейм-сервера . В зависимости от вашего конкретного варианта использования вам может потребоваться реализовать другое решение.