00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "libavutil/intreadwrite.h"
00028 #include "avcodec.h"
00029
00030 typedef struct QdrawContext{
00031 AVCodecContext *avctx;
00032 AVFrame pic;
00033 } QdrawContext;
00034
00035 static int decode_frame(AVCodecContext *avctx,
00036 void *data, int *data_size,
00037 const uint8_t *buf, int buf_size)
00038 {
00039 QdrawContext * const a = avctx->priv_data;
00040 AVFrame * const p= (AVFrame*)&a->pic;
00041 uint8_t* outdata;
00042 int colors;
00043 int i;
00044 uint32_t *pal;
00045 int r, g, b;
00046
00047 if(p->data[0])
00048 avctx->release_buffer(avctx, p);
00049
00050 p->reference= 0;
00051 if(avctx->get_buffer(avctx, p) < 0){
00052 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00053 return -1;
00054 }
00055 p->pict_type= FF_I_TYPE;
00056 p->key_frame= 1;
00057
00058 outdata = a->pic.data[0];
00059
00060 buf += 0x68;
00061 colors = AV_RB32(buf);
00062 buf += 4;
00063
00064 if(colors < 0 || colors > 256) {
00065 av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors);
00066 return -1;
00067 }
00068
00069 pal = (uint32_t*)p->data[1];
00070 for (i = 0; i <= colors; i++) {
00071 unsigned int idx;
00072 idx = AV_RB16(buf);
00073 buf += 2;
00074
00075 if (idx > 255) {
00076 av_log(avctx, AV_LOG_ERROR, "Palette index out of range: %u\n", idx);
00077 buf += 6;
00078 continue;
00079 }
00080 r = *buf++;
00081 buf++;
00082 g = *buf++;
00083 buf++;
00084 b = *buf++;
00085 buf++;
00086 pal[idx] = (r << 16) | (g << 8) | b;
00087 }
00088 p->palette_has_changed = 1;
00089
00090 buf += 18;
00091 for (i = 0; i < avctx->height; i++) {
00092 int size, left, code, pix;
00093 const uint8_t *next;
00094 uint8_t *out;
00095 int tsize = 0;
00096
00097
00098 out = outdata;
00099 size = AV_RB16(buf);
00100 buf += 2;
00101 left = size;
00102 next = buf + size;
00103 while (left > 0) {
00104 code = *buf++;
00105 if (code & 0x80 ) {
00106 pix = *buf++;
00107 if ((out + (257 - code)) > (outdata + a->pic.linesize[0]))
00108 break;
00109 memset(out, pix, 257 - code);
00110 out += 257 - code;
00111 tsize += 257 - code;
00112 left -= 2;
00113 } else {
00114 if ((out + code) > (outdata + a->pic.linesize[0]))
00115 break;
00116 memcpy(out, buf, code + 1);
00117 out += code + 1;
00118 buf += code + 1;
00119 left -= 2 + code;
00120 tsize += code + 1;
00121 }
00122 }
00123 buf = next;
00124 outdata += a->pic.linesize[0];
00125 }
00126
00127 *data_size = sizeof(AVFrame);
00128 *(AVFrame*)data = a->pic;
00129
00130 return buf_size;
00131 }
00132
00133 static av_cold int decode_init(AVCodecContext *avctx){
00134
00135
00136 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
00137 return 1;
00138 }
00139
00140 avctx->pix_fmt= PIX_FMT_PAL8;
00141
00142 return 0;
00143 }
00144
00145 AVCodec qdraw_decoder = {
00146 "qdraw",
00147 CODEC_TYPE_VIDEO,
00148 CODEC_ID_QDRAW,
00149 sizeof(QdrawContext),
00150 decode_init,
00151 NULL,
00152 NULL,
00153 decode_frame,
00154 CODEC_CAP_DR1,
00155 .long_name = NULL_IF_CONFIG_SMALL("Apple QuickDraw"),
00156 };