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 AVPacket *avpkt)
00038 {
00039 const uint8_t *buf = avpkt->data;
00040 int buf_size = avpkt->size;
00041 QdrawContext * const a = avctx->priv_data;
00042 AVFrame * const p= (AVFrame*)&a->pic;
00043 uint8_t* outdata;
00044 int colors;
00045 int i;
00046 uint32_t *pal;
00047 int r, g, b;
00048
00049 if(p->data[0])
00050 avctx->release_buffer(avctx, p);
00051
00052 p->reference= 0;
00053 if(avctx->get_buffer(avctx, p) < 0){
00054 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00055 return -1;
00056 }
00057 p->pict_type= FF_I_TYPE;
00058 p->key_frame= 1;
00059
00060 outdata = a->pic.data[0];
00061
00062 buf += 0x68;
00063 colors = AV_RB32(buf);
00064 buf += 4;
00065
00066 if(colors < 0 || colors > 256) {
00067 av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors);
00068 return -1;
00069 }
00070
00071 pal = (uint32_t*)p->data[1];
00072 for (i = 0; i <= colors; i++) {
00073 unsigned int idx;
00074 idx = AV_RB16(buf);
00075 buf += 2;
00076
00077 if (idx > 255) {
00078 av_log(avctx, AV_LOG_ERROR, "Palette index out of range: %u\n", idx);
00079 buf += 6;
00080 continue;
00081 }
00082 r = *buf++;
00083 buf++;
00084 g = *buf++;
00085 buf++;
00086 b = *buf++;
00087 buf++;
00088 pal[idx] = (r << 16) | (g << 8) | b;
00089 }
00090 p->palette_has_changed = 1;
00091
00092 buf += 18;
00093 for (i = 0; i < avctx->height; i++) {
00094 int size, left, code, pix;
00095 const uint8_t *next;
00096 uint8_t *out;
00097 int tsize = 0;
00098
00099
00100 out = outdata;
00101 size = AV_RB16(buf);
00102 buf += 2;
00103 left = size;
00104 next = buf + size;
00105 while (left > 0) {
00106 code = *buf++;
00107 if (code & 0x80 ) {
00108 pix = *buf++;
00109 if ((out + (257 - code)) > (outdata + a->pic.linesize[0]))
00110 break;
00111 memset(out, pix, 257 - code);
00112 out += 257 - code;
00113 tsize += 257 - code;
00114 left -= 2;
00115 } else {
00116 if ((out + code) > (outdata + a->pic.linesize[0]))
00117 break;
00118 memcpy(out, buf, code + 1);
00119 out += code + 1;
00120 buf += code + 1;
00121 left -= 2 + code;
00122 tsize += code + 1;
00123 }
00124 }
00125 buf = next;
00126 outdata += a->pic.linesize[0];
00127 }
00128
00129 *data_size = sizeof(AVFrame);
00130 *(AVFrame*)data = a->pic;
00131
00132 return buf_size;
00133 }
00134
00135 static av_cold int decode_init(AVCodecContext *avctx){
00136
00137
00138 avctx->pix_fmt= PIX_FMT_PAL8;
00139
00140 return 0;
00141 }
00142
00143 static av_cold int decode_end(AVCodecContext *avctx){
00144 QdrawContext * const a = avctx->priv_data;
00145 AVFrame *pic = &a->pic;
00146
00147 if (pic->data[0])
00148 avctx->release_buffer(avctx, pic);
00149
00150 return 0;
00151 }
00152
00153 AVCodec qdraw_decoder = {
00154 "qdraw",
00155 AVMEDIA_TYPE_VIDEO,
00156 CODEC_ID_QDRAW,
00157 sizeof(QdrawContext),
00158 decode_init,
00159 NULL,
00160 decode_end,
00161 decode_frame,
00162 CODEC_CAP_DR1,
00163 .long_name = NULL_IF_CONFIG_SMALL("Apple QuickDraw"),
00164 };