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 (buf_size < avctx->width * avctx->height) {
00073 av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
00074 return AVERROR_INVALIDDATA;
00075 }
00076
00077 for (i = 0; i < avctx->height; i++) {
00078
00079 buf += stride;
00080
00081 for (j = 0; j < avctx->width; j += 4) {
00082
00083 val = AV_RL32(buf);
00084 buf -= 4;
00085 val = ((val >> 16) & 0xFFFF) | ((val & 0xFFFF) << 16);
00086
00087 if(!j)
00088 y0 = (val & 0x1F) << 2;
00089 else
00090 y0 = y3 + xl_table[val & 0x1F];
00091 val >>= 5;
00092 y1 = y0 + xl_table[val & 0x1F];
00093 val >>= 5;
00094 y2 = y1 + xl_table[val & 0x1F];
00095 val >>= 6;
00096 y3 = y2 + xl_table[val & 0x1F];
00097 val >>= 5;
00098 if(!j)
00099 c0 = (val & 0x1F) << 2;
00100 else
00101 c0 += xl_table[val & 0x1F];
00102 val >>= 5;
00103 if(!j)
00104 c1 = (val & 0x1F) << 2;
00105 else
00106 c1 += xl_table[val & 0x1F];
00107
00108 Y[j + 0] = y0 << 1;
00109 Y[j + 1] = y1 << 1;
00110 Y[j + 2] = y2 << 1;
00111 Y[j + 3] = y3 << 1;
00112
00113 U[j >> 2] = c0 << 1;
00114 V[j >> 2] = c1 << 1;
00115 }
00116
00117 buf += avctx->width + 4;
00118 Y += a->pic.linesize[0];
00119 U += a->pic.linesize[1];
00120 V += a->pic.linesize[2];
00121 }
00122
00123 *data_size = sizeof(AVFrame);
00124 *(AVFrame*)data = a->pic;
00125
00126 return buf_size;
00127 }
00128
00129 static av_cold int decode_init(AVCodecContext *avctx){
00130 VideoXLContext * const a = avctx->priv_data;
00131
00132 avcodec_get_frame_defaults(&a->pic);
00133 avctx->pix_fmt= PIX_FMT_YUV411P;
00134
00135 return 0;
00136 }
00137
00138 static av_cold int decode_end(AVCodecContext *avctx){
00139 VideoXLContext * const a = avctx->priv_data;
00140 AVFrame *pic = &a->pic;
00141
00142 if (pic->data[0])
00143 avctx->release_buffer(avctx, pic);
00144
00145 return 0;
00146 }
00147
00148 AVCodec ff_xl_decoder = {
00149 .name = "xl",
00150 .type = AVMEDIA_TYPE_VIDEO,
00151 .id = CODEC_ID_VIXL,
00152 .priv_data_size = sizeof(VideoXLContext),
00153 .init = decode_init,
00154 .close = decode_end,
00155 .decode = decode_frame,
00156 .capabilities = CODEC_CAP_DR1,
00157 .long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"),
00158 };