X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavdevice%2Fvfwcap.c;h=fea85fc5aee76d55b013fa8be0a378c7b21c91a5;hb=c3311d472a7528c67f76d0d061704ae70a99b32e;hp=92e5925756fd026c1c30fc3e7af46de45a7ed4bf;hpb=ce03ed4df1d8f0fc8f48402886a6dfb0b7099509;p=ffmpeg diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c index 92e5925756f..fea85fc5aee 100644 --- a/libavdevice/vfwcap.c +++ b/libavdevice/vfwcap.c @@ -2,29 +2,31 @@ * VFW capture interface * Copyright (c) 2006-2008 Ramiro Polla * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav 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, + * Libav 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 + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavformat/avformat.h" +#include "libavformat/internal.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" #include #include -//#define DEBUG_VFW - /* Defines for VFW missing from MinGW. * Remove this when MinGW incorporates them. */ #define HWND_MESSAGE ((HWND)-3) @@ -34,52 +36,55 @@ /* End of missing MinGW defines */ struct vfw_ctx { + const AVClass *class; HWND hwnd; HANDLE mutex; HANDLE event; AVPacketList *pktl; unsigned int curbufsize; unsigned int frame_num; + char *video_size; /**< A string describing video size, set by a private option. */ + char *framerate; /**< Set by a private option. */ }; -static enum PixelFormat vfw_pixfmt(DWORD biCompression, WORD biBitCount) +static enum AVPixelFormat vfw_pixfmt(DWORD biCompression, WORD biBitCount) { switch(biCompression) { case MKTAG('U', 'Y', 'V', 'Y'): - return PIX_FMT_UYVY422; + return AV_PIX_FMT_UYVY422; case MKTAG('Y', 'U', 'Y', '2'): - return PIX_FMT_YUYV422; + return AV_PIX_FMT_YUYV422; case MKTAG('I', '4', '2', '0'): - return PIX_FMT_YUV420P; + return AV_PIX_FMT_YUV420P; case BI_RGB: switch(biBitCount) { /* 1-8 are untested */ case 1: - return PIX_FMT_MONOWHITE; + return AV_PIX_FMT_MONOWHITE; case 4: - return PIX_FMT_RGB4; + return AV_PIX_FMT_RGB4; case 8: - return PIX_FMT_RGB8; + return AV_PIX_FMT_RGB8; case 16: - return PIX_FMT_RGB555; + return AV_PIX_FMT_RGB555; case 24: - return PIX_FMT_BGR24; + return AV_PIX_FMT_BGR24; case 32: - return PIX_FMT_RGB32; + return AV_PIX_FMT_RGB32; } } - return PIX_FMT_NONE; + return AV_PIX_FMT_NONE; } -static enum CodecID vfw_codecid(DWORD biCompression) +static enum AVCodecID vfw_codecid(DWORD biCompression) { switch(biCompression) { case MKTAG('d', 'v', 's', 'd'): - return CODEC_ID_DVVIDEO; + return AV_CODEC_ID_DVVIDEO; case MKTAG('M', 'J', 'P', 'G'): case MKTAG('m', 'j', 'p', 'g'): - return CODEC_ID_MJPEG; + return AV_CODEC_ID_MJPEG; } - return CODEC_ID_NONE; + return AV_CODEC_ID_NONE; } #define dstruct(pctx, sname, var, type) \ @@ -116,7 +121,7 @@ static void dump_captureparms(AVFormatContext *s, CAPTUREPARMS *cparms) static void dump_videohdr(AVFormatContext *s, VIDEOHDR *vhdr) { -#ifdef DEBUG_VFW +#ifdef DEBUG av_log(s, AV_LOG_DEBUG, "VIDEOHDR\n"); dstruct(s, vhdr, lpData, "p"); dstruct(s, vhdr, dwBufferLength, "lu"); @@ -210,6 +215,7 @@ fail: static int vfw_read_close(AVFormatContext *s) { struct vfw_ctx *ctx = s->priv_data; + AVPacketList *pktl; if(ctx->hwnd) { SendMessage(ctx->hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0); @@ -221,10 +227,18 @@ static int vfw_read_close(AVFormatContext *s) if(ctx->event) CloseHandle(ctx->event); + pktl = ctx->pktl; + while (pktl) { + AVPacketList *next = pktl->next; + av_destruct_packet(&pktl->pkt); + av_free(pktl); + pktl = next; + } + return 0; } -static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) +static int vfw_read_header(AVFormatContext *s) { struct vfw_ctx *ctx = s->priv_data; AVCodecContext *codec; @@ -235,12 +249,22 @@ static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) CAPTUREPARMS cparms; DWORD biCompression; WORD biBitCount; - int width; - int height; int ret; - - if(!ap->time_base.den) { - av_log(s, AV_LOG_ERROR, "A time base must be specified.\n"); + AVRational framerate_q; + + if (!strcmp(s->filename, "list")) { + for (devnum = 0; devnum <= 9; devnum++) { + char driver_name[256]; + char driver_ver[256]; + ret = capGetDriverDescription(devnum, + driver_name, sizeof(driver_name), + driver_ver, sizeof(driver_ver)); + if (ret) { + av_log(s, AV_LOG_INFO, "Driver %d\n", devnum); + av_log(s, AV_LOG_INFO, " %s\n", driver_name); + av_log(s, AV_LOG_INFO, " %s\n", driver_ver); + } + } return AVERROR(EIO); } @@ -272,10 +296,10 @@ static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) SetWindowLongPtr(ctx->hwnd, GWLP_USERDATA, (LONG_PTR) s); - st = av_new_stream(s, 0); + st = avformat_new_stream(s, NULL); if(!st) { vfw_read_close(s); - return AVERROR_NOMEM; + return AVERROR(ENOMEM); } /* Set video format */ @@ -285,7 +309,7 @@ static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) bi = av_malloc(bisize); if(!bi) { vfw_read_close(s); - return AVERROR_NOMEM; + return AVERROR(ENOMEM); } ret = SendMessage(ctx->hwnd, WM_CAP_GET_VIDEOFORMAT, bisize, (LPARAM) bi); if(!ret) @@ -293,10 +317,14 @@ static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) dump_bih(s, &bi->bmiHeader); - width = ap->width ? ap->width : bi->bmiHeader.biWidth ; - height = ap->height ? ap->height : bi->bmiHeader.biHeight; - bi->bmiHeader.biWidth = width ; - bi->bmiHeader.biHeight = height; + + if (ctx->video_size) { + ret = av_parse_video_size(&bi->bmiHeader.biWidth, &bi->bmiHeader.biHeight, ctx->video_size); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Couldn't parse video size.\n"); + goto fail_bi; + } + } if (0) { /* For testing yet unsupported compressions @@ -331,7 +359,7 @@ static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) cparms.fYield = 1; // Spawn a background thread cparms.dwRequestMicroSecPerFrame = - (ap->time_base.num*1000000) / ap->time_base.den; + (framerate_q.den*1000000) / framerate_q.num; cparms.fAbortLeftMouse = 0; cparms.fAbortRightMouse = 0; cparms.fCaptureAudio = 0; @@ -343,14 +371,14 @@ static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) goto fail_io; codec = st->codec; - codec->time_base = ap->time_base; - codec->codec_type = CODEC_TYPE_VIDEO; - codec->width = width; - codec->height = height; + codec->time_base = (AVRational){framerate_q.den, framerate_q.num}; + codec->codec_type = AVMEDIA_TYPE_VIDEO; + codec->width = bi->bmiHeader.biWidth; + codec->height = bi->bmiHeader.biHeight; codec->pix_fmt = vfw_pixfmt(biCompression, biBitCount); - if(codec->pix_fmt == PIX_FMT_NONE) { + if(codec->pix_fmt == AV_PIX_FMT_NONE) { codec->codec_id = vfw_codecid(biCompression); - if(codec->codec_id == CODEC_ID_NONE) { + if(codec->codec_id == AV_CODEC_ID_NONE) { av_log(s, AV_LOG_ERROR, "Unknown compression type. " "Please report verbose (-v 9) debug information.\n"); vfw_read_close(s); @@ -358,12 +386,18 @@ static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) } codec->bits_per_coded_sample = biBitCount; } else { - codec->codec_id = CODEC_ID_RAWVIDEO; - if(biCompression == BI_RGB) + codec->codec_id = AV_CODEC_ID_RAWVIDEO; + if(biCompression == BI_RGB) { codec->bits_per_coded_sample = biBitCount; + codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE); + if (codec->extradata) { + codec->extradata_size = 9; + memcpy(codec->extradata, "BottomUp", 9); + } + } } - av_set_pts_info(st, 32, 1, 1000); + avpriv_set_pts_info(st, 32, 1, 1000); ctx->mutex = CreateMutex(NULL, 0, NULL); if(!ctx->mutex) { @@ -421,13 +455,28 @@ static int vfw_read_packet(AVFormatContext *s, AVPacket *pkt) return pkt->size; } -AVInputFormat vfwcap_demuxer = { - "vfwcap", - NULL_IF_CONFIG_SMALL("VFW video capture"), - sizeof(struct vfw_ctx), - NULL, - vfw_read_header, - vfw_read_packet, - vfw_read_close, - .flags = AVFMT_NOFILE, +#define OFFSET(x) offsetof(struct vfw_ctx, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc"}, 0, 0, DEC }, + { NULL }, +}; + +static const AVClass vfw_class = { + .class_name = "VFW indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_vfwcap_demuxer = { + .name = "vfwcap", + .long_name = NULL_IF_CONFIG_SMALL("VfW video capture"), + .priv_data_size = sizeof(struct vfw_ctx), + .read_header = vfw_read_header, + .read_packet = vfw_read_packet, + .read_close = vfw_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &vfw_class, };