/src/vlc/modules/packetizer/av1.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * av1.c: AV1 video packetizer |
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 | | |
21 | | /***************************************************************************** |
22 | | * Preamble |
23 | | *****************************************************************************/ |
24 | | |
25 | | #ifdef HAVE_CONFIG_H |
26 | | # include "config.h" |
27 | | #endif |
28 | | |
29 | | #include <vlc_common.h> |
30 | | #include <vlc_plugin.h> |
31 | | #include <vlc_codec.h> |
32 | | #include <vlc_block.h> |
33 | | #include <vlc_bits.h> |
34 | | |
35 | | #include <vlc_block_helper.h> |
36 | | |
37 | | #include "av1.h" |
38 | | #include "av1_obu.h" |
39 | | |
40 | | //#define DEBUG_AV1_PACKETIZER |
41 | | |
42 | | /**************************************************************************** |
43 | | * Local prototypes |
44 | | ****************************************************************************/ |
45 | | typedef struct |
46 | | { |
47 | | struct |
48 | | { |
49 | | block_t *p_chain; |
50 | | block_t **pp_chain_last; |
51 | | } obus; |
52 | | |
53 | | block_t *p_sequence_header_block; |
54 | | av1_OBU_sequence_header_t *p_sequence_header; |
55 | | bool b_sequence_header_changed; |
56 | | struct |
57 | | { |
58 | | bool b_has_visible_frame; |
59 | | struct |
60 | | { |
61 | | block_t *p_chain; |
62 | | block_t **pp_chain_last; |
63 | | } pre, frame, post; |
64 | | vlc_tick_t dts; |
65 | | vlc_tick_t pts; |
66 | | } tu; |
67 | | uint32_t i_seen; |
68 | | int i_next_block_flags; |
69 | | |
70 | | } av1_sys_t; |
71 | | |
72 | 832k | #define BLOCK_FLAG_DROP (1 << BLOCK_FLAG_PRIVATE_SHIFT) |
73 | | |
74 | | /**************************************************************************** |
75 | | * Helpers |
76 | | ****************************************************************************/ |
77 | | static inline void InitQueue(block_t **pp_head, block_t ***ppp_tail) |
78 | 458k | { |
79 | 458k | *pp_head = NULL; |
80 | 458k | *ppp_tail = pp_head; |
81 | 458k | } |
82 | | |
83 | | static bool block_Differs(const block_t *a, const block_t *b) |
84 | 16.4k | { |
85 | 16.4k | return (a->i_buffer != b->i_buffer || |
86 | 13.8k | memcmp(a->p_buffer, b->p_buffer, a->i_buffer)); |
87 | 16.4k | } |
88 | | |
89 | 458k | #define INITQ(name) InitQueue(&p_sys->name.p_chain, &p_sys->name.pp_chain_last) |
90 | 485k | #define PUSHQ(name,b) \ |
91 | 485k | {\ |
92 | 485k | block_ChainLastAppend(&p_sys->name.pp_chain_last, b);\ |
93 | 485k | if(p_sys->tu.dts == VLC_TICK_INVALID)\ |
94 | 485k | {\ |
95 | 413k | p_sys->tu.dts = b->i_dts;\ |
96 | 413k | p_sys->tu.pts = b->i_pts;\ |
97 | 413k | }\ |
98 | 485k | } |
99 | | |
100 | | static void UpdateDecoderFormat(decoder_t *p_dec) |
101 | 405k | { |
102 | 405k | av1_sys_t *p_sys = p_dec->p_sys; |
103 | 405k | if(!p_sys->p_sequence_header) |
104 | 86.5k | return; |
105 | | |
106 | 318k | if(p_dec->fmt_in->i_profile < AV1_PROFILE_MAIN) |
107 | 318k | { |
108 | 318k | int val[3]; |
109 | 318k | AV1_get_profile_level(p_sys->p_sequence_header, &val[0], &val[1], &val[2]); |
110 | 318k | if(p_dec->fmt_out.i_profile != val[0] || p_dec->fmt_out.i_level != val[1]) |
111 | 2.40k | { |
112 | 2.40k | p_dec->fmt_out.i_profile = val[0]; |
113 | 2.40k | p_dec->fmt_out.i_level = val[1]; |
114 | 2.40k | } |
115 | 318k | } |
116 | | |
117 | 318k | unsigned wnum, hden; |
118 | 318k | AV1_get_frame_max_dimensions(p_sys->p_sequence_header, &wnum, &hden); |
119 | 318k | if((!p_dec->fmt_in->video.i_visible_height || |
120 | 276k | !p_dec->fmt_in->video.i_visible_width || |
121 | 274k | p_sys->b_sequence_header_changed) && |
122 | 45.6k | (p_dec->fmt_out.video.i_visible_width != wnum || |
123 | 43.3k | p_dec->fmt_out.video.i_visible_width != hden)) |
124 | 18.4k | { |
125 | 18.4k | p_dec->fmt_out.video.i_width = |
126 | 18.4k | p_dec->fmt_out.video.i_visible_width = wnum; |
127 | 18.4k | p_dec->fmt_out.video.i_height = |
128 | 18.4k | p_dec->fmt_out.video.i_visible_height = hden; |
129 | 18.4k | } |
130 | | |
131 | 318k | if((!p_dec->fmt_in->video.i_frame_rate || |
132 | 249k | !p_dec->fmt_in->video.i_frame_rate_base) && |
133 | 82.2k | AV1_get_frame_rate(p_sys->p_sequence_header, &wnum, &hden) && |
134 | 574 | (p_dec->fmt_out.video.i_frame_rate != wnum || |
135 | 538 | p_dec->fmt_out.video.i_frame_rate_base != hden)) |
136 | 36 | { |
137 | 36 | p_dec->fmt_out.video.i_frame_rate = wnum; |
138 | 36 | p_dec->fmt_out.video.i_frame_rate_base = hden; |
139 | 36 | } |
140 | | |
141 | 318k | video_color_primaries_t prim; |
142 | 318k | video_color_space_t space; |
143 | 318k | video_transfer_func_t xfer; |
144 | 318k | video_color_range_t full; |
145 | 318k | if(p_dec->fmt_in->video.primaries == COLOR_PRIMARIES_UNDEF && |
146 | 317k | AV1_get_colorimetry(p_sys->p_sequence_header, &prim, &xfer, &space, &full) && |
147 | 18.9k | prim != COLOR_PRIMARIES_UNDEF && |
148 | 1.57k | (p_dec->fmt_out.video.primaries != prim || |
149 | 1.45k | p_dec->fmt_out.video.transfer != xfer || |
150 | 1.35k | p_dec->fmt_out.video.space != space)) |
151 | 228 | { |
152 | 228 | p_dec->fmt_out.video.primaries = prim; |
153 | 228 | p_dec->fmt_out.video.transfer = xfer; |
154 | 228 | p_dec->fmt_out.video.space = space; |
155 | 228 | p_dec->fmt_out.video.color_range = full; |
156 | 228 | } |
157 | | |
158 | 318k | if (p_sys->b_sequence_header_changed && p_dec->fmt_out.p_extra) |
159 | 2.91k | { |
160 | 2.91k | free(p_dec->fmt_out.p_extra); |
161 | 2.91k | p_dec->fmt_out.i_extra = 0; |
162 | 2.91k | p_dec->fmt_out.p_extra = NULL; |
163 | 2.91k | } |
164 | | |
165 | 318k | if(p_dec->fmt_out.i_extra <= 4) |
166 | 3.73k | { |
167 | 3.73k | free(p_dec->fmt_out.p_extra); |
168 | 3.73k | p_dec->fmt_out.i_extra = |
169 | 3.73k | AV1_create_DecoderConfigurationRecord((uint8_t **)&p_dec->fmt_out.p_extra, |
170 | 3.73k | p_sys->p_sequence_header, |
171 | 3.73k | 1, |
172 | 3.73k | (const uint8_t **)&p_sys->p_sequence_header_block->p_buffer, |
173 | 3.73k | &p_sys->p_sequence_header_block->i_buffer); |
174 | 3.73k | } |
175 | 318k | p_sys->b_sequence_header_changed = false; |
176 | 318k | } |
177 | | |
178 | | static block_t * OutputQueues(decoder_t *p_dec, bool b_valid) |
179 | 407k | { |
180 | 407k | av1_sys_t *p_sys = p_dec->p_sys; |
181 | 407k | block_t *p_output = NULL; |
182 | 407k | block_t **pp_output_last = &p_output; |
183 | 407k | uint32_t i_flags = 0; /* Because block_ChainGather does not merge flags or times */ |
184 | | |
185 | 407k | if(p_sys->tu.pre.p_chain) |
186 | 405k | { |
187 | 405k | block_ChainLastAppend(&pp_output_last, p_sys->tu.pre.p_chain); |
188 | 405k | INITQ(tu.pre); |
189 | 405k | } |
190 | | |
191 | 407k | if(p_sys->tu.frame.p_chain) |
192 | 49.1k | { |
193 | 49.1k | i_flags |= p_sys->tu.frame.p_chain->i_flags; |
194 | 49.1k | block_ChainLastAppend(&pp_output_last, p_sys->tu.frame.p_chain); |
195 | 49.1k | INITQ(tu.frame); |
196 | 49.1k | } |
197 | | |
198 | 407k | if(p_sys->tu.post.p_chain) |
199 | 0 | { |
200 | 0 | block_ChainLastAppend(&pp_output_last, p_sys->tu.post.p_chain); |
201 | 0 | INITQ(tu.post); |
202 | 0 | } |
203 | | |
204 | 407k | if(p_output) |
205 | 405k | { |
206 | 405k | p_output->i_dts = p_sys->tu.dts; |
207 | 405k | p_output->i_pts = p_sys->tu.pts; |
208 | 405k | p_output->i_flags |= i_flags; |
209 | 405k | if(!b_valid) |
210 | 21.6k | p_output->i_flags |= BLOCK_FLAG_DROP; |
211 | 383k | else |
212 | 383k | { |
213 | 383k | p_output->i_flags |= p_sys->i_next_block_flags; |
214 | 383k | p_sys->i_next_block_flags = 0; |
215 | 383k | } |
216 | 405k | } |
217 | | |
218 | 407k | p_sys->tu.b_has_visible_frame = false; |
219 | 407k | p_sys->tu.dts = VLC_TICK_INVALID; |
220 | 407k | p_sys->tu.pts = VLC_TICK_INVALID; |
221 | 407k | p_sys->i_seen = 0; |
222 | | |
223 | 407k | return p_output; |
224 | 407k | } |
225 | | |
226 | | /**************************************************************************** |
227 | | * Packetizer Helpers |
228 | | ****************************************************************************/ |
229 | | static block_t *GatherAndValidateChain(decoder_t *p_dec, block_t *p_outputchain) |
230 | 405k | { |
231 | 405k | block_t *p_output = NULL; |
232 | 405k | av1_sys_t *p_sys = p_dec->p_sys; |
233 | 405k | VLC_UNUSED(p_sys); |
234 | | |
235 | 405k | if(p_outputchain) |
236 | 405k | { |
237 | | #ifdef DEBUG_AV1_PACKETIZER |
238 | | msg_Dbg(p_dec, "TU output %" PRId64, p_outputchain->i_dts); |
239 | | for(block_t *p = p_outputchain; p; p=p->p_next) |
240 | | { |
241 | | enum av1_obu_type_e OBUtype = AV1_OBUGetType(p->p_buffer); |
242 | | if(OBUtype == AV1_OBU_FRAME || OBUtype == AV1_OBU_FRAME_HEADER) |
243 | | { |
244 | | av1_OBU_frame_header_t *p_fh = NULL; |
245 | | if(AV1_OBUIsBaseLayer(p->p_buffer, p->i_buffer) && p_sys->p_sequence_header) |
246 | | { |
247 | | p_fh = AV1_OBU_parse_frame_header(p->p_buffer, p->i_buffer, |
248 | | p_sys->p_sequence_header); |
249 | | if(p_fh) |
250 | | { |
251 | | msg_Dbg(p_dec,"OBU TYPE %d sz %zu dts %" PRId64 " type %d %d", |
252 | | OBUtype, p->i_buffer, p->i_dts, |
253 | | AV1_get_frame_type(p_fh), |
254 | | AV1_get_frame_visibility(p_fh)); |
255 | | } |
256 | | AV1_release_frame_header(p_fh); |
257 | | } |
258 | | } |
259 | | else msg_Dbg(p_dec, "OBU TYPE %d sz %zu dts %" PRId64, OBUtype, p->i_buffer, p->i_dts); |
260 | | } |
261 | | #endif |
262 | 405k | if(p_outputchain->i_flags & BLOCK_FLAG_DROP) |
263 | 21.6k | p_output = p_outputchain; /* Avoid useless gather */ |
264 | 383k | else |
265 | 383k | p_output = block_ChainGather(p_outputchain); |
266 | 405k | } |
267 | | |
268 | 405k | if(p_output && (p_output->i_flags & BLOCK_FLAG_DROP)) |
269 | 21.6k | { |
270 | 21.6k | block_ChainRelease(p_output); /* Chain! see above */ |
271 | 21.6k | p_output = NULL; |
272 | 21.6k | } |
273 | | |
274 | 405k | return p_output; |
275 | 405k | } |
276 | | |
277 | | static block_t *ParseOBUBlock(decoder_t *p_dec, block_t *p_obu) |
278 | 687k | { |
279 | 687k | av1_sys_t *p_sys = p_dec->p_sys; |
280 | | |
281 | 687k | block_t * p_output = NULL; |
282 | 687k | enum av1_obu_type_e OBUtype = AV1_OBUGetType(p_obu->p_buffer); |
283 | 687k | const bool b_base_layer = AV1_OBUIsBaseLayer(p_obu->p_buffer, p_obu->i_buffer); |
284 | | |
285 | 687k | switch(OBUtype) |
286 | 687k | { |
287 | 21.3k | case AV1_OBU_SEQUENCE_HEADER: |
288 | 21.3k | { |
289 | 21.3k | if(p_sys->tu.frame.p_chain || p_sys->tu.post.p_chain) |
290 | 345 | p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL); |
291 | | |
292 | 21.3k | if(b_base_layer) |
293 | 17.2k | { |
294 | | /* Save a copy for Extradata */ |
295 | 17.2k | if(!p_sys->p_sequence_header_block || |
296 | 16.4k | block_Differs(p_sys->p_sequence_header_block, p_obu)) |
297 | 13.9k | { |
298 | 13.9k | if(p_sys->p_sequence_header_block) |
299 | 13.1k | block_Release(p_sys->p_sequence_header_block); |
300 | 13.9k | p_sys->p_sequence_header_block = block_Duplicate(p_obu); |
301 | 13.9k | } |
302 | | |
303 | 17.2k | av1_OBU_sequence_header_t *new_seq_header; |
304 | 17.2k | new_seq_header = AV1_OBU_parse_sequence_header(p_obu->p_buffer, p_obu->i_buffer); |
305 | 17.2k | if (likely(new_seq_header)) |
306 | 9.29k | { |
307 | 9.29k | if (!p_sys->p_sequence_header || |
308 | 8.46k | !AV1_sequence_header_equal(p_sys->p_sequence_header, new_seq_header)) |
309 | 6.39k | { |
310 | 6.39k | if (p_sys->p_sequence_header) |
311 | 5.56k | { |
312 | 5.56k | AV1_release_sequence_header(p_sys->p_sequence_header); |
313 | 5.56k | p_sys->b_sequence_header_changed = true; |
314 | 5.56k | } |
315 | 6.39k | p_sys->p_sequence_header = new_seq_header; |
316 | 6.39k | } |
317 | 2.90k | else AV1_release_sequence_header(new_seq_header); |
318 | 9.29k | } |
319 | 17.2k | } |
320 | 21.3k | PUSHQ(tu.pre, p_obu); |
321 | 21.3k | } break; |
322 | | |
323 | 405k | case AV1_OBU_TEMPORAL_DELIMITER: |
324 | 405k | { |
325 | 405k | p_output = OutputQueues(p_dec, p_sys->p_sequence_header_block != NULL); |
326 | 405k | PUSHQ(tu.pre, p_obu); |
327 | 405k | } break; |
328 | | |
329 | 17.5k | case AV1_OBU_FRAME: |
330 | 29.7k | case AV1_OBU_FRAME_HEADER: |
331 | 29.7k | { |
332 | 29.7k | if(b_base_layer) |
333 | 17.9k | { |
334 | 17.9k | av1_OBU_frame_header_t *p_fh = NULL; |
335 | 17.9k | if(p_sys->p_sequence_header) |
336 | 13.6k | { |
337 | 13.6k | p_fh = AV1_OBU_parse_frame_header(p_obu->p_buffer, p_obu->i_buffer, |
338 | 13.6k | p_sys->p_sequence_header); |
339 | 13.6k | if(p_fh) |
340 | 13.6k | { |
341 | 13.6k | if((p_sys->i_seen & AV1_OBU_TEMPORAL_DELIMITER) && p_sys->tu.b_has_visible_frame) |
342 | 4 | p_output = OutputQueues(p_dec, true); |
343 | | |
344 | 13.6k | switch(AV1_get_frame_type(p_fh)) |
345 | 13.6k | { |
346 | 9.32k | case AV1_FRAME_TYPE_KEY: |
347 | 10.9k | case AV1_FRAME_TYPE_INTRA_ONLY: |
348 | 10.9k | p_obu->i_flags |= BLOCK_FLAG_TYPE_I; |
349 | 10.9k | break; |
350 | 2.33k | case AV1_FRAME_TYPE_INTER: |
351 | 2.33k | p_obu->i_flags |= BLOCK_FLAG_TYPE_P; |
352 | 2.33k | break; |
353 | 398 | default: |
354 | 398 | break; |
355 | 13.6k | } |
356 | | |
357 | 13.6k | p_sys->tu.b_has_visible_frame |= AV1_get_frame_visibility(p_fh); |
358 | 13.6k | AV1_release_frame_header(p_fh); |
359 | 13.6k | } |
360 | 13.6k | else msg_Warn(p_dec, "could not parse frame header"); |
361 | 13.6k | } |
362 | 17.9k | } |
363 | | |
364 | 29.7k | if(!p_output && p_sys->tu.post.p_chain) |
365 | 0 | p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL); |
366 | | |
367 | 29.7k | PUSHQ(tu.frame, p_obu); |
368 | 29.7k | } break; |
369 | | |
370 | 8.74k | case AV1_OBU_METADATA: |
371 | 8.74k | { |
372 | 8.74k | if(p_sys->tu.frame.p_chain || p_sys->tu.post.p_chain) |
373 | 45 | p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL); |
374 | 8.74k | PUSHQ(tu.pre, p_obu); |
375 | 8.74k | } break; |
376 | | |
377 | 9.33k | case AV1_OBU_TILE_GROUP: |
378 | 20.3k | case AV1_OBU_TILE_LIST: |
379 | 20.3k | if(p_sys->tu.post.p_chain) |
380 | 0 | p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL); |
381 | 20.3k | PUSHQ(tu.frame, p_obu); |
382 | 20.3k | break; |
383 | | |
384 | 10.5k | case AV1_OBU_REDUNDANT_FRAME_HEADER: |
385 | 18.8k | case AV1_OBU_PADDING: |
386 | 201k | default: |
387 | 201k | block_Release(p_obu); |
388 | 201k | break; |
389 | 687k | } |
390 | | |
391 | 687k | if(b_base_layer) |
392 | 612k | p_sys->i_seen |= 1 << OBUtype; |
393 | | |
394 | 687k | return p_output; |
395 | 687k | } |
396 | | |
397 | | /**************************************************************************** |
398 | | * Flush |
399 | | ****************************************************************************/ |
400 | | static void PacketizeFlush(decoder_t *p_dec) |
401 | 853 | { |
402 | 853 | av1_sys_t *p_sys = p_dec->p_sys; |
403 | | |
404 | 853 | block_ChainRelease(OutputQueues(p_dec, false)); |
405 | | |
406 | 853 | if(p_sys->p_sequence_header) |
407 | 832 | { |
408 | 832 | AV1_release_sequence_header(p_sys->p_sequence_header); |
409 | 832 | p_sys->p_sequence_header = NULL; |
410 | 832 | p_sys->b_sequence_header_changed = true; |
411 | 832 | } |
412 | 853 | if(p_sys->p_sequence_header_block) |
413 | 847 | { |
414 | 847 | block_Release(p_sys->p_sequence_header_block); |
415 | 847 | p_sys->p_sequence_header_block = NULL; |
416 | 847 | } |
417 | | |
418 | 853 | block_ChainRelease(p_sys->obus.p_chain); |
419 | 853 | INITQ(obus); |
420 | | |
421 | 853 | p_sys->tu.dts = VLC_TICK_INVALID; |
422 | 853 | p_sys->tu.pts = VLC_TICK_INVALID; |
423 | 853 | p_sys->tu.b_has_visible_frame = false; |
424 | 853 | p_sys->i_seen = 0; |
425 | 853 | p_sys->i_next_block_flags = BLOCK_FLAG_DISCONTINUITY; |
426 | 853 | } |
427 | | |
428 | | /**************************************************************************** |
429 | | * Packetize |
430 | | ****************************************************************************/ |
431 | | static block_t *PacketizeOBU(decoder_t *p_dec, block_t **pp_block) |
432 | 1.61M | { |
433 | 1.61M | av1_sys_t *p_sys = p_dec->p_sys; |
434 | | |
435 | 1.61M | block_t *p_block = pp_block ? *pp_block : NULL; |
436 | 1.61M | if(p_block) |
437 | 1.23M | { |
438 | 1.23M | if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) ) |
439 | 0 | { |
440 | | /* First always drain complete blocks before discontinuity */ |
441 | 0 | block_t *p_drain = PacketizeOBU( p_dec, NULL ); |
442 | 0 | if(p_drain) |
443 | 0 | return p_drain; |
444 | | |
445 | 0 | PacketizeFlush( p_dec ); |
446 | |
|
447 | 0 | if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) |
448 | 0 | { |
449 | 0 | block_Release( p_block ); |
450 | 0 | return NULL; |
451 | 0 | } |
452 | 0 | } |
453 | | |
454 | 1.23M | if(!AV1_OBUIsValid(p_block->p_buffer, p_block->i_buffer)) |
455 | 826k | { |
456 | 826k | msg_Warn(p_dec,"fed with invalid OBU"); |
457 | 826k | block_Release(p_block); |
458 | 826k | return NULL; |
459 | 826k | } |
460 | 405k | *pp_block = NULL; |
461 | 405k | block_ChainLastAppend(&p_sys->obus.pp_chain_last, p_block); |
462 | 405k | } |
463 | | |
464 | 789k | block_t *p_output = NULL; |
465 | 1.20M | while(p_sys->obus.p_chain) |
466 | 823k | { |
467 | 823k | block_t *p_frag = p_sys->obus.p_chain; |
468 | | |
469 | 823k | AV1_OBU_iterator_ctx_t it; |
470 | 823k | AV1_OBU_iterator_init(&it, p_frag->p_buffer, p_frag->i_buffer); |
471 | 823k | const uint8_t *p_obu; size_t i_obu; |
472 | | |
473 | 823k | if(!AV1_OBU_iterate_next(&it, &p_obu, &i_obu)) |
474 | 136k | { |
475 | 136k | msg_Warn(p_dec,"Invalid OBU header in sequence, discarding"); |
476 | | /* frag is not OBU, drop */ |
477 | 136k | p_sys->obus.p_chain = p_frag->p_next; |
478 | 136k | if(p_frag->p_next == NULL) |
479 | 132k | p_sys->obus.pp_chain_last = &p_sys->obus.p_chain; |
480 | 4.42k | else |
481 | 4.42k | p_frag->p_next = NULL; |
482 | 136k | block_Release(p_frag); |
483 | 136k | continue; |
484 | 136k | } |
485 | | |
486 | 687k | block_t *p_obublock; |
487 | 687k | if(i_obu == p_frag->i_buffer) |
488 | 268k | { |
489 | 268k | p_sys->obus.p_chain = p_frag->p_next; |
490 | 268k | if(p_frag->p_next == NULL) |
491 | 252k | p_sys->obus.pp_chain_last = &p_sys->obus.p_chain; |
492 | 15.4k | else |
493 | 15.4k | p_frag->p_next = NULL; |
494 | 268k | p_obublock = p_frag; |
495 | 268k | } |
496 | 418k | else |
497 | 418k | { |
498 | 418k | p_obublock = block_Alloc(i_obu); |
499 | 418k | memcpy(p_obublock->p_buffer, p_frag->p_buffer, i_obu); |
500 | 418k | p_frag->i_buffer -= i_obu; |
501 | 418k | p_frag->p_buffer += i_obu; |
502 | 418k | p_obublock->i_dts = p_frag->i_dts; |
503 | 418k | p_obublock->i_pts = p_frag->i_pts; |
504 | 418k | p_obublock->i_flags = p_frag->i_flags; |
505 | 418k | p_frag->i_flags = 0; |
506 | 418k | p_frag->i_dts = VLC_TICK_INVALID; |
507 | 418k | p_frag->i_pts = VLC_TICK_INVALID; |
508 | 418k | } |
509 | | |
510 | 687k | p_output = ParseOBUBlock(p_dec, p_obublock); |
511 | 687k | if(p_output) |
512 | 404k | break; |
513 | 687k | } |
514 | | |
515 | | |
516 | 789k | if(!p_output && pp_block == NULL) |
517 | 1.69k | p_output = OutputQueues(p_dec, p_sys->p_sequence_header_block != NULL); |
518 | | |
519 | 789k | if(p_output) |
520 | 405k | { |
521 | 405k | p_output = GatherAndValidateChain(p_dec, p_output); |
522 | 405k | UpdateDecoderFormat(p_dec); |
523 | 405k | } |
524 | | |
525 | 789k | return p_output; |
526 | 1.61M | } |
527 | | |
528 | | /***************************************************************************** |
529 | | * Close |
530 | | *****************************************************************************/ |
531 | | static void Close(vlc_object_t *p_this) |
532 | 853 | { |
533 | 853 | decoder_t *p_dec = (decoder_t*)p_this; |
534 | 853 | av1_sys_t *p_sys = p_dec->p_sys; |
535 | | |
536 | 853 | PacketizeFlush(p_dec); |
537 | | |
538 | 853 | free(p_sys); |
539 | 853 | } |
540 | | |
541 | | /***************************************************************************** |
542 | | * Open |
543 | | *****************************************************************************/ |
544 | | static int Open(vlc_object_t *p_this) |
545 | 13.5k | { |
546 | 13.5k | decoder_t *p_dec = (decoder_t*)p_this; |
547 | 13.5k | av1_sys_t *p_sys; |
548 | | |
549 | 13.5k | if (p_dec->fmt_in->i_codec != VLC_CODEC_AV1) |
550 | 12.6k | return VLC_EGENERIC; |
551 | | |
552 | 853 | p_dec->p_sys = p_sys = calloc(1, sizeof(av1_sys_t)); |
553 | 853 | if (!p_dec->p_sys) |
554 | 0 | return VLC_ENOMEM; |
555 | | |
556 | 853 | INITQ(obus); |
557 | 853 | p_sys->p_sequence_header_block = NULL; |
558 | 853 | p_sys->p_sequence_header = NULL; |
559 | 853 | p_sys->b_sequence_header_changed = false; |
560 | 853 | p_sys->tu.b_has_visible_frame = false; |
561 | 853 | p_sys->tu.dts = VLC_TICK_INVALID; |
562 | 853 | p_sys->tu.pts = VLC_TICK_INVALID; |
563 | 853 | p_sys->i_seen = 0; |
564 | 853 | p_sys->i_next_block_flags = 0; |
565 | 853 | INITQ(tu.pre); |
566 | 853 | INITQ(tu.frame); |
567 | 853 | INITQ(tu.post); |
568 | | |
569 | | /* Copy properties */ |
570 | 853 | es_format_Copy(&p_dec->fmt_out, p_dec->fmt_in); |
571 | 853 | p_dec->fmt_out.b_packetized = true; |
572 | | |
573 | 853 | p_dec->pf_packetize = PacketizeOBU; |
574 | 853 | p_dec->pf_flush = PacketizeFlush; |
575 | | |
576 | 853 | return VLC_SUCCESS; |
577 | 853 | } |
578 | | |
579 | | /***************************************************************************** |
580 | | * Module descriptor |
581 | | *****************************************************************************/ |
582 | | |
583 | 168 | vlc_module_begin () |
584 | 84 | set_subcategory(SUBCAT_SOUT_PACKETIZER) |
585 | 84 | set_description(N_("AV1 video packetizer")) |
586 | 84 | set_capability("video packetizer", 50) |
587 | 168 | set_callbacks(Open, Close) |
588 | 84 | vlc_module_end () |