• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/cyuv.c

Go to the documentation of this file.
00001 /*
00002  * Creative YUV (CYUV) Video Decoder
00003  *   by Mike Melanson (melanson@pcisys.net)
00004  * based on "Creative YUV (CYUV) stream format for AVI":
00005  *   http://www.csse.monash.edu.au/~timf/videocodec/cyuv.txt
00006  *
00007  * Copyright (C) 2003 the ffmpeg project
00008  *
00009  * This file is part of FFmpeg.
00010  *
00011  * FFmpeg is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Lesser General Public
00013  * License as published by the Free Software Foundation; either
00014  * version 2.1 of the License, or (at your option) any later version.
00015  *
00016  * FFmpeg is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with FFmpeg; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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     /* width needs to be divisible by 4 for this codec to work */
00052     if (s->width & 0x3)
00053         return -1;
00054     s->height = avctx->height;
00055     avctx->pix_fmt = PIX_FMT_YUV411P;
00056     avcodec_get_frame_defaults(&s->frame);
00057 
00058     return 0;
00059 }
00060 
00061 static int cyuv_decode_frame(AVCodecContext *avctx,
00062                              void *data, int *data_size,
00063                              AVPacket *avpkt)
00064 {
00065     const uint8_t *buf = avpkt->data;
00066     int buf_size = avpkt->size;
00067     CyuvDecodeContext *s=avctx->priv_data;
00068 
00069     unsigned char *y_plane;
00070     unsigned char *u_plane;
00071     unsigned char *v_plane;
00072     int y_ptr;
00073     int u_ptr;
00074     int v_ptr;
00075 
00076     /* prediction error tables (make it clear that they are signed values) */
00077     const signed char *y_table = (const signed char*)buf +  0;
00078     const signed char *u_table = (const signed char*)buf + 16;
00079     const signed char *v_table = (const signed char*)buf + 32;
00080 
00081     unsigned char y_pred, u_pred, v_pred;
00082     int stream_ptr;
00083     unsigned char cur_byte;
00084     int pixel_groups;
00085 
00086     if (avctx->codec_id == CODEC_ID_AURA) {
00087         y_table = u_table;
00088         u_table = v_table;
00089     }
00090     /* sanity check the buffer size: A buffer has 3x16-bytes tables
00091      * followed by (height) lines each with 3 bytes to represent groups
00092      * of 4 pixels. Thus, the total size of the buffer ought to be:
00093      *    (3 * 16) + height * (width * 3 / 4) */
00094     if (buf_size != 48 + s->height * (s->width * 3 / 4)) {
00095         av_log(avctx, AV_LOG_ERROR, "got a buffer with %d bytes when %d were expected\n",
00096                buf_size, 48 + s->height * (s->width * 3 / 4));
00097         return -1;
00098     }
00099 
00100     /* pixel data starts 48 bytes in, after 3x16-byte tables */
00101     stream_ptr = 48;
00102 
00103     if (s->frame.data[0])
00104         avctx->release_buffer(avctx, &s->frame);
00105 
00106     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
00107     s->frame.reference = 0;
00108     if (avctx->get_buffer(avctx, &s->frame) < 0) {
00109         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00110         return -1;
00111     }
00112 
00113     y_plane = s->frame.data[0];
00114     u_plane = s->frame.data[1];
00115     v_plane = s->frame.data[2];
00116 
00117     /* iterate through each line in the height */
00118     for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
00119          y_ptr < (s->height * s->frame.linesize[0]);
00120          y_ptr += s->frame.linesize[0] - s->width,
00121          u_ptr += s->frame.linesize[1] - s->width / 4,
00122          v_ptr += s->frame.linesize[2] - s->width / 4) {
00123 
00124         /* reset predictors */
00125         cur_byte = buf[stream_ptr++];
00126         u_plane[u_ptr++] = u_pred = cur_byte & 0xF0;
00127         y_plane[y_ptr++] = y_pred = (cur_byte & 0x0F) << 4;
00128 
00129         cur_byte = buf[stream_ptr++];
00130         v_plane[v_ptr++] = v_pred = cur_byte & 0xF0;
00131         y_pred += y_table[cur_byte & 0x0F];
00132         y_plane[y_ptr++] = y_pred;
00133 
00134         cur_byte = buf[stream_ptr++];
00135         y_pred += y_table[cur_byte & 0x0F];
00136         y_plane[y_ptr++] = y_pred;
00137         y_pred += y_table[(cur_byte & 0xF0) >> 4];
00138         y_plane[y_ptr++] = y_pred;
00139 
00140         /* iterate through the remaining pixel groups (4 pixels/group) */
00141         pixel_groups = s->width / 4 - 1;
00142         while (pixel_groups--) {
00143 
00144             cur_byte = buf[stream_ptr++];
00145             u_pred += u_table[(cur_byte & 0xF0) >> 4];
00146             u_plane[u_ptr++] = u_pred;
00147             y_pred += y_table[cur_byte & 0x0F];
00148             y_plane[y_ptr++] = y_pred;
00149 
00150             cur_byte = buf[stream_ptr++];
00151             v_pred += v_table[(cur_byte & 0xF0) >> 4];
00152             v_plane[v_ptr++] = v_pred;
00153             y_pred += y_table[cur_byte & 0x0F];
00154             y_plane[y_ptr++] = y_pred;
00155 
00156             cur_byte = buf[stream_ptr++];
00157             y_pred += y_table[cur_byte & 0x0F];
00158             y_plane[y_ptr++] = y_pred;
00159             y_pred += y_table[(cur_byte & 0xF0) >> 4];
00160             y_plane[y_ptr++] = y_pred;
00161 
00162         }
00163     }
00164 
00165     *data_size=sizeof(AVFrame);
00166     *(AVFrame*)data= s->frame;
00167 
00168     return buf_size;
00169 }
00170 
00171 static av_cold int cyuv_decode_end(AVCodecContext *avctx)
00172 {
00173     CyuvDecodeContext *s = avctx->priv_data;
00174 
00175     if (s->frame.data[0])
00176         avctx->release_buffer(avctx, &s->frame);
00177 
00178     return 0;
00179 }
00180 
00181 #if CONFIG_AURA_DECODER
00182 AVCodec ff_aura_decoder = {
00183     .name           = "aura",
00184     .type           = AVMEDIA_TYPE_VIDEO,
00185     .id             = CODEC_ID_AURA,
00186     .priv_data_size = sizeof(CyuvDecodeContext),
00187     .init           = cyuv_decode_init,
00188     .close          = cyuv_decode_end,
00189     .decode         = cyuv_decode_frame,
00190     .capabilities   = CODEC_CAP_DR1,
00191     .long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"),
00192 };
00193 #endif
00194 
00195 #if CONFIG_CYUV_DECODER
00196 AVCodec ff_cyuv_decoder = {
00197     .name           = "cyuv",
00198     .type           = AVMEDIA_TYPE_VIDEO,
00199     .id             = CODEC_ID_CYUV,
00200     .priv_data_size = sizeof(CyuvDecodeContext),
00201     .init           = cyuv_decode_init,
00202     .close          = cyuv_decode_end,
00203     .decode         = cyuv_decode_frame,
00204     .capabilities   = CODEC_CAP_DR1,
00205     .long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"),
00206 };
00207 #endif
Generated on Fri Feb 1 2013 14:34:31 for FFmpeg by doxygen 1.7.1