FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
xbmdec.c
Go to the documentation of this file.
1 /*
2  * XBM image format
3  *
4  * Copyright (c) 2012 Paul B Mahol
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "avcodec.h"
24 #include "internal.h"
25 #include "mathops.h"
26 #include "libavutil/avstring.h"
27 
29 {
31  if (!avctx->coded_frame)
32  return AVERROR(ENOMEM);
33 
34  return 0;
35 }
36 
37 static int convert(uint8_t x)
38 {
39  if (x >= 'a')
40  x -= 87;
41  else if (x >= 'A')
42  x -= 55;
43  else
44  x -= '0';
45  return x;
46 }
47 
48 static int xbm_decode_frame(AVCodecContext *avctx, void *data,
49  int *got_frame, AVPacket *avpkt)
50 {
51  AVFrame *p = avctx->coded_frame;
52  const uint8_t *end, *ptr = avpkt->data;
53  uint8_t *dst;
54  int ret, linesize, i, j;
55 
56  end = avpkt->data + avpkt->size;
57  while (!avctx->width || !avctx->height) {
58  char name[256];
59  int number, len;
60 
61  ptr += strcspn(ptr, "#");
62  if (sscanf(ptr, "#define %255s %u", name, &number) != 2) {
63  av_log(avctx, AV_LOG_ERROR, "Unexpected preprocessor directive\n");
64  return AVERROR_INVALIDDATA;
65  }
66 
67  len = strlen(name);
68  if ((len > 6) && !avctx->height && !memcmp(name + len - 7, "_height", 7)) {
69  avctx->height = number;
70  } else if ((len > 5) && !avctx->width && !memcmp(name + len - 6, "_width", 6)) {
71  avctx->width = number;
72  } else {
73  av_log(avctx, AV_LOG_ERROR, "Unknown define '%s'\n", name);
74  return AVERROR_INVALIDDATA;
75  }
76  ptr += strcspn(ptr, "\n\r") + 1;
77  }
78 
80 
81  if (p->data[0])
82  avctx->release_buffer(avctx, p);
83 
84  p->reference = 0;
85  if ((ret = ff_get_buffer(avctx, p)) < 0)
86  return ret;
87 
88  // goto start of image data
89  ptr += strcspn(ptr, "{") + 1;
90 
91  linesize = (avctx->width + 7) / 8;
92  for (i = 0; i < avctx->height; i++) {
93  dst = p->data[0] + i * p->linesize[0];
94  for (j = 0; j < linesize; j++) {
95  uint8_t val;
96 
97  ptr += strcspn(ptr, "x") + 1;
98  if (ptr < end && av_isxdigit(*ptr)) {
99  val = convert(*ptr);
100  ptr++;
101  if (av_isxdigit(*ptr))
102  val = (val << 4) + convert(*ptr);
103  *dst++ = ff_reverse[val];
104  } else {
105  av_log(avctx, AV_LOG_ERROR, "Unexpected data at '%.8s'\n", ptr);
106  return AVERROR_INVALIDDATA;
107  }
108  }
109  }
110 
111  p->key_frame = 1;
113 
114  *got_frame = 1;
115  *(AVFrame *)data = *p;
116 
117  return avpkt->size;
118 }
119 
121 {
122  if (avctx->coded_frame->data[0])
123  avctx->release_buffer(avctx, avctx->coded_frame);
124 
125  av_freep(&avctx->coded_frame);
126 
127  return 0;
128 }
129 
131  .name = "xbm",
132  .type = AVMEDIA_TYPE_VIDEO,
133  .id = AV_CODEC_ID_XBM,
134  .init = xbm_decode_init,
135  .close = xbm_decode_close,
136  .decode = xbm_decode_frame,
137  .capabilities = CODEC_CAP_DR1,
138  .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"),
139 };