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