00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #define NO_DSHOW_STRSAFE
00023 #include "dshow_capture.h"
00024
00025 #include <stddef.h>
00026 #define imemoffset offsetof(libAVPin, imemvtbl)
00027
00028 DECLARE_QUERYINTERFACE(libAVPin,
00029 { {&IID_IUnknown,0}, {&IID_IPin,0}, {&IID_IMemInputPin,imemoffset} })
00030 DECLARE_ADDREF(libAVPin)
00031 DECLARE_RELEASE(libAVPin)
00032
00033 long WINAPI
00034 libAVPin_Connect(libAVPin *this, IPin *pin, const AM_MEDIA_TYPE *type)
00035 {
00036 dshowdebug("libAVPin_Connect(%p, %p, %p)\n", this, pin, type);
00037
00038 return S_FALSE;
00039 }
00040 long WINAPI
00041 libAVPin_ReceiveConnection(libAVPin *this, IPin *pin,
00042 const AM_MEDIA_TYPE *type)
00043 {
00044 enum dshowDeviceType devtype = this->filter->type;
00045 dshowdebug("libAVPin_ReceiveConnection(%p)\n", this);
00046
00047 if (!pin)
00048 return E_POINTER;
00049 if (this->connectedto)
00050 return VFW_E_ALREADY_CONNECTED;
00051
00052 ff_print_AM_MEDIA_TYPE(type);
00053 if (devtype == VideoDevice) {
00054 if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video))
00055 return VFW_E_TYPE_NOT_ACCEPTED;
00056 } else {
00057 if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio))
00058 return VFW_E_TYPE_NOT_ACCEPTED;
00059 }
00060
00061 IPin_AddRef(pin);
00062 this->connectedto = pin;
00063
00064 ff_copy_dshow_media_type(&this->type, type);
00065
00066 return S_OK;
00067 }
00068 long WINAPI
00069 libAVPin_Disconnect(libAVPin *this)
00070 {
00071 dshowdebug("libAVPin_Disconnect(%p)\n", this);
00072
00073 if (this->filter->state != State_Stopped)
00074 return VFW_E_NOT_STOPPED;
00075 if (!this->connectedto)
00076 return S_FALSE;
00077 IPin_Release(this->connectedto);
00078 this->connectedto = NULL;
00079
00080 return S_OK;
00081 }
00082 long WINAPI
00083 libAVPin_ConnectedTo(libAVPin *this, IPin **pin)
00084 {
00085 dshowdebug("libAVPin_ConnectedTo(%p)\n", this);
00086
00087 if (!pin)
00088 return E_POINTER;
00089 if (!this->connectedto)
00090 return VFW_E_NOT_CONNECTED;
00091 IPin_AddRef(this->connectedto);
00092 *pin = this->connectedto;
00093
00094 return S_OK;
00095 }
00096 long WINAPI
00097 libAVPin_ConnectionMediaType(libAVPin *this, AM_MEDIA_TYPE *type)
00098 {
00099 dshowdebug("libAVPin_ConnectionMediaType(%p)\n", this);
00100
00101 if (!type)
00102 return E_POINTER;
00103 if (!this->connectedto)
00104 return VFW_E_NOT_CONNECTED;
00105
00106 return ff_copy_dshow_media_type(type, &this->type);
00107 }
00108 long WINAPI
00109 libAVPin_QueryPinInfo(libAVPin *this, PIN_INFO *info)
00110 {
00111 dshowdebug("libAVPin_QueryPinInfo(%p)\n", this);
00112
00113 if (!info)
00114 return E_POINTER;
00115
00116 if (this->filter)
00117 libAVFilter_AddRef(this->filter);
00118
00119 info->pFilter = (IBaseFilter *) this->filter;
00120 info->dir = PINDIR_INPUT;
00121 wcscpy(info->achName, L"Capture");
00122
00123 return S_OK;
00124 }
00125 long WINAPI
00126 libAVPin_QueryDirection(libAVPin *this, PIN_DIRECTION *dir)
00127 {
00128 dshowdebug("libAVPin_QueryDirection(%p)\n", this);
00129 if (!dir)
00130 return E_POINTER;
00131 *dir = PINDIR_INPUT;
00132 return S_OK;
00133 }
00134 long WINAPI
00135 libAVPin_QueryId(libAVPin *this, wchar_t **id)
00136 {
00137 dshowdebug("libAVPin_QueryId(%p)\n", this);
00138
00139 if (!id)
00140 return E_POINTER;
00141
00142 *id = wcsdup(L"libAV Pin");
00143
00144 return S_OK;
00145 }
00146 long WINAPI
00147 libAVPin_QueryAccept(libAVPin *this, const AM_MEDIA_TYPE *type)
00148 {
00149 dshowdebug("libAVPin_QueryAccept(%p)\n", this);
00150 return S_FALSE;
00151 }
00152 long WINAPI
00153 libAVPin_EnumMediaTypes(libAVPin *this, IEnumMediaTypes **enumtypes)
00154 {
00155 const AM_MEDIA_TYPE *type = NULL;
00156 libAVEnumMediaTypes *new;
00157 dshowdebug("libAVPin_EnumMediaTypes(%p)\n", this);
00158
00159 if (!enumtypes)
00160 return E_POINTER;
00161 new = libAVEnumMediaTypes_Create(type);
00162 if (!new)
00163 return E_OUTOFMEMORY;
00164
00165 *enumtypes = (IEnumMediaTypes *) new;
00166 return S_OK;
00167 }
00168 long WINAPI
00169 libAVPin_QueryInternalConnections(libAVPin *this, IPin **pin,
00170 unsigned long *npin)
00171 {
00172 dshowdebug("libAVPin_QueryInternalConnections(%p)\n", this);
00173 return E_NOTIMPL;
00174 }
00175 long WINAPI
00176 libAVPin_EndOfStream(libAVPin *this)
00177 {
00178 dshowdebug("libAVPin_EndOfStream(%p)\n", this);
00179
00180 return S_OK;
00181 }
00182 long WINAPI
00183 libAVPin_BeginFlush(libAVPin *this)
00184 {
00185 dshowdebug("libAVPin_BeginFlush(%p)\n", this);
00186
00187 return S_OK;
00188 }
00189 long WINAPI
00190 libAVPin_EndFlush(libAVPin *this)
00191 {
00192 dshowdebug("libAVPin_EndFlush(%p)\n", this);
00193
00194 return S_OK;
00195 }
00196 long WINAPI
00197 libAVPin_NewSegment(libAVPin *this, REFERENCE_TIME start, REFERENCE_TIME stop,
00198 double rate)
00199 {
00200 dshowdebug("libAVPin_NewSegment(%p)\n", this);
00201
00202 return S_OK;
00203 }
00204
00205 static int
00206 libAVPin_Setup(libAVPin *this, libAVFilter *filter)
00207 {
00208 IPinVtbl *vtbl = this->vtbl;
00209 IMemInputPinVtbl *imemvtbl;
00210
00211 if (!filter)
00212 return 0;
00213
00214 imemvtbl = av_malloc(sizeof(IMemInputPinVtbl));
00215 if (!imemvtbl)
00216 return 0;
00217
00218 SETVTBL(imemvtbl, libAVMemInputPin, QueryInterface);
00219 SETVTBL(imemvtbl, libAVMemInputPin, AddRef);
00220 SETVTBL(imemvtbl, libAVMemInputPin, Release);
00221 SETVTBL(imemvtbl, libAVMemInputPin, GetAllocator);
00222 SETVTBL(imemvtbl, libAVMemInputPin, NotifyAllocator);
00223 SETVTBL(imemvtbl, libAVMemInputPin, GetAllocatorRequirements);
00224 SETVTBL(imemvtbl, libAVMemInputPin, Receive);
00225 SETVTBL(imemvtbl, libAVMemInputPin, ReceiveMultiple);
00226 SETVTBL(imemvtbl, libAVMemInputPin, ReceiveCanBlock);
00227
00228 this->imemvtbl = imemvtbl;
00229
00230 SETVTBL(vtbl, libAVPin, QueryInterface);
00231 SETVTBL(vtbl, libAVPin, AddRef);
00232 SETVTBL(vtbl, libAVPin, Release);
00233 SETVTBL(vtbl, libAVPin, Connect);
00234 SETVTBL(vtbl, libAVPin, ReceiveConnection);
00235 SETVTBL(vtbl, libAVPin, Disconnect);
00236 SETVTBL(vtbl, libAVPin, ConnectedTo);
00237 SETVTBL(vtbl, libAVPin, ConnectionMediaType);
00238 SETVTBL(vtbl, libAVPin, QueryPinInfo);
00239 SETVTBL(vtbl, libAVPin, QueryDirection);
00240 SETVTBL(vtbl, libAVPin, QueryId);
00241 SETVTBL(vtbl, libAVPin, QueryAccept);
00242 SETVTBL(vtbl, libAVPin, EnumMediaTypes);
00243 SETVTBL(vtbl, libAVPin, QueryInternalConnections);
00244 SETVTBL(vtbl, libAVPin, EndOfStream);
00245 SETVTBL(vtbl, libAVPin, BeginFlush);
00246 SETVTBL(vtbl, libAVPin, EndFlush);
00247 SETVTBL(vtbl, libAVPin, NewSegment);
00248
00249 this->filter = filter;
00250
00251 return 1;
00252 }
00253 DECLARE_CREATE(libAVPin, libAVPin_Setup(this, filter), libAVFilter *filter)
00254 DECLARE_DESTROY(libAVPin, nothing)
00255
00256
00257
00258
00259 long WINAPI
00260 libAVMemInputPin_QueryInterface(libAVMemInputPin *this, const GUID *riid,
00261 void **ppvObject)
00262 {
00263 libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
00264 dshowdebug("libAVMemInputPin_QueryInterface(%p)\n", this);
00265 return libAVPin_QueryInterface(pin, riid, ppvObject);
00266 }
00267 unsigned long WINAPI
00268 libAVMemInputPin_AddRef(libAVMemInputPin *this)
00269 {
00270 libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
00271 dshowdebug("libAVMemInputPin_AddRef(%p)\n", this);
00272 return libAVPin_AddRef(pin);
00273 }
00274 unsigned long WINAPI
00275 libAVMemInputPin_Release(libAVMemInputPin *this)
00276 {
00277 libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
00278 dshowdebug("libAVMemInputPin_Release(%p)\n", this);
00279 return libAVPin_Release(pin);
00280 }
00281 long WINAPI
00282 libAVMemInputPin_GetAllocator(libAVMemInputPin *this, IMemAllocator **alloc)
00283 {
00284 dshowdebug("libAVMemInputPin_GetAllocator(%p)\n", this);
00285 return VFW_E_NO_ALLOCATOR;
00286 }
00287 long WINAPI
00288 libAVMemInputPin_NotifyAllocator(libAVMemInputPin *this, IMemAllocator *alloc,
00289 WINBOOL rdwr)
00290 {
00291 dshowdebug("libAVMemInputPin_NotifyAllocator(%p)\n", this);
00292 return S_OK;
00293 }
00294 long WINAPI
00295 libAVMemInputPin_GetAllocatorRequirements(libAVMemInputPin *this,
00296 ALLOCATOR_PROPERTIES *props)
00297 {
00298 dshowdebug("libAVMemInputPin_GetAllocatorRequirements(%p)\n", this);
00299 return E_NOTIMPL;
00300 }
00301 long WINAPI
00302 libAVMemInputPin_Receive(libAVMemInputPin *this, IMediaSample *sample)
00303 {
00304 libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
00305 enum dshowDeviceType devtype = pin->filter->type;
00306 void *priv_data;
00307 uint8_t *buf;
00308 int buf_size;
00309 int index;
00310 int64_t curtime;
00311
00312 dshowdebug("libAVMemInputPin_Receive(%p)\n", this);
00313
00314 if (!sample)
00315 return E_POINTER;
00316
00317 if (devtype == VideoDevice) {
00318
00319 IReferenceClock *clock = pin->filter->clock;
00320 IReferenceClock_GetTime(clock, &curtime);
00321 } else {
00322 int64_t dummy;
00323 IMediaSample_GetTime(sample, &curtime, &dummy);
00324 curtime += pin->filter->start_time;
00325 }
00326
00327 buf_size = IMediaSample_GetActualDataLength(sample);
00328 IMediaSample_GetPointer(sample, &buf);
00329 priv_data = pin->filter->priv_data;
00330 index = pin->filter->stream_index;
00331
00332 pin->filter->callback(priv_data, index, buf, buf_size, curtime);
00333
00334 return S_OK;
00335 }
00336 long WINAPI
00337 libAVMemInputPin_ReceiveMultiple(libAVMemInputPin *this,
00338 IMediaSample **samples, long n, long *nproc)
00339 {
00340 int i;
00341 dshowdebug("libAVMemInputPin_ReceiveMultiple(%p)\n", this);
00342
00343 for (i = 0; i < n; i++)
00344 libAVMemInputPin_Receive(this, samples[i]);
00345
00346 *nproc = n;
00347 return S_OK;
00348 }
00349 long WINAPI
00350 libAVMemInputPin_ReceiveCanBlock(libAVMemInputPin *this)
00351 {
00352 dshowdebug("libAVMemInputPin_ReceiveCanBlock(%p)\n", this);
00353
00354 return S_FALSE;
00355 }
00356
00357 void
00358 libAVMemInputPin_Destroy(libAVMemInputPin *this)
00359 {
00360 libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
00361 dshowdebug("libAVMemInputPin_Destroy(%p)\n", this);
00362 return libAVPin_Destroy(pin);
00363 }