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 #include "internal.h"
00038 #include "libavutil/internal.h"
00039
00040
00041 typedef struct CyuvDecodeContext {
00042 AVCodecContext *avctx;
00043 int width, height;
00044 AVFrame frame;
00045 } CyuvDecodeContext;
00046
00047 static av_cold int cyuv_decode_init(AVCodecContext *avctx)
00048 {
00049 CyuvDecodeContext *s = avctx->priv_data;
00050
00051 s->avctx = avctx;
00052 s->width = avctx->width;
00053
00054 if (s->width & 0x3)
00055 return -1;
00056 s->height = avctx->height;
00057 avcodec_get_frame_defaults(&s->frame);
00058
00059 return 0;
00060 }
00061
00062 static int cyuv_decode_frame(AVCodecContext *avctx,
00063 void *data, int *got_frame,
00064 AVPacket *avpkt)
00065 {
00066 const uint8_t *buf = avpkt->data;
00067 int buf_size = avpkt->size;
00068 CyuvDecodeContext *s=avctx->priv_data;
00069
00070 unsigned char *y_plane;
00071 unsigned char *u_plane;
00072 unsigned char *v_plane;
00073 int y_ptr;
00074 int u_ptr;
00075 int v_ptr;
00076
00077
00078 const signed char *y_table = (const signed char*)buf + 0;
00079 const signed char *u_table = (const signed char*)buf + 16;
00080 const signed char *v_table = (const signed char*)buf + 32;
00081
00082 unsigned char y_pred, u_pred, v_pred;
00083 int stream_ptr;
00084 unsigned char cur_byte;
00085 int pixel_groups;
00086 int rawsize = s->height * FFALIGN(s->width,2) * 2;
00087
00088 if (avctx->codec_id == AV_CODEC_ID_AURA) {
00089 y_table = u_table;
00090 u_table = v_table;
00091 }
00092
00093
00094
00095
00096 if (buf_size == 48 + s->height * (s->width * 3 / 4)) {
00097 avctx->pix_fmt = AV_PIX_FMT_YUV411P;
00098 } else if(buf_size == rawsize ) {
00099 avctx->pix_fmt = AV_PIX_FMT_UYVY422;
00100 } else {
00101 av_log(avctx, AV_LOG_ERROR, "got a buffer with %d bytes when %d were expected\n",
00102 buf_size, 48 + s->height * (s->width * 3 / 4));
00103 return -1;
00104 }
00105
00106
00107 stream_ptr = 48;
00108
00109 if (s->frame.data[0])
00110 avctx->release_buffer(avctx, &s->frame);
00111
00112 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
00113 s->frame.reference = 0;
00114 if (ff_get_buffer(avctx, &s->frame) < 0) {
00115 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00116 return -1;
00117 }
00118
00119 y_plane = s->frame.data[0];
00120 u_plane = s->frame.data[1];
00121 v_plane = s->frame.data[2];
00122
00123 if (buf_size == rawsize) {
00124 int linesize = FFALIGN(s->width,2) * 2;
00125 y_plane += s->frame.linesize[0] * s->height;
00126 for (stream_ptr = 0; stream_ptr < rawsize; stream_ptr += linesize) {
00127 y_plane -= s->frame.linesize[0];
00128 memcpy(y_plane, buf+stream_ptr, linesize);
00129 }
00130 } else {
00131
00132
00133 for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
00134 y_ptr < (s->height * s->frame.linesize[0]);
00135 y_ptr += s->frame.linesize[0] - s->width,
00136 u_ptr += s->frame.linesize[1] - s->width / 4,
00137 v_ptr += s->frame.linesize[2] - s->width / 4) {
00138
00139
00140 cur_byte = buf[stream_ptr++];
00141 u_plane[u_ptr++] = u_pred = cur_byte & 0xF0;
00142 y_plane[y_ptr++] = y_pred = (cur_byte & 0x0F) << 4;
00143
00144 cur_byte = buf[stream_ptr++];
00145 v_plane[v_ptr++] = v_pred = cur_byte & 0xF0;
00146 y_pred += y_table[cur_byte & 0x0F];
00147 y_plane[y_ptr++] = y_pred;
00148
00149 cur_byte = buf[stream_ptr++];
00150 y_pred += y_table[cur_byte & 0x0F];
00151 y_plane[y_ptr++] = y_pred;
00152 y_pred += y_table[(cur_byte & 0xF0) >> 4];
00153 y_plane[y_ptr++] = y_pred;
00154
00155
00156 pixel_groups = s->width / 4 - 1;
00157 while (pixel_groups--) {
00158
00159 cur_byte = buf[stream_ptr++];
00160 u_pred += u_table[(cur_byte & 0xF0) >> 4];
00161 u_plane[u_ptr++] = u_pred;
00162 y_pred += y_table[cur_byte & 0x0F];
00163 y_plane[y_ptr++] = y_pred;
00164
00165 cur_byte = buf[stream_ptr++];
00166 v_pred += v_table[(cur_byte & 0xF0) >> 4];
00167 v_plane[v_ptr++] = v_pred;
00168 y_pred += y_table[cur_byte & 0x0F];
00169 y_plane[y_ptr++] = y_pred;
00170
00171 cur_byte = buf[stream_ptr++];
00172 y_pred += y_table[cur_byte & 0x0F];
00173 y_plane[y_ptr++] = y_pred;
00174 y_pred += y_table[(cur_byte & 0xF0) >> 4];
00175 y_plane[y_ptr++] = y_pred;
00176
00177 }
00178 }
00179 }
00180
00181 *got_frame = 1;
00182 *(AVFrame*)data= s->frame;
00183
00184 return buf_size;
00185 }
00186
00187 static av_cold int cyuv_decode_end(AVCodecContext *avctx)
00188 {
00189 CyuvDecodeContext *s = avctx->priv_data;
00190
00191 if (s->frame.data[0])
00192 avctx->release_buffer(avctx, &s->frame);
00193
00194 return 0;
00195 }
00196
00197 #if CONFIG_AURA_DECODER
00198 AVCodec ff_aura_decoder = {
00199 .name = "aura",
00200 .type = AVMEDIA_TYPE_VIDEO,
00201 .id = AV_CODEC_ID_AURA,
00202 .priv_data_size = sizeof(CyuvDecodeContext),
00203 .init = cyuv_decode_init,
00204 .close = cyuv_decode_end,
00205 .decode = cyuv_decode_frame,
00206 .capabilities = CODEC_CAP_DR1,
00207 .long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"),
00208 };
00209 #endif
00210
00211 #if CONFIG_CYUV_DECODER
00212 AVCodec ff_cyuv_decoder = {
00213 .name = "cyuv",
00214 .type = AVMEDIA_TYPE_VIDEO,
00215 .id = AV_CODEC_ID_CYUV,
00216 .priv_data_size = sizeof(CyuvDecodeContext),
00217 .init = cyuv_decode_init,
00218 .close = cyuv_decode_end,
00219 .decode = cyuv_decode_frame,
00220 .capabilities = CODEC_CAP_DR1,
00221 .long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"),
00222 };
00223 #endif