FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dxtory.c
Go to the documentation of this file.
1 /*
2  * Dxtory decoder
3  *
4  * Copyright (c) 2011 Konstantin Shishkov
5  *
6  * This file is part of Libav.
7  *
8  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #define BITSTREAM_READER_LE
24 #include "avcodec.h"
25 #include "bytestream.h"
26 #include "get_bits.h"
27 #include "internal.h"
28 #include "unary.h"
29 #include "libavutil/common.h"
30 #include "libavutil/intreadwrite.h"
31 
32 static int dxtory_decode_v1(AVCodecContext *avctx, AVFrame *pic,
33  const uint8_t *src, int src_size)
34 {
35  int h, w;
36  uint8_t *Y1, *Y2, *U, *V;
37  int ret;
38 
39  if (src_size < avctx->width * avctx->height * 3 / 2) {
40  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
41  return AVERROR_INVALIDDATA;
42  }
43 
44  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
45  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
46  return ret;
47 
48  Y1 = pic->data[0];
49  Y2 = pic->data[0] + pic->linesize[0];
50  U = pic->data[1];
51  V = pic->data[2];
52  for (h = 0; h < avctx->height; h += 2) {
53  for (w = 0; w < avctx->width; w += 2) {
54  AV_COPY16(Y1 + w, src);
55  AV_COPY16(Y2 + w, src + 2);
56  U[w >> 1] = src[4] + 0x80;
57  V[w >> 1] = src[5] + 0x80;
58  src += 6;
59  }
60  Y1 += pic->linesize[0] << 1;
61  Y2 += pic->linesize[0] << 1;
62  U += pic->linesize[1];
63  V += pic->linesize[2];
64  }
65 
66  return 0;
67 }
68 
69 const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF };
70 
71 static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8])
72 {
73  uint8_t c, val;
74 
75  c = get_unary(gb, 0, 8);
76  if (!c) {
77  val = get_bits(gb, 8);
78  memmove(lru + 1, lru, sizeof(*lru) * (8 - 1));
79  } else {
80  val = lru[c - 1];
81  memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
82  }
83  lru[0] = val;
84 
85  return val;
86 }
87 
88 static int dx2_decode_slice(GetBitContext *gb, int width, int height,
89  uint8_t *Y, uint8_t *U, uint8_t *V,
90  int ystride, int ustride, int vstride)
91 {
92  int x, y, i;
93  uint8_t lru[3][8];
94 
95  for (i = 0; i < 3; i++)
96  memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
97 
98  for (y = 0; y < height; y+=2) {
99  for (x = 0; x < width; x += 2) {
100  Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]);
101  Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]);
102  Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]);
103  Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]);
104  U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
105  V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
106  }
107 
108  Y += ystride << 1;
109  U += ustride;
110  V += vstride;
111  }
112 
113  return 0;
114 }
115 
116 static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic,
117  const uint8_t *src, int src_size)
118 {
119  GetByteContext gb;
120  GetBitContext gb2;
121  int nslices, slice, slice_height;
122  uint32_t off, slice_size;
123  uint8_t *Y, *U, *V;
124  int ret;
125 
126  bytestream2_init(&gb, src, src_size);
127  nslices = bytestream2_get_le16(&gb);
128  off = FFALIGN(nslices * 4 + 2, 16);
129  if (src_size < off) {
130  av_log(avctx, AV_LOG_ERROR, "no slice data\n");
131  return AVERROR_INVALIDDATA;
132  }
133 
134  if (!nslices || avctx->height % nslices) {
135  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
136  avctx->width, avctx->height);
137  return AVERROR(ENOSYS);
138  }
139 
140  slice_height = avctx->height / nslices;
141  if ((avctx->width & 1) || (slice_height & 1)) {
142  avpriv_request_sample(avctx, "slice dimensions %dx%d",
143  avctx->width, slice_height);
144  }
145 
146  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
147  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
148  return ret;
149 
150  Y = pic->data[0];
151  U = pic->data[1];
152  V = pic->data[2];
153 
154  for (slice = 0; slice < nslices; slice++) {
155  slice_size = bytestream2_get_le32(&gb);
156  if (slice_size > src_size - off) {
157  av_log(avctx, AV_LOG_ERROR,
158  "invalid slice size %d (only %d bytes left)\n",
159  slice_size, src_size - off);
160  return AVERROR_INVALIDDATA;
161  }
162  if (slice_size <= 16) {
163  av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
164  return AVERROR_INVALIDDATA;
165  }
166 
167  if (AV_RL32(src + off) != slice_size - 16) {
168  av_log(avctx, AV_LOG_ERROR,
169  "Slice sizes mismatch: got %d instead of %d\n",
170  AV_RL32(src + off), slice_size - 16);
171  }
172  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
173  dx2_decode_slice(&gb2, avctx->width, slice_height, Y, U, V,
174  pic->linesize[0], pic->linesize[1], pic->linesize[2]);
175 
176  Y += pic->linesize[0] * slice_height;
177  U += pic->linesize[1] * (slice_height >> 1);
178  V += pic->linesize[2] * (slice_height >> 1);
179  off += slice_size;
180  }
181 
182  return 0;
183 }
184 
185 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
186  AVPacket *avpkt)
187 {
188  AVFrame *pic = data;
189  const uint8_t *src = avpkt->data;
190  int ret;
191 
192  if (avpkt->size < 16) {
193  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
194  return AVERROR_INVALIDDATA;
195  }
196 
197  switch (AV_RB32(src)) {
198  case 0x02000001:
199  ret = dxtory_decode_v1(avctx, pic, src + 16, avpkt->size - 16);
200  break;
201  case 0x02000009:
202  ret = dxtory_decode_v2(avctx, pic, src + 16, avpkt->size - 16);
203  break;
204  default:
205  avpriv_request_sample(avctx, "Frame header %X", AV_RB32(src));
206  return AVERROR_PATCHWELCOME;
207  }
208 
209  if (ret)
210  return ret;
211 
213  pic->key_frame = 1;
214  *got_frame = 1;
215 
216  return avpkt->size;
217 }
218 
220  .name = "dxtory",
221  .long_name = NULL_IF_CONFIG_SMALL("Dxtory"),
222  .type = AVMEDIA_TYPE_VIDEO,
223  .id = AV_CODEC_ID_DXTORY,
224  .decode = decode_frame,
225  .capabilities = CODEC_CAP_DR1,
226 };