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 = &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 (avctx->width & 3) {
00056 av_log(avctx, AV_LOG_ERROR, "width is not a multiple of 4\n");
00057 return AVERROR_INVALIDDATA;
00058 }
00059
00060 if (buf_size < avctx->width * avctx->height) {
00061 av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
00062 return AVERROR_INVALIDDATA;
00063 }
00064
00065 if(p->data[0])
00066 avctx->release_buffer(avctx, p);
00067
00068 p->reference = 0;
00069 if(avctx->get_buffer(avctx, p) < 0){
00070 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00071 return -1;
00072 }
00073 p->pict_type= AV_PICTURE_TYPE_I;
00074 p->key_frame= 1;
00075
00076 Y = a->pic.data[0];
00077 U = a->pic.data[1];
00078 V = a->pic.data[2];
00079
00080 stride = avctx->width - 4;
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 VideoXLContext * const a = avctx->priv_data;
00136
00137 avcodec_get_frame_defaults(&a->pic);
00138 avctx->pix_fmt= PIX_FMT_YUV411P;
00139
00140 return 0;
00141 }
00142
00143 static av_cold int decode_end(AVCodecContext *avctx){
00144 VideoXLContext * const a = avctx->priv_data;
00145 AVFrame *pic = &a->pic;
00146
00147 if (pic->data[0])
00148 avctx->release_buffer(avctx, pic);
00149
00150 return 0;
00151 }
00152
00153 AVCodec ff_xl_decoder = {
00154 .name = "xl",
00155 .type = AVMEDIA_TYPE_VIDEO,
00156 .id = CODEC_ID_VIXL,
00157 .priv_data_size = sizeof(VideoXLContext),
00158 .init = decode_init,
00159 .close = decode_end,
00160 .decode = decode_frame,
00161 .capabilities = CODEC_CAP_DR1,
00162 .long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"),
00163 };