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