00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034
00035 #include "avcodec.h"
00036 #include "dsputil.h"
00037
00038
00039 typedef struct CyuvDecodeContext {
00040 AVCodecContext *avctx;
00041 int width, height;
00042 AVFrame frame;
00043 } CyuvDecodeContext;
00044
00045 static av_cold int cyuv_decode_init(AVCodecContext *avctx)
00046 {
00047 CyuvDecodeContext *s = avctx->priv_data;
00048
00049 s->avctx = avctx;
00050 s->width = avctx->width;
00051
00052 if (s->width & 0x3)
00053 return -1;
00054 s->height = avctx->height;
00055 avctx->pix_fmt = PIX_FMT_YUV411P;
00056
00057 return 0;
00058 }
00059
00060 static int cyuv_decode_frame(AVCodecContext *avctx,
00061 void *data, int *data_size,
00062 AVPacket *avpkt)
00063 {
00064 const uint8_t *buf = avpkt->data;
00065 int buf_size = avpkt->size;
00066 CyuvDecodeContext *s=avctx->priv_data;
00067
00068 unsigned char *y_plane;
00069 unsigned char *u_plane;
00070 unsigned char *v_plane;
00071 int y_ptr;
00072 int u_ptr;
00073 int v_ptr;
00074
00075
00076 const signed char *y_table = (const signed char*)buf + 0;
00077 const signed char *u_table = (const signed char*)buf + 16;
00078 const signed char *v_table = (const signed char*)buf + 32;
00079
00080 unsigned char y_pred, u_pred, v_pred;
00081 int stream_ptr;
00082 unsigned char cur_byte;
00083 int pixel_groups;
00084
00085 if (avctx->codec_id == CODEC_ID_AURA) {
00086 y_table = u_table;
00087 u_table = v_table;
00088 }
00089
00090
00091
00092
00093 if (buf_size != 48 + s->height * (s->width * 3 / 4)) {
00094 av_log(avctx, AV_LOG_ERROR, "got a buffer with %d bytes when %d were expected\n",
00095 buf_size, 48 + s->height * (s->width * 3 / 4));
00096 return -1;
00097 }
00098
00099
00100 stream_ptr = 48;
00101
00102 if (s->frame.data[0])
00103 avctx->release_buffer(avctx, &s->frame);
00104
00105 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
00106 s->frame.reference = 0;
00107 if (avctx->get_buffer(avctx, &s->frame) < 0) {
00108 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00109 return -1;
00110 }
00111
00112 y_plane = s->frame.data[0];
00113 u_plane = s->frame.data[1];
00114 v_plane = s->frame.data[2];
00115
00116
00117 for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
00118 y_ptr < (s->height * s->frame.linesize[0]);
00119 y_ptr += s->frame.linesize[0] - s->width,
00120 u_ptr += s->frame.linesize[1] - s->width / 4,
00121 v_ptr += s->frame.linesize[2] - s->width / 4) {
00122
00123
00124 cur_byte = buf[stream_ptr++];
00125 u_plane[u_ptr++] = u_pred = cur_byte & 0xF0;
00126 y_plane[y_ptr++] = y_pred = (cur_byte & 0x0F) << 4;
00127
00128 cur_byte = buf[stream_ptr++];
00129 v_plane[v_ptr++] = v_pred = cur_byte & 0xF0;
00130 y_pred += y_table[cur_byte & 0x0F];
00131 y_plane[y_ptr++] = y_pred;
00132
00133 cur_byte = buf[stream_ptr++];
00134 y_pred += y_table[cur_byte & 0x0F];
00135 y_plane[y_ptr++] = y_pred;
00136 y_pred += y_table[(cur_byte & 0xF0) >> 4];
00137 y_plane[y_ptr++] = y_pred;
00138
00139
00140 pixel_groups = s->width / 4 - 1;
00141 while (pixel_groups--) {
00142
00143 cur_byte = buf[stream_ptr++];
00144 u_pred += u_table[(cur_byte & 0xF0) >> 4];
00145 u_plane[u_ptr++] = u_pred;
00146 y_pred += y_table[cur_byte & 0x0F];
00147 y_plane[y_ptr++] = y_pred;
00148
00149 cur_byte = buf[stream_ptr++];
00150 v_pred += v_table[(cur_byte & 0xF0) >> 4];
00151 v_plane[v_ptr++] = v_pred;
00152 y_pred += y_table[cur_byte & 0x0F];
00153 y_plane[y_ptr++] = y_pred;
00154
00155 cur_byte = buf[stream_ptr++];
00156 y_pred += y_table[cur_byte & 0x0F];
00157 y_plane[y_ptr++] = y_pred;
00158 y_pred += y_table[(cur_byte & 0xF0) >> 4];
00159 y_plane[y_ptr++] = y_pred;
00160
00161 }
00162 }
00163
00164 *data_size=sizeof(AVFrame);
00165 *(AVFrame*)data= s->frame;
00166
00167 return buf_size;
00168 }
00169
00170 static av_cold int cyuv_decode_end(AVCodecContext *avctx)
00171 {
00172 CyuvDecodeContext *s = avctx->priv_data;
00173
00174 if (s->frame.data[0])
00175 avctx->release_buffer(avctx, &s->frame);
00176
00177 return 0;
00178 }
00179
00180 #if CONFIG_AURA_DECODER
00181 AVCodec aura_decoder = {
00182 "aura",
00183 AVMEDIA_TYPE_VIDEO,
00184 CODEC_ID_AURA,
00185 sizeof(CyuvDecodeContext),
00186 cyuv_decode_init,
00187 NULL,
00188 cyuv_decode_end,
00189 cyuv_decode_frame,
00190 CODEC_CAP_DR1,
00191 NULL,
00192 .long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"),
00193 };
00194 #endif
00195
00196 #if CONFIG_CYUV_DECODER
00197 AVCodec cyuv_decoder = {
00198 "cyuv",
00199 AVMEDIA_TYPE_VIDEO,
00200 CODEC_ID_CYUV,
00201 sizeof(CyuvDecodeContext),
00202 cyuv_decode_init,
00203 NULL,
00204 cyuv_decode_end,
00205 cyuv_decode_frame,
00206 CODEC_CAP_DR1,
00207 NULL,
00208 .long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"),
00209 };
00210 #endif