mmvideo.c
Go to the documentation of this file.
1 /*
2  * American Laser Games MM Video Decoder
3  * Copyright (c) 2006,2008 Peter Ross
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
34 #include "libavutil/intreadwrite.h"
35 #include "avcodec.h"
36 #include "bytestream.h"
37 
38 #define MM_PREAMBLE_SIZE 6
39 
40 #define MM_TYPE_INTER 0x5
41 #define MM_TYPE_INTRA 0x8
42 #define MM_TYPE_INTRA_HH 0xc
43 #define MM_TYPE_INTER_HH 0xd
44 #define MM_TYPE_INTRA_HHV 0xe
45 #define MM_TYPE_INTER_HHV 0xf
46 #define MM_TYPE_PALETTE 0x31
47 
48 typedef struct MmContext {
53 } MmContext;
54 
56 {
57  MmContext *s = avctx->priv_data;
58 
59  s->avctx = avctx;
60 
61  avctx->pix_fmt = AV_PIX_FMT_PAL8;
62 
63  s->frame.reference = 1;
64 
65  return 0;
66 }
67 
68 static int mm_decode_pal(MmContext *s)
69 {
70  int i;
71 
72  bytestream2_skip(&s->gb, 4);
73  for (i = 0; i < 128; i++) {
74  s->palette[i] = bytestream2_get_be24(&s->gb);
75  s->palette[i+128] = s->palette[i]<<2;
76  }
77 
78  return 0;
79 }
80 
85 static int mm_decode_intra(MmContext * s, int half_horiz, int half_vert)
86 {
87  int x = 0, y = 0;
88 
89  while (bytestream2_get_bytes_left(&s->gb) > 0) {
90  int run_length, color;
91 
92  if (y >= s->avctx->height)
93  return 0;
94 
95  color = bytestream2_get_byte(&s->gb);
96  if (color & 0x80) {
97  run_length = 1;
98  }else{
99  run_length = (color & 0x7f) + 2;
100  color = bytestream2_get_byte(&s->gb);
101  }
102 
103  if (half_horiz)
104  run_length *=2;
105 
106  if (color) {
107  memset(s->frame.data[0] + y*s->frame.linesize[0] + x, color, run_length);
108  if (half_vert)
109  memset(s->frame.data[0] + (y+1)*s->frame.linesize[0] + x, color, run_length);
110  }
111  x+= run_length;
112 
113  if (x >= s->avctx->width) {
114  x=0;
115  y += 1 + half_vert;
116  }
117  }
118 
119  return 0;
120 }
121 
122 /*
123  * @param half_horiz Half horizontal resolution (0 or 1)
124  * @param half_vert Half vertical resolution (0 or 1)
125  */
126 static int mm_decode_inter(MmContext * s, int half_horiz, int half_vert)
127 {
128  int data_off = bytestream2_get_le16(&s->gb), y;
129  GetByteContext data_ptr;
130 
131  if (bytestream2_get_bytes_left(&s->gb) < data_off)
132  return AVERROR_INVALIDDATA;
133 
134  bytestream2_init(&data_ptr, s->gb.buffer + data_off, bytestream2_get_bytes_left(&s->gb) - data_off);
135  while (s->gb.buffer < data_ptr.buffer_start) {
136  int i, j;
137  int length = bytestream2_get_byte(&s->gb);
138  int x = bytestream2_get_byte(&s->gb) + ((length & 0x80) << 1);
139  length &= 0x7F;
140 
141  if (length==0) {
142  y += x;
143  continue;
144  }
145 
146  if (y + half_vert >= s->avctx->height)
147  return 0;
148 
149  for(i=0; i<length; i++) {
150  int replace_array = bytestream2_get_byte(&s->gb);
151  for(j=0; j<8; j++) {
152  int replace = (replace_array >> (7-j)) & 1;
153  if (x + half_horiz >= s->avctx->width)
154  return AVERROR_INVALIDDATA;
155  if (replace) {
156  int color = bytestream2_get_byte(&data_ptr);
157  s->frame.data[0][y*s->frame.linesize[0] + x] = color;
158  if (half_horiz)
159  s->frame.data[0][y*s->frame.linesize[0] + x + 1] = color;
160  if (half_vert) {
161  s->frame.data[0][(y+1)*s->frame.linesize[0] + x] = color;
162  if (half_horiz)
163  s->frame.data[0][(y+1)*s->frame.linesize[0] + x + 1] = color;
164  }
165  }
166  x += 1 + half_horiz;
167  }
168  }
169 
170  y += 1 + half_vert;
171  }
172 
173  return 0;
174 }
175 
176 static int mm_decode_frame(AVCodecContext *avctx,
177  void *data, int *got_frame,
178  AVPacket *avpkt)
179 {
180  const uint8_t *buf = avpkt->data;
181  int buf_size = avpkt->size;
182  MmContext *s = avctx->priv_data;
183  int type, res;
184 
185  if (buf_size < MM_PREAMBLE_SIZE)
186  return AVERROR_INVALIDDATA;
187  type = AV_RL16(&buf[0]);
188  buf += MM_PREAMBLE_SIZE;
189  buf_size -= MM_PREAMBLE_SIZE;
190  bytestream2_init(&s->gb, buf, buf_size);
191 
192  if (avctx->reget_buffer(avctx, &s->frame) < 0) {
193  av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
194  return -1;
195  }
196 
197  switch(type) {
198  case MM_TYPE_PALETTE : res = mm_decode_pal(s); return buf_size;
199  case MM_TYPE_INTRA : res = mm_decode_intra(s, 0, 0); break;
200  case MM_TYPE_INTRA_HH : res = mm_decode_intra(s, 1, 0); break;
201  case MM_TYPE_INTRA_HHV : res = mm_decode_intra(s, 1, 1); break;
202  case MM_TYPE_INTER : res = mm_decode_inter(s, 0, 0); break;
203  case MM_TYPE_INTER_HH : res = mm_decode_inter(s, 1, 0); break;
204  case MM_TYPE_INTER_HHV : res = mm_decode_inter(s, 1, 1); break;
205  default:
206  res = AVERROR_INVALIDDATA;
207  break;
208  }
209  if (res < 0)
210  return res;
211 
212  memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
213 
214  *got_frame = 1;
215  *(AVFrame*)data = s->frame;
216 
217  return buf_size;
218 }
219 
221 {
222  MmContext *s = avctx->priv_data;
223 
224  if(s->frame.data[0])
225  avctx->release_buffer(avctx, &s->frame);
226 
227  return 0;
228 }
229 
231  .name = "mmvideo",
232  .type = AVMEDIA_TYPE_VIDEO,
233  .id = AV_CODEC_ID_MMVIDEO,
234  .priv_data_size = sizeof(MmContext),
235  .init = mm_decode_init,
236  .close = mm_decode_end,
238  .capabilities = CODEC_CAP_DR1,
239  .long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM Video"),
240 };
AVFrame frame
Definition: mmvideo.c:50
static int mm_decode_pal(MmContext *s)
Definition: mmvideo.c:68
This structure describes decoded (raw) audio or video data.
Definition: avcodec.h:989
static int mm_decode_intra(MmContext *s, int half_horiz, int half_vert)
Definition: mmvideo.c:85
void(* release_buffer)(struct AVCodecContext *c, AVFrame *pic)
Called to release buffers which were allocated with get_buffer.
Definition: avcodec.h:2259
int size
Definition: avcodec.h:916
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1533
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:130
#define AV_RL16
Definition: intreadwrite.h:42
#define MM_TYPE_INTER_HH
Definition: mmvideo.c:43
AVCodec.
Definition: avcodec.h:2960
int(* reget_buffer)(struct AVCodecContext *c, AVFrame *pic)
Called at the beginning of a frame to get cr buffer for it.
Definition: avcodec.h:2273
static int decode(MimicContext *ctx, int quality, int num_coeffs, int is_iframe)
Definition: mimic.c:228
uint8_t
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:76
static int mm_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: mmvideo.c:176
const char data[16]
Definition: mxf.c:66
uint8_t * data
Definition: avcodec.h:915
const uint8_t * buffer
Definition: bytestream.h:33
static int init(AVCodecParserContext *s)
Definition: h264_parser.c:335
int palette[AVPALETTE_COUNT]
Definition: mmvideo.c:51
int reference
is this picture used as reference The values for this are the same as the MpegEncContext.picture_structure variable, that is 1->top field, 2->bottom field, 3->frame/both fields.
Definition: avcodec.h:1132
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:159
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:88
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:149
static av_cold int mm_decode_end(AVCodecContext *avctx)
Definition: mmvideo.c:220
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:146
const char * name
Name of the codec implementation.
Definition: avcodec.h:2967
#define MM_PREAMBLE_SIZE
Definition: mmvideo.c:38
int width
picture width / height.
Definition: avcodec.h:1508
#define MM_TYPE_INTER
Definition: mmvideo.c:40
#define MM_TYPE_INTRA_HHV
Definition: mmvideo.c:44
#define MM_TYPE_PALETTE
Definition: mmvideo.c:46
AVCodec ff_mmvideo_decoder
Definition: mmvideo.c:230
static int mm_decode_inter(MmContext *s, int half_horiz, int half_vert)
Definition: mmvideo.c:126
struct MmContext MmContext
#define MM_TYPE_INTRA_HH
Definition: mmvideo.c:42
external API header
int linesize[AV_NUM_DATA_POINTERS]
Size, in bytes, of the data for each picture/channel plane.
Definition: avcodec.h:1008
main external API structure.
Definition: avcodec.h:1339
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:326
static av_cold int mm_decode_init(AVCodecContext *avctx)
Definition: mmvideo.c:55
const uint8_t * buffer_start
Definition: bytestream.h:33
#define MM_TYPE_INTRA
Definition: mmvideo.c:41
#define MM_TYPE_INTER_HHV
Definition: mmvideo.c:45
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: avcodec.h:997
GetByteContext gb
Definition: mmvideo.c:52
AVCodecContext * avctx
Definition: mmvideo.c:49
static const uint8_t color[]
Definition: log.c:52
void * priv_data
Definition: avcodec.h:1382
This structure stores compressed data.
Definition: avcodec.h:898
if(!(ptr_align%ac->ptr_align)&&samples_align >=aligned_len)