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  if (ctx->chunks[i].compressed_size > UINT32_MAX - running_size)
109  return AVERROR_INVALIDDATA;
110  running_size += ctx->chunks[i].compressed_size;
111  }
112  }
113 
114  return 0;
115 }
116 
118 {
119  int i;
120  size_t running_offset = 0;
121  for (i = 0; i < ctx->chunk_count; i++) {
122  if (ctx->chunks[i].compressed_offset != running_offset
123  || ctx->chunks[i].compressor != HAP_COMP_NONE)
124  return 0;
125  running_offset += ctx->chunks[i].compressed_size;
126  }
127  return 1;
128 }
129 
131 {
132  HapContext *ctx = avctx->priv_data;
133  GetByteContext *gbc = &ctx->gbc;
134  int section_size;
135  enum HapSectionType section_type;
136  const char *compressorstr;
137  int i, ret;
138 
139  ret = ff_hap_parse_section_header(gbc, &ctx->texture_section_size, &section_type);
140  if (ret != 0)
141  return ret;
142 
143  if ((avctx->codec_tag == MKTAG('H','a','p','1') && (section_type & 0x0F) != HAP_FMT_RGBDXT1) ||
144  (avctx->codec_tag == MKTAG('H','a','p','5') && (section_type & 0x0F) != HAP_FMT_RGBADXT5) ||
145  (avctx->codec_tag == MKTAG('H','a','p','Y') && (section_type & 0x0F) != HAP_FMT_YCOCGDXT5) ||
146  (avctx->codec_tag == MKTAG('H','a','p','A') && (section_type & 0x0F) != HAP_FMT_RGTC1) ||
147  ((avctx->codec_tag == MKTAG('H','a','p','M') && (section_type & 0x0F) != HAP_FMT_RGTC1) &&
148  (section_type & 0x0F) != HAP_FMT_YCOCGDXT5)) {
149  av_log(avctx, AV_LOG_ERROR,
150  "Invalid texture format %#04x.\n", section_type & 0x0F);
151  return AVERROR_INVALIDDATA;
152  }
153 
154  switch (section_type & 0xF0) {
155  case HAP_COMP_NONE:
156  case HAP_COMP_SNAPPY:
157  ret = ff_hap_set_chunk_count(ctx, 1, 1);
158  if (ret == 0) {
159  ctx->chunks[0].compressor = section_type & 0xF0;
160  ctx->chunks[0].compressed_offset = 0;
162  }
163  if (ctx->chunks[0].compressor == HAP_COMP_NONE) {
164  compressorstr = "none";
165  } else {
166  compressorstr = "snappy";
167  }
168  break;
169  case HAP_COMP_COMPLEX:
170  ret = ff_hap_parse_section_header(gbc, &section_size, &section_type);
171  if (ret == 0 && section_type != HAP_ST_DECODE_INSTRUCTIONS)
172  ret = AVERROR_INVALIDDATA;
173  if (ret == 0)
174  ret = hap_parse_decode_instructions(ctx, section_size);
175  compressorstr = "complex";
176  break;
177  default:
178  ret = AVERROR_INVALIDDATA;
179  break;
180  }
181 
182  if (ret != 0)
183  return ret;
184 
185  /* Check the frame is valid and read the uncompressed chunk sizes */
186  ctx->tex_size = 0;
187  for (i = 0; i < ctx->chunk_count; i++) {
188  HapChunk *chunk = &ctx->chunks[i];
189 
190  /* Check the compressed buffer is valid */
191  if (chunk->compressed_offset + (uint64_t)chunk->compressed_size > bytestream2_get_bytes_left(gbc))
192  return AVERROR_INVALIDDATA;
193 
194  /* Chunks are unpacked sequentially, ctx->tex_size is the uncompressed
195  * size thus far */
196  chunk->uncompressed_offset = ctx->tex_size;
197 
198  /* Fill out uncompressed size */
199  if (chunk->compressor == HAP_COMP_SNAPPY) {
200  GetByteContext gbc_tmp;
201  int64_t uncompressed_size;
202  bytestream2_init(&gbc_tmp, gbc->buffer + chunk->compressed_offset,
203  chunk->compressed_size);
204  uncompressed_size = ff_snappy_peek_uncompressed_length(&gbc_tmp);
205  if (uncompressed_size < 0) {
206  return uncompressed_size;
207  }
208  chunk->uncompressed_size = uncompressed_size;
209  } else if (chunk->compressor == HAP_COMP_NONE) {
210  chunk->uncompressed_size = chunk->compressed_size;
211  } else {
212  return AVERROR_INVALIDDATA;
213  }
214  ctx->tex_size += chunk->uncompressed_size;
215  }
216 
217  av_log(avctx, AV_LOG_DEBUG, "%s compressor\n", compressorstr);
218 
219  return ret;
220 }
221 
222 static int decompress_chunks_thread(AVCodecContext *avctx, void *arg,
223  int chunk_nb, int thread_nb)
224 {
225  HapContext *ctx = avctx->priv_data;
226 
227  HapChunk *chunk = &ctx->chunks[chunk_nb];
228  GetByteContext gbc;
229  uint8_t *dst = ctx->tex_buf + chunk->uncompressed_offset;
230 
231  bytestream2_init(&gbc, ctx->gbc.buffer + chunk->compressed_offset, chunk->compressed_size);
232 
233  if (chunk->compressor == HAP_COMP_SNAPPY) {
234  int ret;
235  int64_t uncompressed_size = ctx->tex_size;
236 
237  /* Uncompress the frame */
238  ret = ff_snappy_uncompress(&gbc, dst, &uncompressed_size);
239  if (ret < 0) {
240  av_log(avctx, AV_LOG_ERROR, "Snappy uncompress error\n");
241  return ret;
242  }
243  } else if (chunk->compressor == HAP_COMP_NONE) {
244  bytestream2_get_buffer(&gbc, dst, chunk->compressed_size);
245  }
246 
247  return 0;
248 }
249 
251  int slice, int thread_nb, int texture_num)
252 {
253  HapContext *ctx = avctx->priv_data;
254  AVFrame *frame = arg;
255  const uint8_t *d = ctx->tex_data;
256  int w_block = avctx->coded_width / TEXTURE_BLOCK_W;
257  int h_block = avctx->coded_height / TEXTURE_BLOCK_H;
258  int x, y;
259  int start_slice, end_slice;
260  int base_blocks_per_slice = h_block / ctx->slice_count;
261  int remainder_blocks = h_block % ctx->slice_count;
262 
263  /* When the frame height (in blocks) doesn't divide evenly between the
264  * number of slices, spread the remaining blocks evenly between the first
265  * operations */
266  start_slice = slice * base_blocks_per_slice;
267  /* Add any extra blocks (one per slice) that have been added before this slice */
268  start_slice += FFMIN(slice, remainder_blocks);
269 
270  end_slice = start_slice + base_blocks_per_slice;
271  /* Add an extra block if there are still remainder blocks to be accounted for */
272  if (slice < remainder_blocks)
273  end_slice++;
274 
275  for (y = start_slice; y < end_slice; y++) {
276  uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H;
277  int off = y * w_block;
278  for (x = 0; x < w_block; x++) {
279  if (texture_num == 0) {
280  ctx->tex_fun(p + x * 4 * ctx->uncompress_pix_size, frame->linesize[0],
281  d + (off + x) * ctx->tex_rat);
282  } else {
283  ctx->tex_fun2(p + x * 4 * ctx->uncompress_pix_size, frame->linesize[0],
284  d + (off + x) * ctx->tex_rat2);
285  }
286  }
287  }
288 
289  return 0;
290 }
291 
293  int slice, int thread_nb)
294 {
295  return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 0);
296 }
297 
299  int slice, int thread_nb)
300 {
301  return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 1);
302 }
303 
304 static int hap_decode(AVCodecContext *avctx, void *data,
305  int *got_frame, AVPacket *avpkt)
306 {
307  HapContext *ctx = avctx->priv_data;
308  ThreadFrame tframe;
309  int ret, i, t;
310  int section_size;
311  enum HapSectionType section_type;
312  int start_texture_section = 0;
313  int tex_rat[2] = {0, 0};
314 
315  bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size);
316 
317  tex_rat[0] = ctx->tex_rat;
318 
319  /* check for multi texture header */
320  if (ctx->texture_count == 2) {
321  ret = ff_hap_parse_section_header(&ctx->gbc, &section_size, &section_type);
322  if (ret != 0)
323  return ret;
324  if ((section_type & 0x0F) != 0x0D) {
325  av_log(avctx, AV_LOG_ERROR, "Invalid section type in 2 textures mode %#04x.\n", section_type);
326  return AVERROR_INVALIDDATA;
327  }
328  start_texture_section = 4;
329  tex_rat[1] = ctx->tex_rat2;
330  }
331 
332  /* Get the output frame ready to receive data */
333  tframe.f = data;
334  ret = ff_thread_get_buffer(avctx, &tframe, 0);
335  if (ret < 0)
336  return ret;
337 
338  for (t = 0; t < ctx->texture_count; t++) {
339  bytestream2_seek(&ctx->gbc, start_texture_section, SEEK_SET);
340 
341  /* Check for section header */
342  ret = hap_parse_frame_header(avctx);
343  if (ret < 0)
344  return ret;
345 
346  if (ctx->tex_size != (avctx->coded_width / TEXTURE_BLOCK_W)
347  *(avctx->coded_height / TEXTURE_BLOCK_H)
348  *tex_rat[t]) {
349  av_log(avctx, AV_LOG_ERROR, "uncompressed size mismatches\n");
350  return AVERROR_INVALIDDATA;
351  }
352 
353  start_texture_section += ctx->texture_section_size + 4;
354 
355  if (avctx->codec->update_thread_context)
356  ff_thread_finish_setup(avctx);
357 
358  /* Unpack the DXT texture */
359  if (hap_can_use_tex_in_place(ctx)) {
360  int tex_size;
361  /* Only DXTC texture compression in a contiguous block */
362  ctx->tex_data = ctx->gbc.buffer;
363  tex_size = FFMIN(ctx->texture_section_size, bytestream2_get_bytes_left(&ctx->gbc));
364  if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W)
365  *(avctx->coded_height / TEXTURE_BLOCK_H)
366  *tex_rat[t]) {
367  av_log(avctx, AV_LOG_ERROR, "Insufficient data\n");
368  return AVERROR_INVALIDDATA;
369  }
370  } else {
371  /* Perform the second-stage decompression */
372  ret = av_reallocp(&ctx->tex_buf, ctx->tex_size);
373  if (ret < 0)
374  return ret;
375 
376  avctx->execute2(avctx, decompress_chunks_thread, NULL,
377  ctx->chunk_results, ctx->chunk_count);
378 
379  for (i = 0; i < ctx->chunk_count; i++) {
380  if (ctx->chunk_results[i] < 0)
381  return ctx->chunk_results[i];
382  }
383 
384  ctx->tex_data = ctx->tex_buf;
385  }
386 
387  /* Use the decompress function on the texture, one block per thread */
388  if (t == 0){
389  avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count);
390  } else{
391  tframe.f = data;
392  avctx->execute2(avctx, decompress_texture2_thread, tframe.f, NULL, ctx->slice_count);
393  }
394  }
395 
396  /* Frame is ready to be output */
397  tframe.f->pict_type = AV_PICTURE_TYPE_I;
398  tframe.f->key_frame = 1;
399  *got_frame = 1;
400 
401  return avpkt->size;
402 }
403 
404 static av_cold int hap_init(AVCodecContext *avctx)
405 {
406  HapContext *ctx = avctx->priv_data;
407  const char *texture_name;
408  int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
409 
410  if (ret < 0) {
411  av_log(avctx, AV_LOG_ERROR, "Invalid video size %dx%d.\n",
412  avctx->width, avctx->height);
413  return ret;
414  }
415 
416  /* Since codec is based on 4x4 blocks, size is aligned to 4 */
417  avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W);
418  avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
419 
420  ff_texturedsp_init(&ctx->dxtc);
421 
422  ctx->texture_count = 1;
423  ctx->uncompress_pix_size = 4;
424 
425  switch (avctx->codec_tag) {
426  case MKTAG('H','a','p','1'):
427  texture_name = "DXT1";
428  ctx->tex_rat = 8;
429  ctx->tex_fun = ctx->dxtc.dxt1_block;
430  avctx->pix_fmt = AV_PIX_FMT_RGB0;
431  break;
432  case MKTAG('H','a','p','5'):
433  texture_name = "DXT5";
434  ctx->tex_rat = 16;
435  ctx->tex_fun = ctx->dxtc.dxt5_block;
436  avctx->pix_fmt = AV_PIX_FMT_RGBA;
437  break;
438  case MKTAG('H','a','p','Y'):
439  texture_name = "DXT5-YCoCg-scaled";
440  ctx->tex_rat = 16;
441  ctx->tex_fun = ctx->dxtc.dxt5ys_block;
442  avctx->pix_fmt = AV_PIX_FMT_RGB0;
443  break;
444  case MKTAG('H','a','p','A'):
445  texture_name = "RGTC1";
446  ctx->tex_rat = 8;
447  ctx->tex_fun = ctx->dxtc.rgtc1u_gray_block;
448  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
449  ctx->uncompress_pix_size = 1;
450  break;
451  case MKTAG('H','a','p','M'):
452  texture_name = "DXT5-YCoCg-scaled / RGTC1";
453  ctx->tex_rat = 16;
454  ctx->tex_rat2 = 8;
455  ctx->tex_fun = ctx->dxtc.dxt5ys_block;
456  ctx->tex_fun2 = ctx->dxtc.rgtc1u_alpha_block;
457  avctx->pix_fmt = AV_PIX_FMT_RGBA;
458  ctx->texture_count = 2;
459  break;
460  default:
462  }
463 
464  av_log(avctx, AV_LOG_DEBUG, "%s texture\n", texture_name);
465 
466  ctx->slice_count = av_clip(avctx->thread_count, 1,
467  avctx->coded_height / TEXTURE_BLOCK_H);
468 
469  return 0;
470 }
471 
472 static av_cold int hap_close(AVCodecContext *avctx)
473 {
474  HapContext *ctx = avctx->priv_data;
475 
476  ff_hap_free_context(ctx);
477 
478  return 0;
479 }
480 
482  .name = "hap",
483  .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap"),
484  .type = AVMEDIA_TYPE_VIDEO,
485  .id = AV_CODEC_ID_HAP,
486  .init = hap_init,
487  .decode = hap_decode,
488  .close = hap_close,
489  .priv_data_size = sizeof(HapContext),
492  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
494  .codec_tags = (const uint32_t []){
495  MKTAG('H','a','p','1'),
496  MKTAG('H','a','p','5'),
497  MKTAG('H','a','p','Y'),
498  MKTAG('H','a','p','A'),
499  MKTAG('H','a','p','M'),
501  },
502 };
#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:49
Definition: hap.h:61
#define NULL
Definition: coverity.c:32
const struct AVCodec * codec
Definition: avcodec.h:545
#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:318
HapChunk * chunks
Definition: hap.h:72
static int hap_can_use_tex_in_place(HapContext *ctx)
Definition: hapdec.c:117
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:724
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: packet.h:370
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:746
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
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
AVCodec.
Definition: codec.h:197
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:133
#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:41
uint8_t
#define av_cold
Definition: attributes.h:88
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:481
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
#define av_clip
Definition: common.h:122
uint8_t * data
Definition: packet.h:369
const uint8_t * buffer
Definition: bytestream.h:34
static av_cold int hap_init(AVCodecContext *avctx)
Definition: hapdec.c:404
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:304
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
int(* dxt5ys_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:53
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
uint32_t compressed_offset
Definition: hap.h:55
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:117
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
const char * arg
Definition: jacosubdec.c:66
const char * name
Name of the codec implementation.
Definition: codec.h:204
static int decompress_texture_thread_internal(AVCodecContext *avctx, void *arg, int slice, int thread_nb, int texture_num)
Definition: hapdec.c:250
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition: codec.h:108
int ff_snappy_uncompress(GetByteContext *gb, uint8_t *buf, int64_t *size)
Decompress an input buffer using Snappy algorithm.
Definition: snappy.c:143
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
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 have so the codec calls ff_thread_report set FF_CODEC_CAP_ALLOCATE_PROGRESS in AVCodec caps_internal and use ff_thread_get_buffer() to allocate frames.The frames must then be freed with ff_thread_release_buffer().Otherwise decode directly into the user-supplied frames.Call ff_thread_report_progress() after some part of the current picture has decoded.A good place to put this is where draw_horiz_band() is called-add this if it isn't called anywhere
static av_cold int hap_close(AVCodecContext *avctx)
Definition: hapdec.c:472
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:317
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition: texturedsp.c:637
int(* update_thread_context)(struct AVCodecContext *dst, const struct AVCodecContext *src)
Copy necessary context variables from a previous thread context to the current one.
Definition: codec.h:260
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:401
int uncompressed_offset
Definition: hap.h:57
#define FFMIN(a, b)
Definition: common.h:105
int width
picture width / height.
Definition: avcodec.h:709
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:1773
Snappy decompression.
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:112
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:1844
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:161
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:349
av_cold void ff_hap_free_context(HapContext *ctx)
Definition: hap.c:50
main external API structure.
Definition: avcodec.h:536
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:561
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:724
int slice_count
Definition: hap.h:83
static int decompress_texture2_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb)
Definition: hapdec.c:298
static int decompress_chunks_thread(AVCodecContext *avctx, void *arg, int chunk_nb, int thread_nb)
Definition: hapdec.c:222
static int hap_parse_frame_header(AVCodecContext *avctx)
Definition: hapdec.c:130
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:292
uint8_t * tex_buf
Definition: hap.h:78
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:332
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:563
#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:396
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:212
int uncompress_pix_size
Definition: hap.h:87
#define FF_CODEC_TAGS_END
AVCodec.codec_tags termination value.
Definition: internal.h:85
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:478
#define TEXTURE_BLOCK_W
Definition: texturedsp.h:42
int texture_count
Definition: hap.h:85
This structure stores compressed data.
Definition: packet.h:346
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators...
Definition: codec.h:52
int i
Definition: input.c:407