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
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_ask_for_sample(avctx, "Probably padded data\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= AV_PICTURE_TYPE_I;
00067 pic->key_frame= 1;
00068
00069 for(;;){
00070 uint32_t v= av_be2ne32(*src++);
00071 *udst++= (v>>16) & 0xFFC0;
00072 *ydst++= (v>>6 ) & 0xFFC0;
00073 *vdst++= (v<<4 ) & 0xFFC0;
00074
00075 v= av_be2ne32(*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= av_be2ne32(*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= av_be2ne32(*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 ff_v210x_decoder = {
00136 .name = "v210x",
00137 .type = AVMEDIA_TYPE_VIDEO,
00138 .id = CODEC_ID_V210X,
00139 .init = decode_init,
00140 .close = decode_close,
00141 .decode = decode_frame,
00142 .capabilities = CODEC_CAP_DR1,
00143 .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
00144 };