From patchwork Sun Sep 10 19:03:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 5077 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.36.26 with SMTP id f26csp2289507jaa; Sun, 10 Sep 2017 12:11:17 -0700 (PDT) X-Received: by 10.28.146.68 with SMTP id u65mr1533999wmd.28.1505070677583; Sun, 10 Sep 2017 12:11:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505070677; cv=none; d=google.com; s=arc-20160816; b=ALWGcgcON0H4NsKl1Om6EoThvjWVdDN1HYmnjb5sXf1CGMzOIUZVMZFxS61URk7AjM OX2dtPGXFVipZU7A2VUWuB6EfhfQvDfUDITAhPwxezc+VlsyGxMRnz9gh8ZpV4KzDBSC T6K7iKksIVIOY7ZJRy59dnO++UAVeVLECaMvToKX0SDkWmmIt4fhS53JlLsvKb1A8Ie9 b2fiAhN2DCiuVHdlYcuj71MwrtyjInxeWOsY507kqV5u6U3pNTTW0w7rf+V500scX0m0 E/wRI2m1xZY3FuD0Bwhb62s9175FDbeRWX6kiZ41v/5Kp8tis3BEVItPyVem/sR/zRcY mYIQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=GzOfJivbQ6JSCiv6neCKCZEaZvvNXSMqRN8IlQtTqkY=; b=AC6yIQTKz/o+HkO9Ye80hrMc5mNf51mPBwjYWciBMh2zdxFv2eOwr5oYODvHkqEb58 rvVHg3vh8skYtVyb1Ch5+VgwKYYeV3VoIeTj54mWIF6jBkXbEXAZ/21ygPUtwdpHgkZH avzEJB0OGBPT72VuIViK9Rxe3orR2FqfmJ17yivj5CLreqZs1fXiG7LHo1i8jDjLiU2b REELCBkrj+bGYaCg4GPUBNNKfv5YNQuLRXpSDAHs7GciJR5mZ6VaejaFXfdnmzHU8MuT q3azHLvgEdfPWK7fjASAZnI++vwI99mfeqdM5JMoZPv1J2Nq+Z5PCxzIbsPneLw4cEfU qU/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=crhIJGHe; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 201si5440725wmb.163.2017.09.10.12.11.17; Sun, 10 Sep 2017 12:11:17 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=crhIJGHe; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4DA43689C57; Sun, 10 Sep 2017 22:10:49 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4F044689A26 for ; Sun, 10 Sep 2017 22:10:47 +0300 (EEST) Received: by mail-wm0-f65.google.com with SMTP id 187so5333533wmn.0 for ; Sun, 10 Sep 2017 12:10:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=iXYEEkopfECmPaOZYaTQRosfhK8V76LVbnSe807jdp0=; b=crhIJGHehphM6Kp8J/Va7vwJ2OhTJJLTjOAF2PupPkh848xPD6a3xwYT0GNGpg/EUR wVqUBMQfQdIU6mvUA2x/ML55e7nlmrm55JXJxxS3W6uu7Fub6bjsO6PCsLl/PoQ2z4YP CVCxOuc7mCfhflcgvj/avKV82ygwWHFn2NGJ5MhBjWzCnmSebBBdIKPX+6HDKHzhJPmw s/c3IEHfqIEDHERqEG/hUfLdPcA1HIM6hutwKABzcEEtMe1DI6eGlOIWLyxgC6wQJ2ln sTmEtSIUMcxI5F0MIqCeF2BQ0kYv+b5/s3BvMxX52rg/SUcor8c18+HXaXF1n16c6+Ni k3+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=iXYEEkopfECmPaOZYaTQRosfhK8V76LVbnSe807jdp0=; b=l31kx5gE8Wmff26Io7E0bTJSzM3XtR5ToXvoxf2RlK9XiJesUSdxqyvG4QmyxoxLzj UDT45/s+zwx9QvfJahxyj5Gk/wYCUwQbcO1mZq8fbHcXy5NyOMzbmnL7+knGc/PDcioV 5sPl+EDHtNFCVI4ZHoEH136JByvSy9wq23DkHghUfrW8BR78OCQs80u/2gHN1+KUsnDg bI6IGBxQwU9MSZwtIUK3fqyMYtMqXtAPka8Isr7LmfgtqN7ftpavIb963MNUBKXS2XQz IqyojBC48iwnYINnoZShSzMpjeP5e9DahSHbZ3f8976mjXofkPZTI55qkdLzfhWxe7qH givg== X-Gm-Message-State: AHPjjUgeQBrE2JhjAMTos3lVdSQ9kjC/A7bbIQHP7witS4Rwi543b1AN Jq3zXeJ3LLnHzafm72Wjc9dpDg== X-Google-Smtp-Source: AOwi7QBe0PdWCCjsX3vDO/Xr2+s6/jxCXzVvV6+1XeXjx4+dCfYEG+FU4XAycTASB9Z98ALk5IjrdA== X-Received: by 10.28.4.135 with SMTP id 129mr6321951wme.34.1505070253318; Sun, 10 Sep 2017 12:04:13 -0700 (PDT) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id o14sm3032631wra.54.2017.09.10.12.04.11 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 10 Sep 2017 12:04:12 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Sun, 10 Sep 2017 21:03:29 +0200 Message-Id: <20170910190329.20512-1-onemda@gmail.com> X-Mailer: git-send-email 2.11.0 Subject: [FFmpeg-devel] [PATCH] add Weston Capture demuxer, parser and decoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 2 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 +++ libavcodec/wcap_parser.c | 124 ++++++++++++++++++++++++++++++++++++++ libavcodec/wcapdec.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++ libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/wcapdec.c | 72 ++++++++++++++++++++++ 9 files changed, 361 insertions(+) create mode 100644 libavcodec/wcap_parser.c create mode 100644 libavcodec/wcapdec.c create mode 100644 libavformat/wcapdec.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 999632cf9e..22d85ca009 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -634,6 +634,7 @@ OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackenc.o +OBJS-$(CONFIG_WCAP_DECODER) += wcapdec.o OBJS-$(CONFIG_WEBP_DECODER) += webp.o OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o ass.o OBJS-$(CONFIG_WEBVTT_ENCODER) += webvttenc.o ass_split.o @@ -980,6 +981,7 @@ OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o OBJS-$(CONFIG_VP9_PARSER) += vp9_parser.o +OBJS-$(CONFIG_WCAP_PARSER) += wcap_parser.o OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o # bitstream filters diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index ce0bc7ecf3..a1886590c8 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -376,6 +376,7 @@ static void register_all(void) REGISTER_DECODER(VP9, vp9); REGISTER_DECODER(VQA, vqa); REGISTER_DECODER(BITPACKED, bitpacked); + REGISTER_DECODER(WCAP, wcap); REGISTER_DECODER(WEBP, webp); REGISTER_ENCODER(WRAPPED_AVFRAME, wrapped_avframe); REGISTER_ENCDEC (WMV1, wmv1); @@ -730,6 +731,7 @@ static void register_all(void) REGISTER_PARSER(VP3, vp3); REGISTER_PARSER(VP8, vp8); REGISTER_PARSER(VP9, vp9); + REGISTER_PARSER(WCAP, wcap); REGISTER_PARSER(XMA, xma); } diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7708bb2adb..d9e3b5c84f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -448,6 +448,7 @@ enum AVCodecID { AV_CODEC_ID_SVG, AV_CODEC_ID_GDV, AV_CODEC_ID_FITS, + AV_CODEC_ID_WCAP, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 6a13bbbf0e..d5c174b3c1 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1417,6 +1417,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_WCAP, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wcap", + .long_name = NULL_IF_CONFIG_SMALL("Weston capture"), + .props = AV_CODEC_PROP_LOSSLESS, + }, /* image codecs */ { diff --git a/libavcodec/wcap_parser.c b/libavcodec/wcap_parser.c new file mode 100644 index 0000000000..7b2d6fdf80 --- /dev/null +++ b/libavcodec/wcap_parser.c @@ -0,0 +1,124 @@ +/* + * WCAP parser + * Copyright (c) 2017 Paul B Mahol + * + * 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 + */ + +#include "libavutil/bswap.h" +#include "parser.h" + +typedef struct WCAPParseContext { + ParseContext pc; + uint32_t pos; + uint32_t nrects; + int got_msec; + int got_nrects; + int got_rectangle; + int got_frame; + uint32_t rect_counter; + uint32_t current_rect; + uint32_t x1, y1, x2, y2; + int first; + int64_t pts; +} WCAPParseContext; + +static int wcap_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + WCAPParseContext *ppc = s->priv_data; + uint32_t state = ppc->pc.state; + int i, next = END_NOT_FOUND; + + *poutbuf_size = 0; + + for (i = 0; i < buf_size; i++) { + state = (state << 8) | buf[i]; + + if (((ppc->pc.index + i) % 4) != 3) + continue; + + if (!ppc->got_msec) { + ppc->got_msec = 1; + ppc->pts = av_bswap32(state); + ppc->current_rect = 0; + } else if (ppc->got_msec && !ppc->got_nrects) { + ppc->got_nrects = 1; + ppc->nrects = av_bswap32(state); + } else if (!ppc->got_rectangle && ppc->got_msec && ppc->got_nrects) { + ppc->rect_counter++; + if (ppc->rect_counter == 4) { + ppc->got_rectangle = 1; + ppc->y2 = av_bswap32(state); + } else if (ppc->rect_counter == 3) { + ppc->x2 = av_bswap32(state); + } else if (ppc->rect_counter == 2) { + ppc->y1 = av_bswap32(state); + } else if (ppc->rect_counter == 1) { + ppc->x1 = av_bswap32(state); + } + } else if (ppc->got_rectangle && ppc->got_nrects && ppc->got_msec) { + if (!ppc->got_frame) { + int l = state & 0xFF; + + if (l < 0xE0) + l = l + 1; + else + l = 1 << (l - 0xE0 + 7); + ppc->pos += l; + if (ppc->pos >= (ppc->x2 - ppc->x1) * (ppc->y2 - ppc->y1)) { + ppc->got_frame = 1; + } + } + if (ppc->got_frame) { + ppc->current_rect++; + ppc->got_rectangle = 0; + ppc->rect_counter = 0; + ppc->got_frame = 0; + ppc->pos = 0; + if (ppc->current_rect == ppc->nrects) { + ppc->current_rect = 0; + ppc->nrects = 0; + ppc->got_msec = 0; + ppc->got_nrects = 0; + next = i + 1; + s->key_frame = !ppc->first; + s->pict_type = s->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + s->pts = ppc->pts; + ppc->first++; + break; + } + } + } + } + ppc->pc.state = state; + + if (ff_combine_frame(&ppc->pc, next, &buf, &buf_size) < 0) + return buf_size; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_wcap_parser = { + .codec_ids = { AV_CODEC_ID_WCAP }, + .priv_data_size = sizeof(WCAPParseContext), + .parser_parse = wcap_parse, + .parser_close = ff_parse_close, +}; diff --git a/libavcodec/wcapdec.c b/libavcodec/wcapdec.c new file mode 100644 index 0000000000..f9cffedc03 --- /dev/null +++ b/libavcodec/wcapdec.c @@ -0,0 +1,151 @@ +/* + * WCAP video decoder + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 + */ + +#include + +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct WCAPContext { + AVFrame *frame; +} WCAPContext; + +static av_cold int wcap_decode_init(AVCodecContext *avctx) +{ + WCAPContext *s = avctx->priv_data; + uint32_t format; + + if (avctx->extradata && avctx->extradata_size >= 4) { + format = AV_RL32(avctx->extradata); + + switch (format) { + case 0x34325852: avctx->pix_fmt = AV_PIX_FMT_RGB0; break; + case 0x34325842: avctx->pix_fmt = AV_PIX_FMT_BGR0; break; + case 0x34325258: avctx->pix_fmt = AV_PIX_FMT_0RGB; break; + case 0x34324258: avctx->pix_fmt = AV_PIX_FMT_0BGR; break; + } + } + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + return 0; +} + +static void clear(AVCodecContext *avctx) +{ + WCAPContext *s = avctx->priv_data; + int y; + + if (!s->frame->buf[0]) + return; + + for (y = 0; y < avctx->height; y++) { + memset(s->frame->data[0] + y * s->frame->linesize[0], 0, avctx->width * 4); + } +} + +static int wcap_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + WCAPContext *s = avctx->priv_data; + AVFrame *frame = s->frame; + uint32_t nrects, x1, y1, x2, y2; + int ret, n, i, k, x; + GetByteContext gb; + uint8_t *dst; + + if ((ret = av_image_check_size(avctx->width, avctx->height, 0, NULL)) < 0) + return ret; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + if ((ret = ff_reget_buffer(avctx, frame)) < 0) + return ret; + + if (avpkt->flags & AV_PKT_FLAG_KEY) { + clear(avctx); + } + + bytestream2_skip(&gb, 4); + nrects = bytestream2_get_le32(&gb); + + for (n = 0; n < nrects; n++) { + x1 = bytestream2_get_le32(&gb); + y1 = bytestream2_get_le32(&gb); + x2 = bytestream2_get_le32(&gb); + y2 = bytestream2_get_le32(&gb); + + if (x1 >= x2 || y1 >= y2 || x2 > avctx->width || y2 > avctx->height || + (x2 - x1) > avctx->width || (y2 - y1) > avctx->height) + return AVERROR_INVALIDDATA; + + x = x1; + dst = frame->data[0] + (avctx->height - y1 - 1) * frame->linesize[0]; + + for (i = 0; i < (x2 - x1) * (y2 - y1);) { + unsigned v = bytestream2_get_le32(&gb); + int run_len = v >> 24; + + if (run_len < 0xE0) + run_len++; + else + run_len = 1 << (run_len - 0xE0 + 7); + + i += run_len; + for (k = 0; k < run_len; k++) { + dst[x*4 + 1] += v & 0xFF; + dst[x*4 + 2] += (v >> 8) & 0xFF; + dst[x*4 + 3] += (v >> 16) & 0xFF; + x++; + if (x == x2) { + x = x1; + dst -= frame->linesize[0]; + } + } + } + } + + frame->key_frame = (avpkt->flags & AV_PKT_FLAG_KEY) ? 1 : 0; + frame->pict_type = (avpkt->flags & AV_PKT_FLAG_KEY) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_wcap_decoder = { + .name = "wcap", + .long_name = NULL_IF_CONFIG_SMALL("Weston capture"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WCAP, + .priv_data_size = sizeof(WCAPContext), + .init = wcap_decode_init, + .decode = wcap_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, +}; diff --git a/libavformat/Makefile b/libavformat/Makefile index df709c29dd..4eb42f2727 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -513,6 +513,7 @@ OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o +OBJS-$(CONFIG_WCAP_DEMUXER) += wcapdec.o OBJS-$(CONFIG_WEBM_MUXER) += matroskaenc.o matroska.o \ avc.o hevc.o \ flacenc_header.o avlanguage.o \ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 405ddb5ad9..b90f8291dc 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -336,6 +336,7 @@ static void register_all(void) REGISTER_MUXDEMUX(W64, w64); REGISTER_MUXDEMUX(WAV, wav); REGISTER_DEMUXER (WC3, wc3); + REGISTER_DEMUXER (WCAP, wcap); REGISTER_MUXER (WEBM, webm); REGISTER_MUXDEMUX(WEBM_DASH_MANIFEST, webm_dash_manifest); REGISTER_MUXER (WEBM_CHUNK, webm_chunk); diff --git a/libavformat/wcapdec.c b/libavformat/wcapdec.c new file mode 100644 index 0000000000..c96dc68985 --- /dev/null +++ b/libavformat/wcapdec.c @@ -0,0 +1,72 @@ +/* + * WCAP demuxer + * Copyright (c) 2017 Paul B Mahol + * + * 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 + */ + +#include "libavutil/intreadwrite.h" + +#include "avformat.h" +#include "internal.h" +#include "rawdec.h" + +static int wcap_probe(AVProbeData *pd) +{ + if (AV_RB32(pd->buf) == MKTAG('W','C','A','P')) + return AVPROBE_SCORE_MAX; + else + return 0; +} + +static int wcap_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVStream *st; + + avio_skip(pb, 4); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + if (ff_get_extradata(s, st->codecpar, pb, 4) < 0) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_WCAP; + st->codecpar->width = avio_rl32(pb); + st->codecpar->height = avio_rl32(pb); + st->need_parsing = AVSTREAM_PARSE_FULL_RAW; + avpriv_set_pts_info(st, 64, 1, 1000); + + st->start_time = avio_rl32(pb); + avio_seek(pb, -4, SEEK_CUR); + + return 0; +} + +AVInputFormat ff_wcap_demuxer = { + .name = "wcap", + .long_name = NULL_IF_CONFIG_SMALL("Weston capture"), + .read_probe = wcap_probe, + .read_header = wcap_read_header, + .read_packet = ff_raw_read_partial_packet, + .raw_codec_id = AV_CODEC_ID_WCAP, + .extensions = "wcap", + .flags = AVFMT_GENERIC_INDEX, +};