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