dshow_capture.h 14.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * DirectShow capture interface
 * Copyright (c) 2010 Ramiro Polla
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg 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.
 *
 * FFmpeg 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 FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

22 23 24
#ifndef AVDEVICE_DSHOW_H
#define AVDEVICE_DSHOW_H

25 26
#define DSHOWDEBUG 0

27
#include "avdevice.h"
28 29

#define COBJMACROS
30
#define WIN32_LEAN_AND_MEAN
31
#include <windows.h>
32
#define NO_DSHOW_STRSAFE
33 34 35
#include <dshow.h>
#include <dvdmedia.h>

36 37 38 39 40
/* EC_DEVICE_LOST is not defined in MinGW dshow headers. */
#ifndef EC_DEVICE_LOST
#define EC_DEVICE_LOST 0x1f
#endif

41
long ff_copy_dshow_media_type(AM_MEDIA_TYPE *dst, const AM_MEDIA_TYPE *src);
42 43
void ff_print_VIDEO_STREAM_CONFIG_CAPS(const VIDEO_STREAM_CONFIG_CAPS *caps);
void ff_print_AUDIO_STREAM_CONFIG_CAPS(const AUDIO_STREAM_CONFIG_CAPS *caps);
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type);
void ff_printGUID(const GUID *g);

#if DSHOWDEBUG
extern const AVClass *ff_dshow_context_class_ptr;
#define dshowdebug(...) av_log(&ff_dshow_context_class_ptr, AV_LOG_DEBUG, __VA_ARGS__)
#else
#define dshowdebug(...)
#endif

static inline void nothing(void *foo)
{
}

struct GUIDoffset {
    const GUID *iid;
    int offset;
};

enum dshowDeviceType {
    VideoDevice = 0,
    AudioDevice = 1,
};

#define DECLARE_QUERYINTERFACE(class, ...)                                   \
long WINAPI                                                                  \
class##_QueryInterface(class *this, const GUID *riid, void **ppvObject)      \
{                                                                            \
    struct GUIDoffset ifaces[] = __VA_ARGS__;                                \
    int i;                                                                   \
    dshowdebug(AV_STRINGIFY(class)"_QueryInterface(%p, %p, %p)\n", this, riid, ppvObject); \
    ff_printGUID(riid);                                                      \
    if (!ppvObject)                                                          \
        return E_POINTER;                                                    \
    for (i = 0; i < sizeof(ifaces)/sizeof(ifaces[0]); i++) {                 \
        if (IsEqualGUID(riid, ifaces[i].iid)) {                              \
            void *obj = (void *) ((uint8_t *) this + ifaces[i].offset);      \
            class##_AddRef(this);                                            \
            dshowdebug("\tfound %d with offset %d\n", i, ifaces[i].offset);  \
            *ppvObject = (void *) obj;                                       \
            return S_OK;                                                     \
        }                                                                    \
    }                                                                        \
    dshowdebug("\tE_NOINTERFACE\n");                                         \
    *ppvObject = NULL;                                                       \
    return E_NOINTERFACE;                                                    \
}
#define DECLARE_ADDREF(class)                                                \
unsigned long WINAPI                                                         \
class##_AddRef(class *this)                                                  \
{                                                                            \
    dshowdebug(AV_STRINGIFY(class)"_AddRef(%p)\t%ld\n", this, this->ref+1);  \
    return InterlockedIncrement(&this->ref);                                 \
}
#define DECLARE_RELEASE(class)                                               \
unsigned long WINAPI                                                         \
class##_Release(class *this)                                                 \
{                                                                            \
    long ref = InterlockedDecrement(&this->ref);                             \
    dshowdebug(AV_STRINGIFY(class)"_Release(%p)\t%ld\n", this, ref);         \
    if (!ref)                                                                \
        class##_Destroy(this);                                               \
    return ref;                                                              \
}

