/src/vlc/modules/demux/av1_unpack.h
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * av1_unpack.h: AV1 samples expander |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2018 VideoLabs, VLC authors and VideoLAN |
5 | | * |
6 | | * This program is free software; you can redistribute it and/or modify it |
7 | | * under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation; either version 2.1 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with this program; if not, write to the Free Software Foundation, |
18 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
19 | | *****************************************************************************/ |
20 | | #ifndef VLC_AV1_UNPACK_H |
21 | | #define VLC_AV1_UNPACK_H |
22 | | |
23 | | #include "../packetizer/av1_obu.h" |
24 | | #include <vlc_common.h> |
25 | | #include <vlc_block.h> |
26 | | |
27 | | static inline uint8_t leb128_expected(uint32_t v) |
28 | 0 | { |
29 | 0 | if (v < (1U << 7)) return 1; |
30 | 0 | else if(v < (1U << 14)) return 2; |
31 | 0 | else if(v < (1U << 21)) return 3; |
32 | 0 | else if(v < (1U << 28)) return 4; |
33 | 0 | else return 5; |
34 | 0 | } |
35 | | |
36 | | static inline void leb128_write(uint32_t v, uint8_t *p) |
37 | 0 | { |
38 | 0 | for(;;) |
39 | 0 | { |
40 | 0 | *p = v & 0x7F; |
41 | 0 | v >>= 7; |
42 | 0 | if(v == 0) |
43 | 0 | break; |
44 | 0 | *p++ |= 0x80; |
45 | 0 | } |
46 | 0 | } |
47 | | |
48 | | static inline block_t * AV1_Unpack_Sample_ExpandSize(block_t *p_block) |
49 | 0 | { |
50 | 0 | AV1_OBU_iterator_ctx_t ctx; |
51 | 0 | AV1_OBU_iterator_init(&ctx, p_block->p_buffer, p_block->i_buffer); |
52 | 0 | const uint8_t *p_obu = NULL; size_t i_obu; |
53 | 0 | while(AV1_OBU_iterate_next(&ctx, &p_obu, &i_obu)) |
54 | 0 | { |
55 | 0 | if(AV1_OBUHasSizeField(p_obu)) |
56 | 0 | continue; |
57 | 0 | const uint8_t i_header = 1 + AV1_OBUHasExtensionField(p_obu); |
58 | 0 | if(i_header > i_obu) |
59 | 0 | break; |
60 | 0 | const uint8_t i_sizelen = leb128_expected(i_obu - i_header); |
61 | 0 | const size_t i_obu_offset = p_obu - p_block->p_buffer; |
62 | | |
63 | | /* Make room for i_sizelen after header */ |
64 | 0 | if(2 * (i_obu_offset + i_header) + i_sizelen < p_block->i_buffer) |
65 | 0 | { |
66 | | /* move data to the left */ |
67 | 0 | p_block = block_Realloc(p_block, i_sizelen, p_block->i_buffer); |
68 | 0 | if(p_block) |
69 | 0 | memmove(p_block->p_buffer, &p_block->p_buffer[i_sizelen], |
70 | 0 | i_obu_offset + i_header); |
71 | 0 | } |
72 | 0 | else |
73 | 0 | { |
74 | | /* move data to the right */ |
75 | 0 | p_block = block_Realloc(p_block, 0, p_block->i_buffer + i_sizelen); |
76 | 0 | if(p_block) |
77 | 0 | { |
78 | 0 | const size_t i_off = i_obu_offset + i_header; |
79 | 0 | memmove(&p_block->p_buffer[i_off + i_sizelen], &p_block->p_buffer[i_off], |
80 | 0 | p_block->i_buffer - i_off - i_sizelen); |
81 | 0 | } |
82 | 0 | } |
83 | |
|
84 | 0 | if(likely(p_block)) |
85 | 0 | { |
86 | 0 | leb128_write(i_obu - i_header, &p_block->p_buffer[i_obu_offset + i_header]); |
87 | 0 | p_block->p_buffer[i_obu_offset] |= 0x02; |
88 | 0 | } |
89 | |
|
90 | 0 | break; |
91 | 0 | } |
92 | 0 | return p_block; |
93 | 0 | } |
94 | | |
95 | | /* |
96 | | Restores TD OBU and last size field from MP4/MKV sample format |
97 | | to full AV1 low overhead format. |
98 | | |
99 | | AV1 ISOBMFF Mapping 2.4 |
100 | | https://aomediacodec.github.io/av1-isobmff/#sampleformat |
101 | | Matroska/WebM |
102 | | https://github.com/Matroska-Org/matroska-specification/blob/master/codec/av1.md |
103 | | */ |
104 | | static inline block_t * AV1_Unpack_Sample(block_t *p_block) |
105 | 0 | { |
106 | | /* Restore last size field if missing */ |
107 | 0 | p_block = AV1_Unpack_Sample_ExpandSize(p_block); |
108 | | /* Reinsert removed TU: See av1-isobmff 2.4 */ |
109 | 0 | if(p_block && |
110 | 0 | (p_block->p_buffer[0] & 0x81) == 0 && /* reserved flags */ |
111 | 0 | (p_block->p_buffer[0] & 0x7A) != 0x12) /* no TEMPORAL_DELIMITER */ |
112 | 0 | { |
113 | 0 | p_block = block_Realloc(p_block, 2, p_block->i_buffer); |
114 | 0 | if(p_block) |
115 | 0 | { |
116 | 0 | p_block->p_buffer[0] = 0x12; |
117 | 0 | p_block->p_buffer[1] = 0x00; |
118 | 0 | } |
119 | 0 | } |
120 | 0 | return p_block; |
121 | 0 | } |
122 | | |
123 | | #endif |