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