#define DECLARE_DESTROY(class, func)                                         \
void class##_Destroy(class *this)                                            \
{                                                                            \
    dshowdebug(AV_STRINGIFY(class)"_Destroy(%p)\n", this);                   \
    func(this);                                                              \
    if (this) {                                                              \
        if (this->vtbl)                                                      \
            CoTaskMemFree(this->vtbl);                                       \
        CoTaskMemFree(this);                                                 \
    }                                                                        \
}
#define DECLARE_CREATE(class, setup, ...)                                    \
class *class##_Create(__VA_ARGS__)                                           \
{                                                                            \
    class *this = CoTaskMemAlloc(sizeof(class));                             \
    void  *vtbl = CoTaskMemAlloc(sizeof(*this->vtbl));                       \
    dshowdebug(AV_STRINGIFY(class)"_Create(%p)\n", this);                    \
    if (!this || !vtbl)                                                      \
        goto fail;                                                           \
    ZeroMemory(this, sizeof(class));                                         \
    ZeroMemory(vtbl, sizeof(*this->vtbl));                                   \
    this->ref  = 1;                                                          \
    this->vtbl = vtbl;                                                       \
    if (!setup)                                                              \
        goto fail;                                                           \
    dshowdebug("created "AV_STRINGIFY(class)" %p\n", this);                  \
    return this;                                                             \
fail:                                                                        \
    class##_Destroy(this);                                                   \
    dshowdebug("could not create "AV_STRINGIFY(class)"\n");                  \
    return NULL;                                                             \
}

#define SETVTBL(vtbl, class, fn) \
    do { (vtbl)->fn = (void *) class##_##fn; } while(0)

/*****************************************************************************
 * Forward Declarations
 ****************************************************************************/
typedef struct libAVPin libAVPin;
typedef struct libAVMemInputPin libAVMemInputPin;
typedef struct libAVEnumPins libAVEnumPins;
typedef struct libAVEnumMediaTypes libAVEnumMediaTypes;
typedef struct libAVFilter libAVFilter;

/*****************************************************************************
 * libAVPin
 ****************************************************************************/
struct libAVPin {
    IPinVtbl *vtbl;
    long ref;
    libAVFilter *filter;
    IPin *connectedto;
    AM_MEDIA_TYPE type;
    IMemInputPinVtbl *imemvtbl;
};

long          WINAPI libAVPin_QueryInterface          (libAVPin *, const GUID *, void **);
unsigned long WINAPI libAVPin_AddRef                  (libAVPin *);
unsigned long WINAPI libAVPin_Release                 (libAVPin *);
long          WINAPI libAVPin_Connect                 (libAVPin *, IPin *, const AM_MEDIA_TYPE *);
long          WINAPI libAVPin_ReceiveConnection       (libAVPin *, IPin *, const AM_MEDIA_TYPE *);
long          WINAPI libAVPin_Disconnect              (libAVPin *);
long          WINAPI libAVPin_ConnectedTo             (libAVPin *, IPin **);
long          WINAPI libAVPin_ConnectionMediaType     (libAVPin *, AM_MEDIA_TYPE *);
long          WINAPI libAVPin_QueryPinInfo            (libAVPin *, PIN_INFO *);
long          WINAPI libAVPin_QueryDirection          (libAVPin *, PIN_DIRECTION *);
long          WINAPI libAVPin_QueryId                 (libAVPin *, wchar_t **);
long          WINAPI libAVPin_QueryAccept             (libAVPin *, const AM_MEDIA_TYPE *);
long          WINAPI libAVPin_EnumMediaTypes          (libAVPin *, IEnumMediaTypes **);
long          WINAPI libAVPin_QueryInternalConnections(libAVPin *, IPin **, unsigned long *);
long          WINAPI libAVPin_EndOfStream             (libAVPin *);
long          WINAPI libAVPin_BeginFlush              (libAVPin *);
long          WINAPI libAVPin_EndFlush                (libAVPin *);
long          WINAPI libAVPin_NewSegment              (libAVPin *, REFERENCE_TIME, REFERENCE_TIME, double);

long          WINAPI libAVMemInputPin_QueryInterface          (libAVMemInputPin *, const GUID *, void **);
unsigned long WINAPI libAVMemInputPin_AddRef                  (libAVMemInputPin *);
unsigned long WINAPI libAVMemInputPin_Release                 (libAVMemInputPin *);
long          WINAPI libAVMemInputPin_GetAllocator            (libAVMemInputPin *, IMemAllocator **);
189
long          WINAPI libAVMemInputPin_NotifyAllocator         (libAVMemInputPin *, IMemAllocator *, BOOL);
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
long          WINAPI libAVMemInputPin_GetAllocatorRequirements(libAVMemInputPin *, ALLOCATOR_PROPERTIES *);
long          WINAPI libAVMemInputPin_Receive                 (libAVMemInputPin *, IMediaSample *);
long          WINAPI libAVMemInputPin_ReceiveMultiple         (libAVMemInputPin *, IMediaSample **, long, long *);
long          WINAPI libAVMemInputPin_ReceiveCanBlock         (libAVMemInputPin *);

void                 libAVPin_Destroy(libAVPin *);
libAVPin            *libAVPin_Create (libAVFilter *filter);

void                 libAVMemInputPin_Destroy(libAVMemInputPin *);

/*****************************************************************************
 * libAVEnumPins
 ****************************************************************************/
struct libAVEnumPins {
    IEnumPinsVtbl *vtbl;
    long ref;
    int pos;
    libAVPin *pin;
    libAVFilter *filter;
};

long          WINAPI libAVEnumPins_QueryInterface(libAVEnumPins *, const GUID *, void **);
unsigned long WINAPI libAVEnumPins_AddRef        (libAVEnumPins *);
unsigned long WINAPI libAVEnumPins_Release       (libAVEnumPins *);
long          WINAPI libAVEnumPins_Next          (libAVEnumPins *, unsigned long, IPin **, unsigned long *);
long          WINAPI libAVEnumPins_Skip          (libAVEnumPins *, unsigned long);
long          WINAPI libAVEnumPins_Reset         (libAVEnumPins *);
long          WINAPI libAVEnumPins_Clone         (libAVEnumPins *, libAVEnumPins **);

void                 libAVEnumPins_Destroy(libAVEnumPins *);
libAVEnumPins       *libAVEnumPins_Create (libAVPin *pin, libAVFilter *filter);

/*****************************************************************************
 * libAVEnumMediaTypes
 ****************************************************************************/
struct libAVEnumMediaTypes {
    IEnumPinsVtbl *vtbl;
    long ref;
    int pos;
    AM_MEDIA_TYPE type;
};

long          WINAPI libAVEnumMediaTypes_QueryInterface(libAVEnumMediaTypes *, const GUID *, void **);
unsigned long WINAPI libAVEnumMediaTypes_AddRef        (libAVEnumMediaTypes *);
unsigned long WINAPI libAVEnumMediaTypes_Release       (libAVEnumMediaTypes *);
long          WINAPI libAVEnumMediaTypes_Next          (libAVEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *);
long          WINAPI libAVEnumMediaTypes_Skip          (libAVEnumMediaTypes *, unsigned long);
long          WINAPI libAVEnumMediaTypes_Reset         (libAVEnumMediaTypes *);
long          WINAPI libAVEnumMediaTypes_Clone         (libAVEnumMediaTypes *, libAVEnumMediaTypes **);

void                 libAVEnumMediaTypes_Destroy(libAVEnumMediaTypes *);
libAVEnumMediaTypes *libAVEnumMediaTypes_Create(const AM_MEDIA_TYPE *type);

/*****************************************************************************
 * libAVFilter
 ****************************************************************************/
struct libAVFilter {
    IBaseFilterVtbl *vtbl;
    long ref;
    const wchar_t *name;
    libAVPin *pin;
    FILTER_INFO info;
    FILTER_STATE state;
    IReferenceClock *clock;
    enum dshowDeviceType type;
    void *priv_data;
    int stream_index;
    int64_t start_time;
258
    void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type);
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
};

