FFmpeg  4.3.9
mvha.c
Go to the documentation of this file.
1 /*
2  * MidiVid Archive codec
3  *
4  * Copyright (c) 2019 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 <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #define CACHED_BITSTREAM_READER !ARCH_X86_32
28 #include "libavutil/intreadwrite.h"
29 
30 #include "avcodec.h"
31 #include "bytestream.h"
32 #include "get_bits.h"
33 #include "internal.h"
34 #include "lossless_videodsp.h"
35 
36 #include <zlib.h>
37 
38 typedef struct MVHAContext {
41 
42  uint8_t symb[256];
43  uint32_t prob[256];
45 
46  z_stream zstream;
48 } MVHAContext;
49 
50 typedef struct Node {
51  int16_t sym;
52  int16_t n0;
53  int16_t l, r;
54  uint32_t count;
55 } Node;
56 
57 static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat,
58  Node *nodes, int node,
59  uint32_t pfx, int pl, int *pos)
60 {
61  int s;
62 
63  s = nodes[node].sym;
64  if (s != -1) {
65  bits[*pos] = (~pfx) & ((1ULL << FFMAX(pl, 1)) - 1);
66  lens[*pos] = FFMAX(pl, 1);
67  xlat[*pos] = s + (pl == 0);
68  (*pos)++;
69  } else {
70  pfx <<= 1;
71  pl++;
72  get_tree_codes(bits, lens, xlat, nodes, nodes[node].l, pfx, pl,
73  pos);
74  pfx |= 1;
75  get_tree_codes(bits, lens, xlat, nodes, nodes[node].r, pfx, pl,
76  pos);
77  }
78 }
79 
80 static int build_vlc(AVCodecContext *avctx, VLC *vlc)
81 {
82  MVHAContext *s = avctx->priv_data;
83  Node nodes[512];
84  uint32_t bits[256];
85  int16_t lens[256];
86  uint8_t xlat[256];
87  int cur_node, i, j, pos = 0;
88 
89  ff_free_vlc(vlc);
90 
91  for (i = 0; i < s->nb_symbols; i++) {
92  nodes[i].count = s->prob[i];
93  nodes[i].sym = s->symb[i];
94  nodes[i].n0 = -2;
95  nodes[i].l = i;
96  nodes[i].r = i;
97  }
98 
99  cur_node = s->nb_symbols;
100  j = 0;
101  do {
102  for (i = 0; ; i++) {
103  int new_node = j;
104  int first_node = cur_node;
105  int second_node = cur_node;
106  unsigned nd, st;
107 
108  nodes[cur_node].count = -1;
109 
110  do {
111  int val = nodes[new_node].count;
112  if (val && (val < nodes[first_node].count)) {
113  if (val >= nodes[second_node].count) {
114  first_node = new_node;
115  } else {
116  first_node = second_node;
117  second_node = new_node;
118  }
119  }
120  new_node += 1;
121  } while (new_node != cur_node);
122 
123  if (first_node == cur_node)
124  break;
125 
126  nd = nodes[second_node].count;
127  st = nodes[first_node].count;
128  nodes[second_node].count = 0;
129  nodes[first_node].count = 0;
130  if (nd >= UINT32_MAX - st) {
131  av_log(avctx, AV_LOG_ERROR, "count overflow\n");
132  return AVERROR_INVALIDDATA;
133  }
134  nodes[cur_node].count = nd + st;
135  nodes[cur_node].sym = -1;
136  nodes[cur_node].n0 = cur_node;
137  nodes[cur_node].l = first_node;
138  nodes[cur_node].r = second_node;
139  cur_node++;
140  }
141  j++;
142  } while (cur_node - s->nb_symbols == j);
143 
144  get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos);
145 
146  return ff_init_vlc_sparse(vlc, 12, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0);
147 }
148 
149 static int decode_frame(AVCodecContext *avctx,
150  void *data, int *got_frame,
151  AVPacket *avpkt)
152 {
153  MVHAContext *s = avctx->priv_data;
154  AVFrame *frame = data;
155  uint32_t type, size;
156  int ret;
157 
158  if (avpkt->size <= 8)
159  return AVERROR_INVALIDDATA;
160 
161  type = AV_RB32(avpkt->data);
162  size = AV_RL32(avpkt->data + 4);
163 
164  if (size < 1 || size >= avpkt->size)
165  return AVERROR_INVALIDDATA;
166 
167  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
168  return ret;
169 
170  if (type == MKTAG('L','Z','Y','V')) {
171  ret = inflateReset(&s->zstream);
172  if (ret != Z_OK) {
173  av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
174  return AVERROR_EXTERNAL;
175  }
176 
177  s->zstream.next_in = avpkt->data + 8;
178  s->zstream.avail_in = avpkt->size - 8;
179 
180  for (int p = 0; p < 3; p++) {
181  for (int y = 0; y < avctx->height; y++) {
182  s->zstream.next_out = frame->data[p] + (avctx->height - y - 1) * frame->linesize[p];
183  s->zstream.avail_out = avctx->width >> (p > 0);
184 
185  ret = inflate(&s->zstream, Z_SYNC_FLUSH);
186  if (ret != Z_OK && ret != Z_STREAM_END) {
187  av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret);
188  return AVERROR_EXTERNAL;
189  }
190  if (s->zstream.avail_out > 0)
191  memset(s->zstream.next_out, 0, s->zstream.avail_out);
192  }
193  }
194  } else if (type == MKTAG('H','U','F','Y')) {
195  GetBitContext *gb = &s->gb;
196  int first_symbol, symbol;
197 
198  ret = init_get_bits8(gb, avpkt->data + 8, avpkt->size - 8);
199  if (ret < 0)
200  return ret;
201 
202  skip_bits(gb, 24);
203 
204  first_symbol = get_bits(gb, 8);
205  s->nb_symbols = get_bits(gb, 8) + 1;
206 
207  symbol = first_symbol;
208  for (int i = 0; i < s->nb_symbols; symbol++) {
209  int prob;
210 
211  if (get_bits_left(gb) < 4)
212  return AVERROR_INVALIDDATA;
213 
214  if (get_bits1(gb)) {
215  prob = get_bits(gb, 12);
216  } else {
217  prob = get_bits(gb, 3);
218  }
219 
220  if (prob) {
221  s->symb[i] = symbol;
222  s->prob[i] = prob;
223  i++;
224  }
225  }
226 
227  ret = build_vlc(avctx, &s->vlc);
228  if (ret < 0)
229  return ret;
230 
231  for (int p = 0; p < 3; p++) {
232  int width = avctx->width >> (p > 0);
233  ptrdiff_t stride = frame->linesize[p];
234  uint8_t *dst;
235 
236  dst = frame->data[p] + (avctx->height - 1) * frame->linesize[p];
237  for (int y = 0; y < avctx->height; y++) {
238  if (get_bits_left(gb) < width)
239  return AVERROR_INVALIDDATA;
240  for (int x = 0; x < width; x++) {
241  int v = get_vlc2(gb, s->vlc.table, s->vlc.bits, 3);
242 
243  if (v < 0)
244  return AVERROR_INVALIDDATA;
245 
246  dst[x] = v;
247  }
248  dst -= stride;
249  }
250  }
251  } else {
252  return AVERROR_INVALIDDATA;
253  }
254 
255  for (int p = 0; p < 3; p++) {
256  int left, lefttop;
257  int width = avctx->width >> (p > 0);
258  ptrdiff_t stride = frame->linesize[p];
259  uint8_t *dst;
260 
261  dst = frame->data[p] + (avctx->height - 1) * frame->linesize[p];
262  s->llviddsp.add_left_pred(dst, dst, width, 0);
263  if (avctx->height > 1) {
264  dst -= stride;
265  lefttop = left = dst[0];
266  for (int y = 1; y < avctx->height; y++) {
267  s->llviddsp.add_median_pred(dst, dst + stride, dst, width, &left, &lefttop);
268  lefttop = left = dst[0];
269  dst -= stride;
270  }
271  }
272  }
273 
274  frame->pict_type = AV_PICTURE_TYPE_I;
275  frame->key_frame = 1;
276  *got_frame = 1;
277 
278  return avpkt->size;
279 }
280 
282 {
283  MVHAContext *s = avctx->priv_data;
284  int zret;
285 
286  avctx->pix_fmt = AV_PIX_FMT_YUV422P;
287 
288  s->zstream.zalloc = Z_NULL;
289  s->zstream.zfree = Z_NULL;
290  s->zstream.opaque = Z_NULL;
291  zret = inflateInit(&s->zstream);
292  if (zret != Z_OK) {
293  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
294  return AVERROR_EXTERNAL;
295  }
296 
298 
299  return 0;
300 }
301 
303 {
304  MVHAContext *s = avctx->priv_data;
305 
306  inflateEnd(&s->zstream);
307  ff_free_vlc(&s->vlc);
308 
309  return 0;
310 }
311 
313  .name = "mvha",
314  .long_name = NULL_IF_CONFIG_SMALL("MidiVid Archive Codec"),
315  .type = AVMEDIA_TYPE_VIDEO,
316  .id = AV_CODEC_ID_MVHA,
317  .priv_data_size = sizeof(MVHAContext),
318  .init = decode_init,
319  .close = decode_close,
320  .decode = decode_frame,
321  .capabilities = AV_CODEC_CAP_DR1,
322  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
324 };
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: internal.h:48
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int(* add_left_pred)(uint8_t *dst, const uint8_t *src, ptrdiff_t w, int left)
VLC vlc
Definition: mvha.c:44
int size
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:379
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, const void *bits, int bits_wrap, int bits_size, const void *codes, int codes_wrap, int codes_size, const void *symbols, int symbols_wrap, int symbols_size, int flags)
Definition: bitstream.c:273
int size
Definition: packet.h:356
z_stream zstream
Definition: mvha.c:46
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:736
uint8_t symb[256]
Definition: mvha.c:42
int stride
Definition: mace.c:144
AVCodec.
Definition: codec.h:190
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
Definition: agm.c:913
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: internal.h:40
uint8_t
#define av_cold
Definition: attributes.h:88
LLVidDSPContext llviddsp
Definition: mvha.c:47
#define AV_RB32
Definition: intreadwrite.h:130
static AVFrame * frame
const char data[16]
Definition: mxf.c:91
uint8_t * data
Definition: packet.h:355
void(* add_median_pred)(uint8_t *dst, const uint8_t *top, const uint8_t *diff, ptrdiff_t w, int *left, int *left_top)
bitstream reader API header.
static av_cold int decode_close(AVCodecContext *avctx)
Definition: mvha.c:302
#define av_log(a,...)
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:849
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
GetBitContext gb
Definition: mvha.c:39
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:188
const char * r
Definition: vf_curves.c:114
unsigned int pos
Definition: spdifenc.c:412
const char * name
Name of the codec implementation.
Definition: codec.h:197
uint8_t bits
Definition: vp3data.h:202
#define FFMAX(a, b)
Definition: common.h:94
AVCodec ff_mvha_decoder
Definition: mvha.c:312
Definition: vlc.h:26
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
int16_t r
Definition: mvha.c:53
static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, Node *nodes, int node, uint32_t pfx, int pl, int *pos)
Definition: mvha.c:57
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:383
int nb_symbols
Definition: mvha.c:40
int16_t l
Definition: mvha.c:53
#define width
int width
picture width / height.
Definition: avcodec.h:699
#define s(width, name)
Definition: cbs_vp9.c:257
static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE(*table)[2], int bits, int max_depth)
Parse a vlc code.
Definition: get_bits.h:797
#define AV_RL32
Definition: intreadwrite.h:146
int bits
Definition: vlc.h:27
Libavcodec external API header.
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: mvha.c:149
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:331
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:677
main external API structure.
Definition: avcodec.h:526
static int build_vlc(AVCodecContext *avctx, VLC *vlc)
Definition: mvha.c:80
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1854
void ff_llviddsp_init(LLVidDSPContext *c)
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
static void skip_bits(GetBitContext *s, int n)
Definition: get_bits.h:467
int16_t n0
Definition: huffman.h:34
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
Definition: vf_neighbor.c:198
cl_device_type type
int16_t sym
Definition: huffman.h:33
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:314
common internal api header.
void * priv_data
Definition: avcodec.h:553
VLC_TYPE(* table)[2]
code, bits
Definition: vlc.h:28
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:378
uint32_t count
Definition: huffman.h:35
#define MKTAG(a, b, c, d)
Definition: common.h:406
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
static double val(void *priv, double ch)
Definition: aeval.c:76
This structure stores compressed data.
Definition: packet.h:332
uint32_t prob[256]
Definition: mvha.c:43
void ff_free_vlc(VLC *vlc)
Definition: bitstream.c:359
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:50
for(j=16;j >0;--j)
static av_cold int decode_init(AVCodecContext *avctx)
Definition: mvha.c:281