From dbde14547fec9e57242c0976262745aa8bf8ae29 Mon Sep 17 00:00:00 2001 From: michael Date: Wed, 22 Apr 2009 01:50:15 +0000 Subject: [PATCH] Support reading packed YUV 422 10bit samples from jvt (NewMobCal_YUV10_720p5994_). Ive called the format v210x due to its similarity to v210, note though ive not confirmed that v210x is different from actual v210 samples it just is different from the description of v210 iam aware of. git-svn-id: file:///var/local/repositories/ffmpeg/trunk@18654 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/v210x.c | 137 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 libavcodec/v210x.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5aaf61478..b02b44ec4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -229,6 +229,7 @@ OBJS-$(CONFIG_TSCC_DECODER) += tscc.o msrledec.o OBJS-$(CONFIG_TTA_DECODER) += tta.o OBJS-$(CONFIG_TXD_DECODER) += txd.o s3tc.o OBJS-$(CONFIG_ULTI_DECODER) += ulti.o +OBJS-$(CONFIG_V210X_DECODER) += v210x.o OBJS-$(CONFIG_VB_DECODER) += vb.o OBJS-$(CONFIG_VC1_DECODER) += vc1.o vc1data.o vc1dsp.o msmpeg4data.o h263dec.o h263.o intrax8.o intrax8dsp.o error_resilience.o mpegvideo.o msmpeg4.o OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vc1.o vc1data.o vc1dsp.o msmpeg4data.o h263dec.o h263.o intrax8.o intrax8dsp.o error_resilience.o mpegvideo.o msmpeg4.o vaapi.o vaapi_vc1.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 5f0b0b98b..bcc11d067 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -167,6 +167,7 @@ void avcodec_register_all(void) REGISTER_DECODER (TSCC, tscc); REGISTER_DECODER (TXD, txd); REGISTER_DECODER (ULTI, ulti); + REGISTER_DECODER (V210X, v210x); REGISTER_DECODER (VB, vb); REGISTER_DECODER (VC1, vc1); REGISTER_DECODER (VC1_VDPAU, vc1_vdpau); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c5632c8d0..8016d82fd 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -193,6 +193,7 @@ enum CodecID { CODEC_ID_TQI, CODEC_ID_AURA, CODEC_ID_AURA2, + CODEC_ID_V210X, /* various PCM "codecs" */ CODEC_ID_PCM_S16LE= 0x10000, diff --git a/libavcodec/v210x.c b/libavcodec/v210x.c new file mode 100644 index 000000000..b944666d3 --- /dev/null +++ b/libavcodec/v210x.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2009 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 "avcodec.h" +#include "libavutil/bswap.h" + +static av_cold int decode_init(AVCodecContext *avctx) +{ + if(avctx->width & 1){ + av_log(avctx, AV_LOG_ERROR, "v210x needs even width\n"); + return -1; + } + if(avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) + return -1; + avctx->pix_fmt = PIX_FMT_YUV422P16; + avctx->bits_per_raw_sample= 10; + + avctx->coded_frame= avcodec_alloc_frame(); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) +{ + int y=0; + int width= avctx->width; + AVFrame *pic= avctx->coded_frame; + const uint32_t *src= avpkt->data; + uint16_t *ydst, *udst, *vdst, *yend; + + if(pic->data[0]) + avctx->release_buffer(avctx, pic); + + if(avpkt->size < avctx->width * avctx->height * 8 / 3){ + av_log(avctx, AV_LOG_ERROR, "Packet too small\n"); + return -1; + } + + if(avpkt->size > avctx->width * avctx->height * 8 / 3){ + av_log(avctx, AV_LOG_ERROR, "Probably padded data, need sample!\n"); + } + + pic->reference= 0; + if(avctx->get_buffer(avctx, pic) < 0) + return -1; + + ydst= pic->data[0]; + udst= pic->data[1]; + vdst= pic->data[2]; + yend= ydst + width; + pic->pict_type= FF_I_TYPE; + pic->key_frame= 1; + + for(;;){ + uint32_t v= be2me_32(*src++); + *udst++= (v>>16) & 0xFFC0; + *ydst++= (v>>6 ) & 0xFFC0; + *vdst++= (v<<4 ) & 0xFFC0; + + v= be2me_32(*src++); + *ydst++= (v>>16) & 0xFFC0; + + if(ydst >= yend){ + ydst+= pic->linesize[0]/2 - width; + udst+= pic->linesize[1]/2 - width/2; + vdst+= pic->linesize[2]/2 - width/2; + yend= ydst + width; + if(++y >= avctx->height) + break; + } + + *udst++= (v>>6 ) & 0xFFC0; + *ydst++= (v<<4 ) & 0xFFC0; + + v= be2me_32(*src++); + *vdst++= (v>>16) & 0xFFC0; + *ydst++= (v>>6 ) & 0xFFC0; + + if(ydst >= yend){ + ydst+= pic->linesize[0]/2 - width; + udst+= pic->linesize[1]/2 - width/2; + vdst+= pic->linesize[2]/2 - width/2; + yend= ydst + width; + if(++y >= avctx->height) + break; + } + + *udst++= (v<<4 ) & 0xFFC0; + + v= be2me_32(*src++); + *ydst++= (v>>16) & 0xFFC0; + *vdst++= (v>>6 ) & 0xFFC0; + *ydst++= (v<<4 ) & 0xFFC0; + if(ydst >= yend){ + ydst+= pic->linesize[0]/2 - width; + udst+= pic->linesize[1]/2 - width/2; + vdst+= pic->linesize[2]/2 - width/2; + yend= ydst + width; + if(++y >= avctx->height) + break; + } + } + + *data_size=sizeof(AVFrame); + *(AVFrame*)data= *avctx->coded_frame; + + return avpkt->size; +} + +AVCodec v210x_decoder = { + "v210x", + CODEC_TYPE_VIDEO, + CODEC_ID_V210X, + 0, + decode_init, + NULL, + NULL, + decode_frame, + CODEC_CAP_DR1, +}; -- 2.39.2