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 
28 {
30  if (!avctx->coded_frame)
31  return AVERROR(ENOMEM);
32 
33  return 0;
34 }
35 
36 static int convert(uint8_t x)
37 {
38  if (x >= 'a')
39  x -= 87;
40  else if (x >= 'A')
41  x -= 55;
42  else
43  x -= '0';
44  return x;
45 }
46 
47 static int xbm_decode_frame(AVCodecContext *avctx, void *data,
48  int *got_frame, AVPacket *avpkt)
49 {
50  AVFrame *p = avctx->coded_frame;
51  const uint8_t *end, *ptr = avpkt->data;
52  uint8_t *dst;
53  int ret, linesize, i, j;
54 
55  end = avpkt->data + avpkt->size;
56  while (!avctx->width || !avctx->height) {
57  char name[256];
58  int number, len;
59 
60  ptr += strcspn(ptr, "#");
61  if (sscanf(ptr, "#define %255s %u", name, &number) != 2) {
62  av_log(avctx, AV_LOG_ERROR, "Unexpected preprocessor directive\n");
63  return AVERROR_INVALIDDATA;
64  }
65 
66  len = strlen(name);
67  if ((len > 6) && !avctx->height && !memcmp(name + len - 7, "_height", 7)) {
68  avctx->height = number;
69  } else if ((len > 5) && !avctx->width && !memcmp(name + len - 6, "_width", 6)) {
70  avctx->width = number;
71  } else {
72  av_log(avctx, AV_LOG_ERROR, "Unknown define '%s'\n", name);
73  return AVERROR_INVALIDDATA;
74  }
75  ptr += strcspn(ptr, "\n\r") + 1;
76  }
77 
79 
80  if (p->data[0])
81  avctx->release_buffer(avctx, p);
82 
83  p->reference = 0;
84  if ((ret = ff_get_buffer(avctx, p)) < 0)
85  return ret;
86 
87  // goto start of image data
88  ptr += strcspn(ptr, "{") + 1;
89 
90  linesize = (avctx->width + 7) / 8;
91  for (i = 0; i < avctx->height; i++) {
92  dst = p->data[0] + i * p->linesize[0];
93  for (j = 0; j < linesize; j++) {
94  uint8_t val;
95 
96  ptr += strcspn(ptr, "x") + 1;
97  if (ptr < end && isxdigit(*ptr)) {
98  val = convert(*ptr);
99  ptr++;
100  if (isxdigit(*ptr))
101  val = (val << 4) + convert(*ptr);
102  *dst++ = ff_reverse[val];
103  } else {
104  av_log(avctx, AV_LOG_ERROR, "Unexpected data at '%.8s'\n", ptr);
105  return AVERROR_INVALIDDATA;
106  }
107  }
108  }
109 
110  p->key_frame = 1;
112 
113  *got_frame = 1;
114  *(AVFrame *)data = *p;
115 
116  return avpkt->size;
117 }
118 
120 {
121  if (avctx->coded_frame->data[0])
122  avctx->release_buffer(avctx, avctx->coded_frame);
123 
124  av_freep(&avctx->coded_frame);
125 
126  return 0;
127 }
128 
130  .name = "xbm",
131  .type = AVMEDIA_TYPE_VIDEO,
132  .id = AV_CODEC_ID_XBM,
133  .init = xbm_decode_init,
134  .close = xbm_decode_close,
135  .decode = xbm_decode_frame,
136  .capabilities = CODEC_CAP_DR1,
137  .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"),
138 };