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