libavcodec/xl.c
Go to the documentation of this file.
00001 /*
00002  * Miro VideoXL codec
00003  * Copyright (c) 2004 Konstantin Shishkov
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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 (avctx->width % 4) {
00073         av_log(avctx, AV_LOG_ERROR, "Width not a multiple of 4.\n");
00074         return AVERROR_INVALIDDATA;
00075     }
00076 
00077     if (buf_size < avctx->width * avctx->height) {
00078         av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
00079         return AVERROR_INVALIDDATA;
00080     }
00081 
00082     for (i = 0; i < avctx->height; i++) {
00083         /* lines are stored in reversed order */
00084         buf += stride;
00085 
00086         for (j = 0; j < avctx->width; j += 4) {
00087             /* value is stored in LE dword with word swapped */
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; /* align to word */
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     avctx->pix_fmt= PIX_FMT_YUV411P;
00138 
00139     return 0;
00140 }
00141 
00142 static av_cold int decode_end(AVCodecContext *avctx){
00143     VideoXLContext * const a = avctx->priv_data;
00144     AVFrame *pic = &a->pic;
00145 
00146     if (pic->data[0])
00147         avctx->release_buffer(avctx, pic);
00148 
00149     return 0;
00150 }
00151 
00152 AVCodec ff_xl_decoder = {
00153     .name           = "xl",
00154     .type           = AVMEDIA_TYPE_VIDEO,
00155     .id             = CODEC_ID_VIXL,
00156     .priv_data_size = sizeof(VideoXLContext),
00157     .init           = decode_init,
00158     .close          = decode_end,
00159     .decode         = decode_frame,
00160     .capabilities   = CODEC_CAP_DR1,
00161     .long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"),
00162 };