00001 /* 00002 * Miro VideoXL codec 00003 * Copyright (c) 2004 Konstantin Shishkov 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 const uint8_t *buf, int buf_size) 00044 { 00045 VideoXLContext * const a = avctx->priv_data; 00046 AVFrame * const p= (AVFrame*)&a->pic; 00047 uint8_t *Y, *U, *V; 00048 int i, j; 00049 int stride; 00050 uint32_t val; 00051 int y0, y1, y2, y3 = 0, c0 = 0, c1 = 0; 00052 00053 if(p->data[0]) 00054 avctx->release_buffer(avctx, p); 00055 00056 p->reference = 0; 00057 if(avctx->get_buffer(avctx, p) < 0){ 00058 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00059 return -1; 00060 } 00061 p->pict_type= FF_I_TYPE; 00062 p->key_frame= 1; 00063 00064 Y = a->pic.data[0]; 00065 U = a->pic.data[1]; 00066 V = a->pic.data[2]; 00067 00068 stride = avctx->width - 4; 00069 for (i = 0; i < avctx->height; i++) { 00070 /* lines are stored in reversed order */ 00071 buf += stride; 00072 00073 for (j = 0; j < avctx->width; j += 4) { 00074 /* value is stored in LE dword with word swapped */ 00075 val = AV_RL32(buf); 00076 buf -= 4; 00077 val = ((val >> 16) & 0xFFFF) | ((val & 0xFFFF) << 16); 00078 00079 if(!j) 00080 y0 = (val & 0x1F) << 2; 00081 else 00082 y0 = y3 + xl_table[val & 0x1F]; 00083 val >>= 5; 00084 y1 = y0 + xl_table[val & 0x1F]; 00085 val >>= 5; 00086 y2 = y1 + xl_table[val & 0x1F]; 00087 val >>= 6; /* align to word */ 00088 y3 = y2 + xl_table[val & 0x1F]; 00089 val >>= 5; 00090 if(!j) 00091 c0 = (val & 0x1F) << 2; 00092 else 00093 c0 += xl_table[val & 0x1F]; 00094 val >>= 5; 00095 if(!j) 00096 c1 = (val & 0x1F) << 2; 00097 else 00098 c1 += xl_table[val & 0x1F]; 00099 00100 Y[j + 0] = y0 << 1; 00101 Y[j + 1] = y1 << 1; 00102 Y[j + 2] = y2 << 1; 00103 Y[j + 3] = y3 << 1; 00104 00105 U[j >> 2] = c0 << 1; 00106 V[j >> 2] = c1 << 1; 00107 } 00108 00109 buf += avctx->width + 4; 00110 Y += a->pic.linesize[0]; 00111 U += a->pic.linesize[1]; 00112 V += a->pic.linesize[2]; 00113 } 00114 00115 *data_size = sizeof(AVFrame); 00116 *(AVFrame*)data = a->pic; 00117 00118 return buf_size; 00119 } 00120 00121 static av_cold int decode_init(AVCodecContext *avctx){ 00122 // VideoXLContext * const a = avctx->priv_data; 00123 00124 avctx->pix_fmt= PIX_FMT_YUV411P; 00125 00126 return 0; 00127 } 00128 00129 AVCodec xl_decoder = { 00130 "xl", 00131 CODEC_TYPE_VIDEO, 00132 CODEC_ID_VIXL, 00133 sizeof(VideoXLContext), 00134 decode_init, 00135 NULL, 00136 NULL, 00137 decode_frame, 00138 CODEC_CAP_DR1, 00139 .long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"), 00140 };