/* * Copyright (C) 2023 Lain Bailey * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA */ #pragma once #include #include #include #ifdef DSHOWCAPTURE_EXPORTS #define DSHOWCAPTURE_EXPORT __declspec(dllexport) #else #define DSHOWCAPTURE_EXPORT #endif #define DSHOWCAPTURE_VERSION_MAJOR 0 #define DSHOWCAPTURE_VERSION_MINOR 10 #define DSHOWCAPTURE_VERSION_PATCH 0 #define MAKE_DSHOWCAPTURE_VERSION(major, minor, patch) \ ((major << 24) | (minor << 16) | (patch)) #define DSHOWCAPTURE_VERSION \ MAKE_DSHOWCAPTURE_VERSION(DSHOWCAPTURE_VERSION_MAJOR, \ DSHOWCAPTURE_VERSION_MINOR, \ DSHOWCAPTURE_VERSION_PATCH) #define DSHOW_MAX_PLANES 8 namespace DShow { /* internal forward */ struct HDevice; struct HVideoEncoder; struct VideoConfig; struct AudioConfig; typedef std::function VideoProc; typedef std::function AudioProc; typedef std::function ReactivateProc; enum class InitGraph { False, True, }; /** DirectShow configuration dialog type */ enum class DialogType { ConfigVideo, ConfigAudio, ConfigCrossbar, ConfigCrossbar2, }; enum class VideoFormat { Any, Unknown, /* raw formats */ ARGB = 100, XRGB, RGB24, /* planar YUV formats */ I420 = 200, NV12, YV12, Y800, P010, /* packed YUV formats */ YVYU = 300, YUY2, UYVY, HDYC, /* encoded formats */ MJPEG = 400, H264, HEVC, }; enum class AudioFormat { Any, Unknown, /* raw formats */ Wave16bit = 100, WaveFloat, /* encoded formats */ AAC = 200, AC3, MPGA, /* MPEG 1 */ }; enum class AudioMode { Capture, DirectSound, WaveOut, }; enum class Result { Success, InUse, Error, }; struct VideoInfo { int minCX, minCY; int maxCX, maxCY; int granularityCX, granularityCY; long long minInterval, maxInterval; VideoFormat format; }; struct AudioInfo { int minChannels, maxChannels; int channelsGranularity; int minSampleRate, maxSampleRate; int sampleRateGranularity; AudioFormat format; }; struct DeviceId { std::wstring name; std::wstring path; }; struct VideoDevice : DeviceId { bool audioAttached = false; bool separateAudioFilter = false; std::vector caps; }; struct AudioDevice : DeviceId { std::vector caps; }; struct Config : DeviceId { /** Use the device's desired default config */ bool useDefaultConfig = true; }; struct VideoConfig : Config { VideoProc callback; ReactivateProc reactivateCallback; /** Desired width/height of video. */ int cx = 0, cy_abs = 0; /** Whether or not cy was negative. */ bool cy_flip = false; /** Desired frame interval (in 100-nanosecond units) */ long long frameInterval = 0; /** Internal video format. */ VideoFormat internalFormat = VideoFormat::Any; /** Desired video format. */ VideoFormat format = VideoFormat::Any; }; struct AudioConfig : Config { AudioProc callback; /** * Use the audio attached to the video device * * (name/path member variables will be ignored) */ bool useVideoDevice = false; /** Use separate filter for audio */ bool useSeparateAudioFilter = false; /** Desired sample rate */ int sampleRate = 0; /** Desired channels */ int channels = 0; /** Desired audio format */ AudioFormat format = AudioFormat::Any; /** Audio playback mode */ AudioMode mode = AudioMode::Capture; /** Desired buffer */ int buffer = 0; }; class DSHOWCAPTURE_EXPORT Device { HDevice *context; public: Device(InitGraph initialize = InitGraph::False); ~Device(); bool Valid() const; bool ResetGraph(); void ShutdownGraph(); bool SetVideoConfig(VideoConfig *config); bool SetAudioConfig(AudioConfig *config); /** * Connects all the configured filters together. * * Call SetVideoConfig and/or SetAudioConfig before using. */ bool ConnectFilters(); Result Start(); void Stop(); bool GetVideoConfig(VideoConfig &config) const; bool GetAudioConfig(AudioConfig &config) const; bool GetVideoDeviceId(DeviceId &id) const; bool GetAudioDeviceId(DeviceId &id) const; /** * Opens a DirectShow dialog associated with this device * * @param type The dialog type */ void OpenDialog(void *hwnd, DialogType type) const; static bool EnumVideoDevices(std::vector &devices); static bool EnumAudioDevices(std::vector &devices); }; struct VideoEncoderConfig : DeviceId { int fpsNumerator; int fpsDenominator; int bitrate; int keyframeInterval; int cx; int cy; }; struct EncoderPacket { unsigned char *data; size_t size; long long pts; long long dts; }; class VideoEncoder { HVideoEncoder *context; public: VideoEncoder(); ~VideoEncoder(); bool Valid() const; bool Active() const; bool ResetGraph(); bool SetConfig(VideoEncoderConfig &config); bool GetConfig(VideoEncoderConfig &config) const; bool Encode(unsigned char *data[DSHOW_MAX_PLANES], size_t linesize[DSHOW_MAX_PLANES], long long timestampStart, long long timestampEnd, EncoderPacket &packet, bool &new_packet); static bool EnumEncoders(std::vector &encoders); }; enum class LogType { Error, Warning, Info, Debug, }; typedef void (*LogCallback)(LogType type, const wchar_t *msg, void *param); DSHOWCAPTURE_EXPORT void SetLogCallback(LogCallback callback, void *param); };