@@ -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
@@ -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);
}
@@ -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
@@ -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 */
{
new file mode 100644
@@ -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,
+};
new file mode 100644
@@ -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 <inttypes.h>
+
+#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,
+};
@@ -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 \
@@ -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);
new file mode 100644
@@ -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,
+};
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- 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