1 /*
2 * VFW capture interface
3 * Copyright (c) 2006-2008 Ramiro Polla
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
26
28
29 // windows.h must no be included before winsock2.h, and libavformat internal
30 // headers may include winsock2.h
31 #include <windows.h>
32 // windows.h needs to be included before vfw.h
33 #include <vfw.h>
34
36
37 /* Some obsolete versions of MinGW32 before 4.0.0 lack this. */
38 #ifndef HWND_MESSAGE
39 #define HWND_MESSAGE ((HWND) -3)
40 #endif
41
50 char *
video_size;
/**< A string describing video size, set by a private option. */
52 };
53
55 {
56 switch(biCompression) {
57 case MKTAG(
'U',
'Y',
'V',
'Y'):
59 case MKTAG(
'Y',
'U',
'Y',
'2'):
61 case MKTAG(
'I',
'4',
'2',
'0'):
63 case BI_RGB:
64 switch(biBitCount) { /* 1-8 are untested */
65 case 1:
67 case 4:
69 case 8:
71 case 16:
73 case 24:
75 case 32:
77 }
78 }
80 }
81
83 {
84 switch(biCompression) {
85 case MKTAG(
'd',
'v',
's',
'd'):
87 case MKTAG(
'M',
'J',
'P',
'G'):
88 case MKTAG(
'm',
'j',
'p',
'g'):
90 }
92 }
93
94 #define dstruct(pctx, sname, var, type) \
95 av_log(pctx, AV_LOG_DEBUG, #var":\t%"type"\n", sname->var)
96
98 {
100 dstruct(s, cparms, dwRequestMicroSecPerFrame,
"lu");
101 dstruct(s, cparms, fMakeUserHitOKToCapture,
"d");
102 dstruct(s, cparms, wPercentDropForError,
"u");
103 dstruct(s, cparms, fYield,
"d");
104 dstruct(s, cparms, dwIndexSize,
"lu");
105 dstruct(s, cparms, wChunkGranularity,
"u");
106 dstruct(s, cparms, fUsingDOSMemory,
"d");
107 dstruct(s, cparms, wNumVideoRequested,
"u");
108 dstruct(s, cparms, fCaptureAudio,
"d");
109 dstruct(s, cparms, wNumAudioRequested,
"u");
110 dstruct(s, cparms, vKeyAbort,
"u");
111 dstruct(s, cparms, fAbortLeftMouse,
"d");
112 dstruct(s, cparms, fAbortRightMouse,
"d");
113 dstruct(s, cparms, fLimitEnabled,
"d");
114 dstruct(s, cparms, wTimeLimit,
"u");
115 dstruct(s, cparms, fMCIControl,
"d");
116 dstruct(s, cparms, fStepMCIDevice,
"d");
117 dstruct(s, cparms, dwMCIStartTime,
"lu");
118 dstruct(s, cparms, dwMCIStopTime,
"lu");
119 dstruct(s, cparms, fStepCaptureAt2x,
"d");
120 dstruct(s, cparms, wStepCaptureAverageFrames,
"u");
121 dstruct(s, cparms, dwAudioBufferSize,
"lu");
122 dstruct(s, cparms, fDisableWriteCache,
"d");
123 dstruct(s, cparms, AVStreamMaster,
"u");
124 }
125
127 {
128 #ifdef DEBUG
131 dstruct(s, vhdr, dwBufferLength,
"lu");
132 dstruct(s, vhdr, dwBytesUsed,
"lu");
133 dstruct(s, vhdr, dwTimeCaptured,
"lu");
134 dstruct(s, vhdr, dwUser,
"lu");
135 dstruct(s, vhdr, dwFlags,
"lu");
136 dstruct(s, vhdr, dwReserved[0],
"lu");
137 dstruct(s, vhdr, dwReserved[1],
"lu");
138 dstruct(s, vhdr, dwReserved[2],
"lu");
139 dstruct(s, vhdr, dwReserved[3],
"lu");
140 #endif
141 }
142
144 {
147 dstruct(s, bih, biWidth,
"ld");
148 dstruct(s, bih, biHeight,
"ld");
149 dstruct(s, bih, biPlanes,
"d");
150 dstruct(s, bih, biBitCount,
"d");
151 dstruct(s, bih, biCompression,
"lu");
153 (char*) &bih->biCompression);
154 dstruct(s, bih, biSizeImage,
"lu");
155 dstruct(s, bih, biXPelsPerMeter,
"lu");
156 dstruct(s, bih, biYPelsPerMeter,
"lu");
157 dstruct(s, bih, biClrUsed,
"lu");
158 dstruct(s, bih, biClrImportant,
"lu");
159 }
160
162 {
164 static const uint8_t dropscore[4] = { 62, 75, 87, 100 };
167
168 if(dropscore[++ctx->
frame_num%ndropscores] <= buffer_fullness) {
170 "real-time buffer %d%% full! frame dropped!\n", buffer_fullness);
171 return 1;
172 }
173
174 return 0;
175 }
176
178 {
182
185
187
190
192
194 if(!pktl_next)
196
200 }
201
202 pktl_next->
pkt.
pts = vdhdr->dwTimeCaptured;
203 memcpy(pktl_next->
pkt.
data, vdhdr->lpData, vdhdr->dwBytesUsed);
204
205 for(ppktl = &ctx->
pktl ; *ppktl ; ppktl = &(*ppktl)->
next);
206 *ppktl = pktl_next;
207
209
210 SetEvent(ctx->
event);
211 ReleaseMutex(ctx->
mutex);
212
215 ReleaseMutex(ctx->
mutex);
217 }
218
220 {
223
225 SendMessage(ctx->
hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);
226 SendMessage(ctx->
hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0);
227 DestroyWindow(ctx->
hwnd);
228 }
230 CloseHandle(ctx->
mutex);
232 CloseHandle(ctx->
event);
233
235 while (pktl) {
239 pktl = next;
240 }
241
242 return 0;
243 }
244
246 {
250 int devnum;
251 int bisize;
252 BITMAPINFO *bi =
NULL;
253 CAPTUREPARMS cparms;
256 int ret;
258
259 if (!strcmp(s->
url,
"list")) {
260 for (devnum = 0; devnum <= 9; devnum++) {
261 char driver_name[256];
262 char driver_ver[256];
263 ret = capGetDriverDescription(devnum,
264 driver_name, sizeof(driver_name),
265 driver_ver, sizeof(driver_ver));
266 if (ret) {
270 }
271 }
273 }
274
279 }
280
281 /* If atoi fails, devnum==0 and the default device is used */
282 devnum = atoi(s->
url);
283
284 ret = SendMessage(ctx->
hwnd, WM_CAP_DRIVER_CONNECT, devnum, 0);
285 if(!ret) {
287 DestroyWindow(ctx->
hwnd);
289 }
290
291 SendMessage(ctx->
hwnd, WM_CAP_SET_OVERLAY, 0, 0);
292 SendMessage(ctx->
hwnd, WM_CAP_SET_PREVIEW, 0, 0);
293
294 ret = SendMessage(ctx->
hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0,
296 if(!ret) {
299 }
300
301 SetWindowLongPtr(ctx->
hwnd, GWLP_USERDATA, (
LONG_PTR) s);
302
304 if(!st) {
307 }
308
309 /* Set video format */
310 bisize = SendMessage(ctx->
hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0);
311 if(!bisize)
314 if(!bi) {
317 }
318 ret = SendMessage(ctx->
hwnd, WM_CAP_GET_VIDEOFORMAT, bisize, (LPARAM) bi);
319 if(!ret)
321
323
325 if (ret < 0) {
328 }
329
332 if (ret < 0) {
335 }
336 }
337
338 if (0) {
339 /* For testing yet unsupported compressions
340 * Copy these values from user-supplied verbose information */
341 bi->bmiHeader.biWidth = 320;
342 bi->bmiHeader.biHeight = 240;
343 bi->bmiHeader.biPlanes = 1;
344 bi->bmiHeader.biBitCount = 12;
345 bi->bmiHeader.biCompression =
MKTAG(
'I',
'4',
'2',
'0');
346 bi->bmiHeader.biSizeImage = 115200;
348 }
349
350 ret = SendMessage(ctx->
hwnd, WM_CAP_SET_VIDEOFORMAT, bisize, (LPARAM) bi);
351 if(!ret) {
354 }
355
356 biCompression = bi->bmiHeader.biCompression;
357 biBitCount = bi->bmiHeader.biBitCount;
358
359 /* Set sequence setup */
360 ret = SendMessage(ctx->
hwnd, WM_CAP_GET_SEQUENCE_SETUP,
sizeof(cparms),
361 (LPARAM) &cparms);
362 if(!ret)
364
366
367 cparms.fYield = 1; // Spawn a background thread
368 cparms.dwRequestMicroSecPerFrame =
369 (framerate_q.
den*1000000) / framerate_q.
num;
370 cparms.fAbortLeftMouse = 0;
371 cparms.fAbortRightMouse = 0;
372 cparms.fCaptureAudio = 0;
373 cparms.vKeyAbort = 0;
374
375 ret = SendMessage(ctx->
hwnd, WM_CAP_SET_SEQUENCE_SETUP,
sizeof(cparms),
376 (LPARAM) &cparms);
377 if(!ret)
379
381
384 par->
width = bi->bmiHeader.biWidth;
385 par->
height = bi->bmiHeader.biHeight;
393 }
395 } else {
397 if(biCompression == BI_RGB) {
403 }
404 }
405 }
406
408
410
415 }
420 }
421
422 ret = SendMessage(ctx->
hwnd, WM_CAP_SEQUENCE_NOFILE, 0, 0);
423 if(!ret) {
426 }
427
428 return 0;
429
434 }
435
437 {
440
441 while(!pktl) {
448 }
449 ResetEvent(ctx->
event);
450 ReleaseMutex(ctx->
mutex);
451 if(!pktl) {
454 } else {
456 }
457 }
458 }
459
461
463 }
464
465 #define OFFSET(x) offsetof(struct vfw_ctx, x)
466 #define DEC AV_OPT_FLAG_DECODING_PARAM
471 };
472
479 };
480
484 .priv_data_size =
sizeof(
struct vfw_ctx),
490 };
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
#define WaitForSingleObject(a, b)
int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
Parse str and put in width_ptr and height_ptr the detected values.
#define LIBAVUTIL_VERSION_INT
static enum AVPixelFormat vfw_pixfmt(DWORD biCompression, WORD biBitCount)
unsigned int max_picture_buffer
Maximum amount of memory in bytes to use for buffering frames obtained from realtime capture devices...
static void dump_captureparms(AVFormatContext *s, CAPTUREPARMS *cparms)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
const char * av_default_item_name(void *ptr)
Return the context name.
static int vfw_read_close(AVFormatContext *s)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
static const AVClass vfw_class
This struct describes the properties of an encoded stream.
packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in ...
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
static void dump_videohdr(AVFormatContext *s, VIDEOHDR *vhdr)
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
int flags
Flags modifying the (de)muxer behaviour.
Main libavdevice API header.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
static void dump_bih(AVFormatContext *s, BITMAPINFOHEADER *bih)
AVCodecID
Identify the syntax and semantics of the bitstream.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
char * url
input or output URL.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
enum AVMediaType codec_type
General type of the encoded data.
AVRational avg_frame_rate
Average framerate.
int extradata_size
Size of the extradata content in bytes.
#define dstruct(pctx, sname, var, type)
common internal API header
static enum AVCodecID vfw_codecid(DWORD biCompression)
packed RGB 8:8:8, 24bpp, BGRBGR...
#define FF_ARRAY_ELEMS(a)
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#define AV_LOG_INFO
Standard information.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Describe the class of an AVClass context structure.
Rational number (pair of numerator and denominator).
static int vfw_read_header(AVFormatContext *s)
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
AVInputFormat ff_vfwcap_demuxer
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
struct AVPacketList * next
Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb...
char * framerate
Set by a private option.
static const AVOption options[]
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
#define AV_PIX_FMT_RGB555
static int vfw_read_packet(AVFormatContext *s, AVPacket *pkt)
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
char * video_size
A string describing video size, set by a private option.
static int shall_we_drop(AVFormatContext *s)
void * priv_data
Format private data.
int bits_per_coded_sample
The number of bits per sample in the codedwords.
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
static LRESULT CALLBACK videostream_cb(HWND hwnd, LPVIDEOHDR vdhdr)
AVCodecParameters * codecpar
Codec parameters associated with this stream.
#define MKTAG(a, b, c, d)
AVPixelFormat
Pixel format.
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...