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 "libavutil/internal.h"
00038 
00039 
00040 typedef struct CyuvDecodeContext {
00041     AVCodecContext *avctx;
00042     int width, height;
00043     AVFrame frame;
00044 } CyuvDecodeContext;
00045 
00046 static av_cold int cyuv_decode_init(AVCodecContext *avctx)
00047 {
00048     CyuvDecodeContext *s = avctx->priv_data;
00049 
00050     s->avctx = avctx;
00051     s->width = avctx->width;
00052     
00053     if (s->width & 0x3)
00054         return -1;
00055     s->height = avctx->height;
00056     avctx->pix_fmt = PIX_FMT_YUV411P;
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 *data_size,
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 
00087     if (avctx->codec_id == AV_CODEC_ID_AURA) {
00088         y_table = u_table;
00089         u_table = v_table;
00090     }
00091     
00092 
00093 
00094 
00095     if (buf_size != 48 + s->height * (s->width * 3 / 4)) {
00096         av_log(avctx, AV_LOG_ERROR, "got a buffer with %d bytes when %d were expected\n",
00097                buf_size, 48 + s->height * (s->width * 3 / 4));
00098         return -1;
00099     }
00100 
00101     
00102     stream_ptr = 48;
00103 
00104     if (s->frame.data[0])
00105         avctx->release_buffer(avctx, &s->frame);
00106 
00107     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
00108     s->frame.reference = 0;
00109     if (avctx->get_buffer(avctx, &s->frame) < 0) {
00110         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00111         return -1;
00112     }
00113 
00114     y_plane = s->frame.data[0];
00115     u_plane = s->frame.data[1];
00116     v_plane = s->frame.data[2];
00117 
00118     
00119     for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
00120          y_ptr < (s->height * s->frame.linesize[0]);
00121          y_ptr += s->frame.linesize[0] - s->width,
00122          u_ptr += s->frame.linesize[1] - s->width / 4,
00123          v_ptr += s->frame.linesize[2] - s->width / 4) {
00124 
00125         
00126         cur_byte = buf[stream_ptr++];
00127         u_plane[u_ptr++] = u_pred = cur_byte & 0xF0;
00128         y_plane[y_ptr++] = y_pred = (cur_byte & 0x0F) << 4;
00129 
00130         cur_byte = buf[stream_ptr++];
00131         v_plane[v_ptr++] = v_pred = cur_byte & 0xF0;
00132         y_pred += y_table[cur_byte & 0x0F];
00133         y_plane[y_ptr++] = y_pred;
00134 
00135         cur_byte = buf[stream_ptr++];
00136         y_pred += y_table[cur_byte & 0x0F];
00137         y_plane[y_ptr++] = y_pred;
00138         y_pred += y_table[(cur_byte & 0xF0) >> 4];
00139         y_plane[y_ptr++] = y_pred;
00140 
00141         
00142         pixel_groups = s->width / 4 - 1;
00143         while (pixel_groups--) {
00144 
00145             cur_byte = buf[stream_ptr++];
00146             u_pred += u_table[(cur_byte & 0xF0) >> 4];
00147             u_plane[u_ptr++] = u_pred;
00148             y_pred += y_table[cur_byte & 0x0F];
00149             y_plane[y_ptr++] = y_pred;
00150 
00151             cur_byte = buf[stream_ptr++];
00152             v_pred += v_table[(cur_byte & 0xF0) >> 4];
00153             v_plane[v_ptr++] = v_pred;
00154             y_pred += y_table[cur_byte & 0x0F];
00155             y_plane[y_ptr++] = y_pred;
00156 
00157             cur_byte = buf[stream_ptr++];
00158             y_pred += y_table[cur_byte & 0x0F];
00159             y_plane[y_ptr++] = y_pred;
00160             y_pred += y_table[(cur_byte & 0xF0) >> 4];
00161             y_plane[y_ptr++] = y_pred;
00162 
00163         }
00164     }
00165 
00166     *data_size=sizeof(AVFrame);
00167     *(AVFrame*)data= s->frame;
00168 
00169     return buf_size;
00170 }
00171 
00172 static av_cold int cyuv_decode_end(AVCodecContext *avctx)
00173 {
00174     CyuvDecodeContext *s = avctx->priv_data;
00175 
00176     if (s->frame.data[0])
00177         avctx->release_buffer(avctx, &s->frame);
00178 
00179     return 0;
00180 }
00181 
00182 #if CONFIG_AURA_DECODER
00183 AVCodec ff_aura_decoder = {
00184     .name           = "aura",
00185     .type           = AVMEDIA_TYPE_VIDEO,
00186     .id             = AV_CODEC_ID_AURA,
00187     .priv_data_size = sizeof(CyuvDecodeContext),
00188     .init           = cyuv_decode_init,
00189     .close          = cyuv_decode_end,
00190     .decode         = cyuv_decode_frame,
00191     .capabilities   = CODEC_CAP_DR1,
00192     .long_name      = NULL_IF_CONFIG_SMALL("Auravision AURA"),
00193 };
00194 #endif
00195 
00196 #if CONFIG_CYUV_DECODER
00197 AVCodec ff_cyuv_decoder = {
00198     .name           = "cyuv",
00199     .type           = AVMEDIA_TYPE_VIDEO,
00200     .id             = AV_CODEC_ID_CYUV,
00201     .priv_data_size = sizeof(CyuvDecodeContext),
00202     .init           = cyuv_decode_init,
00203     .close          = cyuv_decode_end,
00204     .decode         = cyuv_decode_frame,
00205     .capabilities   = CODEC_CAP_DR1,
00206     .long_name      = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"),
00207 };
00208 #endif