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 #include <unistd.h>
00035
00036 #include "common.h"
00037 #include "avcodec.h"
00038 #include "dsputil.h"
00039 #include "mpegvideo.h"
00040
00041
00042 typedef struct CyuvDecodeContext {
00043 AVCodecContext *avctx;
00044 int width, height;
00045 AVFrame frame;
00046 } CyuvDecodeContext;
00047
00048 static int cyuv_decode_init(AVCodecContext *avctx)
00049 {
00050 CyuvDecodeContext *s = avctx->priv_data;
00051
00052 s->avctx = avctx;
00053 s->width = avctx->width;
00054 s->height = avctx->height;
00055 avctx->pix_fmt = PIX_FMT_YUV411P;
00056 avctx->has_b_frames = 0;
00057
00058 return 0;
00059 }
00060
00061 static int cyuv_decode_frame(AVCodecContext *avctx,
00062 void *data, int *data_size,
00063 uint8_t *buf, int buf_size)
00064 {
00065 CyuvDecodeContext *s=avctx->priv_data;
00066
00067 unsigned char *y_plane;
00068 unsigned char *u_plane;
00069 unsigned char *v_plane;
00070 int y_ptr;
00071 int u_ptr;
00072 int v_ptr;
00073
00074
00075 signed char *y_table = buf + 0;
00076 signed char *u_table = buf + 16;
00077 signed char *v_table = buf + 32;
00078
00079 unsigned char y_pred, u_pred, v_pred;
00080 int stream_ptr;
00081 unsigned char cur_byte;
00082 int pixel_groups;
00083
00084
00085
00086
00087
00088 if (buf_size != 48 + s->height * (s->width * 3 / 4)) {
00089 av_log(avctx, AV_LOG_ERROR, "ffmpeg: cyuv: got a buffer with %d bytes when %d were expected\n",
00090 buf_size,
00091 48 + s->height * (s->width * 3 / 4));
00092 return -1;
00093 }
00094
00095
00096 stream_ptr = 48;
00097
00098 if(s->frame.data[0])
00099 avctx->release_buffer(avctx, &s->frame);
00100
00101 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
00102 s->frame.reference = 0;
00103 if(avctx->get_buffer(avctx, &s->frame) < 0) {
00104 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00105 return -1;
00106 }
00107
00108 y_plane = s->frame.data[0];
00109 u_plane = s->frame.data[1];
00110 v_plane = s->frame.data[2];
00111
00112
00113 for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
00114 y_ptr < (s->height * s->frame.linesize[0]);
00115 y_ptr += s->frame.linesize[0] - s->width,
00116 u_ptr += s->frame.linesize[1] - s->width / 4,
00117 v_ptr += s->frame.linesize[2] - s->width / 4) {
00118
00119
00120 cur_byte = buf[stream_ptr++];
00121 u_plane[u_ptr++] = u_pred = cur_byte & 0xF0;
00122 y_plane[y_ptr++] = y_pred = (cur_byte & 0x0F) << 4;
00123
00124 cur_byte = buf[stream_ptr++];
00125 v_plane[v_ptr++] = v_pred = cur_byte & 0xF0;
00126 y_pred += y_table[cur_byte & 0x0F];
00127 y_plane[y_ptr++] = y_pred;
00128
00129 cur_byte = buf[stream_ptr++];
00130 y_pred += y_table[cur_byte & 0x0F];
00131 y_plane[y_ptr++] = y_pred;
00132 y_pred += y_table[(cur_byte & 0xF0) >> 4];
00133 y_plane[y_ptr++] = y_pred;
00134
00135
00136 pixel_groups = s->width / 4 - 1;
00137 while (pixel_groups--) {
00138
00139 cur_byte = buf[stream_ptr++];
00140 u_pred += u_table[(cur_byte & 0xF0) >> 4];
00141 u_plane[u_ptr++] = u_pred;
00142 y_pred += y_table[cur_byte & 0x0F];
00143 y_plane[y_ptr++] = y_pred;
00144
00145 cur_byte = buf[stream_ptr++];
00146 v_pred += v_table[(cur_byte & 0xF0) >> 4];
00147 v_plane[v_ptr++] = v_pred;
00148 y_pred += y_table[cur_byte & 0x0F];
00149 y_plane[y_ptr++] = y_pred;
00150
00151 cur_byte = buf[stream_ptr++];
00152 y_pred += y_table[cur_byte & 0x0F];
00153 y_plane[y_ptr++] = y_pred;
00154 y_pred += y_table[(cur_byte & 0xF0) >> 4];
00155 y_plane[y_ptr++] = y_pred;
00156
00157 }
00158 }
00159
00160 *data_size=sizeof(AVFrame);
00161 *(AVFrame*)data= s->frame;
00162
00163 return buf_size;
00164 }
00165
00166 static int cyuv_decode_end(AVCodecContext *avctx)
00167 {
00168
00169
00170 return 0;
00171 }
00172
00173 AVCodec cyuv_decoder = {
00174 "cyuv",
00175 CODEC_TYPE_VIDEO,
00176 CODEC_ID_CYUV,
00177 sizeof(CyuvDecodeContext),
00178 cyuv_decode_init,
00179 NULL,
00180 cyuv_decode_end,
00181 cyuv_decode_frame,
00182 CODEC_CAP_DR1,
00183 NULL
00184 };
00185