FFmpeg
hapdec.c
Go to the documentation of this file.
1 /*
2  * Vidvox Hap decoder
3  * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
4  * Copyright (C) 2015 Tom Butterworth <bangnoise@gmail.com>
5  *
6  * HapQA and HAPAlphaOnly added by Jokyo Images
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 /**
26  * @file
27  * Hap decoder
28  *
29  * Fourcc: Hap1, Hap5, HapY, HapA, HapM
30  *
31  * https://github.com/Vidvox/hap/blob/master/documentation/HapVideoDRAFT.md
32  */
33 
34 #include <stdint.h>
35 
36 #include "libavutil/imgutils.h"
37 
38 #include "avcodec.h"
39 #include "bytestream.h"
40 #include "hap.h"
41 #include "internal.h"
42 #include "snappy.h"
43 #include "texturedsp.h"
44 #include "thread.h"
45 
47 {
48  GetByteContext *gbc = &ctx->gbc;
49  int section_size;
50  enum HapSectionType section_type;
51  int is_first_table = 1, had_offsets = 0, had_compressors = 0, had_sizes = 0;
52  int i, ret;
53 
54  while (size > 0) {
55  int stream_remaining = bytestream2_get_bytes_left(gbc);
56  ret = ff_hap_parse_section_header(gbc, &section_size, &section_type);
57  if (ret != 0)
58  return ret;
59 
60  size -= stream_remaining - bytestream2_get_bytes_left(gbc);
61 
62  switch (section_type) {
64  ret = ff_hap_set_chunk_count(ctx, section_size, is_first_table);
65  if (ret != 0)
66  return ret;
67  for (i = 0; i < section_size; i++) {
68  ctx->chunks[i].compressor = bytestream2_get_byte(gbc) << 4;
69  }
70  had_compressors = 1;
71  is_first_table = 0;
72  break;
73  case HAP_ST_SIZE_TABLE:
74  ret = ff_hap_set_chunk_count(ctx, section_size / 4, is_first_table);
75  if (ret != 0)
76  return ret;
77  for (i = 0; i < section_size / 4; i++) {
78  ctx->chunks[i].compressed_size = bytestream2_get_le32(gbc);
79  }
80  had_sizes = 1;
81  is_first_table = 0;
82  break;
84  ret = ff_hap_set_chunk_count(ctx, section_size / 4, is_first_table);
85  if (ret != 0)
86  return ret;
87  for (i = 0; i < section_size / 4; i++) {
88  ctx->chunks[i].compressed_offset = bytestream2_get_le32(gbc);
89  }
90  had_offsets = 1;
91  is_first_table = 0;
92  break;
93  default:
94  break;
95  }
96  size -= section_size;
97  }
98 
99  if (!had_sizes || !had_compressors)
100  return AVERROR_INVALIDDATA;
101 
102  /* The offsets table is optional. If not present than calculate offsets by
103  * summing the sizes of preceding chunks. */
104  if (!had_offsets) {
105  size_t running_size = 0;
106  for (i = 0; i < ctx->chunk_count; i++) {
107  ctx->chunks[i].compressed_offset = running_size;
108  running_size += ctx->chunks[i].compressed_size;
109  }
110  }
111 
112  return 0;
113 }
114 
116 {
117  int i;
118  size_t running_offset = 0;
119  for (i = 0; i < ctx->chunk_count; i++) {
120  if (ctx->chunks[i].compressed_offset != running_offset
121  || ctx->chunks[i].compressor != HAP_COMP_NONE)
122  return 0;
123  running_offset += ctx->chunks[i].compressed_size;
124  }
125  return 1;
126 }
127 
129 {
130  HapContext *ctx = avctx->priv_data;
131  GetByteContext *gbc = &ctx->gbc;
132  int section_size;
133  enum HapSectionType section_type;
134  const char *compressorstr;
135  int i, ret;
136 
137  ret = ff_hap_parse_section_header(gbc, &ctx->texture_section_size, &section_type);
138  if (ret != 0)
139  return ret;
140 
141  if ((avctx->codec_tag == MKTAG('H','a','p','1') && (section_type & 0x0F) != HAP_FMT_RGBDXT1) ||
142  (avctx->codec_tag == MKTAG('H','a','p','5') && (section_type & 0x0F) != HAP_FMT_RGBADXT5) ||
143  (avctx->codec_tag == MKTAG('H','a','p','Y') && (section_type & 0x0F) != HAP_FMT_YCOCGDXT5) ||
144  (avctx->codec_tag == MKTAG('H','a','p','A') && (section_type & 0x0F) != HAP_FMT_RGTC1) ||
145  ((avctx->codec_tag == MKTAG('H','a','p','M') && (section_type & 0x0F) != HAP_FMT_RGTC1) &&
146  (section_type & 0x0F) != HAP_FMT_YCOCGDXT5)) {
147  av_log(avctx, AV_LOG_ERROR,
148  "Invalid texture format %#04x.\n", section_type & 0x0F);
149  return AVERROR_INVALIDDATA;
150  }
151 
152  switch (section_type & 0xF0) {
153  case HAP_COMP_NONE:
154  case HAP_COMP_SNAPPY:
155  ret = ff_hap_set_chunk_count(ctx, 1, 1);
156  if (ret == 0) {
157  ctx->chunks[0].compressor = section_type & 0xF0;
158  ctx->chunks[0].compressed_offset = 0;
160  }
161  if (ctx->chunks[0].compressor == HAP_COMP_NONE) {
162  compressorstr = "none";
163  } else {
164  compressorstr = "snappy";
165  }
166  break;
167  case HAP_COMP_COMPLEX:
168  ret = ff_hap_parse_section_header(gbc, &section_size, &section_type);
169  if (ret == 0 && section_type != HAP_ST_DECODE_INSTRUCTIONS)
170  ret = AVERROR_INVALIDDATA;
171  if (ret == 0)
172  ret = hap_parse_decode_instructions(ctx, section_size);
173  compressorstr = "complex";
174  break;
175  default:
176  ret = AVERROR_INVALIDDATA;
177  break;
178  }
179 
180  if (ret != 0)
181  return ret;
182 
183  /* Check the frame is valid and read the uncompressed chunk sizes */
184  ctx->tex_size = 0;
185  for (i = 0; i < ctx->chunk_count; i++) {
186  HapChunk *chunk = &ctx->chunks[i];
187 
188  /* Check the compressed buffer is valid */
190  return AVERROR_INVALIDDATA;
191 
192  /* Chunks are unpacked sequentially, ctx->tex_size is the uncompressed
193  * size thus far */
194  chunk->uncompressed_offset = ctx->tex_size;
195 
196  /* Fill out uncompressed size */
197  if (chunk->compressor == HAP_COMP_SNAPPY) {
198  GetByteContext gbc_tmp;
199  int64_t uncompressed_size;
200  bytestream2_init(&gbc_tmp, gbc->buffer + chunk->compressed_offset,
201  chunk->compressed_size);
202  uncompressed_size = ff_snappy_peek_uncompressed_length(&gbc_tmp);
203  if (uncompressed_size < 0) {
204  return uncompressed_size;
205  }
206  chunk->uncompressed_size = uncompressed_size;
207  } else if (chunk->compressor == HAP_COMP_NONE) {
208  chunk->uncompressed_size = chunk->compressed_size;
209  } else {
210  return AVERROR_INVALIDDATA;
211  }
212  ctx->tex_size += chunk->uncompressed_size;
213  }
214 
215  av_log(avctx, AV_LOG_DEBUG, "%s compressor\n", compressorstr);
216 
217  return ret;
218 }
219 
220 static int decompress_chunks_thread(AVCodecContext *avctx, void *arg,
221  int chunk_nb, int thread_nb)
222 {
223  HapContext *ctx = avctx->priv_data;
224 
225  HapChunk *chunk = &ctx->chunks[chunk_nb];
226  GetByteContext gbc;
227  uint8_t *dst = ctx->tex_buf + chunk->uncompressed_offset;
228 
229  bytestream2_init(&gbc, ctx->gbc.buffer + chunk->compressed_offset, chunk->compressed_size);
230 
231  if (chunk->compressor == HAP_COMP_SNAPPY) {
232  int ret;
233  int64_t uncompressed_size = ctx->tex_size;
234 
235  /* Uncompress the frame */
236  ret = ff_snappy_uncompress(&gbc, dst, &uncompressed_size);
237  if (ret < 0) {
238  av_log(avctx, AV_LOG_ERROR, "Snappy uncompress error\n");
239  return ret;
240  }
241  } else if (chunk->compressor == HAP_COMP_NONE) {
242  bytestream2_get_buffer(&gbc, dst, chunk->compressed_size);
243  }
244 
245  return 0;
246 }
247 
249  int slice, int thread_nb, int texture_num)
250 {
251  HapContext *ctx = avctx->priv_data;
252  AVFrame *frame = arg;
253  const uint8_t *d = ctx->tex_data;
254  int w_block = avctx->coded_width / TEXTURE_BLOCK_W;
255  int h_block = avctx->coded_height / TEXTURE_BLOCK_H;
256  int x, y;
257  int start_slice, end_slice;
258  int base_blocks_per_slice = h_block / ctx->slice_count;
259  int remainder_blocks = h_block % ctx->slice_count;
260 
261  /* When the frame height (in blocks) doesn't divide evenly between the
262  * number of slices, spread the remaining blocks evenly between the first
263  * operations */
264  start_slice = slice * base_blocks_per_slice;
265  /* Add any extra blocks (one per slice) that have been added before this slice */
266  start_slice += FFMIN(slice, remainder_blocks);
267 
268  end_slice = start_slice + base_blocks_per_slice;
269  /* Add an extra block if there are still remainder blocks to be accounted for */
270  if (slice < remainder_blocks)
271  end_slice++;
272 
273  for (y = start_slice; y < end_slice; y++) {
274  uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H;
275  int off = y * w_block;
276  for (x = 0; x < w_block; x++) {
277  if (texture_num == 0) {
278  ctx->tex_fun(p + x * 4 * ctx->uncompress_pix_size, frame->linesize[0],
279  d + (off + x) * ctx->tex_rat);
280  } else {
281  ctx->tex_fun2(p + x * 4 * ctx->uncompress_pix_size, frame->linesize[0],
282  d + (off + x) * ctx->tex_rat2);
283  }
284  }
285  }
286 
287  return 0;
288 }
289 
291  int slice, int thread_nb)
292 {
293  return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 0);
294 }
295 
297  int slice, int thread_nb)
298 {
299  return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 1);
300 }
301 
302 static int hap_decode(AVCodecContext *avctx, void *data,
303  int *got_frame, AVPacket *avpkt)
304 {
305  HapContext *ctx = avctx->priv_data;
306  ThreadFrame tframe;
307  int ret, i, t;
308  int tex_size;
309  int section_size;
310  enum HapSectionType section_type;
311  int start_texture_section = 0;
312  int tex_rat[2] = {0, 0};
313 
314  bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size);
315 
316  tex_rat[0] = ctx->tex_rat;
317 
318  /* check for multi texture header */
319  if (ctx->texture_count == 2) {
320  ret = ff_hap_parse_section_header(&ctx->gbc, &section_size, &section_type);
321  if (ret != 0)
322  return ret;
323  if ((section_type & 0x0F) != 0x0D) {
324  av_log(avctx, AV_LOG_ERROR, "Invalid section type in 2 textures mode %#04x.\n", section_type);
325  return AVERROR_INVALIDDATA;
326  }
327  start_texture_section = 4;
328  tex_rat[1] = ctx->tex_rat2;
329  }
330 
331  /* Get the output frame ready to receive data */
332  tframe.f = data;
333  ret = ff_thread_get_buffer(avctx, &tframe, 0);
334  if (ret < 0)
335  return ret;
336 
337  for (t = 0; t < ctx->texture_count; t++) {
338  bytestream2_seek(&ctx->gbc, start_texture_section, SEEK_SET);
339 
340  /* Check for section header */
341  ret = hap_parse_frame_header(avctx);
342  if (ret < 0)
343  return ret;
344 
345  start_texture_section += ctx->texture_section_size + 4;
346 
347  if (avctx->codec->update_thread_context)
348  ff_thread_finish_setup(avctx);
349 
350  /* Unpack the DXT texture */
351  if (hap_can_use_tex_in_place(ctx)) {
352  /* Only DXTC texture compression in a contiguous block */
353  ctx->tex_data = ctx->gbc.buffer;
354  tex_size = FFMIN(ctx->texture_section_size, bytestream2_get_bytes_left(&ctx->gbc));
355  } else {
356  /* Perform the second-stage decompression */
357  ret = av_reallocp(&ctx->tex_buf, ctx->tex_size);
358  if (ret < 0)
359  return ret;
360 
361  avctx->execute2(avctx, decompress_chunks_thread, NULL,
362  ctx->chunk_results, ctx->chunk_count);
363 
364  for (i = 0; i < ctx->chunk_count; i++) {
365  if (ctx->chunk_results[i] < 0)
366  return ctx->chunk_results[i];
367  }
368 
369  ctx->tex_data = ctx->tex_buf;
370  tex_size = ctx->tex_size;
371  }
372 
373  if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W)
374  *(avctx->coded_height / TEXTURE_BLOCK_H)
375  *tex_rat[t]) {
376  av_log(avctx, AV_LOG_ERROR, "Insufficient data\n");
377  return AVERROR_INVALIDDATA;
378  }
379 
380  /* Use the decompress function on the texture, one block per thread */
381  if (t == 0){
382  avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count);
383  } else{
384  tframe.f = data;
385  avctx->execute2(avctx, decompress_texture2_thread, tframe.f, NULL, ctx->slice_count);
386  }
387  }
388 
389  /* Frame is ready to be output */
390  tframe.f->pict_type = AV_PICTURE_TYPE_I;
391  tframe.f->key_frame = 1;
392  *got_frame = 1;
393 
394  return avpkt->size;
395 }
396 
397 static av_cold int hap_init(AVCodecContext *avctx)
398 {
399  HapContext *ctx = avctx->priv_data;
400  const char *texture_name;
401  int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
402 
403  if (ret < 0) {
404  av_log(avctx, AV_LOG_ERROR, "Invalid video size %dx%d.\n",
405  avctx->width, avctx->height);
406  return ret;
407  }
408 
409  /* Since codec is based on 4x4 blocks, size is aligned to 4 */
410  avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W);
411  avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
412 
413  ff_texturedsp_init(&ctx->dxtc);
414 
415  ctx->texture_count = 1;
416  ctx->uncompress_pix_size = 4;
417 
418  switch (avctx->codec_tag) {
419  case MKTAG('H','a','p','1'):
420  texture_name = "DXT1";
421  ctx->tex_rat = 8;
422  ctx->tex_fun = ctx->dxtc.dxt1_block;
423  avctx->pix_fmt = AV_PIX_FMT_RGB0;
424  break;
425  case MKTAG('H','a','p','5'):
426  texture_name = "DXT5";
427  ctx->tex_rat = 16;
428  ctx->tex_fun = ctx->dxtc.dxt5_block;
429  avctx->pix_fmt = AV_PIX_FMT_RGBA;
430  break;
431  case MKTAG('H','a','p','Y'):
432  texture_name = "DXT5-YCoCg-scaled";
433  ctx->tex_rat = 16;
434  ctx->tex_fun = ctx->dxtc.dxt5ys_block;
435  avctx->pix_fmt = AV_PIX_FMT_RGB0;
436  break;
437  case MKTAG('H','a','p','A'):
438  texture_name = "RGTC1";
439  ctx->tex_rat = 8;
440  ctx->tex_fun = ctx->dxtc.rgtc1u_gray_block;
441  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
442  ctx->uncompress_pix_size = 1;
443  break;
444  case MKTAG('H','a','p','M'):
445  texture_name = "DXT5-YCoCg-scaled / RGTC1";
446  ctx->tex_rat = 16;
447  ctx->tex_rat2 = 8;
448  ctx->tex_fun = ctx->dxtc.dxt5ys_block;
449  ctx->tex_fun2 = ctx->dxtc.rgtc1u_alpha_block;
450  avctx->pix_fmt = AV_PIX_FMT_RGBA;
451  ctx->texture_count = 2;
452  break;
453  default:
455  }
456 
457  av_log(avctx, AV_LOG_DEBUG, "%s texture\n", texture_name);
458 
459  ctx->slice_count = av_clip(avctx->thread_count, 1,
460  avctx->coded_height / TEXTURE_BLOCK_H);
461 
462  return 0;
463 }
464 
465 static av_cold int hap_close(AVCodecContext *avctx)
466 {
467  HapContext *ctx = avctx->priv_data;
468 
469  ff_hap_free_context(ctx);
470 
471  return 0;
472 }
473 
475  .name = "hap",
476  .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap"),
477  .type = AVMEDIA_TYPE_VIDEO,
478  .id = AV_CODEC_ID_HAP,
479  .init = hap_init,
480  .decode = hap_decode,
481  .close = hap_close,
482  .priv_data_size = sizeof(HapContext),
485  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
487 };
#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
Definition: hap.h:61
#define NULL
Definition: coverity.c:32
const struct AVCodec * codec
Definition: avcodec.h:1574
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int(* dxt5_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:51
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
HapChunk * chunks
Definition: hap.h:72
static int hap_can_use_tex_in_place(HapContext *ctx)
Definition: hapdec.c:115
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:1753
HapSectionType
Definition: hap.h:46
misc image utilities
AVFrame * f
Definition: thread.h:35
int tex_rat2
Definition: hap.h:76
Texture block (4x4) module.
int size
Definition: avcodec.h:1478
int(* rgtc1u_alpha_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:57
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1775
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
size_t compressed_size
Definition: hap.h:56
int ff_hap_parse_section_header(GetByteContext *gbc, int *section_size, enum HapSectionType *section_type)
Definition: hap.c:57
int compressed_offset
Definition: hap.h:55
AVCodec.
Definition: avcodec.h:3481
size_t uncompressed_size
Definition: hap.h:58
int64_t ff_snappy_peek_uncompressed_length(GetByteContext *gb)
Get the uncompressed length of an input buffer compressed using the Snappy algorithm.
Definition: snappy.c:131
#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:82
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:238
static int hap_parse_decode_instructions(HapContext *ctx, int size)
Definition: hapdec.c:46
Multithreading support functions.
AVCodec ff_hap_decoder
Definition: hapdec.c:474
int ff_hap_set_chunk_count(HapContext *ctx, int count, int first_in_frame)
Definition: hap.c:28
#define TEXTURE_BLOCK_H
Definition: texturedsp.h:43
TextureDSPContext dxtc
Definition: hap.h:64
uint8_t * data
Definition: avcodec.h:1477
const uint8_t * buffer
Definition: bytestream.h:34
static av_cold int hap_init(AVCodecContext *avctx)
Definition: hapdec.c:397
ptrdiff_t size
Definition: opengl_enc.c:100
#define FFALIGN(x, a)
Definition: macros.h:48
GetByteContext gbc
Definition: hap.h:65
#define av_log(a,...)
static int hap_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: hapdec.c:302
int(* dxt5ys_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:53
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int * chunk_results
Definition: hap.h:73
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:263
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
const char * arg
Definition: jacosubdec.c:66
const char * name
Name of the codec implementation.
Definition: avcodec.h:3488
static int decompress_texture_thread_internal(AVCodecContext *avctx, void *arg, int slice, int thread_nb, int texture_num)
Definition: hapdec.c:248
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition: avcodec.h:1037
int ff_snappy_uncompress(GetByteContext *gb, uint8_t *buf, int64_t *size)
Decompress an input buffer using Snappy algorithm.
Definition: snappy.c:141
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
static av_cold int hap_close(AVCodecContext *avctx)
Definition: hapdec.c:465
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:282
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition: texturedsp.c:637
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:378
int uncompressed_offset
Definition: hap.h:57
#define FFMIN(a, b)
Definition: common.h:96
int width
picture width / height.
Definition: avcodec.h:1738
the pkt_dts and pkt_pts fields in AVFrame will work as usual Restrictions on codec whose streams don t reset across will not work because their bitstreams cannot be decoded in parallel *The contents of buffers must not be read before as well as code calling up to before the decode process starts Call ff_thread_finish_setup() afterwards.If some code can't be moved
AVFormatContext * ctx
Definition: movenc.c:48
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
int tex_rat
Definition: hap.h:75
int thread_count
thread count is used to decide how many independent tasks should be passed to execute() ...
Definition: avcodec.h:2824
Snappy decompression.
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: avcodec.h:1041
int(* update_thread_context)(AVCodecContext *dst, const AVCodecContext *src)
Copy necessary context variables from a previous thread context to the current one.
Definition: avcodec.h:3548
int(* execute2)(struct AVCodecContext *c, int(*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count)
The codec may call this to execute several independent things.
Definition: avcodec.h:2884
int(* tex_fun)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: hap.h:90
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
Wrapper around get_buffer() for frame-multithreaded codecs.
av_cold void ff_hap_free_context(HapContext *ctx)
Definition: hap.c:50
main external API structure.
Definition: avcodec.h:1565
const uint8_t * tex_data
Definition: hap.h:77
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> (&#39;D&#39;<<24) + (&#39;C&#39;<<16) + (&#39;B&#39;<<8) + &#39;A&#39;).
Definition: avcodec.h:1590
int chunk_count
Definition: hap.h:71
int(* dxt1_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:46
int coded_height
Definition: avcodec.h:1753
int slice_count
Definition: hap.h:83
static int decompress_texture2_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb)
Definition: hapdec.c:296
static int decompress_chunks_thread(AVCodecContext *avctx, void *arg, int chunk_nb, int thread_nb)
Definition: hapdec.c:220
static int hap_parse_frame_header(AVCodecContext *avctx)
Definition: hapdec.c:128
int(* tex_fun2)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: hap.h:91
static int decompress_texture_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb)
Definition: hapdec.c:290
uint8_t * tex_buf
Definition: hap.h:78
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
Y , 8bpp.
Definition: pixfmt.h:74
common internal api header.
size_t tex_size
Definition: hap.h:79
Definition: hap.h:53
void * priv_data
Definition: avcodec.h:1592
#define AVERROR_DECODER_NOT_FOUND
Decoder not found.
Definition: error.h:52
int texture_section_size
Definition: hap.h:86
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:373
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:208
int uncompress_pix_size
Definition: hap.h:87
int(* rgtc1u_gray_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:56
enum HapCompressor compressor
Definition: hap.h:54
#define MKTAG(a, b, c, d)
Definition: common.h:366
#define TEXTURE_BLOCK_W
Definition: texturedsp.h:42
int texture_count
Definition: hap.h:85
This structure stores compressed data.
Definition: avcodec.h:1454
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:981