long          WINAPI libAVFilter_QueryInterface (libAVFilter *, const GUID *, void **);
unsigned long WINAPI libAVFilter_AddRef         (libAVFilter *);
unsigned long WINAPI libAVFilter_Release        (libAVFilter *);
long          WINAPI libAVFilter_GetClassID     (libAVFilter *, CLSID *);
long          WINAPI libAVFilter_Stop           (libAVFilter *);
long          WINAPI libAVFilter_Pause          (libAVFilter *);
long          WINAPI libAVFilter_Run            (libAVFilter *, REFERENCE_TIME);
long          WINAPI libAVFilter_GetState       (libAVFilter *, DWORD, FILTER_STATE *);
long          WINAPI libAVFilter_SetSyncSource  (libAVFilter *, IReferenceClock *);
long          WINAPI libAVFilter_GetSyncSource  (libAVFilter *, IReferenceClock **);
long          WINAPI libAVFilter_EnumPins       (libAVFilter *, IEnumPins **);
long          WINAPI libAVFilter_FindPin        (libAVFilter *, const wchar_t *, IPin **);
long          WINAPI libAVFilter_QueryFilterInfo(libAVFilter *, FILTER_INFO *);
long          WINAPI libAVFilter_JoinFilterGraph(libAVFilter *, IFilterGraph *, const wchar_t *);
long          WINAPI libAVFilter_QueryVendorInfo(libAVFilter *, wchar_t **);

void                 libAVFilter_Destroy(libAVFilter *);
libAVFilter         *libAVFilter_Create (void *, void *, enum dshowDeviceType);
279 280

#endif /* AVDEVICE_DSHOW_H */