TODO: find out which LSB for 10bit go where Signed-off-by: Michael Niedermayer <mich...@niedermayer.cc> --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 +++ libavcodec/m101.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 libavcodec/m101.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 835b803..8ac2272 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -351,6 +351,7 @@ OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o OBJS-$(CONFIG_LOCO_DECODER) += loco.o +OBJS-$(CONFIG_M101_DECODER) += m101.o OBJS-$(CONFIG_MACE3_DECODER) += mace.o OBJS-$(CONFIG_MACE6_DECODER) += mace.o OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 2b46a13..fe882de 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -218,6 +218,7 @@ void avcodec_register_all(void) REGISTER_DECODER(LAGARITH, lagarith); REGISTER_ENCODER(LJPEG, ljpeg); REGISTER_DECODER(LOCO, loco); + REGISTER_DECODER(M101, m101); REGISTER_DECODER(MDEC, mdec); REGISTER_DECODER(MIMIC, mimic); REGISTER_ENCDEC (MJPEG, mjpeg); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 161ee9d..dd209a9 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -386,6 +386,7 @@ enum AVCodecID { AV_CODEC_ID_DXV, AV_CODEC_ID_SCREENPRESSO, AV_CODEC_ID_RSCC, + AV_CODEC_ID_M101, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 7b48ee6..d3cc10e 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -948,6 +948,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { + .id = AV_CODEC_ID_M101, + .type = AVMEDIA_TYPE_VIDEO, + .name = "m101", + .long_name = NULL_IF_CONFIG_SMALL("matrox uncompressed sd"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { .id = AV_CODEC_ID_MVC1, .type = AVMEDIA_TYPE_VIDEO, .name = "mvc1", diff --git a/libavcodec/m101.c b/libavcodec/m101.c new file mode 100644 index 0000000..b81d5d5 --- /dev/null +++ b/libavcodec/m101.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016 Michael Niedermayer + * + * 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 "avcodec.h" +#include "internal.h" + + +static av_cold int m101_decode_init(AVCodecContext *avctx) +{ + if (avctx->extradata_size < 6*4) + return AVERROR_INVALIDDATA; + + if (avctx->extradata[2*4] == 10) + avctx->pix_fmt = AV_PIX_FMT_YUV422P10; + else + avctx->pix_fmt = AV_PIX_FMT_YUYV422; + + + return 0; +} + +static int m101_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int stride, ret; + int x, y; + int min_stride = 2 * avctx->width; + uint8_t *line; + int bits = avctx->extradata[2*4]; + AVFrame *frame = data; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + + stride = AV_RL32(avctx->extradata + 5*4); + + if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10) + min_stride = (avctx->width + 15) / 16 * 20; + + if (stride < min_stride || avpkt->size < stride * (uint64_t)avctx->height) { + av_log(avctx, AV_LOG_ERROR, "stride (%d) is invalid for packet sized %d\n", + stride, avpkt->size); + return AVERROR_INVALIDDATA; + } + + line = frame->data[0]; + frame->interlaced_frame = ((avctx->extradata[3*4] & 3) != 3); + + for (y = 0; y < avctx->height; y++) { + int src_y = y; + if (frame->interlaced_frame) + src_y = (y&1) ? y/2 : (y/2 + avctx->height/2); + if (bits == 8) { + for (x = 0; x < avctx->width; x++) { + line[y*frame->linesize[0] + 2*x + 0] = buf[src_y*stride + 2*x + 0]; + line[y*frame->linesize[0] + 2*x + 1] = buf[src_y*stride + 2*x + 1]; + } + } else { + int block; + uint16_t *luma = &frame->data[0][y*frame->linesize[0]]; + uint16_t *cb = &frame->data[1][y*frame->linesize[1]]; + uint16_t *cr = &frame->data[2][y*frame->linesize[2]]; + for (block = 0; 16*block < avctx->width; block ++) { +// av_log(0,0, " %d %d %d %d %d %d %d %d\n", buf[src_y*stride + 40*block + 32], +// buf[src_y*stride + 40*block + 33], +// buf[src_y*stride + 40*block + 34], +// buf[src_y*stride + 40*block + 35], +// buf[src_y*stride + 40*block + 36], +// buf[src_y*stride + 40*block + 37], +// buf[src_y*stride + 40*block + 38], +// buf[src_y*stride + 40*block + 39]); + for (x = 0; x < 16 && x + 16*block < avctx->width; x++) { + int xd = x + 16*block; + int xs = x + 20*block; + luma[xd] = 4*buf[src_y*stride + 2*xs + 0] ; + if (!(x&1)) { + cb[xd>>1] = 4*buf[src_y*stride + 2*xs + 1]; + cr[xd>>1] = 4*buf[src_y*stride + 2*xs + 3]; + } + } + } + } + } + + *got_frame = 1; + return avpkt->size; +} + +AVCodec ff_m101_decoder = { + .name = "m101", + .long_name = NULL_IF_CONFIG_SMALL("matrox uncompressed sd"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_M101, + .priv_data_size = 0, + .init = m101_decode_init, + .decode = m101_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, +}; -- 1.7.9.5 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel