1/* 2 * Copyright (C) 2009 Michael Niedermayer <michaelni@gmx.at> 3 * 4 * This file is part of Libav. 5 * 6 * Libav is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * Libav is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with Libav; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include "avcodec.h" 22#include "libavutil/bswap.h" 23 24static av_cold int decode_init(AVCodecContext *avctx) 25{ 26 if(avctx->width & 1){ 27 av_log(avctx, AV_LOG_ERROR, "v210x needs even width\n"); 28 return -1; 29 } 30 avctx->pix_fmt = PIX_FMT_YUV422P16; 31 avctx->bits_per_raw_sample= 10; 32 33 avctx->coded_frame= avcodec_alloc_frame(); 34 35 return 0; 36} 37 38static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) 39{ 40 int y=0; 41 int width= avctx->width; 42 AVFrame *pic= avctx->coded_frame; 43 const uint32_t *src= (const uint32_t *)avpkt->data; 44 uint16_t *ydst, *udst, *vdst, *yend; 45 46 if(pic->data[0]) 47 avctx->release_buffer(avctx, pic); 48 49 if(avpkt->size < avctx->width * avctx->height * 8 / 3){ 50 av_log(avctx, AV_LOG_ERROR, "Packet too small\n"); 51 return -1; 52 } 53 54 if(avpkt->size > avctx->width * avctx->height * 8 / 3){ 55 av_log_ask_for_sample(avctx, "Probably padded data\n"); 56 } 57 58 pic->reference= 0; 59 if(avctx->get_buffer(avctx, pic) < 0) 60 return -1; 61 62 ydst= (uint16_t *)pic->data[0]; 63 udst= (uint16_t *)pic->data[1]; 64 vdst= (uint16_t *)pic->data[2]; 65 yend= ydst + width; 66 pic->pict_type= AV_PICTURE_TYPE_I; 67 pic->key_frame= 1; 68 69 for(;;){ 70 uint32_t v= av_be2ne32(*src++); 71 *udst++= (v>>16) & 0xFFC0; 72 *ydst++= (v>>6 ) & 0xFFC0; 73 *vdst++= (v<<4 ) & 0xFFC0; 74 75 v= av_be2ne32(*src++); 76 *ydst++= (v>>16) & 0xFFC0; 77 78 if(ydst >= yend){ 79 ydst+= pic->linesize[0]/2 - width; 80 udst+= pic->linesize[1]/2 - width/2; 81 vdst+= pic->linesize[2]/2 - width/2; 82 yend= ydst + width; 83 if(++y >= avctx->height) 84 break; 85 } 86 87 *udst++= (v>>6 ) & 0xFFC0; 88 *ydst++= (v<<4 ) & 0xFFC0; 89 90 v= av_be2ne32(*src++); 91 *vdst++= (v>>16) & 0xFFC0; 92 *ydst++= (v>>6 ) & 0xFFC0; 93 94 if(ydst >= yend){ 95 ydst+= pic->linesize[0]/2 - width; 96 udst+= pic->linesize[1]/2 - width/2; 97 vdst+= pic->linesize[2]/2 - width/2; 98 yend= ydst + width; 99 if(++y >= avctx->height) 100 break; 101 } 102 103 *udst++= (v<<4 ) & 0xFFC0; 104 105 v= av_be2ne32(*src++); 106 *ydst++= (v>>16) & 0xFFC0; 107 *vdst++= (v>>6 ) & 0xFFC0; 108 *ydst++= (v<<4 ) & 0xFFC0; 109 if(ydst >= yend){ 110 ydst+= pic->linesize[0]/2 - width; 111 udst+= pic->linesize[1]/2 - width/2; 112 vdst+= pic->linesize[2]/2 - width/2; 113 yend= ydst + width; 114 if(++y >= avctx->height) 115 break; 116 } 117 } 118 119 *data_size=sizeof(AVFrame); 120 *(AVFrame*)data= *avctx->coded_frame; 121 122 return avpkt->size; 123} 124 125static av_cold int decode_close(AVCodecContext *avctx) 126{ 127 AVFrame *pic = avctx->coded_frame; 128 if (pic->data[0]) 129 avctx->release_buffer(avctx, pic); 130 av_freep(&avctx->coded_frame); 131 132 return 0; 133} 134 135AVCodec ff_v210x_decoder = { 136 .name = "v210x", 137 .type = AVMEDIA_TYPE_VIDEO, 138 .id = CODEC_ID_V210X, 139 .init = decode_init, 140 .close = decode_close, 141 .decode = decode_frame, 142 .capabilities = CODEC_CAP_DR1, 143 .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), 144}; 145