/src/vlc/modules/packetizer/mpeg4video.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * mpeg4video.c: mpeg 4 video packetizer |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001-2006 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Gildas Bazin <gbazin@videolan.org> |
7 | | * Laurent Aimar <fenrir@via.ecp.fr> |
8 | | * Eric Petit <titer@videolan.org> |
9 | | * |
10 | | * This program is free software; you can redistribute it and/or modify it |
11 | | * under the terms of the GNU Lesser General Public License as published by |
12 | | * the Free Software Foundation; either version 2.1 of the License, or |
13 | | * (at your option) any later version. |
14 | | * |
15 | | * This program 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 |
18 | | * GNU Lesser General Public License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU Lesser General Public License |
21 | | * along with this program; if not, write to the Free Software Foundation, |
22 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
23 | | *****************************************************************************/ |
24 | | |
25 | | /***************************************************************************** |
26 | | * Preamble |
27 | | *****************************************************************************/ |
28 | | |
29 | | #ifdef HAVE_CONFIG_H |
30 | | # include "config.h" |
31 | | #endif |
32 | | |
33 | | #include <vlc_common.h> |
34 | | #include <vlc_plugin.h> |
35 | | #include <vlc_sout.h> |
36 | | #include <vlc_codec.h> |
37 | | #include <vlc_block.h> |
38 | | |
39 | | #include <vlc_bits.h> |
40 | | #include <vlc_block_helper.h> |
41 | | #include "packetizer_helper.h" |
42 | | #include "startcode_helper.h" |
43 | | #include "h26x_nal_common.h" |
44 | | |
45 | | /***************************************************************************** |
46 | | * Module descriptor |
47 | | *****************************************************************************/ |
48 | | static int Open ( vlc_object_t * ); |
49 | | static void Close( vlc_object_t * ); |
50 | | |
51 | 172 | vlc_module_begin () |
52 | 86 | set_subcategory( SUBCAT_SOUT_PACKETIZER ) |
53 | 86 | set_description( N_("MPEG4 video packetizer") ) |
54 | 86 | set_capability( "video packetizer", 50 ) |
55 | 172 | set_callbacks( Open, Close ) |
56 | 86 | vlc_module_end () |
57 | | |
58 | | /**************************************************************************** |
59 | | * Local prototypes |
60 | | ****************************************************************************/ |
61 | | typedef struct |
62 | | { |
63 | | /* |
64 | | * Input properties |
65 | | */ |
66 | | packetizer_t packetizer; |
67 | | |
68 | | /* |
69 | | * Common properties |
70 | | */ |
71 | | vlc_tick_t i_interpolated_pts; |
72 | | vlc_tick_t i_interpolated_dts; |
73 | | vlc_tick_t i_last_ref_pts; |
74 | | uint64_t i_last_time_ref; |
75 | | uint64_t i_time_ref; |
76 | | int64_t i_last_time; |
77 | | uint32_t i_last_timeincr; |
78 | | |
79 | | unsigned int i_flags; |
80 | | |
81 | | uint16_t i_fps_num; |
82 | | |
83 | | bool b_frame; |
84 | | |
85 | | /* Current frame being built */ |
86 | | block_t *p_frame; |
87 | | block_t **pp_last; |
88 | | } decoder_sys_t; |
89 | | |
90 | | static block_t *Packetize( decoder_t *, block_t ** ); |
91 | | static void PacketizeFlush( decoder_t * ); |
92 | | |
93 | | static void PacketizeReset( void *p_private, bool b_broken ); |
94 | | static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t * ); |
95 | | static int PacketizeValidate( void *p_private, block_t * ); |
96 | | |
97 | | static block_t *ParseMPEGBlock( decoder_t *, block_t * ); |
98 | | static int ParseVOL( decoder_t *, es_format_t *, uint8_t *, int ); |
99 | | static int ParseVO( decoder_t *, block_t * ); |
100 | | static int ParseVOP( decoder_t *, block_t * ); |
101 | | |
102 | | #define VIDEO_OBJECT_MASK 0x01f |
103 | | #define VIDEO_OBJECT_LAYER_MASK 0x00f |
104 | | |
105 | | #define VIDEO_OBJECT_START_CODE 0x100 |
106 | 1.42M | #define VIDEO_OBJECT_LAYER_START_CODE 0x120 |
107 | 553k | #define RESERVED_START_CODE 0x130 |
108 | 1.06M | #define VISUAL_OBJECT_SEQUENCE_START_CODE 0x1b0 |
109 | 1.06M | #define VISUAL_OBJECT_SEQUENCE_END_CODE 0x1b1 |
110 | 532k | #define USER_DATA_START_CODE 0x1b2 |
111 | | #define GROUP_OF_VOP_START_CODE 0x1b3 |
112 | | #define VIDEO_SESSION_ERROR_CODE 0x1b4 |
113 | 355k | #define VISUAL_OBJECT_START_CODE 0x1b5 |
114 | 689k | #define VOP_START_CODE 0x1b6 |
115 | | #define FACE_OBJECT_START_CODE 0x1ba |
116 | | #define FACE_OBJECT_PLANE_START_CODE 0x1bb |
117 | | #define MESH_OBJECT_START_CODE 0x1bc |
118 | | #define MESH_OBJECT_PLANE_START_CODE 0x1bd |
119 | | #define STILL_TEXTURE_OBJECT_START_CODE 0x1be |
120 | | #define TEXTURE_SPATIAL_LAYER_START_CODE 0x1bf |
121 | | #define TEXTURE_SNR_LAYER_START_CODE 0x1c0 |
122 | | |
123 | | static const uint8_t p_mp4v_startcode[3] = { 0x00, 0x00, 0x01 }; |
124 | | |
125 | | /***************************************************************************** |
126 | | * Open: probe the packetizer and return score |
127 | | *****************************************************************************/ |
128 | | static int Open( vlc_object_t *p_this ) |
129 | 79.3k | { |
130 | 79.3k | decoder_t *p_dec = (decoder_t*)p_this; |
131 | 79.3k | decoder_sys_t *p_sys; |
132 | | |
133 | 79.3k | if( p_dec->fmt_in->i_codec != VLC_CODEC_MP4V ) |
134 | 71.9k | return VLC_EGENERIC; |
135 | | |
136 | | /* Allocate the memory needed to store the decoder's structure */ |
137 | 7.41k | if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) |
138 | 0 | return VLC_ENOMEM; |
139 | 7.41k | memset( p_sys, 0, sizeof(decoder_sys_t) ); |
140 | | |
141 | | /* Misc init */ |
142 | 7.41k | packetizer_Init( &p_sys->packetizer, |
143 | 7.41k | p_mp4v_startcode, sizeof(p_mp4v_startcode), startcode_FindAnnexB, |
144 | 7.41k | NULL, 0, 4, |
145 | 7.41k | PacketizeReset, PacketizeParse, PacketizeValidate, NULL, |
146 | 7.41k | p_dec ); |
147 | | |
148 | 7.41k | p_sys->p_frame = NULL; |
149 | 7.41k | p_sys->pp_last = &p_sys->p_frame; |
150 | | |
151 | | /* Setup properties */ |
152 | 7.41k | es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in ); |
153 | 7.41k | p_dec->fmt_out.i_codec = VLC_CODEC_MP4V; |
154 | | |
155 | 7.41k | if( p_dec->fmt_out.i_extra ) |
156 | 1.90k | { |
157 | | /* We have a vol */ |
158 | 1.90k | msg_Dbg( p_dec, "opening with vol size: %zu", p_dec->fmt_out.i_extra ); |
159 | 1.90k | ParseVOL( p_dec, &p_dec->fmt_out, |
160 | 1.90k | p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
161 | 1.90k | } |
162 | | |
163 | | /* Set callback */ |
164 | 7.41k | p_dec->pf_packetize = Packetize; |
165 | 7.41k | p_dec->pf_flush = PacketizeFlush; |
166 | 7.41k | p_dec->pf_get_cc = NULL; |
167 | | |
168 | 7.41k | return VLC_SUCCESS; |
169 | 7.41k | } |
170 | | |
171 | | /***************************************************************************** |
172 | | * Close: clean up the packetizer |
173 | | *****************************************************************************/ |
174 | | static void Close( vlc_object_t *p_this ) |
175 | 7.41k | { |
176 | 7.41k | decoder_t *p_dec = (decoder_t*)p_this; |
177 | 7.41k | decoder_sys_t *p_sys = p_dec->p_sys; |
178 | | |
179 | 7.41k | packetizer_Clean( &p_sys->packetizer ); |
180 | 7.41k | if( p_sys->p_frame ) |
181 | 1.85k | block_ChainRelease( p_sys->p_frame ); |
182 | 7.41k | free( p_sys ); |
183 | 7.41k | } |
184 | | |
185 | | /**************************************************************************** |
186 | | * Packetize: the whole thing |
187 | | ****************************************************************************/ |
188 | | static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) |
189 | 130k | { |
190 | 130k | decoder_sys_t *p_sys = p_dec->p_sys; |
191 | | |
192 | 130k | return packetizer_Packetize( &p_sys->packetizer, pp_block ); |
193 | 130k | } |
194 | | |
195 | | static void PacketizeFlush( decoder_t *p_dec ) |
196 | 0 | { |
197 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
198 | |
|
199 | 0 | packetizer_Flush( &p_sys->packetizer ); |
200 | 0 | } |
201 | | |
202 | | /***************************************************************************** |
203 | | * Helpers: |
204 | | *****************************************************************************/ |
205 | | static void PacketizeReset( void *p_private, bool b_flush ) |
206 | 33.1k | { |
207 | 33.1k | decoder_t *p_dec = p_private; |
208 | 33.1k | decoder_sys_t *p_sys = p_dec->p_sys; |
209 | | |
210 | 33.1k | if( b_flush ) |
211 | 0 | { |
212 | 0 | if( p_sys->p_frame ) |
213 | 0 | block_ChainRelease( p_sys->p_frame ); |
214 | 0 | p_sys->p_frame = NULL; |
215 | 0 | p_sys->pp_last = &p_sys->p_frame; |
216 | 0 | } |
217 | | |
218 | 33.1k | p_sys->i_interpolated_pts = |
219 | 33.1k | p_sys->i_interpolated_dts = |
220 | 33.1k | p_sys->i_last_ref_pts = VLC_TICK_INVALID; |
221 | | |
222 | 33.1k | p_sys->i_last_time_ref = |
223 | 33.1k | p_sys->i_time_ref = |
224 | 33.1k | p_sys->i_last_time = |
225 | 33.1k | p_sys->i_last_timeincr = 0; |
226 | 33.1k | } |
227 | | |
228 | | static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block ) |
229 | 532k | { |
230 | 532k | decoder_t *p_dec = p_private; |
231 | 532k | const vlc_tick_t i_dts = p_block->i_dts; |
232 | 532k | const vlc_tick_t i_pts = p_block->i_pts; |
233 | | |
234 | 532k | block_t *p_au = ParseMPEGBlock( p_dec, p_block ); |
235 | | |
236 | 532k | *pb_ts_used = p_au && p_au->i_dts == i_dts && p_au->i_pts == i_pts; |
237 | | |
238 | 532k | return p_au; |
239 | 532k | } |
240 | | |
241 | | |
242 | | static int PacketizeValidate( void *p_private, block_t *p_au ) |
243 | 15.8k | { |
244 | 15.8k | decoder_t *p_dec = p_private; |
245 | 15.8k | decoder_sys_t *p_sys = p_dec->p_sys; |
246 | | |
247 | | /* We've just started the stream, wait for the first PTS. |
248 | | * We discard here so we can still get the sequence header. */ |
249 | 15.8k | if( p_sys->i_interpolated_pts == VLC_TICK_INVALID && |
250 | 40 | p_sys->i_interpolated_dts == VLC_TICK_INVALID ) |
251 | 0 | { |
252 | 0 | msg_Dbg( p_dec, "need a starting pts/dts" ); |
253 | 0 | return VLC_EGENERIC; |
254 | 0 | } |
255 | | |
256 | | /* When starting the stream we can have the first frame with |
257 | | * a null DTS (i_interpolated_pts is initialized to 0) */ |
258 | 15.8k | if( p_au->i_dts == VLC_TICK_INVALID ) |
259 | 231 | p_au->i_dts = p_au->i_pts; |
260 | 15.8k | return VLC_SUCCESS; |
261 | 15.8k | } |
262 | | |
263 | | /***************************************************************************** |
264 | | * ParseMPEGBlock: Re-assemble fragments into a block containing a picture |
265 | | *****************************************************************************/ |
266 | | static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag ) |
267 | 532k | { |
268 | 532k | decoder_sys_t *p_sys = p_dec->p_sys; |
269 | 532k | block_t *p_pic = NULL; |
270 | | |
271 | 532k | if( p_frag->i_buffer < 4 ) |
272 | 0 | return p_frag; |
273 | | |
274 | 532k | const uint32_t i_startcode = GetDWBE( p_frag->p_buffer ); |
275 | 532k | if( i_startcode == VISUAL_OBJECT_SEQUENCE_START_CODE || |
276 | 532k | i_startcode == VISUAL_OBJECT_SEQUENCE_END_CODE || |
277 | 532k | i_startcode == USER_DATA_START_CODE ) |
278 | 6.93k | { /* VOS and USERDATA */ |
279 | | #if 0 |
280 | | /* Remove VOS start/end code from the original stream */ |
281 | | block_Release( p_frag ); |
282 | | #else |
283 | | /* Append the block for now since ts/ps muxers rely on VOL |
284 | | * being present in the stream */ |
285 | 6.93k | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
286 | 6.93k | #endif |
287 | 6.93k | return NULL; |
288 | 6.93k | } |
289 | 525k | else if( i_startcode >= VIDEO_OBJECT_LAYER_START_CODE && |
290 | 372k | i_startcode < RESERVED_START_CODE ) |
291 | 142k | { |
292 | | /* Copy the complete VOL */ |
293 | 142k | if( (size_t)p_dec->fmt_out.i_extra != p_frag->i_buffer || |
294 | 36.8k | ( p_frag->i_buffer && memcmp(p_dec->fmt_out.p_extra, |
295 | 36.8k | p_frag->p_buffer, p_frag->i_buffer) ) ) |
296 | 111k | { |
297 | 111k | void *p_realloc = realloc( p_dec->fmt_out.p_extra, p_frag->i_buffer ); |
298 | 111k | if( p_realloc ) |
299 | 111k | { |
300 | 111k | p_dec->fmt_out.p_extra = p_realloc; |
301 | 111k | p_dec->fmt_out.i_extra = p_frag->i_buffer; |
302 | 111k | memcpy( p_realloc, p_frag->p_buffer, p_frag->i_buffer ); |
303 | 111k | } |
304 | 111k | } |
305 | 142k | ParseVOL( p_dec, &p_dec->fmt_out, |
306 | 142k | p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
307 | | |
308 | | #if 0 |
309 | | /* Remove from the original stream */ |
310 | | block_Release( p_frag ); |
311 | | #else |
312 | | /* Append the block for now since ts/ps muxers rely on VOL |
313 | | * being present in the stream */ |
314 | 142k | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
315 | 142k | #endif |
316 | 142k | return NULL; |
317 | 142k | } |
318 | 383k | else |
319 | 383k | { |
320 | 383k | if( !p_dec->fmt_out.i_extra ) |
321 | 27.5k | { |
322 | 27.5k | msg_Warn( p_dec, "waiting for VOL" ); |
323 | 27.5k | block_Release( p_frag ); |
324 | 27.5k | return NULL; |
325 | 27.5k | } |
326 | | |
327 | | /* Append the block */ |
328 | 355k | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
329 | 355k | } |
330 | | |
331 | 355k | if( i_startcode == VISUAL_OBJECT_START_CODE ) |
332 | 10.7k | { |
333 | 10.7k | ParseVO( p_dec, p_frag ); |
334 | 10.7k | } |
335 | 344k | else |
336 | 344k | if( i_startcode == VOP_START_CODE && |
337 | 21.6k | ParseVOP( p_dec, p_frag ) == VLC_SUCCESS ) |
338 | 15.8k | { |
339 | | /* We are dealing with a VOP */ |
340 | 15.8k | p_pic = block_ChainGather( p_sys->p_frame ); |
341 | 15.8k | p_pic->i_flags = p_sys->i_flags; |
342 | 15.8k | p_pic->i_pts = p_sys->i_interpolated_pts; |
343 | 15.8k | p_pic->i_dts = p_sys->i_interpolated_dts; |
344 | | |
345 | | #if 0 |
346 | | msg_Err( p_dec, "output dts/pts (%"PRId64",%"PRId64")", p_pic->i_dts, p_pic->i_pts ); |
347 | | #endif |
348 | | /* Reset context */ |
349 | 15.8k | p_sys->p_frame = NULL; |
350 | 15.8k | p_sys->pp_last = &p_sys->p_frame; |
351 | 15.8k | } |
352 | | |
353 | 355k | return p_pic; |
354 | 532k | } |
355 | | |
356 | | /* ParseVOL: */ |
357 | | static int ParseVOL( decoder_t *p_dec, es_format_t *fmt, |
358 | | uint8_t *p_vol, int i_vol ) |
359 | 144k | { |
360 | 144k | decoder_sys_t *p_sys = p_dec->p_sys; |
361 | 144k | int i_vo_ver_id, i_shape; |
362 | 144k | h26x_aspect_ratio_t ar; |
363 | 144k | bs_t s; |
364 | | |
365 | 144k | for( ;; ) |
366 | 192k | { |
367 | 192k | if( i_vol <= 5 ) |
368 | 5.59k | return VLC_EGENERIC; |
369 | | |
370 | 187k | uint32_t i_startcode = GetDWBE( p_vol ); |
371 | 187k | if( i_startcode >= VIDEO_OBJECT_LAYER_START_CODE && |
372 | 181k | i_startcode < RESERVED_START_CODE ) |
373 | 139k | break; |
374 | | |
375 | 48.3k | p_vol++; i_vol--; |
376 | 48.3k | } |
377 | | |
378 | 139k | bs_init( &s, &p_vol[4], i_vol - 4 ); |
379 | | |
380 | 139k | bs_skip( &s, 1 ); /* random access */ |
381 | 139k | bs_skip( &s, 8 ); /* vo_type */ |
382 | 139k | if( bs_read1( &s ) ) |
383 | 93.9k | { |
384 | 93.9k | i_vo_ver_id = bs_read( &s, 4 ); |
385 | 93.9k | bs_skip( &s, 3 ); |
386 | 93.9k | } |
387 | 45.1k | else |
388 | 45.1k | { |
389 | 45.1k | i_vo_ver_id = 1; |
390 | 45.1k | } |
391 | 139k | ar.aspect_ratio_idc = bs_read( &s, 4 ) & 0xf; |
392 | 139k | if( ar.aspect_ratio_idc == 0xf ) |
393 | 31.6k | { |
394 | 31.6k | ar.aspect_ratio_idc = 0xff; // was only coded on 4 bits in MPEG4 |
395 | 31.6k | ar.sar_width = bs_read( &s, 8 ); |
396 | 31.6k | ar.sar_height = bs_read( &s, 8 ); |
397 | 31.6k | } |
398 | 139k | if(!p_dec->fmt_in->video.i_sar_num || |
399 | 5.85k | !p_dec->fmt_in->video.i_sar_den) |
400 | 134k | { |
401 | 134k | h26x_get_aspect_ratio(&ar, |
402 | 134k | &fmt->video.i_sar_num, |
403 | 134k | &fmt->video.i_sar_den); |
404 | 134k | } |
405 | | |
406 | 139k | if( bs_read1( &s ) ) |
407 | 81.8k | { |
408 | | /* vol control parameter */ |
409 | 81.8k | bs_skip( &s, 2 ); /* chroma_format */ |
410 | 81.8k | bs_skip( &s, 1 ); /* low_delay */ |
411 | | |
412 | 81.8k | if( bs_read1( &s ) ) |
413 | 35.9k | { |
414 | 35.9k | bs_skip( &s, 16 ); |
415 | 35.9k | bs_skip( &s, 16 ); |
416 | 35.9k | bs_skip( &s, 16 ); |
417 | 35.9k | bs_skip( &s, 3 ); |
418 | 35.9k | bs_skip( &s, 11 ); |
419 | 35.9k | bs_skip( &s, 1 ); |
420 | 35.9k | bs_skip( &s, 16 ); |
421 | 35.9k | } |
422 | 81.8k | } |
423 | | /* shape 0->RECT, 1->BIN, 2->BIN_ONLY, 3->GRAY */ |
424 | 139k | i_shape = bs_read( &s, 2 ); |
425 | 139k | if( i_shape == 3 && i_vo_ver_id != 1 ) |
426 | 20.6k | { |
427 | 20.6k | bs_skip( &s, 4 ); |
428 | 20.6k | } |
429 | | |
430 | 139k | if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ |
431 | | |
432 | 45.7k | p_sys->i_fps_num = bs_read( &s, 16 ); /* Time increment resolution*/ |
433 | 45.7k | if( !p_sys->i_fps_num ) p_sys->i_fps_num = 1; |
434 | | |
435 | 45.7k | if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ |
436 | | |
437 | 34.0k | if( bs_read1( &s ) ) |
438 | 32.0k | { |
439 | 32.0k | unsigned i_time_increment_bits = vlc_log2( p_sys->i_fps_num - 1 ) + 1; |
440 | | |
441 | 32.0k | bs_skip( &s, i_time_increment_bits ); /* i_fps_den */ |
442 | 32.0k | } |
443 | 34.0k | if( i_shape == 0 ) |
444 | 12.0k | { |
445 | 12.0k | bs_skip( &s, 1 ); |
446 | 12.0k | fmt->video.i_width = bs_read( &s, 13 ); |
447 | 12.0k | bs_skip( &s, 1 ); |
448 | 12.0k | fmt->video.i_height= bs_read( &s, 13 ); |
449 | 12.0k | bs_skip( &s, 1 ); |
450 | 12.0k | } |
451 | | |
452 | 34.0k | return VLC_SUCCESS; |
453 | 45.7k | } |
454 | | |
455 | | static int ParseVO( decoder_t *p_dec, block_t *p_vo ) |
456 | 10.7k | { |
457 | 10.7k | bs_t s; |
458 | 10.7k | bs_init( &s, &p_vo->p_buffer[4], p_vo->i_buffer - 4 ); |
459 | 10.7k | if( bs_read1( &s ) ) |
460 | 2.39k | bs_skip( &s, 7 ); |
461 | | |
462 | 10.7k | const uint8_t visual_object_type = bs_read( &s, 4 ); |
463 | 10.7k | if( visual_object_type == 1 /* video ID */ || |
464 | 10.6k | visual_object_type == 2 /* still texture ID */ ) |
465 | 2.90k | { |
466 | 2.90k | h26x_colour_description_t colour = |
467 | 2.90k | { |
468 | 2.90k | .colour_primaries = 1, |
469 | 2.90k | .transfer_characteristics = 1, |
470 | 2.90k | .matrix_coeffs = 1, |
471 | 2.90k | .full_range_flag = 0, |
472 | 2.90k | }; |
473 | 2.90k | if( bs_read1( &s ) ) /* video_signal_type */ |
474 | 1.93k | { |
475 | 1.93k | bs_skip( &s, 3 ); |
476 | 1.93k | colour.full_range_flag = bs_read( &s, 1 ); |
477 | 1.93k | if( bs_read( &s, 1 ) ) /* colour description */ |
478 | 1.33k | { |
479 | 1.33k | colour.colour_primaries = bs_read( &s, 8 ); |
480 | 1.33k | colour.transfer_characteristics = bs_read( &s, 8 ); |
481 | 1.33k | colour.matrix_coeffs = bs_read( &s, 8 ); |
482 | 1.33k | } |
483 | 1.93k | } |
484 | | |
485 | 2.90k | if( p_dec->fmt_in->video.primaries == COLOR_PRIMARIES_UNDEF ) |
486 | 2.90k | { |
487 | 2.90k | h26x_get_colorimetry( &colour, |
488 | 2.90k | &p_dec->fmt_out.video.primaries, |
489 | 2.90k | &p_dec->fmt_out.video.transfer, |
490 | 2.90k | &p_dec->fmt_out.video.space, |
491 | 2.90k | &p_dec->fmt_out.video.color_range ); |
492 | 2.90k | } |
493 | 2.90k | } |
494 | | |
495 | 10.7k | return VLC_SUCCESS; |
496 | 10.7k | } |
497 | | |
498 | | static int ParseVOP( decoder_t *p_dec, block_t *p_vop ) |
499 | 21.6k | { |
500 | 21.6k | decoder_sys_t *p_sys = p_dec->p_sys; |
501 | 21.6k | uint64_t i_time_ref; |
502 | 21.6k | uint32_t i_time_increment; |
503 | 21.6k | uint64_t i_modulo_time_base = 0; |
504 | 21.6k | bs_t s; |
505 | | |
506 | 21.6k | if( p_sys->i_fps_num == 0 ) |
507 | 1.57k | return VLC_EGENERIC; |
508 | | |
509 | 20.1k | bs_init( &s, &p_vop->p_buffer[4], p_vop->i_buffer - 4 ); |
510 | | |
511 | 20.1k | switch( bs_read( &s, 2 ) ) |
512 | 20.1k | { |
513 | 6.96k | case 0: |
514 | 6.96k | p_sys->i_flags = BLOCK_FLAG_TYPE_I; |
515 | 6.96k | break; |
516 | 4.47k | case 1: |
517 | 4.47k | p_sys->i_flags = BLOCK_FLAG_TYPE_P; |
518 | 4.47k | break; |
519 | 2.44k | case 2: |
520 | 2.44k | p_sys->i_flags = BLOCK_FLAG_TYPE_B; |
521 | 2.44k | p_sys->b_frame = true; |
522 | 2.44k | break; |
523 | 6.22k | case 3: /* gni ? */ |
524 | 6.22k | p_sys->i_flags = BLOCK_FLAG_TYPE_PB; |
525 | 6.22k | break; |
526 | 20.1k | } |
527 | | |
528 | 403k | while( bs_read( &s, 1 ) ) i_modulo_time_base++; |
529 | 20.1k | if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ |
530 | | |
531 | | /* VOP time increment */ |
532 | 15.8k | unsigned i_time_increment_bits = vlc_log2(p_sys->i_fps_num - 1) + 1; |
533 | 15.8k | i_time_increment = bs_read( &s, i_time_increment_bits ); |
534 | | |
535 | | /* Interpolate PTS/DTS */ |
536 | 15.8k | if( !(p_sys->i_flags & BLOCK_FLAG_TYPE_B) ) |
537 | 13.8k | { |
538 | 13.8k | p_sys->i_last_time_ref = p_sys->i_time_ref; |
539 | 13.8k | p_sys->i_time_ref += |
540 | 13.8k | (i_modulo_time_base * p_sys->i_fps_num); |
541 | 13.8k | i_time_ref = p_sys->i_time_ref; |
542 | 13.8k | } |
543 | 1.95k | else |
544 | 1.95k | { |
545 | 1.95k | i_time_ref = p_sys->i_last_time_ref + |
546 | 1.95k | (i_modulo_time_base * p_sys->i_fps_num); |
547 | 1.95k | } |
548 | | |
549 | 15.8k | int64_t i_time_diff = (i_time_ref + i_time_increment) - (p_sys->i_last_time + p_sys->i_last_timeincr); |
550 | 15.8k | if( i_modulo_time_base == 0 && i_time_diff < 0 && -i_time_diff > p_sys->i_fps_num ) |
551 | 1.27k | { |
552 | 1.27k | msg_Warn(p_dec, "missing modulo_time_base update"); |
553 | 1.27k | i_modulo_time_base += -i_time_diff / p_sys->i_fps_num; |
554 | 1.27k | p_sys->i_time_ref += (i_modulo_time_base * p_sys->i_fps_num); |
555 | 1.27k | p_sys->i_time_ref += p_sys->i_last_timeincr % p_sys->i_fps_num; |
556 | 1.27k | i_time_ref = p_sys->i_time_ref; |
557 | 1.27k | } |
558 | | |
559 | 15.8k | if( p_sys->i_fps_num < 5 && /* Work-around buggy streams */ |
560 | 1.95k | p_dec->fmt_in->video.i_frame_rate > 0 && |
561 | 0 | p_dec->fmt_in->video.i_frame_rate_base > 0 ) |
562 | 0 | { |
563 | 0 | p_sys->i_interpolated_pts += vlc_tick_from_samples( |
564 | 0 | p_dec->fmt_in->video.i_frame_rate_base, |
565 | 0 | p_dec->fmt_in->video.i_frame_rate); |
566 | 0 | } |
567 | 15.8k | else |
568 | 15.8k | { |
569 | 15.8k | i_time_diff = (i_time_ref + i_time_increment) - (p_sys->i_last_time + p_sys->i_last_timeincr); |
570 | 15.8k | p_sys->i_interpolated_pts += vlc_tick_from_samples( i_time_diff, p_sys->i_fps_num ); |
571 | 15.8k | } |
572 | | |
573 | | #if 0 |
574 | | msg_Err( p_dec, "interp dts/pts (%"PRId64",%"PRId64"), dts/pts (%"PRId64",%"PRId64") %"PRId64" mod %d inc %"PRId64, |
575 | | p_sys->i_interpolated_dts, p_sys->i_interpolated_pts, |
576 | | p_vop->i_dts, p_vop->i_pts, p_sys->i_time_ref, i_modulo_time_base, i_time_increment ); |
577 | | #endif |
578 | | |
579 | 15.8k | p_sys->i_last_time = i_time_ref; |
580 | 15.8k | p_sys->i_last_timeincr = i_time_increment; |
581 | | |
582 | | /* Correct interpolated dts when we receive a new pts/dts */ |
583 | 15.8k | if( p_vop->i_pts != VLC_TICK_INVALID ) |
584 | 242 | p_sys->i_interpolated_pts = p_vop->i_pts; |
585 | 15.8k | if( p_vop->i_dts != VLC_TICK_INVALID ) |
586 | 6.42k | p_sys->i_interpolated_dts = p_vop->i_dts; |
587 | | |
588 | 15.8k | if( (p_sys->i_flags & BLOCK_FLAG_TYPE_B) || !p_sys->b_frame ) |
589 | 11.2k | { |
590 | | /* Trivial case (DTS == PTS) */ |
591 | | |
592 | 11.2k | p_sys->i_interpolated_dts = p_sys->i_interpolated_pts; |
593 | | |
594 | 11.2k | if( p_vop->i_pts != VLC_TICK_INVALID ) |
595 | 241 | p_sys->i_interpolated_dts = p_vop->i_pts; |
596 | 11.2k | if( p_vop->i_dts != VLC_TICK_INVALID ) |
597 | 2.83k | p_sys->i_interpolated_dts = p_vop->i_dts; |
598 | | |
599 | 11.2k | p_sys->i_interpolated_pts = p_sys->i_interpolated_dts; |
600 | 11.2k | } |
601 | 4.56k | else |
602 | 4.56k | { |
603 | 4.56k | if( p_sys->i_last_ref_pts != VLC_TICK_INVALID ) |
604 | 4.26k | p_sys->i_interpolated_dts = p_sys->i_last_ref_pts; |
605 | | |
606 | 4.56k | p_sys->i_last_ref_pts = p_sys->i_interpolated_pts; |
607 | 4.56k | } |
608 | | |
609 | 15.8k | return VLC_SUCCESS; |
610 | 20.1k | } |
611 | | |