• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/v210x.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009 Michael Niedermayer <michaelni@gmx.at>
00003  *
00004  * This file is part of FFmpeg.
00005  *
00006  * FFmpeg is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * FFmpeg is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with FFmpeg; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00021 #include "avcodec.h"
00022 #include "libavutil/bswap.h"
00023 
00024 static av_cold int decode_init(AVCodecContext *avctx)
00025 {
00026     if(avctx->width & 1){
00027         av_log(avctx, AV_LOG_ERROR, "v210x needs even width\n");
00028         return -1;
00029     }
00030     avctx->pix_fmt = PIX_FMT_YUV422P16;
00031     avctx->bits_per_raw_sample= 10;
00032 
00033     avctx->coded_frame= avcodec_alloc_frame();
00034 
00035     return 0;
00036 }
00037 
00038 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
00039 {
00040     int y=0;
00041     int width= avctx->width;
00042     AVFrame *pic= avctx->coded_frame;
00043     const uint32_t *src= (const uint32_t *)avpkt->data;
00044     uint16_t *ydst, *udst, *vdst, *yend;
00045 
00046     if(pic->data[0])
00047         avctx->release_buffer(avctx, pic);
00048 
00049     if(avpkt->size < avctx->width * avctx->height * 8 / 3){
00050         av_log(avctx, AV_LOG_ERROR, "Packet too small\n");
00051         return -1;
00052     }
00053 
00054     if(avpkt->size > avctx->width * avctx->height * 8 / 3){
00055         av_log(avctx, AV_LOG_ERROR, "Probably padded data, need sample!\n");
00056     }
00057 
00058     pic->reference= 0;
00059     if(avctx->get_buffer(avctx, pic) < 0)
00060         return -1;
00061 
00062     ydst= (uint16_t *)pic->data[0];
00063     udst= (uint16_t *)pic->data[1];
00064     vdst= (uint16_t *)pic->data[2];
00065     yend= ydst + width;
00066     pic->pict_type= FF_I_TYPE;
00067     pic->key_frame= 1;
00068 
00069     for(;;){
00070         uint32_t v= be2me_32(*src++);
00071         *udst++= (v>>16) & 0xFFC0;
00072         *ydst++= (v>>6 ) & 0xFFC0;
00073         *vdst++= (v<<4 ) & 0xFFC0;
00074 
00075         v= be2me_32(*src++);
00076         *ydst++= (v>>16) & 0xFFC0;
00077 
00078         if(ydst >= yend){
00079             ydst+= pic->linesize[0]/2 - width;
00080             udst+= pic->linesize[1]/2 - width/2;
00081             vdst+= pic->linesize[2]/2 - width/2;
00082             yend= ydst + width;
00083             if(++y >= avctx->height)
00084                 break;
00085         }
00086 
00087         *udst++= (v>>6 ) & 0xFFC0;
00088         *ydst++= (v<<4 ) & 0xFFC0;
00089 
00090         v= be2me_32(*src++);
00091         *vdst++= (v>>16) & 0xFFC0;
00092         *ydst++= (v>>6 ) & 0xFFC0;
00093 
00094         if(ydst >= yend){
00095             ydst+= pic->linesize[0]/2 - width;
00096             udst+= pic->linesize[1]/2 - width/2;
00097             vdst+= pic->linesize[2]/2 - width/2;
00098             yend= ydst + width;
00099             if(++y >= avctx->height)
00100                 break;
00101         }
00102 
00103         *udst++= (v<<4 ) & 0xFFC0;
00104 
00105         v= be2me_32(*src++);
00106         *ydst++= (v>>16) & 0xFFC0;
00107         *vdst++= (v>>6 ) & 0xFFC0;
00108         *ydst++= (v<<4 ) & 0xFFC0;
00109         if(ydst >= yend){
00110             ydst+= pic->linesize[0]/2 - width;
00111             udst+= pic->linesize[1]/2 - width/2;
00112             vdst+= pic->linesize[2]/2 - width/2;
00113             yend= ydst + width;
00114             if(++y >= avctx->height)
00115                 break;
00116         }
00117     }
00118 
00119     *data_size=sizeof(AVFrame);
00120     *(AVFrame*)data= *avctx->coded_frame;
00121 
00122     return avpkt->size;
00123 }
00124 
00125 static av_cold int decode_close(AVCodecContext *avctx)
00126 {
00127     AVFrame *pic = avctx->coded_frame;
00128     if (pic->data[0])
00129         avctx->release_buffer(avctx, pic);
00130     av_freep(&avctx->coded_frame);
00131 
00132     return 0;
00133 }
00134 
00135 AVCodec v210x_decoder = {
00136     "v210x",
00137     AVMEDIA_TYPE_VIDEO,
00138     CODEC_ID_V210X,
00139     0,
00140     decode_init,
00141     NULL,
00142     decode_close,
00143     decode_frame,
00144     CODEC_CAP_DR1,
00145     .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
00146 };

Generated on Fri Sep 16 2011 17:17:44 for FFmpeg by  doxygen 1.7.1