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
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036
00037 #include "avcodec.h"
00038
00039
00040 static const enum PixelFormat pixfmt_rgb24[] = {PIX_FMT_BGR24, PIX_FMT_RGB32, PIX_FMT_NONE};
00041
00042
00043
00044
00045 typedef struct EightBpsContext {
00046
00047 AVCodecContext *avctx;
00048 AVFrame pic;
00049
00050 unsigned char planes;
00051 unsigned char planemap[4];
00052 } EightBpsContext;
00053
00054
00055
00056
00057
00058
00059
00060 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size)
00061 {
00062 EightBpsContext * const c = avctx->priv_data;
00063 const unsigned char *encoded = buf;
00064 unsigned char *pixptr, *pixptr_end;
00065 unsigned int height = avctx->height;
00066 unsigned int dlen, p, row;
00067 const unsigned char *lp, *dp;
00068 unsigned char count;
00069 unsigned int px_inc;
00070 unsigned int planes = c->planes;
00071 unsigned char *planemap = c->planemap;
00072
00073 if(c->pic.data[0])
00074 avctx->release_buffer(avctx, &c->pic);
00075
00076 c->pic.reference = 0;
00077 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
00078 if(avctx->get_buffer(avctx, &c->pic) < 0){
00079 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00080 return -1;
00081 }
00082
00083
00084 dp = encoded + planes * (height << 1);
00085
00086
00087 if (planes == 4)
00088 planes--;
00089
00090 px_inc = planes + (avctx->pix_fmt == PIX_FMT_RGB32);
00091
00092 for (p = 0; p < planes; p++) {
00093
00094 lp = encoded + p * (height << 1);
00095
00096
00097 for(row = 0; row < height; row++) {
00098 pixptr = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
00099 pixptr_end = pixptr + c->pic.linesize[0];
00100 dlen = be2me_16(*(const unsigned short *)(lp+row*2));
00101
00102 while(dlen > 0) {
00103 if(dp + 1 >= buf+buf_size) return -1;
00104 if ((count = *dp++) <= 127) {
00105 count++;
00106 dlen -= count + 1;
00107 if (pixptr + count * px_inc > pixptr_end)
00108 break;
00109 if(dp + count > buf+buf_size) return -1;
00110 while(count--) {
00111 *pixptr = *dp++;
00112 pixptr += px_inc;
00113 }
00114 } else {
00115 count = 257 - count;
00116 if (pixptr + count * px_inc > pixptr_end)
00117 break;
00118 while(count--) {
00119 *pixptr = *dp;
00120 pixptr += px_inc;
00121 }
00122 dp++;
00123 dlen -= 2;
00124 }
00125 }
00126 }
00127 }
00128
00129 if (avctx->palctrl) {
00130 memcpy (c->pic.data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
00131 if (avctx->palctrl->palette_changed) {
00132 c->pic.palette_has_changed = 1;
00133 avctx->palctrl->palette_changed = 0;
00134 } else
00135 c->pic.palette_has_changed = 0;
00136 }
00137
00138 *data_size = sizeof(AVFrame);
00139 *(AVFrame*)data = c->pic;
00140
00141
00142 return buf_size;
00143 }
00144
00145
00146
00147
00148
00149
00150
00151 static av_cold int decode_init(AVCodecContext *avctx)
00152 {
00153 EightBpsContext * const c = avctx->priv_data;
00154
00155 c->avctx = avctx;
00156
00157 c->pic.data[0] = NULL;
00158
00159 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
00160 return 1;
00161 }
00162
00163 switch (avctx->bits_per_sample) {
00164 case 8:
00165 avctx->pix_fmt = PIX_FMT_PAL8;
00166 c->planes = 1;
00167 c->planemap[0] = 0;
00168 if (avctx->palctrl == NULL) {
00169 av_log(avctx, AV_LOG_ERROR, "Error: PAL8 format but no palette from demuxer.\n");
00170 return -1;
00171 }
00172 break;
00173 case 24:
00174 avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24);
00175 c->planes = 3;
00176 c->planemap[0] = 2;
00177 c->planemap[1] = 1;
00178 c->planemap[2] = 0;
00179 break;
00180 case 32:
00181 avctx->pix_fmt = PIX_FMT_RGB32;
00182 c->planes = 4;
00183 #ifdef WORDS_BIGENDIAN
00184 c->planemap[0] = 1;
00185 c->planemap[1] = 2;
00186 c->planemap[2] = 3;
00187 c->planemap[3] = 0;
00188 #else
00189 c->planemap[0] = 2;
00190 c->planemap[1] = 1;
00191 c->planemap[2] = 0;
00192 c->planemap[3] = 3;
00193 #endif
00194 break;
00195 default:
00196 av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n", avctx->bits_per_sample);
00197 return -1;
00198 }
00199
00200 return 0;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 static av_cold int decode_end(AVCodecContext *avctx)
00212 {
00213 EightBpsContext * const c = avctx->priv_data;
00214
00215 if (c->pic.data[0])
00216 avctx->release_buffer(avctx, &c->pic);
00217
00218 return 0;
00219 }
00220
00221
00222
00223 AVCodec eightbps_decoder = {
00224 "8bps",
00225 CODEC_TYPE_VIDEO,
00226 CODEC_ID_8BPS,
00227 sizeof(EightBpsContext),
00228 decode_init,
00229 NULL,
00230 decode_end,
00231 decode_frame,
00232 CODEC_CAP_DR1,
00233 .long_name = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"),
00234 };