00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "avcodec.h"
00024 #include "internal.h"
00025
00026 static av_cold int xbm_decode_init(AVCodecContext *avctx)
00027 {
00028 avctx->coded_frame = avcodec_alloc_frame();
00029 if (!avctx->coded_frame)
00030 return AVERROR(ENOMEM);
00031
00032 return 0;
00033 }
00034
00035 static int convert(uint8_t x)
00036 {
00037 if (x >= 'a')
00038 x -= 87;
00039 else if (x >= 'A')
00040 x -= 55;
00041 else
00042 x -= '0';
00043 return x;
00044 }
00045
00046 static int xbm_decode_frame(AVCodecContext *avctx, void *data,
00047 int *data_size, AVPacket *avpkt)
00048 {
00049 AVFrame *p = avctx->coded_frame;
00050 const uint8_t *end, *ptr = avpkt->data;
00051 uint8_t *dst;
00052 int ret, linesize, i, j;
00053
00054 end = avpkt->data + avpkt->size;
00055 while (!avctx->width || !avctx->height) {
00056 char name[256];
00057 int number, len;
00058
00059 ptr += strcspn(ptr, "#");
00060 if (sscanf(ptr, "#define %256s %u", name, &number) != 2) {
00061 av_log(avctx, AV_LOG_ERROR, "Unexpected preprocessor directive\n");
00062 return AVERROR_INVALIDDATA;
00063 }
00064
00065 len = strlen(name);
00066 if ((len > 6) && !avctx->height && !memcmp(name + len - 7, "_height", 7)) {
00067 avctx->height = number;
00068 } else if ((len > 5) && !avctx->width && !memcmp(name + len - 6, "_width", 6)) {
00069 avctx->width = number;
00070 } else {
00071 av_log(avctx, AV_LOG_ERROR, "Unknown define '%s'\n", name);
00072 return AVERROR_INVALIDDATA;
00073 }
00074 ptr += strcspn(ptr, "\n\r") + 1;
00075 }
00076
00077 avctx->pix_fmt = PIX_FMT_MONOWHITE;
00078
00079 if (p->data[0])
00080 avctx->release_buffer(avctx, p);
00081
00082 p->reference = 0;
00083 if ((ret = avctx->get_buffer(avctx, p)) < 0)
00084 return ret;
00085
00086
00087 ptr += strcspn(ptr, "{") + 1;
00088
00089 linesize = (avctx->width + 7) / 8;
00090 for (i = 0; i < avctx->height; i++) {
00091 dst = p->data[0] + i * p->linesize[0];
00092 for (j = 0; j < linesize; j++) {
00093 uint8_t val;
00094
00095 ptr += strcspn(ptr, "x") + 1;
00096 if (ptr < end && isxdigit(*ptr)) {
00097 val = convert(*ptr);
00098 ptr++;
00099 if (isxdigit(*ptr))
00100 val = (val << 4) + convert(*ptr);
00101 *dst++ = av_reverse[val];
00102 } else {
00103 av_log(avctx, AV_LOG_ERROR, "Unexpected data at '%.8s'\n", ptr);
00104 return AVERROR_INVALIDDATA;
00105 }
00106 }
00107 }
00108
00109 p->key_frame = 1;
00110 p->pict_type = AV_PICTURE_TYPE_I;
00111
00112 *data_size = sizeof(AVFrame);
00113 *(AVFrame *)data = *p;
00114
00115 return avpkt->size;
00116 }
00117
00118 static av_cold int xbm_decode_close(AVCodecContext *avctx)
00119 {
00120 if (avctx->coded_frame->data[0])
00121 avctx->release_buffer(avctx, avctx->coded_frame);
00122
00123 av_freep(&avctx->coded_frame);
00124
00125 return 0;
00126 }
00127
00128 AVCodec ff_xbm_decoder = {
00129 .name = "xbm",
00130 .type = AVMEDIA_TYPE_VIDEO,
00131 .id = AV_CODEC_ID_XBM,
00132 .init = xbm_decode_init,
00133 .close = xbm_decode_close,
00134 .decode = xbm_decode_frame,
00135 .capabilities = CODEC_CAP_DR1,
00136 .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"),
00137 };