00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "libavutil/intreadwrite.h"
00028 #include "avcodec.h"
00029
00030 typedef struct VideoXLContext{
00031 AVCodecContext *avctx;
00032 AVFrame pic;
00033 } VideoXLContext;
00034
00035 static const int xl_table[32] = {
00036 0, 1, 2, 3, 4, 5, 6, 7,
00037 8, 9, 12, 15, 20, 25, 34, 46,
00038 64, 82, 94, 103, 108, 113, 116, 119,
00039 120, 121, 122, 123, 124, 125, 126, 127};
00040
00041 static int decode_frame(AVCodecContext *avctx,
00042 void *data, int *data_size,
00043 AVPacket *avpkt)
00044 {
00045 const uint8_t *buf = avpkt->data;
00046 int buf_size = avpkt->size;
00047 VideoXLContext * const a = avctx->priv_data;
00048 AVFrame * const p= (AVFrame*)&a->pic;
00049 uint8_t *Y, *U, *V;
00050 int i, j;
00051 int stride;
00052 uint32_t val;
00053 int y0, y1, y2, y3 = 0, c0 = 0, c1 = 0;
00054
00055 if(p->data[0])
00056 avctx->release_buffer(avctx, p);
00057
00058 p->reference = 0;
00059 if(avctx->get_buffer(avctx, p) < 0){
00060 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00061 return -1;
00062 }
00063 p->pict_type= AV_PICTURE_TYPE_I;
00064 p->key_frame= 1;
00065
00066 Y = a->pic.data[0];
00067 U = a->pic.data[1];
00068 V = a->pic.data[2];
00069
00070 stride = avctx->width - 4;
00071
00072 if (avctx->width % 4) {
00073 av_log(avctx, AV_LOG_ERROR, "Width not a multiple of 4.\n");
00074 return AVERROR_INVALIDDATA;
00075 }
00076
00077 if (buf_size < avctx->width * avctx->height) {
00078 av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
00079 return AVERROR_INVALIDDATA;
00080 }
00081
00082 for (i = 0; i < avctx->height; i++) {
00083
00084 buf += stride;
00085
00086 for (j = 0; j < avctx->width; j += 4) {
00087
00088 val = AV_RL32(buf);
00089 buf -= 4;
00090 val = ((val >> 16) & 0xFFFF) | ((val & 0xFFFF) << 16);
00091
00092 if(!j)
00093 y0 = (val & 0x1F) << 2;
00094 else
00095 y0 = y3 + xl_table[val & 0x1F];
00096 val >>= 5;
00097 y1 = y0 + xl_table[val & 0x1F];
00098 val >>= 5;
00099 y2 = y1 + xl_table[val & 0x1F];
00100 val >>= 6;
00101 y3 = y2 + xl_table[val & 0x1F];
00102 val >>= 5;
00103 if(!j)
00104 c0 = (val & 0x1F) << 2;
00105 else
00106 c0 += xl_table[val & 0x1F];
00107 val >>= 5;
00108 if(!j)
00109 c1 = (val & 0x1F) << 2;
00110 else
00111 c1 += xl_table[val & 0x1F];
00112
00113 Y[j + 0] = y0 << 1;
00114 Y[j + 1] = y1 << 1;
00115 Y[j + 2] = y2 << 1;
00116 Y[j + 3] = y3 << 1;
00117
00118 U[j >> 2] = c0 << 1;
00119 V[j >> 2] = c1 << 1;
00120 }
00121
00122 buf += avctx->width + 4;
00123 Y += a->pic.linesize[0];
00124 U += a->pic.linesize[1];
00125 V += a->pic.linesize[2];
00126 }
00127
00128 *data_size = sizeof(AVFrame);
00129 *(AVFrame*)data = a->pic;
00130
00131 return buf_size;
00132 }
00133
00134 static av_cold int decode_init(AVCodecContext *avctx){
00135
00136
00137 avctx->pix_fmt= PIX_FMT_YUV411P;
00138
00139 return 0;
00140 }
00141
00142 static av_cold int decode_end(AVCodecContext *avctx){
00143 VideoXLContext * const a = avctx->priv_data;
00144 AVFrame *pic = &a->pic;
00145
00146 if (pic->data[0])
00147 avctx->release_buffer(avctx, pic);
00148
00149 return 0;
00150 }
00151
00152 AVCodec ff_xl_decoder = {
00153 .name = "xl",
00154 .type = AVMEDIA_TYPE_VIDEO,
00155 .id = CODEC_ID_VIXL,
00156 .priv_data_size = sizeof(VideoXLContext),
00157 .init = decode_init,
00158 .close = decode_end,
00159 .decode = decode_frame,
00160 .capabilities = CODEC_CAP_DR1,
00161 .long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"),
00162 };