00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 if (!avctx->coded_frame)
00035 return AVERROR(ENOMEM);
00036
00037 return 0;
00038 }
00039
00040 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
00041 {
00042 int y=0;
00043 int width= avctx->width;
00044 AVFrame *pic= avctx->coded_frame;
00045 const uint32_t *src= (const uint32_t *)avpkt->data;
00046 uint16_t *ydst, *udst, *vdst, *yend;
00047
00048 if(pic->data[0])
00049 avctx->release_buffer(avctx, pic);
00050
00051 if(avpkt->size < avctx->width * avctx->height * 8 / 3){
00052 av_log(avctx, AV_LOG_ERROR, "Packet too small\n");
00053 return -1;
00054 }
00055
00056 if(avpkt->size > avctx->width * avctx->height * 8 / 3){
00057 av_log_ask_for_sample(avctx, "Probably padded data\n");
00058 }
00059
00060 pic->reference= 0;
00061 if(avctx->get_buffer(avctx, pic) < 0)
00062 return -1;
00063
00064 ydst= (uint16_t *)pic->data[0];
00065 udst= (uint16_t *)pic->data[1];
00066 vdst= (uint16_t *)pic->data[2];
00067 yend= ydst + width;
00068 pic->pict_type= AV_PICTURE_TYPE_I;
00069 pic->key_frame= 1;
00070
00071 for(;;){
00072 uint32_t v= av_be2ne32(*src++);
00073 *udst++= (v>>16) & 0xFFC0;
00074 *ydst++= (v>>6 ) & 0xFFC0;
00075 *vdst++= (v<<4 ) & 0xFFC0;
00076
00077 v= av_be2ne32(*src++);
00078 *ydst++= (v>>16) & 0xFFC0;
00079
00080 if(ydst >= yend){
00081 ydst+= pic->linesize[0]/2 - width;
00082 udst+= pic->linesize[1]/2 - width/2;
00083 vdst+= pic->linesize[2]/2 - width/2;
00084 yend= ydst + width;
00085 if(++y >= avctx->height)
00086 break;
00087 }
00088
00089 *udst++= (v>>6 ) & 0xFFC0;
00090 *ydst++= (v<<4 ) & 0xFFC0;
00091
00092 v= av_be2ne32(*src++);
00093 *vdst++= (v>>16) & 0xFFC0;
00094 *ydst++= (v>>6 ) & 0xFFC0;
00095
00096 if(ydst >= yend){
00097 ydst+= pic->linesize[0]/2 - width;
00098 udst+= pic->linesize[1]/2 - width/2;
00099 vdst+= pic->linesize[2]/2 - width/2;
00100 yend= ydst + width;
00101 if(++y >= avctx->height)
00102 break;
00103 }
00104
00105 *udst++= (v<<4 ) & 0xFFC0;
00106
00107 v= av_be2ne32(*src++);
00108 *ydst++= (v>>16) & 0xFFC0;
00109 *vdst++= (v>>6 ) & 0xFFC0;
00110 *ydst++= (v<<4 ) & 0xFFC0;
00111 if(ydst >= yend){
00112 ydst+= pic->linesize[0]/2 - width;
00113 udst+= pic->linesize[1]/2 - width/2;
00114 vdst+= pic->linesize[2]/2 - width/2;
00115 yend= ydst + width;
00116 if(++y >= avctx->height)
00117 break;
00118 }
00119 }
00120
00121 *data_size=sizeof(AVFrame);
00122 *(AVFrame*)data= *avctx->coded_frame;
00123
00124 return avpkt->size;
00125 }
00126
00127 static av_cold int decode_close(AVCodecContext *avctx)
00128 {
00129 AVFrame *pic = avctx->coded_frame;
00130 if (pic->data[0])
00131 avctx->release_buffer(avctx, pic);
00132 av_freep(&avctx->coded_frame);
00133
00134 return 0;
00135 }
00136
00137 AVCodec ff_v210x_decoder = {
00138 .name = "v210x",
00139 .type = AVMEDIA_TYPE_VIDEO,
00140 .id = CODEC_ID_V210X,
00141 .init = decode_init,
00142 .close = decode_close,
00143 .decode = decode_frame,
00144 .capabilities = CODEC_CAP_DR1,
00145 .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
00146 };