1 /*
2 * Vidvox Hap encoder
3 * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
4 * Copyright (C) 2015 Tom Butterworth <bangnoise@gmail.com>
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 /**
24 * @file
25 * Hap encoder
26 *
27 * Fourcc: Hap1, Hap5, HapY
28 *
29 * https://github.com/Vidvox/hap/blob/master/documentation/HapVideoDRAFT.md
30 */
31
32 #include <stdint.h>
33 #include "snappy-c.h"
34
39
46
47 #define HAP_MAX_CHUNKS 64
48
50 /* Short header: four bytes with a 24 bit size value */
52 /* Long header: eight bytes with a 32 bit size value */
54 };
55
57 {
59
60 if (
ctx->tex_size > out_length)
62
63 ctx->enc.tex_data.out =
out;
64 ctx->enc.frame_data.in =
f->data[0];
65 ctx->enc.stride =
f->linesize[0];
69
70 return 0;
71 }
72
73 /* section_length does not include the header */
76 int section_length,
78 {
79 /* The first three bytes are the length of the section (not including the
80 * header) or zero if using an eight-byte header.
81 * For an eight-byte header, the length is in the last four bytes.
82 * The fourth byte stores the section type. */
83 bytestream2_put_le24(pbc, header_length ==
HAP_HDR_LONG ? 0 : section_length);
84 bytestream2_put_byte(pbc, section_type);
85
87 bytestream2_put_le32(pbc, section_length);
88 }
89 }
90
92 {
94 int i, final_size = 0;
95
96 for (
i = 0;
i <
ctx->chunk_count;
i++) {
98 uint8_t *chunk_src, *chunk_dst;
100
103 } else {
105 +
ctx->chunks[
i-1].compressed_size;
106 }
112
113 /* Compress with snappy too, write directly on packet buffer. */
116 if (
ret != SNAPPY_OK) {
119 }
120
121 /* If there is no gain from snappy, just use the raw texture. */
129 } else {
131 }
132
134 }
135
136 return final_size;
137 }
138
140 {
141 /* Second-Stage Compressor Table (one byte per entry)
142 * + Chunk Size Table (four bytes per entry)
143 * + headers for both sections (short versions)
144 * = chunk_count + (4 * chunk_count) + 4 + 4 */
145 return (5 *
ctx->chunk_count) + 8;
146 }
147
149 {
150 /* Top section header (long version) */
152
153 if (
ctx->chunk_count > 1) {
154 /* Decode Instructions header (short) + Decode Instructions Container */
156 }
157
158 return length;
159 }
160
162 {
165
167 if (
ctx->chunk_count == 1) {
168 /* Write a simple header */
170 ctx->chunks[0].compressor |
ctx->opt_tex_fmt);
171 } else {
172 /* Write a complex header with Decode Instructions Container */
179
180 for (
i = 0;
i <
ctx->chunk_count;
i++) {
181 bytestream2_put_byte(&pbc,
ctx->chunks[
i].compressor >> 4);
182 }
183
186
187 for (
i = 0;
i <
ctx->chunk_count;
i++) {
188 bytestream2_put_le32(&pbc,
ctx->chunks[
i].compressed_size);
189 }
190 }
191 }
192
195 {
198 int final_data_size,
ret;
199 int pktsize =
FFMAX(
ctx->tex_size,
ctx->max_snappy *
ctx->chunk_count) + header_length;
200
201 /* Allocate maximum size packet, shrink later. */
205
207 /* DXTC compression directly to the packet buffer. */
211
213 final_data_size =
ctx->tex_size;
214 } else {
215 /* DXTC compression. */
219
220 /* Compress (using Snappy) the frame */
222 if (final_data_size < 0)
223 return final_data_size;
224 }
225
226 /* Write header at the start. */
228
230 *got_packet = 1;
231 return 0;
232 }
233
235 {
238 int corrected_chunk_count;
240
245 }
246
251 }
252
254
255 switch (
ctx->opt_tex_fmt) {
257 ctx->enc.tex_ratio = 8;
261 break;
263 ctx->enc.tex_ratio = 16;
267 break;
269 ctx->enc.tex_ratio = 16;
273 break;
274 default:
277 }
278 ctx->enc.raw_ratio = 16;
280
281 /* Texture compression ratio is constant, so can we computer
282 * beforehand the final size of the uncompressed buffer. */
285
286 switch (
ctx->opt_compressor) {
288 /* No benefit chunking uncompressed data */
289 corrected_chunk_count = 1;
290
291 ctx->max_snappy =
ctx->tex_size;
293 break;
295 /* Round the chunk count to divide evenly on DXT block edges */
297 while ((
ctx->tex_size /
ctx->enc.tex_ratio) % corrected_chunk_count != 0) {
298 corrected_chunk_count--;
299 }
300
301 ctx->max_snappy = snappy_max_compressed_length(
ctx->tex_size / corrected_chunk_count);
305 }
306 break;
307 default:
310 }
311 if (corrected_chunk_count !=
ctx->opt_chunk_count) {
313 ctx->opt_chunk_count, corrected_chunk_count);
314 }
318
319 return 0;
320 }
321
323 {
325
327
328 return 0;
329 }
330
331 #define OFFSET(x) offsetof(HapContext, x)
332 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
343 };
344
350 };
351
366 },
368 };